50 #include <util/delay_basic.h>
51 #define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) )
53 #include <avr/pgmspace.h>
54 #elif defined(__MSP430__)
68 #define WITH_SEND_CCA 0
71 #if RF230_CONF_TIMESTAMPS
73 #define TIMESTAMP_LEN 3
75 #define TIMESTAMP_LEN 0
81 #ifndef RF230_CONF_CHECKSUM
82 #define RF230_CONF_CHECKSUM 0
86 #ifndef RF230_CONF_AUTOACK
87 #define RF230_CONF_AUTOACK 1
91 #if RF230_CONF_AUTOACK
92 static bool is_promiscuous;
97 #ifndef RF230_CONF_AUTORETRIES
98 #define RF230_CONF_AUTORETRIES 3
103 #ifndef RF230_CONF_CSMARETRIES
104 #define RF230_CONF_CSMARETRIES 5
108 #if RF230_CONF_CHECKSUM || defined(RF230BB_HOOK_TX_PACKET)
111 #define CHECKSUM_LEN 2
114 #define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN)
115 #if AUX_LEN != CHECKSUM_LEN
116 #warning RF230 Untested Configuration!
121 uint8_t authority_level;
124 #define FOOTER1_CRC_OK 0x80
125 #define FOOTER1_CORRELATION 0x7f
130 #define RADIOALWAYSON 1
132 #define RADIOALWAYSON 0
133 #define RADIOSLEEPSWHENOFF 1
139 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
140 #define PRINTSHORT(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
143 #define PRINTSHORT(...)
159 uint16_t RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail;
162 #if RADIO_CONF_CALIBRATE_INTERVAL
165 uint8_t rf230_calibrate;
166 uint8_t rf230_calibrated;
171 extern uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE];
172 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c
178 rtimer_clock_t rf230_time_of_arrival, rf230_time_of_departure;
180 int rf230_authority_level_of_sender;
182 #if RF230_CONF_TIMESTAMPS
183 static rtimer_clock_t setup_time_for_transmission;
184 static unsigned long total_time_for_transmission, total_transmission_len;
185 static int num_transmissions;
188 #if defined(__AVR_ATmega128RFA1__)
189 volatile uint8_t rf230_interruptwait;
192 uint8_t
volatile rf230_pending;
194 uint8_t ack_pending=0;
195 uint8_t ack_seqnum=0;
213 PROCESS(rf230_process,
"RF230 driver");
219 static int rf230_read(
void *buf,
unsigned short bufsize);
220 static int rf230_read_fakeack(
void *buf,
unsigned short bufsize);
222 static int rf230_prepare(
const void *data,
unsigned short len);
223 static int rf230_transmit(
unsigned short len);
224 static int rf230_send(
const void *data,
unsigned short len);
226 static int rf230_receiving_packet(
void);
227 static int rf230_pending_packet(
void);
228 static int rf230_cca(
void);
230 uint8_t rf230_last_correlation,rf230_last_rssi,rf230_smallest_rssi;
240 rf230_receiving_packet,
241 rf230_pending_packet,
246 uint8_t RF230_receive_on;
247 static uint8_t channel;
250 uint8_t rxframe_head,rxframe_tail;
312 bool sleeping =
false;
363 if (rf230_isidle())
break;
389 uint8_t original_state;
392 if (!((new_state ==
TRX_OFF) ||
393 (new_state ==
RX_ON) ||
416 if (new_state == original_state){
450 if (original_state ==
TRX_OFF){
464 return set_state_status;
468 rf230_set_promiscuous_mode(
bool isPromiscuous) {
469 #if RF230_CONF_AUTOACK
470 is_promiscuous = isPromiscuous;
477 rf230_is_ready_to_send() {
491 rxframe[rxframe_head].
length=0;
494 static uint8_t locked, lock_on, lock_off;
499 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
501 #ifdef RF230BB_HOOK_RADIO_ON
502 RF230BB_HOOK_RADIO_ON();
506 #if defined(__AVR_ATmega128RFA1__)
507 rf230_interruptwait=1;
508 ENERGEST_ON(ENERGEST_TYPE_LED_RED);
509 #if RF230BB_CONF_LEDONPORTE1
513 while (rf230_interruptwait) {}
527 #if RF230_CONF_AUTOACK
536 RF230_receive_on = 1;
541 #ifdef RF230BB_HOOK_RADIO_OFF
542 RF230BB_HOOK_RADIO_OFF();
547 RF230_receive_on = 0;
555 #if RADIOSLEEPSWHENOFF
558 ENERGEST_OFF(ENERGEST_TYPE_LED_RED);
559 #if RF230BB_CONF_LEDONPORTE1
569 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
572 #define GET_LOCK() locked = 1
573 static void RELEASE_LOCK(
void) {
586 set_txpower(uint8_t power)
588 if (power > TX_PWR_17_2DBM){
589 power=TX_PWR_17_2DBM;
593 PRINTF(
"rf230_set_txpower:Sleeping");
608 #define AVR_ENTER_CRITICAL_REGION( ) {uint8_t volatile saved_sreg = SREG; cli( )
609 #define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg;}
610 uint8_t osccal_original,osccal_calibrated;
623 uint8_t osccal_original = OSCCAL;
624 volatile uint16_t temp;
643 uint8_t counter = 128;
649 while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)|(1 << TCR2BUB))) { ; }
660 while (!(TIFR2 & (1 << TOV2))){
668 #define cal_upper 32812 //(31250*1.05) // 32812 = 0x802c
669 #define cal_lower 29687 //(31250*0.95) // 29687 = 0x73f7
671 if (temp < cal_lower) {
673 if (OSCCAL==0x7e)
break;
674 if (OSCCAL==0xff)
break;
676 }
else if (temp > cal_upper) {
678 if (OSCCAL==0x81)
break;
679 if (OSCCAL==0x00)
break;
687 }
while ((counter != 0) && (
false == cal_ok));
689 osccal_calibrated=OSCCAL;
690 if (
true != cal_ok) {
692 OSCCAL = osccal_original;
695 OSCCAL = osccal_original;
725 for (i=0;i<RF230_CONF_RX_BUFFERS;i++) rxframe[i].length=0;
726 rxframe_head=0;rxframe_tail=0;
744 if ((tvers != RF230_REVA) && (tvers != RF230_REVB))
745 PRINTF(
"rf230: Unsupported version %u\n",tvers);
746 if (tmanu != SUPPORTED_MANUFACTURER_ID)
747 PRINTF(
"rf230: Unsupported manufacturer ID %u\n",tmanu);
749 PRINTF(
"rf230: Version %u, ID %u\n",tvers,tmanu);
763 void rf230_warm_reset(
void) {
764 #if RF230_CONF_SNEEZER && JACKDAW
766 #warning Manipulating PORTB pins for RF230 Sneezer mode!
790 #ifdef RF230_CONF_CCA_THRES
791 #if RF230_CONF_CCA_THRES < -91
793 #warning RF230_CONF_CCA_THRES below hardware limit, setting to -91dBm
796 #elif RF230_CONF_CCA_THRES > -61
798 #warning RF230_CONF_CCA_THRES above hardware limit, setting to -61dBm
807 #if RF230_CONF_CHECKSUM
814 #ifdef RF230_MAX_TX_POWER
815 set_txpower(RF230_MAX_TX_POWER);
822 rf230_transmit(
unsigned short payload_len)
828 #if RF230_CONF_TIMESTAMPS
829 struct timestamp timestamp;
835 radiowason=RF230_receive_on;
840 #if defined(__AVR_ATmega128RFA1__)
841 if (radiowason) DEBUGFLOW(
'e');
844 ENERGEST_ON(ENERGEST_TYPE_LED_RED);
845 #if RF230BB_CONF_LEDONPORTE1
848 rf230_interruptwait=1;
850 while (rf230_interruptwait) {}
859 #if RADIO_CONF_CALIBRATE_INTERVAL
861 if (rf230_calibrate) {
874 if(RF230_receive_on) {
875 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
878 #if RF230_CONF_AUTORETRIES
888 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
890 txpower = rf230_get_txpower();
892 set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
895 total_len = payload_len + AUX_LEN;
897 #if RF230_CONF_TIMESTAMPS
901 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
903 #if defined(__AVR_ATmega128RFA1__)
913 #if defined(__AVR_ATmega128RFA1__)
916 PRINTF(
"rf230_transmit:\n");
924 for (i=0;i<total_len;i++) PRINTF(
" %02x",buffer[i]);
938 #if RF230_CONF_AUTORETRIES
944 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
945 ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower());
949 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
950 set_txpower(txpower & 0xff);
961 #if RF230_CONF_TIMESTAMPS
962 setup_time_for_transmission = txtime - timestamp.time;
964 if(num_transmissions < 10000) {
966 total_transmission_len += total_len;
972 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
973 if(RF230_receive_on) {
974 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
986 if (!((buffer[5]==0xff) && (buffer[6]==0xff)) && (buffer[0]&(1<<6))){
990 tx_result = RADIO_TX_OK;
991 }
else if (tx_result==3) {
994 RIMESTATS_ADD(contentiondrop);
995 PRINTF(
"rf230_transmit: Transmission never started\n");
996 tx_result = RADIO_TX_COLLISION;
997 }
else if (tx_result==5) {
1000 tx_result = RADIO_TX_NOACK;
1001 }
else if (tx_result==7) {
1004 tx_result = RADIO_TX_ERR;
1011 rf230_prepare(
const void *payload,
unsigned short payload_len)
1013 ack_seqnum=*(((uint8_t *)payload)+2);
1015 uint8_t total_len,*pbuf;
1016 #if RF230_CONF_TIMESTAMPS
1017 struct timestamp timestamp;
1019 #if RF230_CONF_CHECKSUM
1029 RIMESTATS_ADD(lltx);
1031 #if RF230_CONF_CHECKSUM
1032 checksum =
crc16_data(payload, payload_len, 0);
1036 total_len = payload_len + AUX_LEN;
1049 memcpy(pbuf,payload,payload_len);
1052 #if RF230_CONF_CHECKSUM
1053 memcpy(pbuf,&checksum,CHECKSUM_LEN);
1057 #if RF230_CONF_TIMESTAMPS
1060 memcpy(pbuf,×tamp,TIMESTAMP_LEN);
1061 pbuf+=TIMESTAMP_LEN;
1065 #ifdef RF230BB_HOOK_TX_PACKET
1066 #if !RF230_CONF_CHECKSUM
1069 checksum =
crc16_data(payload, payload_len, 0);
1070 memcpy(buffer+total_len-CHECKSUM_LEN,&checksum,CHECKSUM_LEN);
1073 RF230BB_HOOK_TX_PACKET(buffer,total_len);
1081 rf230_send(
const void *payload,
unsigned short payload_len)
1085 #ifdef RF230BB_HOOK_IS_SEND_ENABLED
1086 if(!RF230BB_HOOK_IS_SEND_ENABLED()) {
1091 if((ret=rf230_prepare(payload, payload_len))) {
1093 printf_P(PSTR(
"rf230_send: Unable to send, prep failed (%d)\n"),ret);
1098 ret = rf230_transmit(payload_len);
1102 if (ret) RF230_sendfail++;
1111 if(RF230_receive_on == 0) {
1126 if (!rf230_isidle()) {
1138 if(RF230_receive_on) {
1153 rf230_get_channel(
void)
1161 rf230_set_channel(uint8_t c)
1164 PRINTF(
"rf230: Set Channel %u\n",c);
1171 rf230_listen_channel(uint8_t c)
1175 rf230_set_channel(c);
1180 rf230_set_pan_addr(
unsigned pan,
1182 const uint8_t ieee_addr[8])
1185 PRINTF(
"rf230: PAN=%x Short Addr=%x\n",pan,addr);
1190 abyte = (pan >> 8*1) & 0xFF;
1193 abyte = addr & 0xFF;
1195 abyte = (addr >> 8*1) & 0xFF;
1198 if (ieee_addr !=
NULL) {
1199 PRINTF(
"MAC=%x",*ieee_addr);
1201 PRINTF(
":%x",*ieee_addr);
1203 PRINTF(
":%x",*ieee_addr);
1205 PRINTF(
":%x",*ieee_addr);
1207 PRINTF(
":%x",*ieee_addr);
1209 PRINTF(
":%x",*ieee_addr);
1211 PRINTF(
":%x",*ieee_addr);
1213 PRINTF(
":%x",*ieee_addr);
1222 #if RF230_CONF_TIMESTAMPS
1223 static volatile rtimer_clock_t interrupt_time;
1224 static volatile int interrupt_time_set;
1226 #if RF230_TIMETABLE_PROFILING
1227 #define rf230_timetable_size 16
1228 TIMETABLE(rf230_timetable);
1229 TIMETABLE_AGGREGATE(aggregate_time, 10);
1232 rf230_interrupt(
void)
1236 if (RF230_receive_on) {
1239 #if RF230_CONF_TIMESTAMPS
1241 interrupt_time_set = 1;
1246 #if RF230_TIMETABLE_PROFILING
1247 timetable_clear(&rf230_timetable);
1248 TIMETABLE_TIMESTAMP(rf230_timetable,
"interrupt");
1253 #if RADIOSTATS //TODO:This will double count buffered packets
1254 RF230_receivepackets++;
1260 rxframe[rxframe_head].
length=0;
1272 uint8_t rf230processflag;
1273 #define RF230PROCESSFLAG(arg) rf230processflag=arg
1275 #define RF230PROCESSFLAG(arg)
1282 RF230PROCESSFLAG(99);
1286 RF230PROCESSFLAG(42);
1287 #if RF230_TIMETABLE_PROFILING
1288 TIMETABLE_TIMESTAMP(rf230_timetable,
"poll");
1295 RF230PROCESSFLAG(1);
1298 RF230PROCESSFLAG(2);
1299 NETSTACK_RDC.input();
1300 #if RF230_TIMETABLE_PROFILING
1301 TIMETABLE_TIMESTAMP(rf230_timetable,
"end");
1302 timetable_aggregate_compute_detailed(&aggregate_time,
1304 timetable_clear(&rf230_timetable);
1308 RF230_receivefail++;
1320 rf230_read_fakeack(
void *buf,
unsigned short bufsize)
1322 if(ack_pending && bufsize == 3){
1324 uint8_t *buff=(uint8_t *)buf;
1330 rf230_read(buf,bufsize);
1340 rf230_read(
void *buf,
unsigned short bufsize)
1342 uint8_t len,*framep;
1344 uint8_t footer[FOOTER_LEN];
1346 #if RF230_CONF_CHECKSUM
1349 #if RF230_CONF_TIMESTAMPS
1353 len=rxframe[rxframe_head].
length;
1355 #if RADIOALWAYSON && DEBUGFLOWSIZE
1356 if (RF230_receive_on==0) {
if (debugflow[debugflowsize-1]!=
'z') DEBUGFLOW(
'z');}
1362 if (RF230_receive_on) {
1368 if (!RF230_receive_on) {
1374 #if RF230_CONF_TIMESTAMPS
1375 if(interrupt_time_set) {
1376 rf230_time_of_arrival = interrupt_time;
1377 interrupt_time_set = 0;
1379 rf230_time_of_arrival = 0;
1381 rf230_time_of_departure = 0;
1385 PRINTF(
"rf230_read: %u bytes lqi %u crc %u\n",rxframe[rxframe_head].length,rxframe[rxframe_head].lqi,rxframe[rxframe_head].crc);
1390 for (i=0;i<rxframe[rxframe_head].
length;i++) PRINTF(
" %02x",rxframe[rxframe_head].data[i]);
1402 RIMESTATS_ADD(badsynch);
1407 if(len <= AUX_LEN) {
1409 PRINTF(
"len <= AUX_LEN\n");
1411 RIMESTATS_ADD(tooshort);
1416 if(len - AUX_LEN > bufsize) {
1418 PRINTF(
"len - AUX_LEN > bufsize\n");
1420 RIMESTATS_ADD(toolong);
1425 framep=&(rxframe[rxframe_head].
data[0]);
1426 memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
1427 rf230_last_correlation = rxframe[rxframe_head].
lqi;
1430 rxframe[rxframe_head].
length=0;
1431 rxframe_head++;
if (rxframe_head >= RF230_CONF_RX_BUFFERS) rxframe_head=0;
1433 if (rxframe[rxframe_head].length) rf230_interrupt();
1436 framep+=len-AUX_LEN;
1437 #if RF230_CONF_CHECKSUM
1438 memcpy(&checksum,framep,CHECKSUM_LEN);
1440 framep+=CHECKSUM_LEN;
1441 #if RF230_CONF_TIMESTAMPS
1442 memcpy(&t,framep,TIMESTAMP_LEN);
1444 framep+=TIMESTAMP_LEN;
1446 memcpy(footer,framep,FOOTER_LEN);
1448 #if RF230_CONF_CHECKSUM
1449 if(checksum !=
crc16_data(buf, len - AUX_LEN, 0)) {
1451 PRINTF(
"checksum failed 0x%04x != 0x%04x\n",
1452 checksum,
crc16_data(buf, len - AUX_LEN, 0));
1455 if(footer[1] & FOOTER1_CRC_OK &&
1456 checksum ==
crc16_data(buf, len - AUX_LEN, 0)) {
1461 #if 0 //more general
1462 rf230_last_rssi = rf230_get_raw_rssi();
1464 #if RF230_CONF_AUTOACK
1474 if ((rf230_smallest_rssi==0) || (rf230_last_rssi<rf230_smallest_rssi))
1475 rf230_smallest_rssi=rf230_last_rssi;
1478 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf230_last_rssi);
1479 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf230_last_correlation);
1481 RIMESTATS_ADD(llrx);
1483 #if RF230_CONF_TIMESTAMPS
1484 rf230_time_of_departure =
1486 setup_time_for_transmission +
1487 (total_time_for_transmission * (len - 2)) / total_transmission_len;
1489 rf230_authority_level_of_sender = t.authority_level;
1491 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
1494 #if RF230_CONF_CHECKSUM
1499 RIMESTATS_ADD(badcrc);
1505 #ifdef RF230BB_HOOK_RX_PACKET
1506 RF230BB_HOOK_RX_PACKET(buf,len);
1510 return len - AUX_LEN;
1521 rf230_set_txpower(uint8_t power)
1529 rf230_get_txpower(
void)
1531 uint8_t power = TX_PWR_UNDEFINED;
1533 PRINTF(
"rf230_get_txpower:Sleeping");
1542 rf230_get_raw_rssi(
void)
1545 bool radio_was_off = 0;
1548 if(!RF230_receive_on) {
1560 #if 0 // 3-clock shift and add is faster on machines with no hardware multiply
1563 rssi = (rssi << 1) + rssi;
1564 #else // 1 or 2 clock multiply, or compiler with correct optimization
1581 uint8_t radio_was_off = 0;
1582 uint8_t
volatile saved_sreg = SREG;
1600 if(RF230_receive_on) {
1605 if (!rf230_isidle()) {DEBUGFLOW(
'2');
goto busyexit;}
1619 #if defined(__AVR_ATmega128RFA1__)
1622 rf230_interruptwait=1;
1625 while (rf230_interruptwait) {}
1630 #ifdef RF230_CONF_CCA_THRES
1640 while ((cca & 0x80) == 0 ) {
1662 rf230_receiving_packet(
void)
1664 uint8_t radio_state;
1679 rf230_pending_packet(
void)
1681 if(ack_pending ==1){
1684 if (rf230_pending) DEBUGFLOW(
'@');
1685 return rf230_pending;
1688 #if RF230_CONF_SNEEZER && JACKDAW
1694 void rf230_start_sneeze(
void) {