diff --git a/arch/cpu/cc2538/dev/cc2538-rf.c b/arch/cpu/cc2538/dev/cc2538-rf.c index bddfcc942..e3a548067 100644 --- a/arch/cpu/cc2538/dev/cc2538-rf.c +++ b/arch/cpu/cc2538/dev/cc2538-rf.c @@ -140,6 +140,8 @@ static const output_config_t output_power[] = { {-24, 0x00 }, }; +static radio_result_t get_value(radio_param_t param, radio_value_t *value); + #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) /* Max and Min Output Power in dBm */ @@ -394,6 +396,48 @@ get_sfd_timestamp(void) return RTIMER_NOW() - RADIO_TO_RTIMER(timer_val - sfd); } /*---------------------------------------------------------------------------*/ +/* Enable or disable radio test mode emmiting modulated or unmodulated + * (carrier) signal. See User's Guide pages 719 and 741. + */ +static uint32_t prev_FRMCTRL0, prev_MDMTEST1; +static uint8_t was_on; + +static void +set_test_mode(uint8_t enable, uint8_t modulated) +{ + radio_value_t mode; + get_value(RADIO_PARAM_POWER_MODE, &mode); + + if(enable) { + if(mode == RADIO_POWER_MODE_CARRIER_ON) { + return; + } + was_on = (mode == RADIO_POWER_MODE_ON); + off(); + prev_FRMCTRL0 = REG(RFCORE_XREG_FRMCTRL0); + /* This constantly transmits random data */ + REG(RFCORE_XREG_FRMCTRL0) = 0x00000042; + if(!modulated) { + prev_MDMTEST1 = REG(RFCORE_XREG_MDMTEST1); + /* ...adding this we send an unmodulated carrier instead */ + REG(RFCORE_XREG_MDMTEST1) = 0x00000018; + } + CC2538_RF_CSP_ISTXON(); + } else { + if(mode != RADIO_POWER_MODE_CARRIER_ON) { + return; + } + CC2538_RF_CSP_ISRFOFF(); + REG(RFCORE_XREG_FRMCTRL0) = prev_FRMCTRL0; + if(!modulated) { + REG(RFCORE_XREG_MDMTEST1) = prev_MDMTEST1; + } + if(was_on) { + on(); + } + } +} +/*---------------------------------------------------------------------------*/ /* Netstack API radio driver functions */ /*---------------------------------------------------------------------------*/ static int @@ -806,8 +850,12 @@ get_value(radio_param_t param, radio_value_t *value) switch(param) { case RADIO_PARAM_POWER_MODE: - *value = (REG(RFCORE_XREG_RXENABLE) && RFCORE_XREG_RXENABLE_RXENMASK) == 0 - ? RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON; + if((REG(RFCORE_XREG_RXENABLE) & RFCORE_XREG_RXENABLE_RXENMASK) == 0) { + *value = RADIO_POWER_MODE_OFF; + } else { + *value = (REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_TX_MODE) == 0 + ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_CARRIER_ON; + } return RADIO_RESULT_OK; case RADIO_PARAM_CHANNEL: *value = (radio_value_t)get_channel(); @@ -896,6 +944,11 @@ set_value(radio_param_t param, radio_value_t value) off(); return RADIO_RESULT_OK; } + if(value == RADIO_POWER_MODE_CARRIER_ON || + value == RADIO_POWER_MODE_CARRIER_OFF) { + set_test_mode((value == RADIO_POWER_MODE_CARRIER_ON), 0); + return RADIO_RESULT_OK; + } return RADIO_RESULT_INVALID_VALUE; case RADIO_PARAM_CHANNEL: if(value < CC2538_RF_CHANNEL_MIN || diff --git a/arch/dev/cc2420/cc2420.c b/arch/dev/cc2420/cc2420.c index a1572b0ef..545f917ac 100644 --- a/arch/dev/cc2420/cc2420.c +++ b/arch/dev/cc2420/cc2420.c @@ -114,6 +114,7 @@ PROCESS(cc2420_process, "CC2420 driver"); #define CORR_THR(n) (((n) & 0x1f) << 6) #define FIFOP_THR(n) ((n) & 0x7f) #define RXBPF_LOCUR (1 << 13); +#define TX_MODE (3 << 2) int cc2420_on(void); int cc2420_off(void); @@ -135,6 +136,8 @@ static void set_poll_mode(uint8_t enable); static void set_send_on_cca(uint8_t enable); static void set_auto_ack(uint8_t enable); +static void set_test_mode(uint8_t enable, uint8_t modulated); + signed char cc2420_last_rssi; uint8_t cc2420_last_correlation; @@ -156,7 +159,11 @@ get_value(radio_param_t param, radio_value_t *value) } switch(param) { case RADIO_PARAM_POWER_MODE: - *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + if((getreg(CC2420_MDMCTRL1) & TX_MODE) & 0x08) { + *value = RADIO_POWER_MODE_CARRIER_ON; + } else { + *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + } return RADIO_RESULT_OK; case RADIO_PARAM_CHANNEL: *value = cc2420_get_channel(); @@ -237,6 +244,11 @@ set_value(radio_param_t param, radio_value_t value) cc2420_off(); return RADIO_RESULT_OK; } + if(value == RADIO_POWER_MODE_CARRIER_ON || + value == RADIO_POWER_MODE_CARRIER_OFF) { + set_test_mode((value == RADIO_POWER_MODE_CARRIER_ON), 0); + return RADIO_RESULT_OK; + } return RADIO_RESULT_INVALID_VALUE; case RADIO_PARAM_CHANNEL: if(value < 11 || value > 26) { @@ -1120,3 +1132,45 @@ set_send_on_cca(uint8_t enable) send_on_cca = enable; } /*---------------------------------------------------------------------------*/ +/* Enable or disable radio test mode emmiting modulated or unmodulated + * (carrier) signal. See datasheet page 55. + */ +static uint16_t prev_MDMCTRL1, prev_DACTST; +static uint8_t was_on; + +static void +set_test_mode(uint8_t enable, uint8_t modulated) +{ + radio_value_t mode; + get_value(RADIO_PARAM_POWER_MODE, &mode); + + if(enable) { + if(mode == RADIO_POWER_MODE_CARRIER_ON) { + return; + } + was_on = (mode == RADIO_POWER_MODE_ON); + off(); + prev_MDMCTRL1 = getreg(CC2420_MDMCTRL1); + setreg(CC2420_MDMCTRL1, 0x050C); + if(!modulated) { + prev_DACTST = getreg(CC2420_DACTST); + setreg(CC2420_DACTST, 0x1800); + } + /* actually starts the test mode */ + strobe(CC2420_STXON); + } else { + if(mode != RADIO_POWER_MODE_CARRIER_ON) { + return; + } + strobe(CC2420_SRFOFF); + if(!modulated) { + setreg(CC2420_DACTST, prev_DACTST); + } + setreg(CC2420_MDMCTRL1, prev_MDMCTRL1); + /* actually stops the carrier */ + if(was_on) { + on(); + } + } +} +/*---------------------------------------------------------------------------*/ diff --git a/os/dev/radio.h b/os/dev/radio.h index e6ca64f3d..e279e9efe 100644 --- a/os/dev/radio.h +++ b/os/dev/radio.h @@ -196,7 +196,9 @@ enum { /* Radio power modes */ enum { RADIO_POWER_MODE_OFF, - RADIO_POWER_MODE_ON + RADIO_POWER_MODE_ON, + RADIO_POWER_MODE_CARRIER_ON, + RADIO_POWER_MODE_CARRIER_OFF }; /**