[efr32] implement otPlatRadioEnergyScan API (#3631)

* refactor for energy scan API

* rename enum, init status in init func, tidy up and fix issue in GetRssi

* add cast and fix start energy scan error return
This commit is contained in:
Joseph Newman
2019-02-27 12:03:51 -08:00
committed by Jonathan Hui
parent ceed19c4b5
commit f9884b8afc
+77 -22
View File
@@ -95,15 +95,25 @@ enum
#endif
};
typedef enum
{
ENERGY_SCAN_STATUS_IDLE,
ENERGY_SCAN_STATUS_IN_PROGRESS,
ENERGY_SCAN_STATUS_COMPLETED
} energyScanStatus;
typedef enum
{
ENERGY_SCAN_MODE_SYNC,
ENERGY_SCAN_MODE_ASYNC
} energyScanMode;
static uint16_t sPanId = 0;
static volatile bool sTransmitBusy = false;
static bool sPromiscuous = false;
static bool sIsSrcMatchEnabled = false;
static otRadioState sState = OT_RADIO_STATE_DISABLED;
static volatile bool sSampleRssiDone;
static volatile int8_t sRssi;
static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH];
static otRadioFrame sReceiveFrame;
static otError sReceiveError;
@@ -123,6 +133,13 @@ static sSrcMatchEntry srcMatchExtEntry[RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM];
efr32BandConfig sBandConfigs[EFR32_NUM_BAND_CONFIGS];
static volatile energyScanStatus sEnergyScanStatus;
static volatile int8_t sEnergyScanResultDbm;
static energyScanMode sEnergyScanMode;
#define QUARTER_DBM_IN_DBM 4
#define US_IN_MS 1000
static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents);
static const RAIL_IEEE802154_Config_t sRailIeee802154Config = {
@@ -300,6 +317,8 @@ void efr32RadioInit(void)
sTxBandConfig = sRxBandConfig;
efr32RadioSetTxPower(sTxBandConfig->mRailHandle, sTxBandConfig->mChannelConfig, sTxPowerDbm);
sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
otLogInfoPlat("Initialized", NULL);
}
@@ -321,6 +340,26 @@ void efr32RadioDeinit(void)
sRxBandConfig = NULL;
}
static otError efr32StartEnergyScan(energyScanMode aMode, uint16_t aChannel, RAIL_Time_t aAveragingTimeUs)
{
RAIL_Status_t status;
RAIL_SchedulerInfo_t schedulerInfo = {.priority = EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY};
otError error = OT_ERROR_NONE;
otEXPECT_ACTION(sEnergyScanStatus == ENERGY_SCAN_STATUS_IDLE, error = OT_ERROR_BUSY);
sEnergyScanStatus = ENERGY_SCAN_STATUS_IN_PROGRESS;
sEnergyScanMode = aMode;
RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, true);
status = RAIL_StartAverageRssi(sRxBandConfig->mRailHandle, aChannel, aAveragingTimeUs, &schedulerInfo);
otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
exit:
return error;
}
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -525,35 +564,38 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
int8_t otPlatRadioGetRssi(otInstance *aInstance)
{
RAIL_Status_t status;
RAIL_SchedulerInfo_t schedulerInfo = {.priority = EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY};
uint32_t start;
otError error;
uint32_t start;
int8_t rssi = OT_RADIO_RSSI_INVALID;
OT_UNUSED_VARIABLE(aInstance);
RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, true);
sSampleRssiDone = false;
sRssi = OT_RADIO_RSSI_INVALID;
status = RAIL_StartAverageRssi(sRxBandConfig->mRailHandle, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME,
&schedulerInfo);
otEXPECT(status == RAIL_STATUS_NO_ERROR);
error = efr32StartEnergyScan(ENERGY_SCAN_MODE_SYNC, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME);
otEXPECT(error == OT_ERROR_NONE);
start = RAIL_GetTime();
// waiting for the event RAIL_EVENT_RSSI_AVERAGE_DONE
while (!sSampleRssiDone && ((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT))
while (sEnergyScanStatus == ENERGY_SCAN_STATUS_IN_PROGRESS &&
((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT))
;
if (sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
{
rssi = sEnergyScanResultDbm;
}
sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
exit:
return sRssi;
return rssi;
}
otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF;
return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN;
}
bool otPlatRadioGetPromiscuous(otInstance *aInstance)
@@ -958,8 +1000,18 @@ static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE)
{
sSampleRssiDone = true;
sRssi = (int8_t)(RAIL_GetAverageRssi(aRailHandle) >> 2);
const int16_t energyScanResultQuarterDbm = RAIL_GetAverageRssi(aRailHandle);
sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
if (energyScanResultQuarterDbm == RAIL_RSSI_INVALID)
{
sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
}
else
{
sEnergyScanResultDbm = energyScanResultQuarterDbm / QUARTER_DBM_IN_DBM;
}
RAIL_YieldRadio(aRailHandle);
}
@@ -968,10 +1020,8 @@ static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aScanChannel);
OT_UNUSED_VARIABLE(aScanDuration);
return OT_ERROR_NOT_IMPLEMENTED;
return efr32StartEnergyScan(ENERGY_SCAN_MODE_ASYNC, aScanChannel, (RAIL_Time_t)aScanDuration * US_IN_MS);
}
void efr32RadioProcess(otInstance *aInstance)
@@ -1001,6 +1051,11 @@ void efr32RadioProcess(otInstance *aInstance)
otPlatRadioTxDone(aInstance, &sTransmitFrame, &sReceiveFrame, sTransmitError);
}
}
else if (sEnergyScanMode == ENERGY_SCAN_MODE_ASYNC && sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
{
sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
otPlatRadioEnergyScanDone(aInstance, sEnergyScanResultDbm);
}
processNextRxPacket(aInstance, sRxBandConfig->mRailHandle);
}