diff --git a/doc/spinel-protocol-src/spinel-prop-phy.md b/doc/spinel-protocol-src/spinel-prop-phy.md index d95b5854e..21d6c1461 100644 --- a/doc/spinel-protocol-src/spinel-prop-phy.md +++ b/doc/spinel-protocol-src/spinel-prop-phy.md @@ -63,3 +63,10 @@ Value is the current RSSI (Received signal strength indication) from the radio. This value can be used in energy scans and for determining the ambient noise floor for the operating environment. +### PROP 39: PROP_PHY_RX_SENSITIVITY {#prop-phy-rx-sensitivity} +* Type: Read-Only +* Packed-Encoding: `c` (int8) +* Unit: dBm + +Value is the radio receive sensitivity. This value can be used as +lower bound noise floor for link metrics computation. diff --git a/examples/drivers/windows/otLwf/radio.c b/examples/drivers/windows/otLwf/radio.c index 1e485faa6..6bf05a70c 100644 --- a/examples/drivers/windows/otLwf/radio.c +++ b/examples/drivers/windows/otLwf/radio.c @@ -814,6 +814,31 @@ void otPlatRadioSetDefaultTxPower(_In_ otInstance *otCtx, int8_t aPower) } } +int8_t otPlatRadioGetReceiveSensitivity(_In_ otInstance *otCtx) +{ + NT_ASSERT(otCtx); + PMS_FILTER pFilter = otCtxToFilter(otCtx); + NTSTATUS status; + int8_t receiveSensitivity; + + status = + otLwfCmdGetProp( + pFilter, + NULL, + SPINEL_PROP_PHY_RX_SENSITIVITY, + SPINEL_DATATYPE_INT8_S, + &receiveSensitivity + ); + + if (!NT_SUCCESS(status)) + { + LogError(DRIVER_DEFAULT, "Get SPINEL_PROP_PHY_RX_SENSITIVITY, failed, %!STATUS!", status); + return -100; // return default value -100dBm + } + + return receiveSensitivity; +} + inline USHORT getDstShortAddress(const UCHAR *frame) { return (((USHORT)frame[IEEE802154_DSTADDR_OFFSET + 1]) << 8) | frame[IEEE802154_DSTADDR_OFFSET]; diff --git a/examples/platforms/cc2538/radio.c b/examples/platforms/cc2538/radio.c index 5065386ea..b2419db37 100644 --- a/examples/platforms/cc2538/radio.c +++ b/examples/platforms/cc2538/radio.c @@ -62,6 +62,11 @@ enum CC2538_LQI_BIT_MASK = 0x7f, }; +enum +{ + CC2538_RECEIVE_SENSITIVITY = -100, // dBm +}; + static RadioPacket sTransmitFrame; static RadioPacket sReceiveFrame; static ThreadError sTransmitError; @@ -793,3 +798,9 @@ void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower) (void)aInstance; (void)aPower; } + +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + (void)aInstance; + return CC2538_RECEIVE_SENSITIVITY; +} diff --git a/examples/platforms/cc2650/radio.c b/examples/platforms/cc2650/radio.c index 419755f8b..fb273696d 100644 --- a/examples/platforms/cc2650/radio.c +++ b/examples/platforms/cc2650/radio.c @@ -48,6 +48,11 @@ #include #include +enum +{ + CC2650_RECEIVE_SENSITIVITY = -100, // dBm +}; + /* phy state as defined by openthread */ static volatile cc2650_PhyState sState; @@ -1799,3 +1804,9 @@ void cc2650RadioProcess(otInstance *aInstance) sReceiveFrame.mLength = 0; } } + +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + (void)aInstance; + return CC2650_RECEIVE_SENSITIVITY; +} diff --git a/examples/platforms/da15000/radio.c b/examples/platforms/da15000/radio.c index 595496025..9b92b4a96 100644 --- a/examples/platforms/da15000/radio.c +++ b/examples/platforms/da15000/radio.c @@ -57,6 +57,11 @@ #define IEEE802154_ACK_REQUEST 1 << 5 #define IEEE802154_DSN_OFFSET 2 +enum +{ + DA15000_RECEIVE_SENSITIVITY = -100, // dBm +}; + static otInstance *sThreadInstance; static PhyState sRadioState = kStateDisabled; @@ -500,3 +505,8 @@ void FTDF_rcvFrameTransparent(FTDF_DataLength frameLength, } } +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + (void)aInstance; + return DA15000_RECEIVE_SENSITIVITY; +} diff --git a/examples/platforms/efr32/radio.c b/examples/platforms/efr32/radio.c index 02bdb2a3b..ea1bd757d 100644 --- a/examples/platforms/efr32/radio.c +++ b/examples/platforms/efr32/radio.c @@ -60,6 +60,11 @@ enum IEEE802154_DSN_OFFSET = 2, }; +enum +{ + EFR32_RECEIVE_SENSITIVITY = -100, // dBm +}; + static uint16_t sPanId = 0; static uint8_t sChannel = 0; static bool sTransmitBusy = false; @@ -842,3 +847,9 @@ void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower) (void)aInstance; RAIL_TxPowerSet(aPower); } + +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + (void)aInstance; + return EFR32_RECEIVE_SENSITIVITY; +} diff --git a/examples/platforms/nrf52840/radio.c b/examples/platforms/nrf52840/radio.c index 4ef8f24b6..cf41f5fdb 100644 --- a/examples/platforms/nrf52840/radio.c +++ b/examples/platforms/nrf52840/radio.c @@ -64,6 +64,11 @@ #define SHORT_ADDRESS_SIZE 2 #define EXTENDED_ADDRESS_SIZE 8 +enum +{ + NRF52840_RECEIVE_SENSITIVITY = -100, // dBm +}; + static bool sDisabled; static RadioPacket sReceivedFrames[RADIO_RX_BUFFERS]; @@ -608,3 +613,9 @@ void nrf_drv_radio802154_energy_detected(int8_t result) setPendingEvent(kPendingEventEnergyDetected); } + +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + (void)aInstance; + return NRF52840_RECEIVE_SENSITIVITY; +} diff --git a/examples/platforms/posix/radio.c b/examples/platforms/posix/radio.c index 5e8d0215d..0ca1ed529 100644 --- a/examples/platforms/posix/radio.c +++ b/examples/platforms/posix/radio.c @@ -75,6 +75,11 @@ enum IEEE802154_MACCMD_DATA_REQ = 4, }; +enum +{ + POSIX_RECEIVE_SENSITIVITY = -100, // dBm +}; + OT_TOOL_PACKED_BEGIN struct RadioMessage { @@ -749,3 +754,9 @@ void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower) (void)aInstance; (void)aPower; } + +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + (void)aInstance; + return POSIX_RECEIVE_SENSITIVITY; +} diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 12b886619..6ca3e2458 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -498,6 +498,15 @@ ThreadError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, u */ extern void otPlatRadioEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi); +/** + * Get the radio receive sensitivity value. + * + * @param[in] aInstance The OpenThread instance structure. + * + * @returns The radio receive sensitivity value in dBm. + */ +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance); + /** * @} * diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index a16eada01..9ef4ac793 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -156,8 +156,6 @@ Mac::Mac(ThreadNetif &aThreadNetif): { GenerateExtAddress(&mExtAddress); - ClearNoiseFloorAverage(mNoiseFloor); - memset(&mCounters, 0, sizeof(otMacCounters)); SetExtendedPanId(sExtendedPanidInit); @@ -1417,7 +1415,7 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError) if (neighbor != NULL) { - neighbor->GetLinkInfo().AddRss(mNoiseFloor, aFrame->mPower); + neighbor->GetLinkInfo().AddRss(GetNoiseFloor(), aFrame->mPower); if (aFrame->GetSecurityEnabled() == true) { diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index c09c5f2ee..c1fab318c 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -601,12 +601,12 @@ public: otMacCounters &GetCounters(void) { return mCounters; } /** - * This method returns the noise floor state. + * This method returns the noise floor value (currently use the radio receive sensitivity value). * - * @returns A reference to the noise floor state. + * @returns The noise floor value in dBm. * */ - LinkQualityInfo &GetNoiseFloor(void) { return mNoiseFloor; } + int8_t GetNoiseFloor(void) { return otPlatRadioGetReceiveSensitivity(GetInstance()); } /** * This method indicates whether or not CSMA backoff is supported by the radio layer. @@ -714,8 +714,6 @@ private: int8_t mEnergyScanCurrentMaxRssi; Tasklet mEnergyScanSampleRssiTask; - LinkQualityInfo mNoiseFloor; - otLinkPcapCallback mPcapCallback; void *mPcapCallbackContext; diff --git a/src/core/thread/link_quality.cpp b/src/core/thread/link_quality.cpp index 765cc8147..f13997cb5 100644 --- a/src/core/thread/link_quality.cpp +++ b/src/core/thread/link_quality.cpp @@ -76,7 +76,7 @@ void LinkQualityInfo::Clear(void) mLastRss = 0; } -void LinkQualityInfo::AddRss(LinkQualityInfo &aNoiseFloor, int8_t aRss) +void LinkQualityInfo::AddRss(int8_t aNoiseFloor, int8_t aRss) { uint16_t newValue; uint16_t oldAverage; @@ -178,12 +178,12 @@ exit: return error; } -uint8_t LinkQualityInfo::GetLinkMargin(LinkQualityInfo &aNoiseFloor) const +uint8_t LinkQualityInfo::GetLinkMargin(int8_t aNoiseFloor) const { return ConvertRssToLinkMargin(aNoiseFloor, GetAverageRss()); } -uint8_t LinkQualityInfo::GetLinkQuality(LinkQualityInfo &aNoiseFloor) +uint8_t LinkQualityInfo::GetLinkQuality(int8_t aNoiseFloor) { UpdateLinkQuality(aNoiseFloor); @@ -195,7 +195,7 @@ int8_t LinkQualityInfo::GetLastRss(void) const return mLastRss; } -void LinkQualityInfo::UpdateLinkQuality(LinkQualityInfo &aNoiseFloor) +void LinkQualityInfo::UpdateLinkQuality(int8_t aNoiseFloor) { if (mCount != 0) { @@ -207,9 +207,9 @@ void LinkQualityInfo::UpdateLinkQuality(LinkQualityInfo &aNoiseFloor) } } -uint8_t LinkQualityInfo::ConvertRssToLinkMargin(LinkQualityInfo &aNoiseFloor, int8_t aRss) +uint8_t LinkQualityInfo::ConvertRssToLinkMargin(int8_t aNoiseFloor, int8_t aRss) { - int8_t linkMargin = aRss - GetAverageNoiseFloor(aNoiseFloor); + int8_t linkMargin = aRss - aNoiseFloor; if (linkMargin < 0 || aRss == kUnknownRss) { @@ -224,7 +224,7 @@ uint8_t LinkQualityInfo::ConvertLinkMarginToLinkQuality(uint8_t aLinkMargin) return CalculateLinkQuality(aLinkMargin, kNoLastLinkQualityValue); } -uint8_t LinkQualityInfo::ConvertRssToLinkQuality(LinkQualityInfo &aNoiseFloor, int8_t aRss) +uint8_t LinkQualityInfo::ConvertRssToLinkQuality(int8_t aNoiseFloor, int8_t aRss) { return ConvertLinkMarginToLinkQuality(ConvertRssToLinkMargin(aNoiseFloor, aRss)); } @@ -277,26 +277,4 @@ uint8_t LinkQualityInfo::CalculateLinkQuality(uint8_t aLinkMargin, uint8_t aLast return linkQuality; } -int8_t GetAverageNoiseFloor(LinkQualityInfo &aNoiseFloor) -{ - int8_t averageNoiseFloor = aNoiseFloor.GetAverageRss(); - - if (averageNoiseFloor == LinkQualityInfo::kUnknownRss) - { - averageNoiseFloor = kDefaultNoiseFloor; - } - - return averageNoiseFloor; -} - -void AddNoiseFloor(LinkQualityInfo &aNoiseFloor, int8_t aNoise) -{ - aNoiseFloor.AddRss(aNoiseFloor, aNoise); -} - -void ClearNoiseFloorAverage(LinkQualityInfo &aNoiseFloor) -{ - aNoiseFloor.Clear(); -} - } // namespace ot diff --git a/src/core/thread/link_quality.hpp b/src/core/thread/link_quality.hpp index fb6e207c2..4507f0146 100644 --- a/src/core/thread/link_quality.hpp +++ b/src/core/thread/link_quality.hpp @@ -76,11 +76,11 @@ public: /** * This method adds a new received signal strength (RSS) value to the average. * - * @param[in] aNoiseFloor A reference to the noise floor state. + * @param[in] aNoiseFloor The noise floor value (in dBm). * @param[in] aRss A new received signal strength value (in dBm) to be added to the average. * */ - void AddRss(LinkQualityInfo &aNoiseFloor, int8_t aRss); + void AddRss(int8_t aNoiseFloor, int8_t aRss); /** * This method returns the current average signal strength value. @@ -116,12 +116,12 @@ public: * This method returns the link margin. The link margin is calculated using the link's current average received * signal strength (RSS) and average noise floor. * - * @param[in] aNoiseFloor A reference to the noise state. + * @param[in] aNoiseFloor The noise floor value (in dBm). * * @returns Link margin derived from average received signal strength and average noise floor. * */ - uint8_t GetLinkMargin(LinkQualityInfo &aNoiseFloor) const; + uint8_t GetLinkMargin(int8_t aNoiseFloor) const; /** * Returns the current one-way link quality value. The link quality value is a number 0-3. @@ -134,11 +134,11 @@ public: * frequent changes, a hysteresis of 2 dB is applied when determining the link quality. For example, the average * link margin must be at least 12 dB to change a quality 1 link to a quality 2 link. * - * @param[in] aNoiseFloor A reference to the noise state. + * @param[in] aNoiseFloor The noise floor value (in dBm). * * @returns The current link quality value (value 0-3 as per Thread specification). */ - uint8_t GetLinkQuality(LinkQualityInfo &aNoiseFloor); + uint8_t GetLinkQuality(int8_t aNoiseFloor); /** * Returns the most recent RSS value. @@ -151,13 +151,13 @@ public: /** * This method converts a received signal strength value to a link margin value. * - * @param[in] aNoiseFloor A reference to the noise state. + * @param[in] aNoiseFloor The noise floor value (in dBm). * @param[in] aRss The received signal strength value (in dBm). * * @returns The link margin value. * */ - static uint8_t ConvertRssToLinkMargin(LinkQualityInfo &aNoiseFloor, int8_t aRss); + static uint8_t ConvertRssToLinkMargin(int8_t aNoiseFloor, int8_t aRss); /** * This method converts a link margin value to a link quality value. @@ -172,13 +172,13 @@ public: /** * This method converts a received signal strength value to a link quality value. * - * @param[in] aNoiseFloor A reference to the noise state. + * @param[in] aNoiseFloor The noise floor value (in dBm). * @param[in] aRss The received signal strength value (in dBm). * * @returns The link quality value (0-3). * */ - static uint8_t ConvertRssToLinkQuality(LinkQualityInfo &aNoiseFloor, int8_t aRss); + static uint8_t ConvertRssToLinkQuality(int8_t aNoiseFloor, int8_t aRss); private: enum @@ -208,7 +208,7 @@ private: /* Private method to update the mLinkQuality value. This is called when a new RSS value is added to average * or when GetLinkQuality() is invoked. */ - void UpdateLinkQuality(LinkQualityInfo &aNoiseFloor); + void UpdateLinkQuality(int8_t aNoiseFloor); /* Static private method to calculate the link quality from a given link margin while taking into account the last * link quality value and adding the hysteresis value to the thresholds. If there is no previous value for link @@ -227,33 +227,6 @@ private: int8_t mLastRss; }; -/** - * This function returns the current average noise floor level (in dBm). - * - * @param[in] aNoiseFloor A reference to the noise state. - * - * @returns The current average noise floor level (in dBm). - */ -int8_t GetAverageNoiseFloor(LinkQualityInfo &aNoiseFloor); - -/** - * This function adds a new noise floor value (in dBm) to the running average. - * - * @param[in] aNoiseFloor A reference to the noise state. - * @param[in] aNoise A new noise floor value (in dBm) to be added to the average. - * - */ -void AddNoiseFloor(LinkQualityInfo &aNoiseFloor, int8_t aNoise); - -/** - * This function clears the current average noise floor value. - * - * @param[in] aNoiseFloor A reference to the noise state. - * - */ -void ClearNoiseFloorAverage(LinkQualityInfo &aNoiseFloor); - - /** * @} */ diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index bec6f2c09..1a12cc1d4 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -124,6 +124,7 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] = { SPINEL_PROP_PHY_CHAN, &NcpBase::GetPropertyHandler_PHY_CHAN }, { SPINEL_PROP_PHY_RSSI, &NcpBase::GetPropertyHandler_PHY_RSSI }, { SPINEL_PROP_PHY_TX_POWER, &NcpBase::GetPropertyHandler_PHY_TX_POWER }, + { SPINEL_PROP_PHY_RX_SENSITIVITY, &NcpBase::GetPropertyHandler_PHY_RX_SENSITIVITY }, { SPINEL_PROP_MAC_SCAN_STATE, &NcpBase::GetPropertyHandler_MAC_SCAN_STATE }, { SPINEL_PROP_MAC_SCAN_MASK, &NcpBase::GetPropertyHandler_MAC_SCAN_MASK }, @@ -2007,6 +2008,17 @@ ThreadError NcpBase::GetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop ); } +ThreadError NcpBase::GetPropertyHandler_PHY_RX_SENSITIVITY(uint8_t header, spinel_prop_key_t key) +{ + return SendPropertyUpdate( + header, + SPINEL_CMD_PROP_VALUE_IS, + key, + SPINEL_DATATYPE_INT8_S, + otPlatRadioGetReceiveSensitivity(mInstance) + ); +} + ThreadError NcpBase::GetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key) { ThreadError errorCode = kThreadError_None; diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index ab1388832..838816eb3 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -342,6 +342,7 @@ private: ThreadError GetPropertyHandler_PHY_CHAN(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_PHY_RSSI(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_PHY_RX_SENSITIVITY(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_MAC_SCAN_STATE(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_MAC_15_4_PANID(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_MAC_15_4_LADDR(uint8_t header, spinel_prop_key_t key); diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index ac4a29e9e..ec873a648 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -529,6 +529,7 @@ typedef enum SPINEL_PROP_PHY_CCA_THRESHOLD = SPINEL_PROP_PHY__BEGIN + 4, ///< dBm [c] SPINEL_PROP_PHY_TX_POWER = SPINEL_PROP_PHY__BEGIN + 5, ///< [c] SPINEL_PROP_PHY_RSSI = SPINEL_PROP_PHY__BEGIN + 6, ///< dBm [c] + SPINEL_PROP_PHY_RX_SENSITIVITY = SPINEL_PROP_PHY__BEGIN + 7, ///< dBm [c] SPINEL_PROP_PHY__END = 0x30, SPINEL_PROP_PHY_EXT__BEGIN = 0x1200, diff --git a/tests/unit/test_link_quality.cpp b/tests/unit/test_link_quality.cpp index 9fc5deaf8..e47b6768d 100644 --- a/tests/unit/test_link_quality.cpp +++ b/tests/unit/test_link_quality.cpp @@ -61,7 +61,7 @@ struct RssTestData uint8_t mExpectedLinkQuality; // Expected final link quality value. }; -static LinkQualityInfo sNoiseFloor; +int8_t sNoiseFloor = -100; // dBm // Checks the encoded average RSS value to match the value from GetAverageRss(). void VerifyEncodedRssValue(LinkQualityInfo &aLinkInfo) diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index 22b95dc08..70526b883 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -325,6 +325,11 @@ extern "C" { (void)aPower; } + int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) + { + (void)aInstance; + return 0; + } // // Random //