New radio interface parameters: Rx poll mode, last packet timestamp, last packet rssi, last packet lqi. Implementation of these parameters for cc2420, with, in addition, runtime configuration of CCA before Tx, auto-ack and frame filtering

This commit is contained in:
Simon Duquennoy 2015-09-21 22:03:51 +02:00
parent ecba49c282
commit 1e0adbbf24
2 changed files with 185 additions and 42 deletions

View file

@ -150,6 +150,12 @@ enum {
/* Received signal strength indicator in dBm. */ /* Received signal strength indicator in dBm. */
RADIO_PARAM_RSSI, RADIO_PARAM_RSSI,
/* RSSI of the last received packet */
RADIO_PARAM_LAST_RSSI,
/* Link quality of the last received packet */
RADIO_PARAM_LAST_LINK_QUALITY,
/* /*
* Long (64 bits) address for the radio, which is used by the address filter. * Long (64 bits) address for the radio, which is used by the address filter.
* The address is specified in network byte order. * The address is specified in network byte order.
@ -159,6 +165,11 @@ enum {
*/ */
RADIO_PARAM_64BIT_ADDR, RADIO_PARAM_64BIT_ADDR,
/* Last packet timestamp, of type rtimer_clock_t.
* Because this parameter value mat be larger than what fits in radio_value_t,
* it needs to be used with radio.get_object()/set_object(). */
RADIO_PARAM_LAST_PACKET_TIMESTAMP,
/* Constants (read only) */ /* Constants (read only) */
/* The lowest radio channel. */ /* The lowest radio channel. */
@ -192,6 +203,7 @@ enum {
*/ */
#define RADIO_RX_MODE_ADDRESS_FILTER (1 << 0) #define RADIO_RX_MODE_ADDRESS_FILTER (1 << 0)
#define RADIO_RX_MODE_AUTOACK (1 << 1) #define RADIO_RX_MODE_AUTOACK (1 << 1)
#define RADIO_RX_MODE_POLL_MODE (1 << 2)
/** /**
* The radio transmission mode controls whether transmissions should * The radio transmission mode controls whether transmissions should

View file

@ -140,6 +140,13 @@ static volatile uint16_t last_packet_timestamp;
PROCESS(cc2420_process, "CC2420 driver"); PROCESS(cc2420_process, "CC2420 driver");
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define AUTOACK (1 << 4)
#define AUTOCRC (1 << 5)
#define ADR_DECODE (1 << 11)
#define RXFIFO_PROTECTION (1 << 9)
#define CORR_THR(n) (((n) & 0x1f) << 6)
#define FIFOP_THR(n) ((n) & 0x7f)
#define RXBPF_LOCUR (1 << 13);
int cc2420_on(void); int cc2420_on(void);
int cc2420_off(void); int cc2420_off(void);
@ -154,6 +161,12 @@ static int cc2420_receiving_packet(void);
static int pending_packet(void); static int pending_packet(void);
static int get_cca_threshold(void); static int get_cca_threshold(void);
static int cc2420_cca(void); static int cc2420_cca(void);
static uint16_t getreg(enum cc2420_register regname);
static void set_frame_filtering(uint8_t enable);
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);
signed char cc2420_last_rssi; signed char cc2420_last_rssi;
uint8_t cc2420_last_correlation; uint8_t cc2420_last_correlation;
@ -161,6 +174,11 @@ uint8_t cc2420_last_correlation;
static uint8_t receive_on; static uint8_t receive_on;
static int channel; static int channel;
/* Are we currently in poll mode? */
static uint8_t volatile poll_mode = 0;
/* Do we perform a CCA before sending? */
static uint8_t send_on_cca = WITH_SEND_CCA;
static radio_result_t static radio_result_t
get_value(radio_param_t param, radio_value_t *value) get_value(radio_param_t param, radio_value_t *value)
{ {
@ -176,6 +194,24 @@ get_value(radio_param_t param, radio_value_t *value)
case RADIO_PARAM_CHANNEL: case RADIO_PARAM_CHANNEL:
*value = cc2420_get_channel(); *value = cc2420_get_channel();
return RADIO_RESULT_OK; return RADIO_RESULT_OK;
case RADIO_PARAM_RX_MODE:
*value = 0;
if(getreg(CC2420_MDMCTRL0) & ADR_DECODE) {
*value |= RADIO_RX_MODE_ADDRESS_FILTER;
}
if(getreg(CC2420_MDMCTRL0) & AUTOACK) {
*value |= RADIO_RX_MODE_AUTOACK;
}
if(poll_mode) {
*value |= RADIO_RX_MODE_POLL_MODE;
}
return RADIO_RESULT_OK;
case RADIO_PARAM_TX_MODE:
*value = 0;
if(send_on_cca) {
*value |= RADIO_TX_MODE_SEND_ON_CCA;
}
return RADIO_RESULT_OK;
case RADIO_PARAM_TXPOWER: case RADIO_PARAM_TXPOWER:
v = cc2420_get_txpower(); v = cc2420_get_txpower();
*value = OUTPUT_POWER_MIN; *value = OUTPUT_POWER_MIN;
@ -194,6 +230,14 @@ get_value(radio_param_t param, radio_value_t *value)
/* Return the RSSI value in dBm */ /* Return the RSSI value in dBm */
*value = cc2420_rssi(); *value = cc2420_rssi();
return RADIO_RESULT_OK; return RADIO_RESULT_OK;
case RADIO_PARAM_LAST_RSSI:
/* RSSI of the last packet received */
*value = cc2420_last_rssi;
return RADIO_RESULT_OK;
case RADIO_PARAM_LAST_LINK_QUALITY:
/* LQI of the last packet received */
*value = cc2420_last_correlation;
return RADIO_RESULT_OK;
case RADIO_CONST_CHANNEL_MIN: case RADIO_CONST_CHANNEL_MIN:
*value = 11; *value = 11;
return RADIO_RESULT_OK; return RADIO_RESULT_OK;
@ -233,6 +277,21 @@ set_value(radio_param_t param, radio_value_t value)
} }
cc2420_set_channel(value); cc2420_set_channel(value);
return RADIO_RESULT_OK; return RADIO_RESULT_OK;
case RADIO_PARAM_RX_MODE:
if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
return RADIO_RESULT_INVALID_VALUE;
}
set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
return RADIO_RESULT_OK;
case RADIO_PARAM_TX_MODE:
if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
return RADIO_RESULT_INVALID_VALUE;
}
set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
return RADIO_RESULT_OK;
case RADIO_PARAM_TXPOWER: case RADIO_PARAM_TXPOWER:
if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
return RADIO_RESULT_INVALID_VALUE; return RADIO_RESULT_INVALID_VALUE;
@ -256,6 +315,17 @@ set_value(radio_param_t param, radio_value_t value)
static radio_result_t static radio_result_t
get_object(radio_param_t param, void *dest, size_t size) get_object(radio_param_t param, void *dest, size_t size)
{ {
if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
#if CC2420_CONF_SFD_TIMESTAMPS
if(size != sizeof(rtimer_clock_t) || !dest) {
return RADIO_RESULT_INVALID_VALUE;
}
*(rtimer_clock_t*)dest = cc2420_sfd_start_time;
return RADIO_RESULT_OK;
#else
return RADIO_RESULT_NOT_SUPPORTED;
#endif
}
return RADIO_RESULT_NOT_SUPPORTED; return RADIO_RESULT_NOT_SUPPORTED;
} }
@ -447,7 +517,10 @@ wait_for_transmission(void)
static void static void
on(void) on(void)
{ {
CC2420_ENABLE_FIFOP_INT(); if(!poll_mode) {
CC2420_ENABLE_FIFOP_INT();
}
strobe(CC2420_SRXON); strobe(CC2420_SRXON);
ENERGEST_ON(ENERGEST_TYPE_LISTEN); ENERGEST_ON(ENERGEST_TYPE_LISTEN);
@ -465,7 +538,9 @@ off(void)
ENERGEST_OFF(ENERGEST_TYPE_LISTEN); ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
strobe(CC2420_SRFOFF); strobe(CC2420_SRFOFF);
CC2420_DISABLE_FIFOP_INT(); if(!poll_mode) {
CC2420_DISABLE_FIFOP_INT();
}
if(!CC2420_FIFOP_IS_1) { if(!CC2420_FIFOP_IS_1) {
flushrx(); flushrx();
@ -539,14 +614,6 @@ set_txpower(uint8_t power)
setreg(CC2420_TXCTRL, reg); setreg(CC2420_TXCTRL, reg);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define AUTOACK (1 << 4)
#define AUTOCRC (1 << 5)
#define ADR_DECODE (1 << 11)
#define RXFIFO_PROTECTION (1 << 9)
#define CORR_THR(n) (((n) & 0x1f) << 6)
#define FIFOP_THR(n) ((n) & 0x7f)
#define RXBPF_LOCUR (1 << 13);
/*---------------------------------------------------------------------------*/
int int
cc2420_init(void) cc2420_init(void)
{ {
@ -573,20 +640,15 @@ cc2420_init(void)
/* And wait until it stabilizes */ /* And wait until it stabilizes */
wait_for_status(BV(CC2420_XOSC16M_STABLE)); wait_for_status(BV(CC2420_XOSC16M_STABLE));
/* Turn on/off automatic packet acknowledgment and address decoding. */ /* Set auto-ack and frame filtering */
reg = getreg(CC2420_MDMCTRL0); set_auto_ack(CC2420_CONF_AUTOACK);
set_frame_filtering(CC2420_CONF_AUTOACK);
#if CC2420_CONF_AUTOACK
reg |= AUTOACK | ADR_DECODE;
#else
reg &= ~(AUTOACK | ADR_DECODE);
#endif /* CC2420_CONF_AUTOACK */
/* Enabling CRC in hardware; this is required by AUTOACK anyway /* Enabling CRC in hardware; this is required by AUTOACK anyway
and provides us with RSSI and link quality indication (LQI) and provides us with RSSI and link quality indication (LQI)
information. */ information. */
reg = getreg(CC2420_MDMCTRL0);
reg |= AUTOCRC; reg |= AUTOCRC;
setreg(CC2420_MDMCTRL0, reg); setreg(CC2420_MDMCTRL0, reg);
/* Set transmission turnaround time to the lower setting (8 symbols /* Set transmission turnaround time to the lower setting (8 symbols
@ -614,6 +676,8 @@ cc2420_init(void)
flushrx(); flushrx();
set_poll_mode(0);
process_start(&cc2420_process, NULL); process_start(&cc2420_process, NULL);
return 1; return 1;
} }
@ -646,13 +710,13 @@ cc2420_transmit(unsigned short payload_len)
#define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
#endif #endif
#if WITH_SEND_CCA if(send_on_cca) {
strobe(CC2420_SRXON); strobe(CC2420_SRXON);
wait_for_status(BV(CC2420_RSSI_VALID)); wait_for_status(BV(CC2420_RSSI_VALID));
strobe(CC2420_STXONCCA); strobe(CC2420_STXONCCA);
#else /* WITH_SEND_CCA */ } else {
strobe(CC2420_STXON); strobe(CC2420_STXON);
#endif /* WITH_SEND_CCA */ }
for(i = LOOP_20_SYMBOLS; i > 0; i--) { for(i = LOOP_20_SYMBOLS; i > 0; i--) {
if(CC2420_SFD_IS_1) { if(CC2420_SFD_IS_1) {
#if PACKETBUF_WITH_PACKET_TYPE #if PACKETBUF_WITH_PACKET_TYPE
@ -704,7 +768,7 @@ cc2420_transmit(unsigned short payload_len)
} }
} }
/* If we are using WITH_SEND_CCA, we get here if the packet wasn't /* If we send with cca (cca_on_send), we get here if the packet wasn't
transmitted because of other channel activity. */ transmitted because of other channel activity. */
RIMESTATS_ADD(contentiondrop); RIMESTATS_ADD(contentiondrop);
PRINTF("cc2420: do_send() transmission never started\n"); PRINTF("cc2420: do_send() transmission never started\n");
@ -869,7 +933,7 @@ PROCESS_THREAD(cc2420_process, ev, data)
PRINTF("cc2420_process: started\n"); PRINTF("cc2420_process: started\n");
while(1) { while(1) {
PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); PROCESS_YIELD_UNTIL(!poll_mode && ev == PROCESS_EVENT_POLL);
PRINTF("cc2420_process: calling receiver callback\n"); PRINTF("cc2420_process: calling receiver callback\n");
@ -913,9 +977,13 @@ cc2420_read(void *buf, unsigned short bufsize)
if(footer[1] & FOOTER1_CRC_OK) { if(footer[1] & FOOTER1_CRC_OK) {
cc2420_last_rssi = footer[0] + RSSI_OFFSET; cc2420_last_rssi = footer[0] + RSSI_OFFSET;
cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION; cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
if(!poll_mode) {
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi); /* Not in poll mode: packetbuf should not be accessed in interrupt context.
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation); * In poll mode, the last packet RSSI and link quality can be obtained through
* RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
}
RIMESTATS_ADD(llrx); RIMESTATS_ADD(llrx);
} else { } else {
@ -923,15 +991,17 @@ cc2420_read(void *buf, unsigned short bufsize)
len = FOOTER_LEN; len = FOOTER_LEN;
} }
if(CC2420_FIFOP_IS_1) { if(!poll_mode) {
if(!CC2420_FIFO_IS_1) { if(CC2420_FIFOP_IS_1) {
/* Clean up in case of FIFO overflow! This happens for every if(!CC2420_FIFO_IS_1) {
* full length frame and is signaled by FIFOP = 1 and FIFO = /* Clean up in case of FIFO overflow! This happens for every
* 0. */ * full length frame and is signaled by FIFOP = 1 and FIFO =
flushrx(); * 0. */
} else { flushrx();
/* Another packet has been received and needs attention. */ } else {
process_poll(&cc2420_process); /* Another packet has been received and needs attention. */
process_poll(&cc2420_process);
}
} }
} }
@ -1062,3 +1132,64 @@ cc2420_set_cca_threshold(int value)
RELEASE_LOCK(); RELEASE_LOCK();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Set or unset frame autoack */
static void
set_auto_ack(uint8_t enable)
{
GET_LOCK();
uint16_t reg = getreg(CC2420_MDMCTRL0);
if(enable) {
reg |= AUTOACK;
} else {
reg &= ~(AUTOACK);
}
setreg(CC2420_MDMCTRL0, reg);
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/
/* Set or unset frame filtering */
static void
set_frame_filtering(uint8_t enable)
{
GET_LOCK();
/* Turn on/off address decoding. */
uint16_t reg = getreg(CC2420_MDMCTRL0);
if(enable) {
reg |= ADR_DECODE;
} else {
reg &= ~(ADR_DECODE);
}
setreg(CC2420_MDMCTRL0, reg);
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/
/* Enable or disable radio interrupts (both FIFOP and SFD timer capture) */
static void
set_poll_mode(uint8_t enable)
{
GET_LOCK();
poll_mode = enable;
if(enable) {
/* Disable FIFOP interrupt */
CC2420_CLEAR_FIFOP_INT();
CC2420_DISABLE_FIFOP_INT();
} else {
/* Initialize and enable FIFOP interrupt */
CC2420_FIFOP_INT_INIT();
CC2420_ENABLE_FIFOP_INT();
CC2420_CLEAR_FIFOP_INT();
}
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/
/* Enable or disable CCA before sending */
static void
set_send_on_cca(uint8_t enable)
{
send_on_cca = enable;
}
/*---------------------------------------------------------------------------*/