Add sniffer and 802 frame reporting
[contiki-2.x.git] / cpu / avr / radio / rf230bb / rf230bb.c
blobfbe18a19856ba20a954cafcbed461565eedef728
1 /*
2 * Copyright (c) 2007, Swedish Institute of Computer Science
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * This file is part of the Contiki operating system.
31 * @(#)$Id: rf230bb.c,v 1.6 2010/02/23 17:37:51 dak664 Exp $
34 * This code is almost device independent and should be easy to port.
35 * Ported to Atmel RF230 21Feb2010 by dak
38 #include <stdio.h>
39 #include <string.h>
41 #include "contiki.h"
43 #if defined(__AVR__)
44 #include <avr/io.h>
45 #include <util/delay.h>
46 //#include <avr/pgmspace.h>
47 #elif defined(__MSP430__)
48 #include <io.h>
49 #endif
51 #include "dev/leds.h"
52 #include "dev/spi.h"
53 #include "rf230bb.h"
55 #include "net/rime/packetbuf.h"
56 #include "net/rime/rimestats.h"
57 #include "net/netstack.h"
59 #if JACKDAW
60 #include "sicslow_ethernet.h"
61 #include "uip.h"
62 #include "uip_arp.h" //For ethernet header structure
63 #define ETHBUF(x) ((struct uip_eth_hdr *)x)
64 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
65 /* 6lowpan max size + ethernet header size + 1 */
66 static uint8_t raw_buf[127+ UIP_LLH_LEN +1];
67 extern uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan);
68 extern rimeaddr_t macLongAddr;
69 #include "rndis/rndis_task.h"
70 #endif
73 #include "sys/timetable.h"
75 #define WITH_SEND_CCA 0
77 #if RF230_CONF_TIMESTAMPS
78 #include "net/rime/timesynch.h"
79 #define TIMESTAMP_LEN 3
80 #else /* RF230_CONF_TIMESTAMPS */
81 #define TIMESTAMP_LEN 0
82 #endif /* RF230_CONF_TIMESTAMPS */
83 //#define FOOTER_LEN 2
84 #define FOOTER_LEN 0
86 #ifndef RF230_CONF_CHECKSUM
87 #define RF230_CONF_CHECKSUM 0
88 #endif /* RF230_CONF_CHECKSUM */
90 #ifndef RF230_CONF_AUTOACK
91 #define RF230_CONF_AUTOACK 0
92 #endif /* RF230_CONF_AUTOACK */
94 //Automatic and manual CRC both append 2 bytes to packets
95 #if RF230_CONF_CHECKSUM
96 #include "lib/crc16.h"
97 #define CHECKSUM_LEN 2
98 #else
99 #define CHECKSUM_LEN 2
100 #endif /* RF230_CONF_CHECKSUM */
102 #define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN)
104 struct timestamp {
105 uint16_t time;
106 uint8_t authority_level;
109 #define FOOTER1_CRC_OK 0x80
110 #define FOOTER1_CORRELATION 0x7f
112 #define DEBUG 0
113 #if DEBUG
114 #define PRINTF(...) printf(__VA_ARGS__)
115 #define PRINTSHORT(...) printf(__VA_ARGS__)
116 #else
117 #define PRINTF(...)
118 #define PRINTSHORT(...)
119 //#define PRINTSHORT(...) printf(__VA_ARGS__)
120 #endif
122 //void rf230_arch_init(void);
124 /* XXX hack: these will be made as Chameleon packet attributes */
125 rtimer_clock_t rf230_time_of_arrival, rf230_time_of_departure;
127 int rf230_authority_level_of_sender;
129 #if RF230_CONF_TIMESTAMPS
130 static rtimer_clock_t setup_time_for_transmission;
131 static unsigned long total_time_for_transmission, total_transmission_len;
132 static int num_transmissions;
133 #endif /* RF230_CONF_TIMESTAMPS */
135 int rf230_packets_seen, rf230_packets_read;
137 static uint8_t volatile pending;
139 /* RF230 hardware delay times, from datasheet */
140 typedef enum{
141 TIME_TO_ENTER_P_ON = 510, /**< Transition time from VCC is applied to P_ON - most favorable case! */
142 TIME_P_ON_TO_TRX_OFF = 510, /**< Transition time from P_ON to TRX_OFF. */
143 TIME_SLEEP_TO_TRX_OFF = 880, /**< Transition time from SLEEP to TRX_OFF. */
144 TIME_RESET = 6, /**< Time to hold the RST pin low during reset */
145 TIME_ED_MEASUREMENT = 140, /**< Time it takes to do a ED measurement. */
146 TIME_CCA = 140, /**< Time it takes to do a CCA. */
147 TIME_PLL_LOCK = 150, /**< Maximum time it should take for the PLL to lock. */
148 TIME_FTN_TUNING = 25, /**< Maximum time it should take to do the filter tuning. */
149 TIME_NOCLK_TO_WAKE = 6, /**< Transition time from *_NOCLK to being awake. */
150 TIME_CMD_FORCE_TRX_OFF = 1, /**< Time it takes to execute the FORCE_TRX_OFF command. */
151 TIME_TRX_OFF_TO_PLL_ACTIVE = 180, /**< Transition time from TRX_OFF to: RX_ON, PLL_ON, TX_ARET_ON and RX_AACK_ON. */
152 TIME_STATE_TRANSITION_PLL_ACTIVE = 1, /**< Transition time from PLL active state to another. */
153 }radio_trx_timing_t;
154 /*---------------------------------------------------------------------------*/
155 PROCESS(rf230_process, "RF230 driver");
156 /*---------------------------------------------------------------------------*/
158 int rf230_on(void);
159 int rf230_off(void);
161 static int rf230_read(void *buf, unsigned short bufsize);
163 static int rf230_prepare(const void *data, unsigned short len);
164 static int rf230_transmit(unsigned short len);
165 static int rf230_send(const void *data, unsigned short len);
167 static int rf230_receiving_packet(void);
168 static int pending_packet(void);
169 static int rf230_cca(void);
171 signed char rf230_last_rssi;
172 uint8_t rf230_last_correlation;
174 const struct radio_driver rf230_driver =
176 rf230_init,
177 rf230_prepare,
178 rf230_transmit,
179 rf230_send,
180 rf230_read,
181 rf230_cca,
182 rf230_receiving_packet,
183 pending_packet,
184 rf230_on,
185 rf230_off,
188 static uint8_t receive_on;
189 static int channel;
191 /* Received frames are buffered to rxframe in the interrupt routine in hal.c */
192 hal_rx_frame_t rxframe;
194 /*----------------------------------------------------------------------------*/
195 /** \brief This function return the Radio Transceivers current state.
197 * \retval P_ON When the external supply voltage (VDD) is
198 * first supplied to the transceiver IC, the
199 * system is in the P_ON (Poweron) mode.
200 * \retval BUSY_RX The radio transceiver is busy receiving a
201 * frame.
202 * \retval BUSY_TX The radio transceiver is busy transmitting a
203 * frame.
204 * \retval RX_ON The RX_ON mode enables the analog and digital
205 * receiver blocks and the PLL frequency
206 * synthesizer.
207 * \retval TRX_OFF In this mode, the SPI module and crystal
208 * oscillator are active.
209 * \retval PLL_ON Entering the PLL_ON mode from TRX_OFF will
210 * first enable the analog voltage regulator. The
211 * transceiver is ready to transmit a frame.
212 * \retval BUSY_RX_AACK The radio was in RX_AACK_ON mode and received
213 * the Start of Frame Delimiter (SFD). State
214 * transition to BUSY_RX_AACK is done if the SFD
215 * is valid.
216 * \retval BUSY_TX_ARET The radio transceiver is busy handling the
217 * auto retry mechanism.
218 * \retval RX_AACK_ON The auto acknowledge mode of the radio is
219 * enabled and it is waiting for an incomming
220 * frame.
221 * \retval TX_ARET_ON The auto retry mechanism is enabled and the
222 * radio transceiver is waiting for the user to
223 * send the TX_START command.
224 * \retval RX_ON_NOCLK The radio transceiver is listening for
225 * incomming frames, but the CLKM is disabled so
226 * that the controller could be sleeping.
227 * However, this is only true if the controller
228 * is run from the clock output of the radio.
229 * \retval RX_AACK_ON_NOCLK Same as the RX_ON_NOCLK state, but with the
230 * auto acknowledge module turned on.
231 * \retval BUSY_RX_AACK_NOCLK Same as BUSY_RX_AACK, but the controller
232 * could be sleeping since the CLKM pin is
233 * disabled.
234 * \retval STATE_TRANSITION The radio transceiver's state machine is in
235 * transition between two states.
237 static uint8_t
238 radio_get_trx_state(void)
240 return hal_subregister_read(SR_TRX_STATUS);
243 /*----------------------------------------------------------------------------*/
244 /** \brief This function checks if the radio transceiver is sleeping.
246 * \retval true The radio transceiver is in SLEEP or one of the *_NOCLK
247 * states.
248 * \retval false The radio transceiver is not sleeping.
250 static bool radio_is_sleeping(void)
252 bool sleeping = false;
254 /* The radio transceiver will be at SLEEP or one of the *_NOCLK states only if */
255 /* the SLP_TR pin is high. */
256 if (hal_get_slptr() != 0){
257 sleeping = true;
260 return sleeping;
263 /*----------------------------------------------------------------------------*/
264 /** \brief This function will reset the state machine (to TRX_OFF) from any of
265 * its states, except for the SLEEP state.
267 static void
268 radio_reset_state_machine(void)
270 hal_set_slptr_low();
271 delay_us(TIME_NOCLK_TO_WAKE);
272 hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
273 delay_us(TIME_CMD_FORCE_TRX_OFF);
275 /*----------------------------------------------------------------------------*/
276 /** \brief This function will change the current state of the radio
277 * transceiver's internal state machine.
279 * \param new_state Here is a list of possible states:
280 * - RX_ON Requested transition to RX_ON state.
281 * - TRX_OFF Requested transition to TRX_OFF state.
282 * - PLL_ON Requested transition to PLL_ON state.
283 * - RX_AACK_ON Requested transition to RX_AACK_ON state.
284 * - TX_ARET_ON Requested transition to TX_ARET_ON state.
286 * \retval RADIO_SUCCESS Requested state transition completed
287 * successfully.
288 * \retval RADIO_INVALID_ARGUMENT Supplied function parameter out of bounds.
289 * \retval RADIO_WRONG_STATE Illegal state to do transition from.
290 * \retval RADIO_BUSY_STATE The radio transceiver is busy.
291 * \retval RADIO_TIMED_OUT The state transition could not be completed
292 * within resonable time.
294 static radio_status_t
295 radio_set_trx_state(uint8_t new_state)
297 uint8_t original_state;
299 /*Check function paramter and current state of the radio transceiver.*/
300 if (!((new_state == TRX_OFF) ||
301 (new_state == RX_ON) ||
302 (new_state == PLL_ON) ||
303 (new_state == RX_AACK_ON) ||
304 (new_state == TX_ARET_ON))){
305 return RADIO_INVALID_ARGUMENT;
308 if (radio_is_sleeping() == true){
309 return RADIO_WRONG_STATE;
312 // Wait for radio to finish previous operation
313 for(;;)
315 original_state = radio_get_trx_state();
316 if (original_state != BUSY_TX_ARET &&
317 original_state != BUSY_RX_AACK &&
318 original_state != BUSY_RX &&
319 original_state != BUSY_TX)
320 break;
323 if (new_state == original_state){
324 return RADIO_SUCCESS;
328 /* At this point it is clear that the requested new_state is: */
329 /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON or TX_ARET_ON. */
331 /* The radio transceiver can be in one of the following states: */
332 /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON, TX_ARET_ON. */
333 if(new_state == TRX_OFF){
334 radio_reset_state_machine(); /* Go to TRX_OFF from any state. */
335 } else {
336 /* It is not allowed to go from RX_AACK_ON or TX_AACK_ON and directly to */
337 /* TX_AACK_ON or RX_AACK_ON respectively. Need to go via RX_ON or PLL_ON. */
338 if ((new_state == TX_ARET_ON) &&
339 (original_state == RX_AACK_ON)){
340 /* First do intermediate state transition to PLL_ON, then to TX_ARET_ON. */
341 /* The final state transition to TX_ARET_ON is handled after the if-else if. */
342 hal_subregister_write(SR_TRX_CMD, PLL_ON);
343 delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
344 } else if ((new_state == RX_AACK_ON) &&
345 (original_state == TX_ARET_ON)){
346 /* First do intermediate state transition to RX_ON, then to RX_AACK_ON. */
347 /* The final state transition to RX_AACK_ON is handled after the if-else if. */
348 hal_subregister_write(SR_TRX_CMD, RX_ON);
349 delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
352 /* Any other state transition can be done directly. */
353 hal_subregister_write(SR_TRX_CMD, new_state);
355 /* When the PLL is active most states can be reached in 1us. However, from */
356 /* TRX_OFF the PLL needs time to activate. */
357 if (original_state == TRX_OFF){
358 delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
359 } else {
360 delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
362 } /* end: if(new_state == TRX_OFF) ... */
364 /*Verify state transition.*/
365 radio_status_t set_state_status = RADIO_TIMED_OUT;
367 if (radio_get_trx_state() == new_state){
368 set_state_status = RADIO_SUCCESS;
369 /* set rx_mode flag based on mode we're changing to */
370 // if (new_state == RX_ON ||
371 // new_state == RX_AACK_ON){
372 // rx_mode = true;
373 // } else {
374 // rx_mode = false;
375 // }
378 return set_state_status;
381 /*---------------------------------------------------------------------------*/
382 static int
383 rf230_isidle(void)
385 uint8_t radio_state;
386 radio_state = hal_subregister_read(SR_TRX_STATUS);
387 if (radio_state != BUSY_TX_ARET &&
388 radio_state != BUSY_RX_AACK &&
389 radio_state != BUSY_RX &&
390 radio_state != BUSY_TX) {
391 return(1);
392 } else {
393 return(0);
397 static void
398 rf230_waitidle(void)
400 // PRINTF("rf230_waitidle");
402 while (1) {
403 if (rf230_isidle()) break;
404 // PRINTSHORT(".");
408 static void
409 flushrx(void)
411 // rxframe.length=0;
412 // FASTSPI_READ_FIFO_BYTE(dummy);
413 // FASTSPI_STROBE(RF230_SFLUSHRX);
414 // FASTSPI_STROBE(RF230_SFLUSHRX);
416 /*---------------------------------------------------------------------------*/
417 static uint8_t locked, lock_on, lock_off;
419 static void
420 on(void)
422 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
423 #if JACKDAW
424 //blue=0 red=1 green=2 yellow=3
425 #define Led0_on() (PORTD |= 0x80)
426 #define Led1_on() (PORTD &= ~0x20)
427 #define Led2_on() (PORTE &= ~0x80)
428 #define Led3_on() (PORTE &= ~0x40)
429 #define Led0_off() (PORTD &= ~0x80)
430 #define Led1_off() (PORTD |= 0x20)
431 #define Led2_off() (PORTE |= 0x80)
432 #define Led3_off() (PORTE |= 0x40)
433 Led2_on();
434 #else
435 PRINTSHORT("o");
436 // PRINTF("on\n");
437 #endif
439 receive_on = 1;
441 hal_set_slptr_low();
442 //radio_is_waking=1;//can test this before tx instead of delaying
443 delay_us(TIME_SLEEP_TO_TRX_OFF);
444 delay_us(TIME_SLEEP_TO_TRX_OFF);//extra delay for now, wake time depends on board capacitance
446 #if RF230_CONF_NO_AUTO_ACK
447 radio_set_trx_state(RX_ON);
448 #else
449 radio_set_trx_state(RX_AACK_ON);
450 #endif
451 flushrx();
453 static void
454 off(void)
456 receive_on = 0;
458 #if JACKDAW
459 Led2_off();
460 #else
461 PRINTF("off\n");
462 PRINTSHORT("f");
463 #endif
465 #if !JACKDAW && 0 //Leave stick radio on for testing
466 rf230_radio_on = 0;
468 /* Wait for transmission to end before turning radio off. */
469 rf230_waitidle();
471 /* Force the device into TRX_OFF. */
472 radio_reset_state_machine();
474 /* Sleep Radio */
475 hal_set_slptr_high();
476 #endif
478 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
480 /*---------------------------------------------------------------------------*/
481 #define GET_LOCK() locked = 1
482 static void RELEASE_LOCK(void) {
483 if(lock_on) {
484 on();
485 lock_on = 0;
487 if(lock_off) {
488 off();
489 lock_off = 0;
491 locked = 0;
493 /*---------------------------------------------------------------------------*/
494 static void
495 set_txpower(uint8_t power)
497 if (power > TX_PWR_17_2DBM){
498 power=TX_PWR_17_2DBM;
500 if (radio_is_sleeping() ==true) {
501 PRINTF("rf230_set_txpower:Sleeping"); //happens with cxmac
502 } else {
503 hal_subregister_write(SR_TX_PWR, power);
506 /*---------------------------------------------------------------------------*/
508 rf230_init(void)
510 /* Wait in case VCC just applied */
511 delay_us(TIME_TO_ENTER_P_ON);
513 /* Calibrate oscillator */
514 // calibrate_rc_osc_32k();
516 /* Initialize Hardware Abstraction Layer. */
517 hal_init();
519 /* Do full rf230 Reset */
520 hal_set_rst_low();
521 hal_set_slptr_low();
522 delay_us(TIME_RESET);
523 hal_set_rst_high();
525 /* Force transition to TRX_OFF. */
526 hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
527 delay_us(TIME_P_ON_TO_TRX_OFF);
529 /* Verify that it is a supported version */
530 uint8_t tvers = hal_register_read(RG_VERSION_NUM);
531 uint8_t tmanu = hal_register_read(RG_MAN_ID_0);
533 if ((tvers != RF230_REVA) && (tvers != RF230_REVB))
534 PRINTF("rf230: Unsupported version %u\n",tvers);
535 if (tmanu != SUPPORTED_MANUFACTURER_ID)
536 PRINTF("rf230: Unsupported manufacturer ID %u\n",tmanu);
538 PRINTF("rf230: Version %u, ID %u\n",tvers,tmanu);
539 hal_register_write(RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK);
541 // rf230_set_pan_addr(0xffff, 0x0000, NULL);
542 // rf230_set_channel(26);
544 /* Set up the radio for auto mode operation. */
545 /* May need changing for different mac protocols! */
546 hal_subregister_write(SR_MAX_FRAME_RETRIES, 2 );
548 /* Use automatic CRC unless manual is specified */
549 #if RF230_CONF_CHECKSUM
550 hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);
551 #else
552 hal_subregister_write(SR_TX_AUTO_CRC_ON, 1);
553 #endif
555 #if RF230_CONF_NO_AUTO_ACK
556 hal_subregister_write(SR_TRX_CMD, CMD_RX_ON);
557 #else
558 hal_subregister_write(SR_TRX_CMD, CMD_RX_AACK_ON);
559 #endif
561 /* Start the packet receive process */
562 process_start(&rf230_process, NULL);
563 return 1;
565 /*---------------------------------------------------------------------------*/
566 static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH];
567 static int
568 rf230_transmit(unsigned short payload_len)
570 int txpower;
571 uint8_t total_len;
572 #if RF230_CONF_TIMESTAMPS
573 struct timestamp timestamp;
574 #endif /* RF230_CONF_TIMESTAMPS */
575 #if RF230_CONF_CHECKSUM
576 uint16_t checksum;
577 #endif /* RF230_CONF_CHECKSUM */
579 GET_LOCK();
581 txpower = 0;
583 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
584 /* Remember the current transmission power */
585 txpower = rf230_get_txpower();
586 /* Set the specified transmission power */
587 set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
590 total_len = payload_len + AUX_LEN;
592 #if RF230_CONF_TIMESTAMPS
593 rtimer_clock_t txtime = timesynch_time();
594 #endif /* RF230_CONF_TIMESTAMPS */
596 /* Wait for any previous transmission to finish (?) */
597 rf230_waitidle();
599 hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
600 delay_us(TIME_P_ON_TO_TRX_OFF);
602 /* Enable auto retry (?) */
603 radio_set_trx_state(TX_ARET_ON);
605 /* Toggle the SLP_TR pin to initiate the frame transmission. */
606 hal_set_slptr_high();
607 hal_set_slptr_low();
608 hal_frame_write(buffer, total_len);
610 if(receive_on) {
611 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
613 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
615 /* We wait until transmission has ended so that we get an
616 accurate measurement of the transmission time.*/
617 rf230_waitidle();
619 /* Reenable receive mode */
620 #if RF230_CONF_NO_AUTO_ACK
621 radio_set_trx_state(RX_ON);
622 #else
623 radio_set_trx_state(RX_AACK_ON);
624 #endif
626 #if RF230_CONF_TIMESTAMPS
627 setup_time_for_transmission = txtime - timestamp.time;
629 if(num_transmissions < 10000) {
630 total_time_for_transmission += timesynch_time() - txtime;
631 total_transmission_len += total_len;
632 num_transmissions++;
635 #endif /* RF230_CONF_TIMESTAMPS */
637 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
638 ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower());
639 #endif
640 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
641 if(receive_on) {
642 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
643 } else {
644 /* We need to explicitly turn off the radio,
645 * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
646 off();
649 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
650 /* Restore the transmission power */
651 set_txpower(txpower & 0xff);
654 RELEASE_LOCK();
655 return 0;
657 /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
658 transmitted because of other channel activity. */
659 // RIMESTATS_ADD(contentiondrop);
660 // PRINTF("rf230: do_send() transmission never started\n");
662 //if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
663 /* Restore the transmission power */
664 // set_txpower(txpower & 0xff);
665 // }
667 // RELEASE_LOCK();
668 // return -3; /* Transmission never started! */
670 /*---------------------------------------------------------------------------*/
671 static int
672 rf230_prepare(const void *payload, unsigned short payload_len)
674 uint8_t total_len,*pbuf;
675 #if RF230_CONF_TIMESTAMPS
676 struct timestamp timestamp;
677 #endif /* RF230_CONF_TIMESTAMPS */
678 #if RF230_CONF_CHECKSUM
679 uint16_t checksum;
680 #endif /* RF230_CONF_CHECKSUM */
682 GET_LOCK();
684 // PRINTF("rf230: sending %d bytes\n", payload_len);
685 // PRINTSHORT("s%d ",payload_len);
687 RIMESTATS_ADD(lltx);
689 #if RF230_CONF_CHECKSUM
690 checksum = crc16_data(payload, payload_len, 0);
691 #endif /* RF230_CONF_CHECKSUM */
693 /* Copy payload to RAM buffer */
694 total_len = payload_len + AUX_LEN;
695 if (total_len > RF230_MAX_TX_FRAME_LENGTH){
696 #if RADIOSTATS
697 rf230_sendfail++;
698 #endif
699 return -1;
701 pbuf=&buffer[0];
702 memcpy(pbuf,payload,payload_len);
703 pbuf+=payload_len;
705 #if RF230_CONF_CHECKSUM
706 memcpy(pbuf,&checksum,CHECKSUM_LEN);
707 pbuf+=CHECKSUM_LEN;
708 #endif /* RF230_CONF_CHECKSUM */
710 #if RF230_CONF_TIMESTAMPS
711 timestamp.authority_level = timesynch_authority_level();
712 timestamp.time = timesynch_time();
713 memcpy(pbuf,&timestamp,TIMESTAMP_LEN);
714 pbuf+=TIMESTAMP_LEN;
715 #endif /* RF230_CONF_TIMESTAMPS */
716 /*------------------------------------------------------------*/
717 /* If jackdaw report frame to ethernet interface */
718 #if JACKDAW
719 // mac_logTXtoEthernet(&params, &result);
720 if (usbstick_mode.raw != 0) {
721 uint8_t sendlen;
723 /* Get the raw frame */
724 memcpy(&raw_buf[UIP_LLH_LEN], buffer, total_len);
725 sendlen = total_len;
727 /* Setup generic ethernet stuff */
728 ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A
730 // uint64_t tempaddr;
732 /* Check for broadcast message */
733 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
734 ETHBUF(raw_buf)->dest.addr[0] = 0x33;
735 ETHBUF(raw_buf)->dest.addr[1] = 0x33;
736 ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
737 ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
738 ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
739 ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
740 } else {
741 /* Otherwise we have a real address */
742 // tempaddr = p->dest_addr.addr64;
743 // byte_reverse((uint8_t *)&tempaddr, 8);
744 mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
745 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
748 // tempaddr = p->src_addr.addr64;
749 // memcpy(&tempaddr,packetbuf_addr(PACKETBUF_ADDR_SENDER),sizeof(tempaddr));
750 // byte_reverse((uint8_t *)&tempaddr, 8);
751 mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr);
753 // printf("Low2Eth: Sending 802.15.4 packet to ethernet\n\r");
755 sendlen += UIP_LLH_LEN;
756 usb_eth_send(raw_buf, sendlen, 0);
757 // rndis_stat.rxok++;
759 #endif /* JACKDAW */
761 RELEASE_LOCK();
762 return 0;
764 /*---------------------------------------------------------------------------*/
765 static int
766 rf230_send(const void *payload, unsigned short payload_len)
768 rf230_prepare(payload, payload_len);
769 #if JACKDAW
770 // In sniffer mode we don't ever send anything
771 if (usbstick_mode.sendToRf == 0) {
772 uip_len = 0;
773 return 0;
775 #endif /* JACKDAW */
776 return rf230_transmit(payload_len);
778 /*---------------------------------------------------------------------------*/
780 rf230_off(void)
782 /* Don't do anything if we are already turned off. */
783 if(receive_on == 0) {
784 return 1;
787 /* If we are called when the driver is locked, we indicate that the
788 radio should be turned off when the lock is unlocked. */
789 if(locked) {
790 lock_off = 1;
791 return 1;
794 /* If we are currently receiving a packet
795 we don't actually switch the radio off now, but signal that the
796 driver should switch off the radio once the packet has been
797 received and processed, by setting the 'lock_off' variable. */
798 if (!rf230_isidle()) {
799 // if (radio_get_trx_state()==BUSY_RX) {
800 lock_off = 1;
801 return 1;
804 off();
805 return 1;
807 /*---------------------------------------------------------------------------*/
809 rf230_on(void)
811 if(receive_on) {
812 return 1;
814 if(locked) {
815 lock_on = 1;
816 return 1;
819 on();
820 return 1;
822 /*---------------------------------------------------------------------------*/
824 rf230_get_channel(void)
826 //jackdaw reads zero channel, raven reads correct channel?
827 //return hal_subregister_read(SR_CHANNEL);
828 return channel;
830 /*---------------------------------------------------------------------------*/
831 void
832 rf230_set_channel(int c)
834 /* Wait for any transmission to end. */
835 // PRINTF("rf230: Set Channel %u\n",c);
836 rf230_waitidle();
837 channel=c;
838 hal_subregister_write(SR_CHANNEL, c);
840 /*---------------------------------------------------------------------------*/
841 void
842 rf230_set_pan_addr(unsigned pan,
843 unsigned addr,
844 const uint8_t *ieee_addr)
845 //rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr)
847 PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr);
849 uint8_t abyte;
850 abyte = pan & 0xFF;
851 hal_register_write(RG_PAN_ID_0,abyte);
852 abyte = (pan >> 8*1) & 0xFF;
853 hal_register_write(RG_PAN_ID_1, abyte);
855 abyte = addr & 0xFF;
856 hal_register_write(RG_SHORT_ADDR_0, abyte);
857 abyte = (addr >> 8*1) & 0xFF;
858 hal_register_write(RG_SHORT_ADDR_1, abyte);
860 if (ieee_addr != NULL) {
861 PRINTF("MAC=%x",*ieee_addr);
862 hal_register_write(RG_IEEE_ADDR_7, *ieee_addr++);
863 PRINTF(":%x",*ieee_addr);
864 hal_register_write(RG_IEEE_ADDR_6, *ieee_addr++);
865 PRINTF(":%x",*ieee_addr);
866 hal_register_write(RG_IEEE_ADDR_5, *ieee_addr++);
867 PRINTF(":%x",*ieee_addr);
868 hal_register_write(RG_IEEE_ADDR_4, *ieee_addr++);
869 PRINTF(":%x",*ieee_addr);
870 hal_register_write(RG_IEEE_ADDR_3, *ieee_addr++);
871 PRINTF(":%x",*ieee_addr);
872 hal_register_write(RG_IEEE_ADDR_2, *ieee_addr++);
873 PRINTF(":%x",*ieee_addr);
874 hal_register_write(RG_IEEE_ADDR_1, *ieee_addr++);
875 PRINTF(":%x",*ieee_addr);
876 hal_register_write(RG_IEEE_ADDR_0, *ieee_addr);
877 PRINTF("\n");
880 /*---------------------------------------------------------------------------*/
882 * Interrupt leaves frame intact in FIFO.
884 #if RF230_CONF_TIMESTAMPS
885 static volatile rtimer_clock_t interrupt_time;
886 static volatile int interrupt_time_set;
887 #endif /* RF230_CONF_TIMESTAMPS */
888 #if RF230_TIMETABLE_PROFILING
889 #define rf230_timetable_size 16
890 TIMETABLE(rf230_timetable);
891 TIMETABLE_AGGREGATE(aggregate_time, 10);
892 #endif /* RF230_TIMETABLE_PROFILING */
894 rf230_interrupt(void)
896 #if RF230_CONF_TIMESTAMPS
897 interrupt_time = timesynch_time();
898 interrupt_time_set = 1;
899 #endif /* RF230_CONF_TIMESTAMPS */
901 // CLEAR_FIFOP_INT();
902 process_poll(&rf230_process);
903 #if RF230_TIMETABLE_PROFILING
904 timetable_clear(&rf230_timetable);
905 TIMETABLE_TIMESTAMP(rf230_timetable, "interrupt");
906 #endif /* RF230_TIMETABLE_PROFILING */
908 pending = 1;
910 rf230_packets_seen++;
911 return 1;
913 /*---------------------------------------------------------------------------*/
914 /* Process to handle input packets
915 * Receive interrupts cause this process to be polled
916 * It calls the core MAC layer which calls rf230_read to get the packet
918 uint8_t rf230processflag; //for debugging process call problems
919 PROCESS_THREAD(rf230_process, ev, data)
921 int len;
922 PROCESS_BEGIN();
923 rf230processflag=99;
924 // PRINTF("rf230_process: started\n");
926 while(1) {
927 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
928 rf230processflag=42;
929 #if RF230_TIMETABLE_PROFILING
930 TIMETABLE_TIMESTAMP(rf230_timetable, "poll");
931 #endif /* RF230_TIMETABLE_PROFILING */
933 pending = 0;
935 // PRINTF("rf230_process: callback\n");
937 packetbuf_clear();
938 len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
939 rf230processflag=1;
940 if(len > 0) {
941 packetbuf_set_datalen(len);
942 rf230processflag=2;
943 NETSTACK_RDC.input();
944 #if RF230_TIMETABLE_PROFILING
945 TIMETABLE_TIMESTAMP(rf230_timetable, "end");
946 timetable_aggregate_compute_detailed(&aggregate_time,
947 &rf230_timetable);
948 timetable_clear(&rf230_timetable);
949 #endif /* RF230_TIMETABLE_PROFILING */
953 PROCESS_END();
955 /*---------------------------------------------------------------------------*/
956 static int
957 rf230_read(void *buf, unsigned short bufsize)
959 uint8_t len,*framep;
960 #if FOOTER_LEN
961 uint8_t footer[FOOTER_LEN];
962 #endif /* FOOTER_LEN */
963 #if RF230_CONF_CHECKSUM
964 uint16_t checksum;
965 #endif /* RF230_CONF_CHECKSUM */
966 #if RF230_CONF_TIMESTAMPS
967 struct timestamp t;
968 #endif /* RF230_CONF_TIMESTAMPS */
970 len=rxframe.length;
971 if (len==0) {
972 return 0;
975 PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe.length,rxframe.lqi,rxframe.crc);
976 #if DEBUG>1
977 for (len=0;len<rxframe.length;len++) PRINTF(" %x",rxframe.data[len]);PRINTF("\n");
978 #endif
980 #if RF230_CONF_TIMESTAMPS
981 if(interrupt_time_set) {
982 rf230_time_of_arrival = interrupt_time;
983 interrupt_time_set = 0;
984 } else {
985 rf230_time_of_arrival = 0;
987 rf230_time_of_departure = 0;
988 #endif /* RF230_CONF_TIMESTAMPS */
989 GET_LOCK();
990 rf230_packets_read++;
992 //if(len > RF230_MAX_PACKET_LEN) {
993 if(len > RF230_MAX_TX_FRAME_LENGTH) {
994 /* Oops, we must be out of sync. */
995 flushrx();
996 RIMESTATS_ADD(badsynch);
997 RELEASE_LOCK();
998 return 0;
1001 if(len <= AUX_LEN) {
1002 PRINTF("len <= AUX_LEN\n");
1003 flushrx();
1004 RIMESTATS_ADD(tooshort);
1005 RELEASE_LOCK();
1006 return 0;
1009 if(len - AUX_LEN > bufsize) {
1010 PRINTF("len - AUX_LEN > bufsize\n");
1011 flushrx();
1012 RIMESTATS_ADD(toolong);
1013 RELEASE_LOCK();
1014 return 0;
1016 /* Transfer the frame, stripping the footer */
1017 framep=&(rxframe.data[0]);
1018 memcpy(buf,framep,len-AUX_LEN);
1019 framep+=len-AUX_LEN;
1020 /* Clear the length field to allow buffering of the next packet */
1021 rxframe.length=0;
1023 #if RF230_CONF_CHECKSUM
1024 memcpy(&checksum,framep,CHECKSUM_LEN);
1025 framep+=CHECKSUM_LEN;
1026 #endif /* RF230_CONF_CHECKSUM */
1027 #if RF230_CONF_TIMESTAMPS
1028 memcpy(&t,framep,TIMESTAMP_LEN);
1029 framep+=TIMESTAMP_LEN;
1030 #endif /* RF230_CONF_TIMESTAMPS */
1031 #if FOOTER_LEN
1032 memcpy(footer,framep,FOOTER_LEN);
1033 #endif
1034 #if RF230_CONF_CHECKSUM
1035 if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
1036 PRINTF("checksum failed 0x%04x != 0x%04x\n",
1037 checksum, crc16_data(buf, len - AUX_LEN, 0));
1040 if(footer[1] & FOOTER1_CRC_OK &&
1041 checksum == crc16_data(buf, len - AUX_LEN, 0)) {
1042 #else
1043 if (1) {
1044 // if(footer[1] & FOOTER1_CRC_OK) {
1045 #endif /* RF230_CONF_CHECKSUM */
1046 // rf230_last_rssi = footer[0];
1047 rf230_last_rssi = hal_subregister_read(SR_RSSI);
1048 // rf230_last_correlation = footer[1] & FOOTER1_CORRELATION;
1049 rf230_last_correlation = rxframe.lqi;
1050 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf230_last_rssi);
1051 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf230_last_correlation);
1053 RIMESTATS_ADD(llrx);
1055 #if RF230_CONF_TIMESTAMPS
1056 rf230_time_of_departure =
1057 t.time +
1058 setup_time_for_transmission +
1059 (total_time_for_transmission * (len - 2)) / total_transmission_len;
1061 rf230_authority_level_of_sender = t.authority_level;
1063 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
1064 #endif /* RF230_CONF_TIMESTAMPS */
1066 } else {
1067 RIMESTATS_ADD(badcrc);
1068 len = AUX_LEN;
1071 /* Clean up in case of FIFO overflow! This happens for every full
1072 * length frame and is signaled by FIFOP = 1 and FIFO = 0.
1074 // if(FIFOP_IS_1 && !FIFO_IS_1) {
1075 /* printf("rf230_read: FIFOP_IS_1 1\n");*/
1076 // flushrx();
1077 // } else if(FIFOP_IS_1) {
1078 /* Another packet has been received and needs attention. */
1079 /* printf("attention\n");*/
1080 // process_poll(&rf230_process);
1081 // }
1083 RELEASE_LOCK();
1084 if(len < AUX_LEN) {
1085 return 0;
1087 #if JACKDAW
1088 /*------------------------------------------------------------*/
1089 /* If jackdaw report frame to ethernet interface */
1090 // mac_logRXtoEthernet(&params, &result);
1091 if (usbstick_mode.raw != 0) {
1092 uint8_t sendlen;
1094 /* Get the raw frame */
1095 memcpy(&raw_buf[UIP_LLH_LEN], buf, len);
1096 sendlen = len;
1098 /* Setup generic ethernet stuff */
1099 ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A
1101 // uint64_t tempaddr;
1103 /* Check for broadcast message */
1104 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
1105 ETHBUF(raw_buf)->dest.addr[0] = 0x33;
1106 ETHBUF(raw_buf)->dest.addr[1] = 0x33;
1107 ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
1108 ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
1109 ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
1110 ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
1111 } else {
1112 /* Otherwise we have a real address */
1113 // tempaddr = p->dest_addr.addr64;
1114 // byte_reverse((uint8_t *)&tempaddr, 8);
1115 mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
1116 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1119 // tempaddr = p->src_addr.addr64;
1120 // memcpy(&tempaddr,packetbuf_addr(PACKETBUF_ADDR_SENDER),sizeof(tempaddr));
1121 // byte_reverse((uint8_t *)&tempaddr, 8);
1122 mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr);
1124 // printf("Low2Eth: Sending 802.15.4 packet to ethernet\n\r");
1126 sendlen += UIP_LLH_LEN;
1127 usb_eth_send(raw_buf, sendlen, 0);
1129 #endif /* JACKDAW */
1131 return len - AUX_LEN;
1133 /*---------------------------------------------------------------------------*/
1134 void
1135 rf230_set_txpower(uint8_t power)
1137 GET_LOCK();
1138 set_txpower(power);
1139 RELEASE_LOCK();
1141 /*---------------------------------------------------------------------------*/
1143 rf230_get_txpower(void)
1145 if (radio_is_sleeping() ==true) {
1146 PRINTF("rf230_get_txpower:Sleeping");
1147 return 0;
1148 } else {
1149 return hal_subregister_read(SR_TX_PWR);
1152 /*---------------------------------------------------------------------------*/
1154 rf230_rssi(void)
1156 int rssi;
1157 int radio_was_off = 0;
1159 /*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/
1160 if(!receive_on) {
1161 radio_was_off = 1;
1162 rf230_on();
1165 rssi = (int)((signed char)hal_subregister_read(SR_RSSI));
1167 if(radio_was_off) {
1168 rf230_off();
1170 return rssi;
1172 /*---------------------------------------------------------------------------*/
1173 static int
1174 rf230_cca(void)
1176 int cca;
1177 int radio_was_off = 0;
1179 /* If the radio is locked by an underlying thread (because we are
1180 being invoked through an interrupt), we preted that the coast is
1181 clear (i.e., no packet is currently being transmitted by a
1182 neighbor). */
1183 if(locked) {
1184 return 1;
1187 if(!receive_on) {
1188 radio_was_off = 1;
1189 rf230_on();
1192 // cca = CCA_IS_1;
1193 cca=0;
1195 if(radio_was_off) {
1196 rf230_off();
1198 return cca;
1200 /*---------------------------------------------------------------------------*/
1202 rf230_receiving_packet(void)
1204 return (hal_subregister_read(SR_TRX_STATUS)==BUSY_RX);
1206 /*---------------------------------------------------------------------------*/
1207 static int
1208 pending_packet(void)
1210 return pending;
1212 /*---------------------------------------------------------------------------*/