diff --git a/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c b/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c index 84168adfe9..adc6f053ba 100644 --- a/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c +++ b/drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c @@ -196,7 +196,11 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info) if (info) { netdev_ieee802154_rx_info_t *netdev_rx_info = info; - netdev_rx_info->rssi = rx_info.rssi; + + /* The Radio HAL uses the IEEE 802.15.4 definition for RSSI. + * Netdev uses dBm. Therefore we need a translation here */ + netdev_rx_info->rssi = ieee802154_rssi_to_dbm(rx_info.rssi); + netdev_rx_info->lqi = rx_info.lqi; } diff --git a/sys/include/net/ieee802154.h b/sys/include/net/ieee802154.h index 3beb24a94d..0d8154f08c 100644 --- a/sys/include/net/ieee802154.h +++ b/sys/include/net/ieee802154.h @@ -422,6 +422,49 @@ static inline eui64_t *ieee802154_get_iid(eui64_t *eui64, const uint8_t *addr, return eui64; } +/** + * @brief Convert from RSSI scale to dBm. + * + * The RSSI calculation is based on the IEEE 802.15.4 2020 specification and + * it's represented as one octet of integer. + * + * RSSI equal to zero maps to -174 dBm and has the same scale as dBm (1 RSSI + * step == 1 dBm). Therefore an RSSI value of 254 maps to +80 dBm. + * + * @note RSSI == 255 is defined as reserved by the standard and ignored by this + * function. + * + * @param[in] rssi RF power in RSSI scale + * + * @return RF power in dBm scale + */ +static inline int16_t ieee802154_rssi_to_dbm(uint8_t rssi) +{ + return rssi + IEEE802154_RADIO_RSSI_OFFSET; +} + +/** + * @brief Convert from dBm scale to RSSI. + * + * The RSSI calculation is based on the IEEE 802.15.4 2020 specification and + * it's represented as one octet of integer. + * + * RSSI equal to zero maps to -174 dBm and has the same scale as dBm (1 RSSI + * step == 1 dBm). Therefore an RSSI value of 254 maps to +80 dBm. + * + * @param[in] dbm RF power in dBm scale. + * + * @return RF power in RSSI scale. + */ +static inline uint8_t ieee802154_dbm_to_rssi(int16_t dbm) +{ + const int min = IEEE802154_RADIO_RSSI_OFFSET; + const int max = min + (UINT8_MAX - 1); + + int val = dbm <= min ? min : (dbm >= max ? max : dbm); + return val - IEEE802154_RADIO_RSSI_OFFSET; +} + #ifdef __cplusplus } #endif diff --git a/tests/unittests/tests-ieee802154/tests-ieee802154.c b/tests/unittests/tests-ieee802154/tests-ieee802154.c index a1492ee696..b966cb8ad1 100644 --- a/tests/unittests/tests-ieee802154/tests-ieee802154.c +++ b/tests/unittests/tests-ieee802154/tests-ieee802154.c @@ -1006,6 +1006,31 @@ static void test_ieee802154_get_iid_addr_len_8(void) TEST_ASSERT_EQUAL_INT(0, memcmp((const char *)exp, (char *) &iid, sizeof(iid))); } +static void test_ieee802154_dbm_to_rssi(void) +{ + /* RF Power below -174 is represented with RSSI zero. + * RF power above 80 is represented with RSSI 254 */ + const int16_t dbm[] = {0, -73, -180, 85}; + const uint8_t expected[] = {174, 101, 0, 254}; + + TEST_ASSERT_EQUAL_INT(expected[0], ieee802154_dbm_to_rssi(dbm[0])); + TEST_ASSERT_EQUAL_INT(expected[1], ieee802154_dbm_to_rssi(dbm[1])); + TEST_ASSERT_EQUAL_INT(expected[2], ieee802154_dbm_to_rssi(dbm[2])); + TEST_ASSERT_EQUAL_INT(expected[3], ieee802154_dbm_to_rssi(dbm[3])); + +} + +static void test_ieee802154_rssi_to_dbm(void) +{ + const uint8_t rssi[] = {174, 101, 0, 254}; + const int16_t expected[]= {0, -73, -174, 80}; + + TEST_ASSERT_EQUAL_INT(expected[0], ieee802154_rssi_to_dbm(rssi[0])); + TEST_ASSERT_EQUAL_INT(expected[1], ieee802154_rssi_to_dbm(rssi[1])); + TEST_ASSERT_EQUAL_INT(expected[2], ieee802154_rssi_to_dbm(rssi[2])); + TEST_ASSERT_EQUAL_INT(expected[3], ieee802154_rssi_to_dbm(rssi[3])); +} + Test *tests_ieee802154_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -1069,6 +1094,8 @@ Test *tests_ieee802154_tests(void) new_TestFixture(test_ieee802154_get_iid_addr_len_2), new_TestFixture(test_ieee802154_get_iid_addr_len_4), new_TestFixture(test_ieee802154_get_iid_addr_len_8), + new_TestFixture(test_ieee802154_rssi_to_dbm), + new_TestFixture(test_ieee802154_dbm_to_rssi), }; EMB_UNIT_TESTCALLER(ieee802154_tests, NULL, NULL, fixtures);