Merged in antmerlino/nuttx/ieee802154_energydetect (pull request #977)

wireless/ieee8021254: Adds support for energy detect.

Adds support for energy detect by introducing a new radio call/callback, as the PHY layer is required to perform the energy detect.

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Anthony Merlino
2019-08-10 17:03:24 +00:00
committed by Gregory Nutt
parent 70186874e3
commit 90317a9eeb
9 changed files with 162 additions and 25 deletions
@@ -467,6 +467,7 @@ FAR struct ieee802154_radio_s *
dev->radio.txnotify = mrf24j40_txnotify; dev->radio.txnotify = mrf24j40_txnotify;
dev->radio.txdelayed = mrf24j40_txdelayed; dev->radio.txdelayed = mrf24j40_txdelayed;
dev->radio.rxenable = mrf24j40_rxenable; dev->radio.rxenable = mrf24j40_rxenable;
dev->radio.energydetect = mrf24j40_energydetect;
dev->radio.beaconstart = mrf24j40_beaconstart; dev->radio.beaconstart = mrf24j40_beaconstart;
dev->radio.beaconupdate = mrf24j40_beaconupdate; dev->radio.beaconupdate = mrf24j40_beaconupdate;
dev->radio.beaconstop = mrf24j40_beaconstop; dev->radio.beaconstop = mrf24j40_beaconstop;
@@ -426,6 +426,11 @@ int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable)
return OK; return OK;
} }
int mrf24j40_energydetect(FAR struct ieee802154_radio_s *radio, uint32_t nsymbols)
{
return -ENOTTY;
}
int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
{ {
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
@@ -57,6 +57,8 @@ int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio,
int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable); int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable);
int mrf24j40_energydetect(FAR struct ieee802154_radio_s *radio, uint32_t nsymbols);
int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio, int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec, FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon); FAR struct ieee802154_beaconframe_s *beacon);
@@ -1425,11 +1425,14 @@ struct ieee802154_scan_conf_s
enum ieee802154_status_e status; enum ieee802154_status_e status;
enum ieee802154_scantype_e type; enum ieee802154_scantype_e type;
uint8_t chpage; uint8_t chpage;
uint8_t unscanned[15];
uint8_t chlist[15]; /* Used for both scanned channels (ED) and unscanned
* channels (Active/Passive) */
uint8_t numunscanned; uint8_t numunscanned;
uint8_t numdesc;
struct ieee802154_pandesc_s pandescs[MAC802154_NPANDESC]; struct ieee802154_pandesc_s pandescs[MAC802154_NPANDESC];
uint8_t edlist[MAC802154_NPANDESC]; uint8_t edlist[15];
uint8_t numresults;
}; };
/***************************************************************************** /*****************************************************************************
@@ -118,6 +118,8 @@ struct ieee802154_radiocb_s
FAR struct ieee802154_data_ind_s *ind); FAR struct ieee802154_data_ind_s *ind);
CODE void (*sfevent) (FAR const struct ieee802154_radiocb_s *radiocb, CODE void (*sfevent) (FAR const struct ieee802154_radiocb_s *radiocb,
enum ieee802154_sfevent_e sfevent); enum ieee802154_sfevent_e sfevent);
CODE void (*edresult) (FAR const struct ieee802154_radiocb_s *radiocb,
uint8_t edval);
}; };
struct ieee802154_radio_s struct ieee802154_radio_s
@@ -136,6 +138,8 @@ struct ieee802154_radio_s
FAR struct ieee802154_txdesc_s *txdesc, FAR struct ieee802154_txdesc_s *txdesc,
uint32_t symboldelay); uint32_t symboldelay);
CODE int (*rxenable) (FAR struct ieee802154_radio_s *radio, bool enable); CODE int (*rxenable) (FAR struct ieee802154_radio_s *radio, bool enable);
CODE int (*energydetect) (FAR struct ieee802154_radio_s *radio,
uint32_t symboldelay);
CODE int (*beaconstart)(FAR struct ieee802154_radio_s *radio, CODE int (*beaconstart)(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec, FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon); FAR struct ieee802154_beaconframe_s *beacon);
+43
View File
@@ -88,6 +88,9 @@ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_data_ind_s *ind); FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxframe_worker(FAR void *arg); static void mac802154_rxframe_worker(FAR void *arg);
static void mac802154_edresult(FAR const struct ieee802154_radiocb_s *radiocb,
uint8_t edval);
static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb, static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
enum ieee802154_sfevent_e sfevent); enum ieee802154_sfevent_e sfevent);
@@ -1635,6 +1638,45 @@ static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
} }
/****************************************************************************
* Name: mac802154_edresult
*
* Description:
* Called from the radio driver through the callback struct. This
* function is called when the radio has finished an energy detect operation.
* This is triggered by a SCAN.request primitive with ScanType set to Energy
* Detect (ED)
*
****************************************************************************/
static void mac802154_edresult(FAR const struct ieee802154_radiocb_s *radiocb,
uint8_t edval)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
mac802154_lock(priv, false);
/* If we are actively performing a scan operation, notify the scan handler */
if (priv->curr_op == MAC802154_OP_SCAN)
{
mac802154_edscan_onresult(priv, edval);
}
/* Relinquish control of the private structure */
mac802154_unlock(priv);
}
static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb, static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
enum ieee802154_sfevent_e sfevent) enum ieee802154_sfevent_e sfevent)
{ {
@@ -2125,6 +2167,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
radiocb->txdone = mac802154_txdone; radiocb->txdone = mac802154_txdone;
radiocb->rxframe = mac802154_rxframe; radiocb->rxframe = mac802154_rxframe;
radiocb->sfevent = mac802154_sfevent; radiocb->sfevent = mac802154_sfevent;
radiocb->edresult = mac802154_edresult;
/* Bind our callback structure */ /* Bind our callback structure */
+1 -2
View File
@@ -150,9 +150,8 @@ struct ieee802154_privmac_s
/******************* Fields related to SCAN operation ***********************/ /******************* Fields related to SCAN operation ***********************/
/* List of PAN descriptors to track during scan procedures */
uint8_t scanindex; uint8_t scanindex;
uint8_t edlist[15];
uint8_t npandesc; uint8_t npandesc;
struct ieee802154_pandesc_s pandescs[MAC802154_NPANDESC]; struct ieee802154_pandesc_s pandescs[MAC802154_NPANDESC];
uint8_t panidbeforescan[IEEE802154_PANIDSIZE]; uint8_t panidbeforescan[IEEE802154_PANIDSIZE];
+98 -20
View File
@@ -124,11 +124,13 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
priv->scanindex = 0; priv->scanindex = 0;
priv->npandesc = 0; priv->npandesc = 0;
priv->scansymdur = IEEE802154_BASE_SUPERFRAME_DURATION * ((1 << req->duration) + 1);
switch (req->type) switch (req->type)
{ {
case IEEE802154_SCANTYPE_PASSIVE: case IEEE802154_SCANTYPE_PASSIVE:
{ {
wlinfo("MLME: Starting Passive scan\n"); wlinfo("MLME: Starting Passive Scan\n");
/* Set the channel to the first channel in the list */ /* Set the channel to the first channel in the list */
@@ -154,9 +156,6 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
*/ */
mac802154_rxenable(priv); mac802154_rxenable(priv);
priv->scansymdur = IEEE802154_BASE_SUPERFRAME_DURATION *
((1 << req->duration) + 1);
mac802154_timerstart(priv, priv->scansymdur, mac802154_scantimeout); mac802154_timerstart(priv, priv->scansymdur, mac802154_scantimeout);
} }
break; break;
@@ -168,8 +167,15 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
break; break;
case IEEE802154_SCANTYPE_ED: case IEEE802154_SCANTYPE_ED:
{ {
ret = -ENOTTY; wlinfo("MLME: Starting Energy Scan\n");
goto errout_with_sem;
/* Set the channel to the first channel in the list, and trigger an
* energy detect operation with the radio layer.
*/
mac802154_setchpage(priv, req->chpage);
mac802154_setchannel(priv, req->channels[priv->scanindex]);
priv->radio->energydetect(priv->radio, priv->scansymdur);
} }
break; break;
case IEEE802154_SCANTYPE_ORPHAN: case IEEE802154_SCANTYPE_ORPHAN:
@@ -213,33 +219,105 @@ void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
scanconf->type = priv->currscan.type; scanconf->type = priv->currscan.type;
scanconf->chpage = priv->currscan.chpage; scanconf->chpage = priv->currscan.chpage;
/* Copy in the channels that did not get scanned */ if (priv->currscan.type == IEEE802154_SCANTYPE_ED)
if (priv->scanindex != priv->currscan.numchan)
{ {
scanconf->numunscanned = priv->currscan.numchan - priv->scanindex; /* "The list of energy measurements, one for each channel searched during an
memcpy(scanconf->unscanned, &priv->currscan.channels[priv->scanindex], * ED scan. This parameter is null for active, passive, and orphan scans." [1]
scanconf->numunscanned); */
memcpy(scanconf->edlist, priv->edlist, sizeof(scanconf->edlist));
memcpy(scanconf->chlist, priv->currscan.channels, sizeof(scanconf->chlist));
scanconf->numresults = priv->currscan.numchan;
} }
/* Copy the PAN descriptors into the primitive */ else
{
/* "A list of the channels given in the request which were not scanned. This
* parameter is not valid for ED scans." [1]
*/
memcpy(scanconf->pandescs, priv->pandescs, scanconf->numunscanned = priv->currscan.numchan - priv->scanindex;
sizeof(struct ieee802154_pandesc_s) * priv->npandesc); if (scanconf->numunscanned)
{
memcpy(scanconf->chlist, &priv->currscan.channels[priv->scanindex],
scanconf->numunscanned);
}
/* "The list of PAN descriptors, one for each beacon found during an active or
* passive scan if macAutoRequest is set to TRUE. This parameter is null for
* ED and orphan scans or when macAutoRequest is set to FALSE during an
* active or passive scan." [1]
*/
if (priv->currscan.type != IEEE802154_SCANTYPE_ORPHAN && priv->autoreq)
{
memcpy(scanconf->pandescs, priv->pandescs,
sizeof(struct ieee802154_pandesc_s) * priv->npandesc);
scanconf->numresults = priv->npandesc;
}
if (priv->currscan.type == IEEE802154_SCANTYPE_PASSIVE)
{
/* Reset the PAN ID to the setting before the scan started */
mac802154_setpanid(priv, priv->panidbeforescan);
}
}
scanconf->numdesc = priv->npandesc;
scanconf->status = status; scanconf->status = status;
/* Reset the PAN ID to the setting before the scan started */
mac802154_setpanid(priv, priv->panidbeforescan);
priv->curr_op = MAC802154_OP_NONE; priv->curr_op = MAC802154_OP_NONE;
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
mac802154_notify(priv, primitive); mac802154_notify(priv, primitive);
} }
/****************************************************************************
* Name: mac802154_edscan_onresult
*
* Description:
* Function indirectly called from the radio layer via the radiocb edresult()
* call.
*
* Assumptions:
* Called with the priv mac struct locked
*
****************************************************************************/
void mac802154_edscan_onresult(FAR struct ieee802154_privmac_s *priv, uint8_t edval)
{
DEBUGASSERT(priv->curr_op == MAC802154_OP_SCAN &&
priv->currscan.type == IEEE802154_SCANTYPE_ED);
/* Copy the energy value into our local list */
priv->edlist[priv->scanindex] = edval;
/* If we got here it means we are done scanning that channel */
priv->scanindex++;
/* Check to see if this was the last channel to scan */
if (priv->scanindex == priv->currscan.numchan)
{
mac802154_scanfinish(priv, IEEE802154_STATUS_SUCCESS);
return;
}
/* Continue on with the next channel in the list */
mac802154_setchannel(priv, priv->currscan.channels[priv->scanindex]);
/* ...after switching to the channel for a passive scan, the device
* shall enable its receiver for at most
* [aBaseSuperframeDuration × (2 * n + 1)],
* where n is the value of the ScanDuration parameter. [1] pg. 25
*/
priv->radio->energydetect(priv->radio, priv->scansymdur);
}
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
+2
View File
@@ -60,6 +60,8 @@
struct ieee802154_privmac_s; /* Forward Reference */ struct ieee802154_privmac_s; /* Forward Reference */
void mac802154_edscan_onresult(FAR struct ieee802154_privmac_s *priv, uint8_t edval);
void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv, void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
enum ieee802154_status_e status); enum ieee802154_status_e status);