diff --git a/cpu/cc2538/include/cc2538_rf.h b/cpu/cc2538/include/cc2538_rf.h index afa798e4f118ea804ecbf8093613371a3770765b..93170113fa75faed5585d6ece5e6b0f158ff052e 100644 --- a/cpu/cc2538/include/cc2538_rf.h +++ b/cpu/cc2538/include/cc2538_rf.h @@ -70,6 +70,13 @@ extern "C" { #define OUTPUT_POWER_MAX (7) /**< Max output power in dBm */ #define NUM_POWER_LEVELS ( OUTPUT_POWER_MAX - OUTPUT_POWER_MIN + 1 ) +#define CC2538_CORR_VAL_MIN (50U) +#define CC2538_CORR_VAL_MAX (110U) +#define CC2538_CORR_VAL_MASK (0x7F) + +#define CC2538_RSSI_OFFSET (-73) /**< Signal strength offset value */ +#define CC2538_RF_SENSITIVITY (-97) /**< dBm typical, normal conditions */ + #define RFCORE_ASSERT(expr) (void)( (expr) || RFCORE_ASSERT_failure(#expr, __FUNCTION__, __LINE__) ) #if DEVELHELP diff --git a/cpu/cc2538/radio/cc2538_rf_netdev.c b/cpu/cc2538/radio/cc2538_rf_netdev.c index 008c396891ae197e653345205eb4ad0e64ccbaad..e9721632ef94d14b96207d30bf135cf7dabad5e7 100644 --- a/cpu/cc2538/radio/cc2538_rf_netdev.c +++ b/cpu/cc2538/radio/cc2538_rf_netdev.c @@ -293,6 +293,8 @@ static int _send(netdev2_t *netdev, const struct iovec *vector, unsigned count) static int _recv(netdev2_t *netdev, void *buf, size_t len, void *info) { cc2538_rf_t *dev = (cc2538_rf_t *) netdev; + uint8_t corr_val; + int8_t rssi_val; size_t pkt_len; mutex_lock(&dev->mutex); @@ -331,17 +333,29 @@ static int _recv(netdev2_t *netdev, void *buf, size_t len, void *info) rfcore_read_fifo(buf, pkt_len); - if (info != NULL) { + if (info != NULL && RFCORE->XREG_RSSISTATbits.RSSI_VALID) { netdev2_ieee802154_rx_info_t *radio_info = info; - radio_info->rssi = rfcore_read_byte(); - - /* This is not strictly 802.15.4 compliant, since according to - the CC2538 documentation, this value will tend between ~50 - for the lowest quality link detectable by the receiver, and - ~110 for the highest. The IEEE 802.15.4 spec mandates that - this value be between 0-255, with 0 as lowest quality and - 255 as the highest. FIXME. */ - radio_info->lqi = rfcore_read_byte() & 0x7F; + rssi_val = rfcore_read_byte() + CC2538_RSSI_OFFSET; + + RFCORE_ASSERT(rssi_val > CC2538_RF_SENSITIVITY); + + /* The number of dB above maximum sensitivity detected for the + * received packet */ + radio_info->rssi = -CC2538_RF_SENSITIVITY + rssi_val; + + corr_val = rfcore_read_byte() & CC2538_CORR_VAL_MASK; + + if (corr_val < CC2538_CORR_VAL_MIN) { + corr_val = CC2538_CORR_VAL_MIN; + } + else if (corr_val > CC2538_CORR_VAL_MAX) { + corr_val = CC2538_CORR_VAL_MAX; + } + + /* Interpolate the correlation value between 0 - 255 + * to provide an LQI value */ + radio_info->lqi = 255 * (corr_val - CC2538_CORR_VAL_MIN) / + (CC2538_CORR_VAL_MAX - CC2538_CORR_VAL_MIN); } RFCORE_SFR_RFST = ISFLUSHRX;