static void handleRx(void) { if (sRxDone) { sRxDone = false; if (otPlatRadioGetPromiscuous(sInstance)) { // Timestamp sReceiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow(); sReceiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now. } #if OPENTHREAD_ENABLE_DIAG if (otPlatDiagModeGet()) { otPlatDiagRadioReceiveDone(sInstance, &sReceiveFrame, OT_ERROR_NONE); } else #endif { // signal MAC layer for each received frame if promiscous is enabled // otherwise only signal MAC layer for non-ACK frame if (sPromiscuous || sReceiveFrame.mLength > IEEE802154_ACK_LENGTH) { otLogDebgPlat(sInstance, "Radio receive done, rssi: %d", sReceiveFrame.mInfo.mRxInfo.mRssi); otPlatRadioReceiveDone(sInstance, &sReceiveFrame, OT_ERROR_NONE); } } } }
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) { (void)aInstance; otLogDebgPlat(sInstance, "Radio transmit"); otError error = OT_ERROR_NONE; otEXPECT_ACTION(sState == OT_RADIO_STATE_RECEIVE, error = OT_ERROR_INVALID_STATE); uint8_t frame[OT_RADIO_FRAME_MAX_SIZE + 1]; setChannel(aFrame->mChannel); frame[0] = aFrame->mLength - IEEE802154_FCS_SIZE; memcpy(frame + 1, aFrame->mPsdu, aFrame->mLength); PHY_DataReq(frame); otPlatRadioTxStarted(aInstance, aFrame); sState = OT_RADIO_STATE_TRANSMIT; exit: return error; }
static void setTxPower(uint8_t aPower) { if (aPower != sPower) { uint8_t i; for (i = 0; i < (sizeof(sTxPowerTable) / sizeof(*sTxPowerTable) - 1); i++) { if (aPower >= sTxPowerTable[i]) { break; } } otLogDebgPlat(sInstance, "Radio set tx power: %d, %d", aPower, i); radioTrxOff(); PHY_SetTxPower(i); radioRestore(); sPower = aPower; } }
void LinkRaw::InvokeTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError) { otLogDebgPlat(&mInstance, "LinkRaw Transmit Done (err=0x%x)", aError); #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT mTimer.Stop(); #endif #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT if (aError == OT_ERROR_CHANNEL_ACCESS_FAILURE) { if (mCsmaAttempts < Mac::kMaxCSMABackoffs) { mCsmaAttempts++; StartCsmaBackoff(); goto exit; } } else { mCsmaAttempts = 0; } if (aError == OT_ERROR_NO_ACK) { if (mTransmitAttempts < aFrame->mMaxTxAttempts) { mTransmitAttempts++; StartCsmaBackoff(); goto exit; } } #endif // Transition back to receive state on previous channel otPlatRadioReceive(&mInstance, mReceiveChannel); if (mTransmitDoneCallback) { if (aError == OT_ERROR_NONE) { otLogInfoPlat(&mInstance, "LinkRaw Invoke Transmit Done"); } else { otLogWarnPlat(&mInstance, "LinkRaw Invoke Transmit Failed (err=0x%x)", aError); } mTransmitDoneCallback(&mInstance, aFrame, aAckFrame, aError); mTransmitDoneCallback = NULL; } #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT exit: return; #endif }
otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) { (void)aInstance; otLogDebgPlat(sInstance, "Radio set default TX power: %d", aPower); setTxPower(aPower); return OT_ERROR_NONE; }
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId) { (void)aInstance; otLogDebgPlat(sInstance, "Set Pan ID: 0x%04X", aPanId); radioTrxOff(); PHY_SetPanId(aPanId); radioRestore(); }
otError otPlatRadioDisable(otInstance *aInstance) { otLogDebgPlat(sInstance, "Radio disable"); if (otPlatRadioIsEnabled(aInstance)) { radioSleep(); sState = OT_RADIO_STATE_DISABLED; } return OT_ERROR_NONE; }
otError otPlatRadioEnable(otInstance *aInstance) { otLogDebgPlat(sInstance, "Radio enable"); if (!otPlatRadioIsEnabled(aInstance)) { radioSleep(); sState = OT_RADIO_STATE_SLEEP; } return OT_ERROR_NONE; }
static void setChannel(uint8_t aChannel) { if (aChannel != sChannel) { otLogDebgPlat(sInstance, "Radio set channel: %d", aChannel); radioTrxOff(); PHY_SetChannel(aChannel); radioRestore(); sChannel = aChannel; } }
otError otPlatRadioSleep(otInstance *aInstance) { (void)aInstance; otLogDebgPlat(sInstance, "Radio sleep"); otError error = OT_ERROR_NONE; otEXPECT_ACTION(sState == OT_RADIO_STATE_SLEEP || sState == OT_RADIO_STATE_RECEIVE, error = OT_ERROR_INVALID_STATE); radioSleep(); sState = OT_RADIO_STATE_SLEEP; exit: return error; }
otError LinkRaw::DoTransmit(otRadioFrame *aFrame) { otError error = otPlatRadioTransmit(&mInstance, aFrame); #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT // If we are implementing the ACK timeout logic, start a timer here (if ACK request) // to fire if we don't get a transmit done callback in time. if (static_cast<Mac::Frame *>(aFrame)->GetAckRequest()) { otLogDebgPlat(aInstance, "LinkRaw Starting AckTimeout Timer"); mTimerReason = kTimerReasonAckTimeout; mTimer.Start(Mac::kAckTimeout); } #endif return error; }
otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) { (void)aInstance; otLogDebgPlat(sInstance, "Radio receive, channel: %d", aChannel); otError error = OT_ERROR_NONE; otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, error = OT_ERROR_INVALID_STATE); setChannel(aChannel); radioRxEnable(); sState = OT_RADIO_STATE_RECEIVE; exit: return error; }
static void handleTx(void) { if (sTxDone) { sTxDone = false; #if OPENTHREAD_ENABLE_DIAG if (otPlatDiagModeGet()) { otPlatDiagRadioTransmitDone(sInstance, &sTransmitFrame, sTxStatus); } else #endif { otLogDebgPlat(sInstance, "Radio transmit done, status: %d", sTxStatus); otPlatRadioTxDone(sInstance, &sTransmitFrame, NULL, sTxStatus); } } }
void LinkRaw::StartCsmaBackoff(void) { uint32_t backoffExponent = Mac::kMinBE + mTransmitAttempts + mCsmaAttempts; uint32_t backoff; if (backoffExponent > Mac::kMaxBE) { backoffExponent = Mac::kMaxBE; } backoff = Random::GetUint32InRange(0, 1U << backoffExponent); backoff *= (static_cast<uint32_t>(Mac::kUnitBackoffPeriod) * OT_RADIO_SYMBOL_TIME); otLogDebgPlat(&mInstance, "LinkRaw Starting RetransmitTimeout Timer (%d ms)", backoff); mTimerReason = kTimerReasonRetransmitTimeout; #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER mTimerMicro.Start(backoff); #else // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER mTimer.Start(backoff / 1000UL); #endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER }