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

View File

@ -467,6 +467,7 @@ FAR struct ieee802154_radio_s *
dev->radio.txnotify = mrf24j40_txnotify;
dev->radio.txdelayed = mrf24j40_txdelayed;
dev->radio.rxenable = mrf24j40_rxenable;
dev->radio.energydetect = mrf24j40_energydetect;
dev->radio.beaconstart = mrf24j40_beaconstart;
dev->radio.beaconupdate = mrf24j40_beaconupdate;
dev->radio.beaconstop = mrf24j40_beaconstop;

View File

@ -426,6 +426,11 @@ int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable)
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)
{
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;

View File

@ -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_energydetect(FAR struct ieee802154_radio_s *radio, uint32_t nsymbols);
int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon);

View File

@ -1425,11 +1425,14 @@ struct ieee802154_scan_conf_s
enum ieee802154_status_e status;
enum ieee802154_scantype_e type;
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 numdesc;
struct ieee802154_pandesc_s pandescs[MAC802154_NPANDESC];
uint8_t edlist[MAC802154_NPANDESC];
uint8_t edlist[15];
uint8_t numresults;
};
/*****************************************************************************

View File

@ -118,6 +118,8 @@ struct ieee802154_radiocb_s
FAR struct ieee802154_data_ind_s *ind);
CODE void (*sfevent) (FAR const struct ieee802154_radiocb_s *radiocb,
enum ieee802154_sfevent_e sfevent);
CODE void (*edresult) (FAR const struct ieee802154_radiocb_s *radiocb,
uint8_t edval);
};
struct ieee802154_radio_s
@ -136,6 +138,8 @@ struct ieee802154_radio_s
FAR struct ieee802154_txdesc_s *txdesc,
uint32_t symboldelay);
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,
FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon);

View File

@ -88,6 +88,9 @@ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_data_ind_s *ind);
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,
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);
}
/****************************************************************************
* 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,
enum ieee802154_sfevent_e sfevent)
{
@ -2125,6 +2167,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
radiocb->txdone = mac802154_txdone;
radiocb->rxframe = mac802154_rxframe;
radiocb->sfevent = mac802154_sfevent;
radiocb->edresult = mac802154_edresult;
/* Bind our callback structure */

View File

@ -150,9 +150,8 @@ struct ieee802154_privmac_s
/******************* Fields related to SCAN operation ***********************/
/* List of PAN descriptors to track during scan procedures */
uint8_t scanindex;
uint8_t edlist[15];
uint8_t npandesc;
struct ieee802154_pandesc_s pandescs[MAC802154_NPANDESC];
uint8_t panidbeforescan[IEEE802154_PANIDSIZE];

View File

@ -124,11 +124,13 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
priv->scanindex = 0;
priv->npandesc = 0;
priv->scansymdur = IEEE802154_BASE_SUPERFRAME_DURATION * ((1 << req->duration) + 1);
switch (req->type)
{
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 */
@ -154,9 +156,6 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
*/
mac802154_rxenable(priv);
priv->scansymdur = IEEE802154_BASE_SUPERFRAME_DURATION *
((1 << req->duration) + 1);
mac802154_timerstart(priv, priv->scansymdur, mac802154_scantimeout);
}
break;
@ -168,8 +167,15 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
break;
case IEEE802154_SCANTYPE_ED:
{
ret = -ENOTTY;
goto errout_with_sem;
wlinfo("MLME: Starting Energy Scan\n");
/* 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;
case IEEE802154_SCANTYPE_ORPHAN:
@ -213,33 +219,105 @@ void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
scanconf->type = priv->currscan.type;
scanconf->chpage = priv->currscan.chpage;
/* Copy in the channels that did not get scanned */
if (priv->scanindex != priv->currscan.numchan)
if (priv->currscan.type == IEEE802154_SCANTYPE_ED)
{
scanconf->numunscanned = priv->currscan.numchan - priv->scanindex;
memcpy(scanconf->unscanned, &priv->currscan.channels[priv->scanindex],
scanconf->numunscanned);
/* "The list of energy measurements, one for each channel searched during an
* ED scan. This parameter is null for active, passive, and orphan scans." [1]
*/
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,
sizeof(struct ieee802154_pandesc_s) * priv->npandesc);
scanconf->numunscanned = priv->currscan.numchan - priv->scanindex;
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;
/* Reset the PAN ID to the setting before the scan started */
mac802154_setpanid(priv, priv->panidbeforescan);
priv->curr_op = MAC802154_OP_NONE;
mac802154_givesem(&priv->opsem);
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
****************************************************************************/

View File

@ -60,6 +60,8 @@
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,
enum ieee802154_status_e status);