atmega128rfa1 cca fixes, energest and rimestat macros.

Add option to return ACK to RDC layer when in extended mode, based on Georg von Zengen code.
This commit is contained in:
David Kopf 2011-11-08 12:20:22 -05:00
parent 9587b39707
commit c2364897f8
3 changed files with 145 additions and 63 deletions

View file

@ -67,6 +67,7 @@
#define RG_IEEE_ADDR_7 IEEE_ADDR_7
//#define SR_ED_LEVEL 0x147, 0xff, 0
#define RG_PHY_ED_LEVEL PHY_ED_LEVEL
#define RG_RX_SYN RX_SYN
#define SR_RSSI 0x146, 0x1f, 0
#define SR_PLL_CF_START 0x1a, 0x80, 7
#define SR_PLL_DCU_START 0x1b, 0x80, 7

View file

@ -871,7 +871,7 @@ ISR(TRX24_PLL_UNLOCK_vect)
DEBUGFLOW('5');
}
/* Flag is set by the following interrupts */
extern volatile uint8_t rf230_interruptwait;
extern volatile uint8_t rf230_interruptwait,rf230_ccawait;
/* Wake has finished */
ISR(TRX24_AWAKE_vect)
@ -899,7 +899,7 @@ ISR(TRX24_XAH_AMI_vect)
ISR(TRX24_CCA_ED_DONE_vect)
{
DEBUGFLOW('4');
rf230_interruptwait=0;
rf230_ccawait=0;
}
#else /* defined(__AVR_ATmega128RFA1__) */

View file

@ -28,7 +28,6 @@
*
* This file is part of the Contiki operating system.
*
* @(#)$Id: rf230bb.c,v 1.24 2010/12/22 20:10:00 dak664 Exp $
*/
/*
* This code is almost device independent and should be easy to port.
@ -98,6 +97,19 @@ static bool is_promiscuous;
#define RF230_CONF_AUTORETRIES 3
#endif
/* In extended mode (AUTORETRIES>0) the tx routine waits for hardware
* processing of an expected ACK and returns RADIO_TX_OK/NOACK result.
* In non-extended mode the ACK is treated as a normal rx packet.
* If the caller needs the ACK to be returned as an rx packet,
* RF230_INSERTACK will generate one based on the hardware result.
* This is triggered when the read routine is called with a buffer
* length of three (the ack length).
*/
#if RF320_CONF_INSERTACK && RF230_CONF_AUTORETRIES
#define RF230_INSERTACK 1
uint8_t ack_pending,ack_seqnum;
#endif
/* RF230_CONF_CSMARETRIES is number of random-backoff/CCA retries. */
/* The hardware will accept 0-7, but 802.15.4-2003 only allows 5 maximum */
#ifndef RF230_CONF_CSMARETRIES
@ -186,7 +198,7 @@ static int num_transmissions;
#endif
#if defined(__AVR_ATmega128RFA1__)
volatile uint8_t rf230_interruptwait;
volatile uint8_t rf230_interruptwait,rf230_ccawait;
#endif
uint8_t volatile rf230_pending;
@ -355,9 +367,12 @@ rf230_isidle(void)
static void
rf230_waitidle(void)
{
while (1) {
int i;
for (i=0;i<10000;i++) { //to avoid potential hangs
// while (1) {
if (rf230_isidle()) break;
}
if (i>=10000) {DEBUGFLOW('H');DEBUGFLOW('R');}
}
/*----------------------------------------------------------------------------*/
@ -492,59 +507,59 @@ static uint8_t locked, lock_on, lock_off;
static void
on(void)
{
// ENERGEST_OFF(ENERGEST_TYPE_LISTEN);//testing
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
RF230_receive_on = 1;
#ifdef RF230BB_HOOK_RADIO_ON
RF230BB_HOOK_RADIO_ON();
#endif
/* If radio is off (slptr high), turn it on */
if (hal_get_slptr()) {
#if defined(__AVR_ATmega128RFA1__)
rf230_interruptwait=1;
ENERGEST_ON(ENERGEST_TYPE_LED_RED);
ENERGEST_ON(ENERGEST_TYPE_LED_RED);
#if RF230BB_CONF_LEDONPORTE1
// PORTE|=(1<<PE1); //ledon
PORTE|=(1<<PE1); //ledon
#endif
hal_set_slptr_low();
while (rf230_interruptwait) {}
}
#if defined(__AVR_ATmega128RFA1__)
/* Use the poweron interrupt for delay */
rf230_interruptwait=1;
sei();
hal_set_slptr_low();
while (rf230_interruptwait) {}
#else
/* SPI based radios. The wake time depends on board capacitance, use 2x the nominal value for safety */
uint8_t sreg = SREG;
cli();
// DEBUGFLOW('0');
hal_set_slptr_low();
delay_us(TIME_SLEEP_TO_TRX_OFF);
delay_us(TIME_SLEEP_TO_TRX_OFF);//extra delay for now, wake time depends on board capacitance
SREG=sreg;
delay_us(TIME_SLEEP_TO_TRX_OFF * 2);
SREG=sreg;
#endif
}
rf230_waitidle();
#endif
#if RF230_CONF_AUTOACK
// radio_set_trx_state(is_promiscuous?RX_ON:RX_AACK_ON);
radio_set_trx_state(RX_AACK_ON);
//DEBUGFLOW('a');
#else
radio_set_trx_state(RX_ON);
DEBUGFLOW('b');
#endif
RF230_receive_on = 1;
}
static void
off(void)
{
#if RF230BB_CONF_LEDONPORTE1
PORTE&=~(1<<PE1); //ledoff
#endif
#ifdef RF230BB_HOOK_RADIO_OFF
RF230BB_HOOK_RADIO_OFF();
#endif
/* Wait any transmission to end */
/* Wait for any transmission to end */
rf230_waitidle();
RF230_receive_on = 0;
#if RADIOALWAYSON
/* Do not transmit autoacks when stack thinks radio is off */
radio_set_trx_state(RX_ON);
//DEBUGFLOW('c');
#else
/* Force the device into TRX_OFF. */
radio_reset_state_machine();
@ -552,17 +567,11 @@ off(void)
/* Sleep Radio */
hal_set_slptr_high();
ENERGEST_OFF(ENERGEST_TYPE_LED_RED);
#if RF230BB_CONF_LEDONPORTE1
// PORTE&=~(1<<PE1); //ledoff
#endif
// DEBUGFLOW('d');
#else
// DEBUGFLOW('e');
#endif
#endif /* RADIOALWAYSON */
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
RF230_receive_on = 0;
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
}
/*---------------------------------------------------------------------------*/
#define GET_LOCK() locked = 1
@ -781,6 +790,18 @@ void rf230_warm_reset(void) {
/* Carrier sense threshold (not implemented in RF230 or RF231) */
// hal_subregister_write(SR_CCA_CS_THRES,1);
/* Receiver sensitivity. If nonzero rf231/128rfa1 saves 0.5ma in rx mode */
/* Not implemented on rf230 but does not hurt to write to it */
#ifdef RF230_MIN_RX_POWER
#if RF230_MIN_RX_POWER > 84
#warning rf231 power threshold clipped to -48dBm by hardware register
hal_register_write(RG_RX_SYN, 0xf);
#elif RF230_MIN_RX_POWER < 0
#error RF230_MIN_RX_POWER can not be negative!
#endif
hal_register_write(RG_RX_SYN, RF230_MIN_RX_POWER/6 + 1); //1-15 -> -90 to -48dBm
#endif
/* CCA energy threshold = -91dB + 2*SR_CCA_ED_THRESH. Reset defaults to -77dB */
/* Use RF230 base of -91; RF231 base is -90 according to datasheet */
#ifdef RF230_CONF_CCA_THRES
@ -839,23 +860,29 @@ rf230_transmit(unsigned short payload_len)
// DEBUGFLOW('j');
ENERGEST_ON(ENERGEST_TYPE_LED_RED);
#if RF230BB_CONF_LEDONPORTE1
// PORTE|=(1<<PE1); //ledon
PORTE|=(1<<PE1); //ledon
#endif
rf230_interruptwait=1;
hal_set_slptr_low();
while (rf230_interruptwait) {}
// while (rf230_interruptwait) {}
{
int i;
for (i=0;i<10000;i++) {
if (!rf230_interruptwait) break;
}
}
#else
hal_set_slptr_low();
DEBUGFLOW('j');
DEBUGFLOW('j');
delay_us(TIME_SLEEP_TO_TRX_OFF);
delay_us(TIME_SLEEP_TO_TRX_OFF); //extra delay depends on board capacitance
delay_us(TIME_SLEEP_TO_TRX_OFF); //extra delay depends on board capacitance
#endif
} else {
#if RADIO_CONF_CALIBRATE_INTERVAL
/* If nonzero, do periodic calibration. See clock.c */
if (rf230_calibrate) {
DEBUGFLOW('k');
DEBUGFLOW('k');
hal_subregister_write(SR_PLL_CF_START,1); //takes 80us max
hal_subregister_write(SR_PLL_DCU_START,1); //takes 6us, concurrently
rf230_calibrate=0;
@ -979,8 +1006,25 @@ rf230_transmit(unsigned short payload_len)
}
RELEASE_LOCK();
if (tx_result==1) { //success, data pending from adressee
tx_result = RADIO_TX_OK; //Just show success?
#if RF230_INSERTACK
ack_pending = 0;
#endif
if (tx_result==1) { //success, data pending from adressee
tx_result=RADIO_TX_OK; //handle as ordinary success
}
if (tx_result==RADIO_TX_OK) {
RIMESTATS_ADD(lltx);
if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE))
RIMESTATS_ADD(ackrx); //ack was requested and received
#if RF230_INSERTACK
/* Not PAN broadcast to FFFF, and ACK was requested and received */
if (!((buffer[5]==0xff) && (buffer[6]==0xff)) && (buffer[0]&(1<<6)))
ack_pending=1;
#endif
} else if (tx_result==3) { //CSMA channel access failure
DEBUGFLOW('m');
RIMESTATS_ADD(contentiondrop);
@ -989,6 +1033,7 @@ rf230_transmit(unsigned short payload_len)
} else if (tx_result==5) { //Expected ACK, none received
DEBUGFLOW('n');
tx_result = RADIO_TX_NOACK;
RIMESTATS_ADD(badackrx); //ack was requested but not received
} else if (tx_result==7) { //Invalid (Can't happen since waited for idle above?)
DEBUGFLOW('o');
tx_result = RADIO_TX_ERR;
@ -1004,10 +1049,14 @@ rf230_prepare(const void *payload, unsigned short payload_len)
uint8_t total_len,*pbuf;
#if RF230_CONF_TIMESTAMPS
struct timestamp timestamp;
#endif /* RF230_CONF_TIMESTAMPS */
#endif
#if RF230_CONF_CHECKSUM
uint16_t checksum;
#endif /* RF230_CONF_CHECKSUM */
#endif
#if RF230_INSERTACK
/* The sequence number is needed to construct the ack packet */
ack_seqnum=*(((uint8_t *)payload)+2);
#endif
GET_LOCK();
DEBUGFLOW('p');
@ -1015,7 +1064,7 @@ rf230_prepare(const void *payload, unsigned short payload_len)
// PRINTF("rf230: sending %d bytes\n", payload_len);
// PRINTSHORT("s%d ",payload_len);
RIMESTATS_ADD(lltx);
RIMESTATS_ADD(tx);
#if RF230_CONF_CHECKSUM
checksum = crc16_data(payload, payload_len, 0);
@ -1031,7 +1080,7 @@ rf230_prepare(const void *payload, unsigned short payload_len)
printf_P(PSTR("rf230_prepare: packet too large (%d, max: %d)\n"),total_len,RF230_MAX_TX_FRAME_LENGTH);
#endif
ret = -1;
goto bail;
goto bail;
}
pbuf=&buffer[0];
memcpy(pbuf,payload,payload_len);
@ -1243,6 +1292,7 @@ if (RF230_receive_on) {
#if RADIOSTATS //TODO:This will double count buffered packets
RF230_receivepackets++;
#endif
RIMESTATS_ADD(llrx);
#if RADIOALWAYSON
} else {
@ -1305,7 +1355,7 @@ PROCESS_THREAD(rf230_process, ev, data)
/* Get packet from Radio if any, else return zero.
* The two-byte checksum is appended but the returned length does not include it.
* Frames are buffered in the interrupt routine so this routine
* does not access the hardware or change its status
* does not access the hardware or change its status.
*/
/*---------------------------------------------------------------------------*/
static int
@ -1314,13 +1364,25 @@ rf230_read(void *buf, unsigned short bufsize)
uint8_t len,*framep;
#if FOOTER_LEN
uint8_t footer[FOOTER_LEN];
#endif /* FOOTER_LEN */
#endif
#if RF230_CONF_CHECKSUM
uint16_t checksum;
#endif /* RF230_CONF_CHECKSUM */
#endif
#if RF230_CONF_TIMESTAMPS
struct timestamp t;
#endif /* RF230_CONF_TIMESTAMPS */
#endif
#if RF230_INSERTACK
/* Return an ACK to the mac layer */
if(ack_pending && bufsize == 3){
ack_pending=0;
uint8_t *buff=(uint8_t *)buf;
buff[0]=2;
buff[1]=0;
buff[2]=ack_seqnum;
return bufsize;
}
#endif
/* The length includes the twp-byte checksum but not the LQI byte */
len=rxframe[rxframe_head].length;
if (len==0) {
@ -1450,7 +1512,7 @@ if (!RF230_receive_on) {
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf230_last_rssi);
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf230_last_correlation);
RIMESTATS_ADD(llrx);
RIMESTATS_ADD(rx);
#if RF230_CONF_TIMESTAMPS
rf230_time_of_departure =
@ -1563,12 +1625,9 @@ rf230_cca(void)
return 0;
}
/* Don't allow interrupts! */
cli();
/* Turn radio on if necessary. If radio is currently busy return busy channel */
/* This may happen when testing radio duty cycling with RADIOALWAYSON */
if(RF230_receive_on) {
if (hal_get_slptr()) { //should not be sleeping!
DEBUGFLOW('<');
@ -1577,11 +1636,12 @@ rf230_cca(void)
if (!rf230_isidle()) {DEBUGFLOW('2');goto busyexit;}
}
} else {
DEBUGFLOW('3');
radio_was_off = 1;
rf230_on();
}
/* Don't allow interrupts! */
// cli();
ENERGEST_ON(ENERGEST_TYPE_LED_YELLOW);
/* CCA Mode Mode 1=Energy above threshold 2=Carrier sense only 3=Both 0=Either (RF231 only) */
/* Use the current mode. Note triggering a manual CCA is not recommended in extended mode */
//hal_subregister_write(SR_CCA_MODE,1);
@ -1589,31 +1649,50 @@ rf230_cca(void)
/* Start the CCA, wait till done, return result */
/* Note reading the TRX_STATUS register clears both CCA_STATUS and CCA_DONE bits */
#if defined(__AVR_ATmega128RFA1__)
/* Manual CCA gives no interrupt in extended mode, and testing cca done hangs the MCU */
#if 0
rf230_interruptwait=1;
#if 1 //interrupt method
sei();
hal_subregister_write(SR_CCA_REQUEST,1);
while (rf230_interruptwait) {}
cca=hal_register_read(RG_TRX_STATUS);
//rf230_waitidle();
//TODO:disable reception for version bug
radio_set_trx_state(RX_ON);
// rf230_waitidle();
rf230_ccawait=1;
//CCA_REQUEST is supposed to trigger the interrupt but it doesn't
// hal_subregister_write(SR_CCA_REQUEST,1);
hal_register_write(PHY_ED_LEVEL,0);
// delay_us(TIME_CCA);
// if (hal_register_read(RG_PHY_ED_LEVEL)<(91-77)) cca=0xff;
while (rf230_ccawait) {}
#ifdef RF230_CONF_CCA_THRES
if (hal_register_read(RG_PHY_ED_LEVEL)<(91+RF230_CONF_CCA_THRES) cca=0xff;
#else
if (hal_register_read(RG_PHY_ED_LEVEL)<(91-77)) cca=0xff;
#endif
/* So just read the current ED register without delay */
//TODO:see if the status register works!
// cca=hal_register_read(RG_TRX_STATUS);
#if RF230_CONF_AUTOACK
radio_set_trx_state(RX_AACK_ON);
#endif
#else
/* If already in receive mode can read the current ED register without delay */
/* CCA energy threshold = -91dB + 2*SR_CCA_ED_THRESH. Reset defaults to -77dB */
#ifdef RF230_CONF_CCA_THRES
if (hal_register_read(RG_PHY_ED_LEVEL)<(91+RF230_CONF_CCA_THRES) cca=0xff;
#else
if (hal_register_read(RG_PHY_ED_LEVEL)<(91-77)) cca=0xff;
#endif
#endif
#else /* RF230, RF231 */
/* Start the CCA, wait till done, return result */
/* Note reading the TRX_STATUS register clears both CCA_STATUS and CCA_DONE bits */
hal_subregister_write(SR_CCA_REQUEST,1);
delay_us(TIME_CCA);
while ((cca & 0x80) == 0 ) {
cca=hal_register_read(RG_TRX_STATUS);
}
#endif
ENERGEST_OFF(ENERGEST_TYPE_LED_YELLOW);
if(radio_was_off) {
rf230_off();
}
@ -1650,7 +1729,9 @@ rf230_receiving_packet(void)
static int
rf230_pending_packet(void)
{
if (rf230_pending) DEBUGFLOW('@');
#if RF230_INSERTACK
if(ack_pending == 1) return 1;
#endif
return rf230_pending;
}
/*---------------------------------------------------------------------------*/