Cleaned up RF230BB, and refactored FRAME_RETRIES and CSMA_RETRIES

#defines.
This commit is contained in:
Ivan Delamer 2012-09-04 11:12:18 -06:00
parent 2e72ec3594
commit b43dad00b0
8 changed files with 320 additions and 638 deletions

View file

@ -2,6 +2,11 @@
* Copyright (c) 2007, Swedish Institute of Computer Science
* All rights reserved.
*
* Additional fixes for AVR contributed by:
*
* David Kopf dak664@embarqmail.com
* Ivan Delamer delamer@ieee.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@ -91,13 +96,17 @@
static bool is_promiscuous;
#endif
/* RF230_CONF_AUTORETRIES is 1 plus the number written to the hardware. */
/* RF230_CONF_FRAME_RETRIES is 1 plus the number written to the hardware. */
/* Valid range 1-16, zero disables extended mode. */
#ifndef RF230_CONF_AUTORETRIES
#define RF230_CONF_AUTORETRIES 3
#ifndef RF230_CONF_FRAME_RETRIES
#ifdef RF230_CONF_AUTORETRIES /* Support legacy definition. */
#define RF230_CONF_FRAME_RETRIES RF230_CONF_AUTORETRIES
#else
#define RF230_CONF_FRAME_RETRIES 0 /* Extended mode disabled by default. */
#endif
#endif
/* In extended mode (AUTORETRIES>0) the tx routine waits for hardware
/* In extended mode (FRAME_RETRIES>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,
@ -109,15 +118,19 @@ static bool is_promiscuous;
* that use the TX_OK result to signal a successful ACK.
* Adds 100 bytes of program flash and two bytes of RAM.
*/
#if RF320_CONF_INSERTACK && RF230_CONF_AUTORETRIES
#if RF320_CONF_INSERTACK && RF230_CONF_FRAME_RETRIES
#define RF230_INSERTACK 1
uint8_t ack_pending,ack_seqnum;
#endif
/* RF230_CONF_CSMARETRIES is number of random-backoff/CCA retries. */
/* RF230_CONF_CSMA_RETRIES 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
#define RF230_CONF_CSMARETRIES 5
/* In RF231/128RFA1, a value of 7 means no CSMA bebofe the Tx. */
/* CSMA backoffs are long and can block radio duty cycling
* over several channel check periods! */
/* Used only if RF230_CONF_FRAME_RETRIES > 0. */
#ifndef RF230_CONF_CSMA_RETRIES
#define RF230_CONF_CSMA_RETRIES 5
#endif
//Automatic and manual CRC both append 2 bytes to packets
@ -191,18 +204,18 @@ extern uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE];
#endif
/* XXX hack: these will be made as Chameleon packet attributes */
#if RF230_CONF_TIMESTAMPS
rtimer_clock_t rf230_time_of_arrival, rf230_time_of_departure;
int rf230_authority_level_of_sender;
#if RF230_CONF_TIMESTAMPS
static rtimer_clock_t setup_time_for_transmission;
static unsigned long total_time_for_transmission, total_transmission_len;
static int num_transmissions;
#endif
#if defined(__AVR_ATmega128RFA1__)
volatile uint8_t rf230_interruptwait,rf230_ccawait;
volatile uint8_t rf230_wakewait, rf230_txendwait, rf230_ccawait;
#endif
uint8_t volatile rf230_pending;
@ -226,8 +239,8 @@ typedef enum{
PROCESS(rf230_process, "RF230 driver");
/*---------------------------------------------------------------------------*/
int rf230_on(void);
int rf230_off(void);
static int rf230_on(void);
static int rf230_off(void);
static int rf230_read(void *buf, unsigned short bufsize);
@ -340,9 +353,17 @@ static bool radio_is_sleeping(void)
static void
radio_reset_state_machine(void)
{
if (hal_get_slptr()) DEBUGFLOW('"');
hal_set_slptr_low();
delay_us(TIME_NOCLK_TO_WAKE);
/* The data sheet is not clear on what happens when slptr is raised in RX on
* states, it "remains in the new state and returns to the preceding state
* when slptr is lowered". Possibly that is why there is an undocumented
* TIME_NOCLK_TO_WAKE delay here?
*/
if (hal_get_slptr()) {
DEBUGFLOW('V');
hal_set_slptr_low();
delay_us(TIME_NOCLK_TO_WAKE);
}
hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
delay_us(TIME_CMD_FORCE_TRX_OFF);
}
@ -351,33 +372,36 @@ static char
rf230_isidle(void)
{
uint8_t radio_state;
/* Contikimac can turn the radio off during an interrupt, so we always check
* slptr before doing the SPI transfer. The caller must also make this test
* if it could otherwise hang waiting for idle! */
if (hal_get_slptr()) {
DEBUGFLOW(']');
return 1;
} else {
radio_state = hal_subregister_read(SR_TRX_STATUS);
if (radio_state != BUSY_TX_ARET &&
if (RF230_receive_on) DEBUGFLOW('-');
return 1;
}
else {
radio_state = hal_subregister_read(SR_TRX_STATUS);
if (radio_state != BUSY_TX_ARET &&
radio_state != BUSY_RX_AACK &&
radio_state != STATE_TRANSITION &&
radio_state != BUSY_RX &&
radio_state != BUSY_TX) {
return(1);
} else {
// printf(".%u",radio_state);
return(0);
}
return(1);
}
else {
return(0);
}
}
}
static void
rf230_waitidle(void)
{
int i;
for (i=0;i<10000;i++) { //to avoid potential hangs
// while (1) {
/* TX_ARET with multiple csma retries can take a very long time to finish */
while (1) {
if (hal_get_slptr()) return;
if (rf230_isidle()) break;
}
if (i>=10000) {DEBUGFLOW('H');DEBUGFLOW('R');}
}
/*----------------------------------------------------------------------------*/
@ -402,9 +426,9 @@ int i;
static radio_status_t
radio_set_trx_state(uint8_t new_state)
{
uint8_t original_state;
uint8_t current_state;
/*Check function paramter and current state of the radio transceiver.*/
/*Check function parameter and current state of the radio transceiver.*/
if (!((new_state == TRX_OFF) ||
(new_state == RX_ON) ||
(new_state == PLL_ON) ||
@ -413,23 +437,16 @@ radio_set_trx_state(uint8_t new_state)
return RADIO_INVALID_ARGUMENT;
}
if (hal_get_slptr()) {
if (hal_get_slptr()) {
DEBUGFLOW('W');
return RADIO_WRONG_STATE;
}
/* Wait for radio to finish previous operation */
rf230_waitidle();
// for(;;)
// {
original_state = radio_get_trx_state();
// if (original_state != BUSY_TX_ARET &&
// original_state != BUSY_RX_AACK &&
// original_state != BUSY_RX &&
// original_state != BUSY_TX)
// break;
// }
current_state = radio_get_trx_state();
if (new_state == original_state){
if (new_state == current_state){
return RADIO_SUCCESS;
}
@ -440,14 +457,15 @@ radio_set_trx_state(uint8_t new_state)
/* The radio transceiver can be in one of the following states: */
/* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON, TX_ARET_ON. */
if(new_state == TRX_OFF){
if (hal_get_slptr()) DEBUGFLOW('K');DEBUGFLOW('K');DEBUGFLOW('A'+hal_subregister_read(SR_TRX_STATUS));
radio_reset_state_machine(); /* Go to TRX_OFF from any state. */
} else {
/* It is not allowed to go from RX_AACK_ON or TX_AACK_ON and directly to */
/* TX_AACK_ON or RX_AACK_ON respectively. Need to go via PLL_ON. */
/* (Old datasheets allowed other transitions, but this code complies with */
/* the current specification for RF230, RF231 and 128RFA1.) */
if (((new_state == TX_ARET_ON) && (original_state == RX_AACK_ON)) ||
((new_state == RX_AACK_ON) && (original_state == TX_ARET_ON))){
if (((new_state == TX_ARET_ON) && (current_state == RX_AACK_ON)) ||
((new_state == RX_AACK_ON) && (current_state == TX_ARET_ON))){
/* First do intermediate state transition to PLL_ON. */
/* The final state transition is handled after the if-else if. */
hal_subregister_write(SR_TRX_CMD, PLL_ON);
@ -459,21 +477,28 @@ radio_set_trx_state(uint8_t new_state)
/* When the PLL is active most states can be reached in 1us. However, from */
/* TRX_OFF the PLL needs time to activate. */
if (original_state == TRX_OFF){
if (current_state == TRX_OFF){
delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
} else {
delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
}
} /* end: if(new_state == TRX_OFF) ... */
/*Verify state transition.*/
radio_status_t set_state_status = RADIO_TIMED_OUT;
if (radio_get_trx_state() == new_state){
set_state_status = RADIO_SUCCESS;
/* Verify state transition.
* Radio could have already switched to an RX_BUSY state, at least in cooja.
* Don't know what the hardware does but this would not be an error.*/
current_state = radio_get_trx_state();
if (current_state != new_state) {
if (((new_state == RX_ON) && (current_state == BUSY_RX)) ||
((new_state == RX_AACK_ON) && (current_state == BUSY_RX_AACK))) {
/* This is OK. */
} else {
DEBUGFLOW('N');DEBUGFLOW('A'+new_state);DEBUGFLOW('A'+radio_get_trx_state());DEBUGFLOW('N');
return RADIO_TIMED_OUT;
}
}
return set_state_status;
return RADIO_SUCCESS;
}
void
@ -504,7 +529,7 @@ flushrx(void)
}
/*---------------------------------------------------------------------------*/
static void
on(void)
radio_on(void)
{
// ENERGEST_OFF(ENERGEST_TYPE_LISTEN);//testing
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
@ -520,11 +545,22 @@ on(void)
PORTE|=(1<<PE1); //ledon
#endif
#if defined(__AVR_ATmega128RFA1__)
/* Use the poweron interrupt for delay */
rf230_interruptwait=1;
sei();
hal_set_slptr_low();
while (rf230_interruptwait) {}
/* Use the poweron interrupt for delay */
rf230_wakewait=1;
{
uint8_t sreg = SREG;
sei();
if (hal_get_slptr() == 0) DEBUGFLOW('$');
hal_set_slptr_low();
{
int i;
for (i=0;i<10000;i++) {
if (!rf230_wakewait) break;
}
if (i>=10000) {DEBUGFLOW('G');DEBUGFLOW('g');DEBUGFLOW('A'+hal_subregister_read(SR_TRX_STATUS));}
}
SREG = sreg;
}
#else
/* SPI based radios. The wake time depends on board capacitance.
* Make sure the delay is long enough, as using SPI too soon will reset the MCU!
@ -533,7 +569,6 @@ on(void)
// uint8_t sreg = SREG;cli();
hal_set_slptr_low();
delay_us(2*TIME_SLEEP_TO_TRX_OFF);
// delay_us(TIME_SLEEP_TO_TRX_OFF+TIME_SLEEP_TO_TRX_OFF/2);
// SREG=sreg;
#endif
}
@ -547,8 +582,14 @@ on(void)
rf230_waitidle();
}
static void
off(void)
radio_off(void)
{
RF230_receive_on = 0;
if (hal_get_slptr()) {
DEBUGFLOW('F');
return;
}
#if RF230BB_CONF_LEDONPORTE1
PORTE&=~(1<<PE1); //ledoff
#endif
@ -563,7 +604,12 @@ off(void)
/* Do not transmit autoacks when stack thinks radio is off */
radio_set_trx_state(RX_ON);
#else
/* Force the device into TRX_OFF. */
/* Force the device into TRX_OFF.
* First make sure an interrupt did not initiate a sleep. */
if (hal_get_slptr()) {
DEBUGFLOW('?');
return;
}
radio_reset_state_machine();
#if RADIOSLEEPSWHENOFF
/* Sleep Radio */
@ -572,7 +618,6 @@ off(void)
#endif
#endif /* RADIOALWAYSON */
RF230_receive_on = 0;
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
}
/*---------------------------------------------------------------------------*/
@ -586,7 +631,7 @@ set_txpower(uint8_t power)
DEBUGFLOW('f');
PRINTF("rf230_set_txpower:Sleeping"); //happens with cxmac
} else {
DEBUGFLOW('g');
//DEBUGFLOW('g');
hal_subregister_write(SR_TX_PWR, power);
}
}
@ -718,13 +763,14 @@ rf230_init(void)
// printf_P(PSTR("After calibration OSCCAL=%x\n"),OSCCAL);
/* Set receive buffers empty and point to the first */
for (i=0;i<RF230_CONF_RX_BUFFERS;i++) rxframe[i].length=0;
for (i=0;i<RF230_CONF_RX_BUFFERS;i++) {
rxframe[i].length=0;
}
rxframe_head=0;rxframe_tail=0;
/* Do full rf230 Reset */
hal_set_rst_low();
hal_set_slptr_low();
#if 1
/* On powerup a TIME_RESET delay is needed here, however on some other MCU reset
* (JTAG, WDT, Brownout) the radio may be sleeping. It can enter an uncertain
* state (sending wrong hardware FCS for example) unless the full wakeup delay
@ -733,9 +779,7 @@ rf230_init(void)
* See www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=78725
*/
delay_us(2*TIME_SLEEP_TO_TRX_OFF);
#else
delay_us(TIME_RESET);
#endif
//delay_us(TIME_RESET); /* Old impl. */
hal_set_rst_high();
/* Force transition to TRX_OFF */
@ -761,7 +805,7 @@ rf230_init(void)
process_start(&rf230_process, NULL);
/* Leave radio in on state (?)*/
on();
radio_on();
return 1;
}
@ -777,11 +821,13 @@ void rf230_warm_reset(void) {
hal_register_write(RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK);
/* Set up number of automatic retries 0-15 (0 implies PLL_ON sends instead of the extended TX_ARET mode */
hal_subregister_write(SR_MAX_FRAME_RETRIES, RF230_CONF_AUTORETRIES );
/* Set up number of automatic retries 0-15
* (0 implies PLL_ON sends instead of the extended TX_ARET mode */
hal_subregister_write(SR_MAX_FRAME_RETRIES,
(RF230_CONF_FRAME_RETRIES > 0) ? (RF230_CONF_FRAME_RETRIES - 1) : 0 );
/* Set up carrier sense/clear channel assesment parameters for extended operating mode */
hal_subregister_write(SR_MAX_CSMA_RETRIES, 5 );//highest allowed retries
hal_subregister_write(SR_MAX_CSMA_RETRIES, RF230_CONF_CSMA_RETRIES );//highest allowed retries
hal_register_write(RG_CSMA_BE, 0x80); //min backoff exponent 0, max 8 (highest allowed)
hal_register_write(RG_CSMA_SEED_0,hal_register_read(RG_PHY_RSSI) );//upper two RSSI reg bits RND_VALUE are random in rf231
// hal_register_write(CSMA_SEED_1,42 );
@ -855,20 +901,19 @@ rf230_transmit(unsigned short payload_len)
#if RF230BB_CONF_LEDONPORTE1
PORTE|=(1<<PE1); //ledon
#endif
rf230_interruptwait=1;
hal_set_slptr_low();
// while (rf230_interruptwait) {}
rf230_wakewait=1;
hal_set_slptr_low();
{
int i;
for (i=0;i<10000;i++) {
if (!rf230_interruptwait) break;
if (!rf230_wakewait) break;
}
if (i>=10000) {DEBUGFLOW('G');DEBUGFLOW('G');DEBUGFLOW('A'+hal_subregister_read(SR_TRX_STATUS));}
}
#else
hal_set_slptr_low();
DEBUGFLOW('j');
delay_us(2*TIME_SLEEP_TO_TRX_OFF); //extra delay depends on board capacitance
// delay_us(TIME_SLEEP_TO_TRX_OFF+TIME_SLEEP_TO_TRX_OFF/2);
delay_us(2*TIME_SLEEP_TO_TRX_OFF); //extra delay (2x) depends on board capacitance
#endif
} else {
@ -891,7 +936,7 @@ rf230_transmit(unsigned short payload_len)
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
}
/* Prepare to transmit */
#if RF230_CONF_AUTORETRIES
#if RF230_CONF_FRAME_RETRIES
radio_set_trx_state(TX_ARET_ON);
DEBUGFLOW('t');
#else
@ -916,20 +961,17 @@ rf230_transmit(unsigned short payload_len)
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
#if defined(__AVR_ATmega128RFA1__)
/* No interrupts across frame download! */
cli();
/* slow down the transmit? */
// delay_us(500);
#endif
/* Toggle the SLP_TR pin to initiate the frame transmission */
HAL_ENTER_CRITICAL_REGION();
/* Toggle the SLP_TR pin to initiate the frame transmission */
hal_set_slptr_high();
hal_set_slptr_low();
hal_frame_write(buffer, total_len);
#if defined(__AVR_ATmega128RFA1__)
sei();
#endif
HAL_LEAVE_CRITICAL_REGION();
PRINTF("rf230_transmit: %d\n", (int)total_len);
#if DEBUG>1
/* Note the dumped packet will have a zero checksum unless compiled with RF230_CONF_CHECKSUM
* since we don't know what it will be if calculated by the hardware.
@ -951,7 +993,7 @@ rf230_transmit(unsigned short payload_len)
rf230_waitidle();
/* Get the transmission result */
#if RF230_CONF_AUTORETRIES
#if RF230_CONF_FRAME_RETRIES
tx_result = hal_subregister_read(SR_TRAC_STATUS);
#else
tx_result=RADIO_TX_OK;
@ -981,13 +1023,13 @@ rf230_transmit(unsigned short payload_len)
if(RF230_receive_on) {
DEBUGFLOW('l');
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
on();
radio_on();
} else {
#if RADIOALWAYSON
/* Enable reception */
on();
radio_on();
#else
off();
radio_off();
PRINTF("rf230_transmit: turning radio off\n");
#endif
}
@ -1123,36 +1165,39 @@ bail:
return ret;
}
/*---------------------------------------------------------------------------*/
int
static int
rf230_off(void)
{
/* Don't do anything if we are already turned off. */
if(RF230_receive_on == 0) {
//if (!hal_get_slptr()) DEBUGFLOW('5');
return 0;
}
//if (hal_get_slptr()) DEBUGFLOW('6');
/* If we are currently receiving a packet, we still call off(),
/* If we are currently receiving a packet, we still call radio_off(),
as that routine waits until Rx is complete (packet uploaded in ISR
so no worries about losing it). If using RX_AACK_MODE, chances are
the packet is not for us and will be discarded. */
so no worries about losing it). The transmit routine may also turn
+ the radio off on a return to sleep. rf230_isidle checks for that. */
if (!rf230_isidle()) {
//DEBUGFLOW('X');DEBUGFLOW('X');DEBUGFLOW('A'+hal_subregister_read(SR_TRX_STATUS));
PRINTF("rf230_off: busy receiving\r\n");
//return 1;
}
off();
radio_off();
return 0;
}
/*---------------------------------------------------------------------------*/
int
static int
rf230_on(void)
{
if(RF230_receive_on) {
DEBUGFLOW('q');
//if (hal_get_slptr()) DEBUGFLOW('Q');//Cooja TODO: shows sleeping occasionally
return 1;
}
on();
radio_on();
return 1;
}
/*---------------------------------------------------------------------------*/
@ -1296,18 +1341,26 @@ PROCESS_THREAD(rf230_process, ev, data)
TIMETABLE_TIMESTAMP(rf230_timetable, "poll");
#endif /* RF230_TIMETABLE_PROFILING */
rf230_pending = 0;
packetbuf_clear();
/* Turn off interrupts to avoid ISR writing to the same buffers we are reading. */
HAL_ENTER_CRITICAL_REGION();
len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
/* Restore interrupts. */
HAL_LEAVE_CRITICAL_REGION();
PRINTF("rf230_read: %u bytes lqi %u\n",len,rf230_last_correlation);
#if DEBUG>1
{
uint8_t i;
unsigned const char * rxdata = packetbuf_dataptr();
PRINTF("0000");
for (i=0;i<len+AUX_LEN;i++) PRINTF(" %02x",rxdata[i]);
PRINTF("\n");
}
#endif
RF230PROCESSFLAG(1);
if(len > 0) {
@ -1372,19 +1425,6 @@ rf230_read(void *buf, unsigned short bufsize)
return 0;
}
#if RADIOALWAYSON
if (RF230_receive_on) {
#else
if (hal_get_slptr()) {
DEBUGFLOW('!');
return 0;
}
if (!RF230_receive_on) {
DEBUGFLOW('[');
return 0;
}
#endif
#if RF230_CONF_TIMESTAMPS
if(interrupt_time_set) {
rf230_time_of_arrival = interrupt_time;
@ -1395,19 +1435,6 @@ if (!RF230_receive_on) {
rf230_time_of_departure = 0;
#endif /* RF230_CONF_TIMESTAMPS */
// can't use PRINTF as interrupts are disabled
// PRINTSHORT("r%d",rxframe[rxframe_head].length);
//PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe[rxframe_head].length,rxframe[rxframe_head].lqi,rxframe[rxframe_head].crc);
#if DEBUG>1
{
//uint8_t i;
//PRINTF("0000");
//for (i=0;i<rxframe[rxframe_head].length;i++) PRINTF(" %02x",rxframe[rxframe_head].data[i]);
//PRINTF("\n");
}
#endif
//if(len > RF230_MAX_PACKET_LEN) {
if(len > RF230_MAX_TX_FRAME_LENGTH) {
/* Oops, we must be out of sync. */
DEBUGFLOW('u');
@ -1431,6 +1458,7 @@ if (!RF230_receive_on) {
RIMESTATS_ADD(toolong);
return 0;
}
/* Transfer the frame, stripping the footer, but copying the checksum */
framep=&(rxframe[rxframe_head].data[0]);
memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
@ -1438,9 +1466,17 @@ if (!RF230_receive_on) {
/* Clear the length field to allow buffering of the next packet */
rxframe[rxframe_head].length=0;
rxframe_head++;if (rxframe_head >= RF230_CONF_RX_BUFFERS) rxframe_head=0;
rxframe_head++;
if (rxframe_head >= RF230_CONF_RX_BUFFERS) {
rxframe_head=0;
}
/* If another packet has been buffered, schedule another receive poll */
if (rxframe[rxframe_head].length) rf230_interrupt();
if (rxframe[rxframe_head].length) {
rf230_interrupt();
}
else {
rf230_pending = 0;
}
/* Point to the checksum */
framep+=len-AUX_LEN;
@ -1518,13 +1554,6 @@ if (!RF230_receive_on) {
/* Here return just the data length. The checksum is however still in the buffer for packet sniffing */
return len - AUX_LEN;
#if RADIOALWAYSON
} else {
DEBUGFLOW('y'); //Stack thought radio was off
return 0;
}
#endif
}
/*---------------------------------------------------------------------------*/
void
@ -1589,13 +1618,17 @@ rf230_cca(void)
uint8_t radio_was_off = 0;
/* Turn radio on if necessary. If radio is currently busy return busy channel */
/* This may happen when testing radio duty cycling with RADIOALWAYSON */
/* This may happen when testing radio duty cycling with RADIOALWAYSON,
* or because a packet just started. */
if(RF230_receive_on) {
if (hal_get_slptr()) { //should not be sleeping!
DEBUGFLOW('<');
goto busyexit;
} else {
if (!rf230_isidle()) {DEBUGFLOW('2');goto busyexit;}
if (!rf230_isidle()) {
//DEBUGFLOW('2');
goto busyexit;
}
}
} else {
radio_was_off = 1;
@ -1611,18 +1644,30 @@ rf230_cca(void)
/* Note reading the TRX_STATUS register clears both CCA_STATUS and CCA_DONE bits */
#if defined(__AVR_ATmega128RFA1__)
#if 1 //interrupt method
sei();
//rf230_waitidle();
//TODO:disable reception for version bug
radio_set_trx_state(RX_ON);
// rf230_waitidle();
/* Disable rx transitions to busy (RX_PDT_BIT) */
/* Note: for speed this resets rx threshold to the compiled default */
#ifdef RF230_MIN_RX_POWER
hal_register_write(RG_RX_SYN, RF230_MIN_RX_POWER/6 + 0x81);
#else
hal_register_write(RG_RX_SYN, 0x80);
#endif
/* Switch to RX_ON for measurement. This will wait if a packet is being received */
radio_set_trx_state(RX_ON);
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) {}
/* Write to ED_LEVEL register to start CCA */
{
uint8_t volatile saved_sreg = SREG;
sei( );
hal_register_write(PHY_ED_LEVEL,0);
while (rf230_ccawait) {}
SREG = saved_sreg;
}
/* Use ED register to determine result. 77dBm is poweron csma default.*/
#ifdef RF230_CONF_CCA_THRES
if (hal_register_read(RG_PHY_ED_LEVEL)<(91+RF230_CONF_CCA_THRES) cca=0xff;
#else
@ -1631,8 +1676,17 @@ rf230_cca(void)
//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);
radio_set_trx_state(RX_AACK_ON);
#endif
/* Enable packet reception */
#ifdef RF230_MIN_RX_POWER
hal_register_write(RG_RX_SYN, RF230_MIN_RX_POWER/6 + 0x01);
#else
hal_register_write(RG_RX_SYN, 0x00);
#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 */
@ -1654,6 +1708,10 @@ rf230_cca(void)
hal_subregister_write(SR_CCA_REQUEST,1);
delay_us(TIME_CCA);
while ((cca & 0x80) == 0 ) {
if (hal_get_slptr()) {
DEBUGFLOW('S');
break;
}
cca=hal_register_read(RG_TRX_STATUS);
}
SREG=saved_sreg;
@ -1684,7 +1742,6 @@ rf230_receiving_packet(void)
radio_state = hal_subregister_read(SR_TRX_STATUS);
if ((radio_state==BUSY_RX) || (radio_state==BUSY_RX_AACK)) {
// DEBUGFLOW('8');
// rf230_pending=1;
return 1;
}
}