Contiki 2.5
halbb.c
Go to the documentation of this file.
1 /* Copyright (c) 2009, Swedish Institute of Computer Science
2  * All rights reserved.
3  *
4  * Additional fixes for AVR contributed by:
5  *
6  * Colin O'Flynn coflynn@newae.com
7  * Eric Gnoske egnoske@gmail.com
8  * Blake Leverett bleverett@gmail.com
9  * Mike Vidales mavida404@gmail.com
10  * Kevin Brown kbrown3@uccs.edu
11  * Nate Bohlmann nate@elfwerks.com
12  * David Kopf dak664@embarqmail.com
13  *
14  * All rights reserved.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions are met:
18  *
19  * * Redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer.
21  * * Redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in
23  * the documentation and/or other materials provided with the
24  * distribution.
25  * * Neither the name of the copyright holders nor the names of
26  * contributors may be used to endorse or promote products derived
27  * from this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  * POSSIBILITY OF SUCH DAMAGE.
40  *
41  *
42 */
43 
44 /**
45  * \addtogroup wireless
46  * @{
47 */
48 
49 /**
50  * \defgroup hal RF230 hardware level drivers
51  * @{
52  */
53 
54 /**
55  * \file
56  * This file contains low-level radio driver code.
57  * This version is optimized for use with the "barebones" RF230bb driver,
58  * which communicates directly with the contiki core MAC layer.
59  * It is optimized for speed at the expense of generality.
60  */
61 #include "contiki-conf.h"
62 #if DEBUGFLOWSIZE
63 extern uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE];
64 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c
65 #else
66 #define DEBUGFLOW(c)
67 #endif
68 
69 
70 /*============================ INCLUDE =======================================*/
71 #include <stdlib.h>
72 
73 #include "hal.h"
74 
75 #if defined(__AVR_ATmega128RFA1__)
76 #include <avr/io.h>
78 #else
79 #include "at86rf230_registermap.h"
80 #endif
81 
82 /*============================ VARIABLES =====================================*/
83 /** \brief This is a file internal variable that contains the 16 MSB of the
84  * system time.
85  *
86  * The system time (32-bit) is the current time in microseconds. For the
87  * AVR microcontroller implementation this is solved by using a 16-bit
88  * timer (Timer1) with a clock frequency of 1MHz. The hal_system_time is
89  * incremented when the 16-bit timer overflows, representing the 16 MSB.
90  * The timer value it self (TCNT1) is then the 16 LSB.
91  *
92  * \see hal_get_system_time
93  */
94 static uint16_t hal_system_time = 0;
95 volatile extern signed char rf230_last_rssi;
96 
97 //static uint8_t volatile hal_bat_low_flag;
98 //static uint8_t volatile hal_pll_lock_flag;
99 
100 /*============================ CALLBACKS =====================================*/
101 
102 /** \brief This function is called when a rx_start interrupt is signaled.
103  *
104  * If this function pointer is set to something else than NULL, it will
105  * be called when a RX_START event is signaled. The function takes two
106  * parameters: timestamp in IEEE 802.15.4 symbols (16 us resolution) and
107  * frame length. The event handler will be called in the interrupt domain,
108  * so the function must be kept short and not be blocking! Otherwise the
109  * system performance will be greatly degraded.
110  *
111  * \see hal_set_rx_start_event_handler
112  */
113 //static hal_rx_start_isr_event_handler_t rx_start_callback;
114 
115 /** \brief This function is called when a trx_end interrupt is signaled.
116  *
117  * If this function pointer is set to something else than NULL, it will
118  * be called when a TRX_END event is signaled. The function takes one
119  * parameter: timestamp in IEEE 802.15.4 symbols (16 us resolution).
120  * The event handler will be called in the interrupt domain,
121  * so the function must not block!
122  *
123  * \see hal_set_trx_end_event_handler
124  */
125 //static hal_trx_end_isr_event_handler_t trx_end_callback;
126 
127 /*============================ IMPLEMENTATION ================================*/
128 #if defined(__AVR_ATmega128RFA1__)
129 //#include <avr/io.h>
130 #include <avr/interrupt.h>
131 /* AVR1281 with internal RF231 radio */
132 #define HAL_SPI_TRANSFER_OPEN()
133 //#define HAL_SPI_TRANSFER_WRITE(to_write) (SPDR = (to_write))
134 #define HAL_SPI_TRANSFER_WAIT()
135 #define HAL_SPI_TRANSFER_READ() (SPDR)
136 #define HAL_SPI_TRANSFER_CLOSE()
137 #if 0
138 #define HAL_SPI_TRANSFER(to_write) ( \
139  HAL_SPI_TRANSFER_WRITE(to_write), \
140  HAL_SPI_TRANSFER_WAIT(), \
141  HAL_SPI_TRANSFER_READ() )
142 #endif
143 #elif defined(__AVR__)
144 /*
145  * AVR with hardware SPI tranfers (TODO: move to hw spi hal for avr cpu)
146  */
147 #include <avr/io.h>
148 #include <avr/interrupt.h>
149 
150 #define HAL_SPI_TRANSFER_OPEN() { \
151  HAL_ENTER_CRITICAL_REGION(); \
152  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
153 #define HAL_SPI_TRANSFER_WRITE(to_write) (SPDR = (to_write))
154 #define HAL_SPI_TRANSFER_WAIT() ({while ((SPSR & (1 << SPIF)) == 0) {;}}) /* gcc extension, alternative inline function */
155 #define HAL_SPI_TRANSFER_READ() (SPDR)
156 #define HAL_SPI_TRANSFER_CLOSE() \
157  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
158  HAL_LEAVE_CRITICAL_REGION(); \
159  }
160 #define HAL_SPI_TRANSFER(to_write) ( \
161  HAL_SPI_TRANSFER_WRITE(to_write), \
162  HAL_SPI_TRANSFER_WAIT(), \
163  HAL_SPI_TRANSFER_READ() )
164 
165 #else /* __AVR__ */
166 /*
167  * Other SPI architecture (parts to core, parts to m16c6Xp
168  */
169 #include "contiki-mulle.h" // MULLE_ENTER_CRITICAL_REGION
170 
171 // Software SPI transfers
172 #define HAL_SPI_TRANSFER_OPEN() { uint8_t spiTemp; \
173  HAL_ENTER_CRITICAL_REGION(); \
174  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
175 #define HAL_SPI_TRANSFER_WRITE(to_write) (spiTemp = spiWrite(to_write))
176 #define HAL_SPI_TRANSFER_WAIT() ({0;})
177 #define HAL_SPI_TRANSFER_READ() (spiTemp)
178 #define HAL_SPI_TRANSFER_CLOSE() \
179  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
180  HAL_LEAVE_CRITICAL_REGION(); \
181  }
182 #define HAL_SPI_TRANSFER(to_write) (spiTemp = spiWrite(to_write))
183 
184 inline uint8_t spiWrite(uint8_t byte)
185 {
186  uint8_t data = 0;
187  uint8_t mask = 0x80;
188  do
189  {
190  if( (byte & mask) != 0 )
191  HAL_PORT_MOSI |= (1 << HAL_MOSI_PIN); //call MOSI.set();
192  else
193  HAL_PORT_MOSI &= ~(1 << HAL_MOSI_PIN); //call MOSI.clr();
194 
195  if( (HAL_PORT_MISO & (1 << HAL_MISO_PIN)) > 0) //call MISO.get() )
196  data |= mask;
197 
198  HAL_PORT_SCK &= ~(1 << HAL_SCK_PIN); //call SCLK.clr();
199  HAL_PORT_SCK |= (1 << HAL_SCK_PIN); //call SCLK.set();
200  } while( (mask >>= 1) != 0 );
201  return data;
202 }
203 
204 #endif /* !__AVR__ */
205 
206 /** \brief This function initializes the Hardware Abstraction Layer.
207  */
208 #if defined(__AVR_ATmega128RFA1__)
209 //#define HAL_RF230_ISR() ISR(RADIO_VECT)
210 #define HAL_TIME_ISR() ISR(TIMER1_OVF_vect)
211 #define HAL_TICK_UPCNT() (TCNT1)
212 void
213 hal_init(void)
214 {
215  /*Reset variables used in file.*/
216  hal_system_time = 0;
217  // TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */
218  // TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */
219  // HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */
220  hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */
221 }
222 
223 #elif defined(__AVR__)
224 #define HAL_RF230_ISR() ISR(RADIO_VECT)
225 #define HAL_TIME_ISR() ISR(TIMER1_OVF_vect)
226 #define HAL_TICK_UPCNT() (TCNT1)
227 void
228 hal_init(void)
229 {
230  /*Reset variables used in file.*/
231  hal_system_time = 0;
232 // hal_reset_flags();
233 
234  /*IO Specific Initialization - sleep and reset pins. */
235  DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */
236  DDR_RST |= (1 << RST); /* Enable RST as output. */
237 
238  /*SPI Specific Initialization.*/
239  /* Set SS, CLK and MOSI as output. */
240  HAL_DDR_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI);
241  HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */
242  /* Run SPI at max speed */
243  SPCR = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */
244  SPSR = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */
245 
246  /*TIMER1 Specific Initialization.*/
247  TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */
248  TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */
249  HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */
250  hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */
251 }
252 
253 #else /* __AVR__ */
254 
255 #define HAL_RF230_ISR() M16C_INTERRUPT(M16C_INT1)
256 #define HAL_TIME_ISR() M16C_INTERRUPT(M16C_TMRB4)
257 #define HAL_TICK_UPCNT() (0xFFFF-TB4) // TB4 counts down so we need to convert it to upcounting
258 
259 void
260 hal_init(void)
261 {
262  /*Reset variables used in file.*/
263  hal_system_time = 0;
264 // hal_reset_flags();
265 
266  /*IO Specific Initialization - sleep and reset pins. */
267  DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */
268  DDR_RST |= (1 << RST); /* Enable RST as output. */
269 
270  /*SPI Specific Initialization.*/
271  /* Set SS, CLK and MOSI as output. */
272  HAL_DDR_SS |= (1 << HAL_SS_PIN);
273  HAL_DDR_SCK |= (1 << HAL_SCK_PIN);
274  HAL_DDR_MOSI |= (1 << HAL_MOSI_PIN);
275  HAL_DDR_MISO &= ~(1 << HAL_MISO_PIN);
276 
277  /* Set SS */
278  HAL_PORT_SS |= (1 << HAL_SS_PIN); // HAL_SS_HIGH()
279  HAL_PORT_SCK &= ~(1 << HAL_SCK_PIN); // SCLK.clr()
280 
281  /*TIMER Specific Initialization.*/
282  // Init count source (Timer B3)
283  TB3 = ((16*10) - 1); // 16 us ticks
284  TB3MR.BYTE = 0b00000000; // Timer mode, F1
285  TBSR.BIT.TB3S = 1; // Start Timer B3
286 
287  TB4 = 0xFFFF; //
288  TB4MR.BYTE = 0b10000001; // Counter mode, count TB3
289  TBSR.BIT.TB4S = 1; // Start Timer B4
290  INT1IC.BIT.POL = 1; // Select rising edge
291  HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer overflow interrupt. */
292  hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */
293 }
294 #endif /* !__AVR__ */
295 
296 /*----------------------------------------------------------------------------*/
297 /** \brief This function reset the interrupt flags and interrupt event handlers
298  * (Callbacks) to their default value.
299  */
300 //void
301 //hal_reset_flags(void)
302 //{
303 // HAL_ENTER_CRITICAL_REGION();
304 
305  /* Reset Flags. */
306 // hal_bat_low_flag = 0;
307 // hal_pll_lock_flag = 0;
308 
309  /* Reset Associated Event Handlers. */
310 // rx_start_callback = NULL;
311 // trx_end_callback = NULL;
312 
313 // HAL_LEAVE_CRITICAL_REGION();
314 //}
315 
316 /*----------------------------------------------------------------------------*/
317 /** \brief This function returns the current value of the BAT_LOW flag.
318  *
319  * The BAT_LOW flag is incremented each time a BAT_LOW event is signaled from the
320  * radio transceiver. This way it is possible for the end user to poll the flag
321  * for new event occurances.
322  */
323 //uint8_t
324 //hal_get_bat_low_flag(void)
325 //{
326 // return hal_bat_low_flag;
327 //}
328 
329 /*----------------------------------------------------------------------------*/
330 /** \brief This function clears the BAT_LOW flag.
331  */
332 //void
333 //hal_clear_bat_low_flag(void)
334 //{
335 // HAL_ENTER_CRITICAL_REGION();
336 // hal_bat_low_flag = 0;
337 // HAL_LEAVE_CRITICAL_REGION();
338 //}
339 
340 /*----------------------------------------------------------------------------*/
341 /** \brief This function is used to set new TRX_END event handler, overriding
342  * old handler reference.
343  */
344 //hal_trx_end_isr_event_handler_t
345 //hal_get_trx_end_event_handler(void)
346 //{
347 // return trx_end_callback;
348 //}
349 
350 /*----------------------------------------------------------------------------*/
351 /** \brief This function is used to set new TRX_END event handler, overriding
352  * old handler reference.
353  */
354 //void
355 //hal_set_trx_end_event_handler(hal_trx_end_isr_event_handler_t trx_end_callback_handle)
356 //{
357 // HAL_ENTER_CRITICAL_REGION();
358 // trx_end_callback = trx_end_callback_handle;
359 // HAL_LEAVE_CRITICAL_REGION();
360 //}
361 
362 /*----------------------------------------------------------------------------*/
363 /** \brief Remove event handler reference.
364  */
365 //void
366 //hal_clear_trx_end_event_handler(void)
367 //{
368 // HAL_ENTER_CRITICAL_REGION();
369 // trx_end_callback = NULL;
370 // HAL_LEAVE_CRITICAL_REGION();
371 //}
372 
373 /*----------------------------------------------------------------------------*/
374 /** \brief This function returns the active RX_START event handler
375  *
376  * \return Current RX_START event handler registered.
377  */
378 //hal_rx_start_isr_event_handler_t
379 //hal_get_rx_start_event_handler(void)
380 //{
381 // return rx_start_callback;
382 //}
383 
384 /*----------------------------------------------------------------------------*/
385 /** \brief This function is used to set new RX_START event handler, overriding
386  * old handler reference.
387  */
388 //void
389 //hal_set_rx_start_event_handler(hal_rx_start_isr_event_handler_t rx_start_callback_handle)
390 //{
391 // HAL_ENTER_CRITICAL_REGION();
392 // rx_start_callback = rx_start_callback_handle;
393 // HAL_LEAVE_CRITICAL_REGION();
394 //}
395 
396 /*----------------------------------------------------------------------------*/
397 /** \brief Remove event handler reference.
398  */
399 //void
400 //hal_clear_rx_start_event_handler(void)
401 //{
402 // HAL_ENTER_CRITICAL_REGION();
403 // rx_start_callback = NULL;
404 // HAL_LEAVE_CRITICAL_REGION();
405 //}
406 
407 /*----------------------------------------------------------------------------*/
408 /** \brief This function returns the current value of the PLL_LOCK flag.
409  *
410  * The PLL_LOCK flag is incremented each time a PLL_LOCK event is signaled from the
411  * radio transceiver. This way it is possible for the end user to poll the flag
412  * for new event occurances.
413  */
414 //uint8_t
415 //hal_get_pll_lock_flag(void)
416 //{
417 // return hal_pll_lock_flag;
418 //}
419 
420 /*----------------------------------------------------------------------------*/
421 /** \brief This function clears the PLL_LOCK flag.
422  */
423 //void
424 //hal_clear_pll_lock_flag(void)
425 //{
426 // HAL_ENTER_CRITICAL_REGION();
427 // hal_pll_lock_flag = 0;
428 // HAL_LEAVE_CRITICAL_REGION();
429 //}
430 
431 #if defined(__AVR_ATmega128RFA1__)
432 /* Hack for internal radio registers. hal_register_read and hal_register_write are
433  handled through defines, but the preprocesser can't parse a macro containing
434  another #define with multiple arguments, e.g. using
435  #define hal_subregister_read( address, mask, position ) (address&mask)>>position
436  #define SR_TRX_STATUS TRX_STATUS, 0x1f, 0
437  the following only sees 1 argument to the macro
438  return hal_subregister_read(SR_TRX_STATUS);
439 
440  Possible fix is through two defines:
441  #define x_hal_subregister_read(x) hal_subregister_read(x);
442  #define hal_subregister_read( address, mask, position ) (address&mask)>>position
443  but the subregister defines in atmega128rfa1_registermap.h are currently set up without
444  the _SFR_MEM8 attribute, for use by hal_subregister_write.
445 
446  */
447 uint8_t
448 hal_subregister_read(uint16_t address, uint8_t mask, uint8_t position)
449 {
450  return (_SFR_MEM8(address)&mask)>>position;
451 }
452 void
453 hal_subregister_write(uint16_t address, uint8_t mask, uint8_t position,
454  uint8_t value)
455 {
456  cli();
457  uint8_t register_value = _SFR_MEM8(address);
458  register_value &= ~mask;
459  value <<= position;
460  value &= mask;
461  value |= register_value;
462  _SFR_MEM8(address) = value;
463  sei();
464 }
465 
466 #else /* defined(__AVR_ATmega128RFA1__) */
467 /*----------------------------------------------------------------------------*/
468 /** \brief This function reads data from one of the radio transceiver's registers.
469  *
470  * \param address Register address to read from. See datasheet for register
471  * map.
472  *
473  * \see Look at the at86rf230_registermap.h file for register address definitions.
474  *
475  * \returns The actual value of the read register.
476  */
477 uint8_t
478 hal_register_read(uint8_t address)
479 {
480  uint8_t register_value;
481  /* Add the register read command to the register address. */
482  /* Address should be < 0x2f so no need to mask */
483 // address &= 0x3f;
484  address |= 0x80;
485 
487 
488  /*Send Register address and read register content.*/
489  HAL_SPI_TRANSFER(address);
490  register_value = HAL_SPI_TRANSFER(0);
491 
492  HAL_SPI_TRANSFER_CLOSE();
493 
494  return register_value;
495 }
496 
497 /*----------------------------------------------------------------------------*/
498 /** \brief This function writes a new value to one of the radio transceiver's
499  * registers.
500  *
501  * \see Look at the at86rf230_registermap.h file for register address definitions.
502  *
503  * \param address Address of register to write.
504  * \param value Value to write.
505  */
506 void
507 hal_register_write(uint8_t address, uint8_t value)
508 {
509  /* Add the Register Write (short mode) command to the address. */
510  address = 0xc0 | address;
511 
513 
514  /*Send Register address and write register content.*/
515  HAL_SPI_TRANSFER(address);
516  HAL_SPI_TRANSFER(value);
517 
518  HAL_SPI_TRANSFER_CLOSE();
519 }
520 /*----------------------------------------------------------------------------*/
521 /** \brief This function reads the value of a specific subregister.
522  *
523  * \see Look at the at86rf230_registermap.h file for register and subregister
524  * definitions.
525  *
526  * \param address Main register's address.
527  * \param mask Bit mask of the subregister.
528  * \param position Bit position of the subregister
529  * \retval Value of the read subregister.
530  */
531 uint8_t
532 hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position)
533 {
534  /* Read current register value and mask out subregister. */
535  uint8_t register_value = hal_register_read(address);
536  register_value &= mask;
537  register_value >>= position; /* Align subregister value. */
538 
539  return register_value;
540 }
541 /*----------------------------------------------------------------------------*/
542 /** \brief This function writes a new value to one of the radio transceiver's
543  * subregisters.
544  *
545  * \see Look at the at86rf230_registermap.h file for register and subregister
546  * definitions.
547  *
548  * \param address Main register's address.
549  * \param mask Bit mask of the subregister.
550  * \param position Bit position of the subregister
551  * \param value Value to write into the subregister.
552  */
553 void
554 hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position,
555  uint8_t value)
556 {
557  /* Read current register value and mask area outside the subregister. */
558  volatile uint8_t register_value = hal_register_read(address);
559  register_value &= ~mask;
560 
561  /* Start preparing the new subregister value. shift in place and mask. */
562  value <<= position;
563  value &= mask;
564 
565  value |= register_value; /* Set the new subregister value. */
566 
567  /* Write the modified register value. */
568  hal_register_write(address, value);
569 }
570 #endif /* defined(__AVR_ATmega128RFA1__) */
571 /*----------------------------------------------------------------------------*/
572 /** \brief This function will upload a frame from the radio transceiver's frame
573  * buffer.
574  *
575  * If the frame currently available in the radio transceiver's frame buffer
576  * is out of the defined bounds. Then the frame length, lqi value and crc
577  * be set to zero. This is done to indicate an error.
578  * This version is optimized for use with contiki RF230BB driver.
579  * The callback routine and CRC are left out for speed in reading the rx buffer.
580  * Any delays here can lead to overwrites by the next packet!
581  *
582  * \param rx_frame Pointer to the data structure where the frame is stored.
583  * \param rx_callback Pointer to callback function for receiving one byte at a time.
584  */
585 void
586 //hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback)
588 {
589 #if defined(__AVR_ATmega128RFA1__)
590 
591  uint8_t frame_length,*rx_data,*rx_buffer;
592 
593  rx_data = (rx_frame->data);
594  frame_length = TST_RX_LENGTH; //frame length, not including lqi?
595  rx_frame->length = frame_length;
596  rx_buffer=(uint8_t *)0x180; //start of fifo in i/o space
597 
598  do{
599  *rx_data++ = _SFR_MEM8(rx_buffer++);
600 
601  } while (--frame_length > 0);
602 
603  /*Read LQI value for this frame.*/
604  rx_frame->lqi = *rx_buffer;
605  if (1) {
606 
607 #else /* defined(__AVR_ATmega128RFA1__) */
608 
609  uint8_t *rx_data;
610 
611  /* check that we have either valid frame pointer or callback pointer */
612 // if (!rx_frame && !rx_callback)
613 // return;
614 
616 
617  /*Send frame read (long mode) command.*/
618  HAL_SPI_TRANSFER(0x20);
619 
620  /*Read frame length. This includes the checksum. */
621  uint8_t frame_length = HAL_SPI_TRANSFER(0);
622 
623  /*Check for correct frame length.*/
624 // if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){
625  if (1) {
626 // uint16_t crc = 0;
627 // if (rx_frame){
628  rx_data = (rx_frame->data);
629  rx_frame->length = frame_length;
630 // } else {
631 // rx_callback(frame_length);
632 // }
633  /*Upload frame buffer to data pointer */
634 
635  HAL_SPI_TRANSFER_WRITE(0);
636  HAL_SPI_TRANSFER_WAIT();
637 
638  do{
639  *rx_data++ = HAL_SPI_TRANSFER_READ();
640  HAL_SPI_TRANSFER_WRITE(0);
641 
642 // if (rx_frame){
643 // *rx_data++ = tempData;
644 // } else {
645 // rx_callback(tempData);
646 // }
647 /* RF230 does crc in hardware, doing the checksum here ensures the rx buffer has not been overwritten by the next packet */
648 /* Since doing the checksum makes such overwrites more probable, we skip it and hope for the best. */
649 /* A full buffer should be read in 320us at 2x spi clocking, so with a low interrupt latency overwrites should not occur */
650 // crc = _crc_ccitt_update(crc, tempData);
651 
652  HAL_SPI_TRANSFER_WAIT();
653 
654  } while (--frame_length > 0);
655 
656  /*Read LQI value for this frame.*/
657 // if (rx_frame){
658  rx_frame->lqi = HAL_SPI_TRANSFER_READ();
659 // } else {
660 // rx_callback(HAL_SPI_TRANSFER_READ());
661 // }
662 
663 #endif /* defined(__AVR_ATmega128RFA1__) */
664 
665  /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/
666 // if (rx_frame){
667  rx_frame->crc = 1;
668 // } else {
669 // rx_callback(crc != 0);
670 // }
671  } else {
672 // if (rx_frame){
673  rx_frame->length = 0;
674  rx_frame->lqi = 0;
675  rx_frame->crc = false;
676 // }
677  }
678 
679  HAL_SPI_TRANSFER_CLOSE();
680 }
681 
682 /*----------------------------------------------------------------------------*/
683 /** \brief This function will download a frame to the radio transceiver's frame
684  * buffer.
685  *
686  * \param write_buffer Pointer to data that is to be written to frame buffer.
687  * \param length Length of data. The maximum length is 127 bytes.
688  */
689 void
690 hal_frame_write(uint8_t *write_buffer, uint8_t length)
691 {
692 #if defined(__AVR_ATmega128RFA1__)
693  uint8_t *tx_buffer;
694  tx_buffer=(uint8_t *)0x180; //start of fifo in i/o space
695  /* Write frame length, including the two byte checksum */
696  /* The top bit of the length field shall be set to 0 for IEEE 802.15.4 compliant frames */
697  /* It should already be clear, so bypassing the masking is sanity check of the uip stack */
698 // length &= 0x7f;
699  _SFR_MEM8(tx_buffer++) = length;
700 
701  /* Download to the Frame Buffer.
702  * When the FCS is autogenerated there is no need to transfer the last two bytes
703  * since they will be overwritten.
704  */
705 #if !RF230_CONF_CHECKSUM
706  length -= 2;
707 #endif
708  do _SFR_MEM8(tx_buffer++)= *write_buffer++; while (--length);
709 
710 #else /* defined(__AVR_ATmega128RFA1__) */
711  /* Optionally truncate length to maximum frame length.
712  * Not doing this is a fast way to know when the application needs fixing!
713  */
714 // length &= 0x7f;
715 
717 
718  /* Send Frame Transmit (long mode) command and frame length */
719  HAL_SPI_TRANSFER(0x60);
720  HAL_SPI_TRANSFER(length);
721 
722  /* Download to the Frame Buffer.
723  * When the FCS is autogenerated there is no need to transfer the last two bytes
724  * since they will be overwritten.
725  */
726 #if !RF230_CONF_CHECKSUM
727  length -= 2;
728 #endif
729  do HAL_SPI_TRANSFER(*write_buffer++); while (--length);
730 
731  HAL_SPI_TRANSFER_CLOSE();
732 #endif /* defined(__AVR_ATmega128RFA1__) */
733 }
734 
735 /*----------------------------------------------------------------------------*/
736 /** \brief Read SRAM
737  *
738  * This function reads from the SRAM of the radio transceiver.
739  *
740  * \param address Address in the TRX's SRAM where the read burst should start
741  * \param length Length of the read burst
742  * \param data Pointer to buffer where data is stored.
743  */
744 #if 0 //Uses 80 bytes (on Raven) omit unless needed
745 void
746 hal_sram_read(uint8_t address, uint8_t length, uint8_t *data)
747 {
749 
750  /*Send SRAM read command and address to start*/
751  HAL_SPI_TRANSFER(0x00);
752  HAL_SPI_TRANSFER(address);
753 
754  HAL_SPI_TRANSFER_WRITE(0);
755  HAL_SPI_TRANSFER_WAIT();
756 
757  /*Upload the chosen memory area.*/
758  do{
759  *data++ = HAL_SPI_TRANSFER_READ();
760  HAL_SPI_TRANSFER_WRITE(0);
761  HAL_SPI_TRANSFER_WAIT();
762  } while (--length > 0);
763 
764  HAL_SPI_TRANSFER_CLOSE();
765 }
766 #endif
767 /*----------------------------------------------------------------------------*/
768 /** \brief Write SRAM
769  *
770  * This function writes into the SRAM of the radio transceiver. It can reduce
771  * SPI transfers if only part of a frame is to be changed before retransmission.
772  *
773  * \param address Address in the TRX's SRAM where the write burst should start
774  * \param length Length of the write burst
775  * \param data Pointer to an array of bytes that should be written
776  */
777 //void
778 //hal_sram_write(uint8_t address, uint8_t length, uint8_t *data)
779 //{
780 // HAL_SPI_TRANSFER_OPEN();
781 
782  /*Send SRAM write command.*/
783 // HAL_SPI_TRANSFER(0x40);
784 
785  /*Send address where to start writing to.*/
786 // HAL_SPI_TRANSFER(address);
787 
788  /*Upload the chosen memory area.*/
789 // do{
790 // HAL_SPI_TRANSFER(*data++);
791 // } while (--length > 0);
792 
793 // HAL_SPI_TRANSFER_CLOSE();
794 
795 //}
796 
797 /*----------------------------------------------------------------------------*/
798 /* This #if compile switch is used to provide a "standard" function body for the */
799 /* doxygen documentation. */
800 #if defined(DOXYGEN)
801 /** \brief ISR for the radio IRQ line, triggered by the input capture.
802  * This is the interrupt service routine for timer1.ICIE1 input capture.
803  * It is triggered of a rising edge on the radio transceivers IRQ line.
804  */
805 void RADIO_VECT(void);
806 #else /* !DOXYGEN */
807 /* These link to the RF230BB driver in rf230.c */
808 void rf230_interrupt(void);
809 
810 extern hal_rx_frame_t rxframe[RF230_CONF_RX_BUFFERS];
811 extern uint8_t rxframe_head,rxframe_tail;
812 
813 /* rf230interruptflag can be printed in the main idle loop for debugging */
814 #define DEBUG 0
815 #if DEBUG
816 volatile char rf230interruptflag;
817 #define INTERRUPTDEBUG(arg) rf230interruptflag=arg
818 #else
819 #define INTERRUPTDEBUG(arg)
820 #endif
821 
822 #if defined(__AVR_ATmega128RFA1__)
823 /* The atmega128rfa1 has individual interrupts for the integrated radio'
824  * Whichever are enabled by the RF230 driver must be present even if not used!
825  */
826 /* Received packet interrupt */
827 ISR(TRX24_RX_END_vect)
828 {
829 /* Get the rssi from ED if extended mode */
830 #if RF230_CONF_AUTOACK
831  rf230_last_rssi=hal_register_read(RG_PHY_ED_LEVEL);
832 #endif
833 
834 /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */
835 /* Is a ram buffer available? */
836  if (rxframe[rxframe_tail].length) {DEBUGFLOW('0');} else /*DEBUGFLOW('1')*/;
837 
838 #ifdef RF230_MIN_RX_POWER
839 /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes */
840 /* This does not prevent an autoack. TODO:rfa1 radio can be set up to not autoack weak packets */
841  if (rf230_last_rssi >= RF230_MIN_RX_POWER) {
842 #else
843  if (1) {
844 #endif
845 // DEBUGFLOW('2');
846  hal_frame_read(&rxframe[rxframe_tail]);
847  rxframe_tail++;if (rxframe_tail >= RF230_CONF_RX_BUFFERS) rxframe_tail=0;
848  rf230_interrupt();
849  }
850 }
851 /* Preamble detected, starting frame reception */
852 ISR(TRX24_RX_START_vect)
853 {
854 // DEBUGFLOW('3');
855 /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */
856 #if !RF230_CONF_AUTOACK
857  rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI);
858 #endif
859 
860 }
861 
862 /* PLL has locked, either from a transition out of TRX_OFF or a channel change while on */
863 ISR(TRX24_PLL_LOCK_vect)
864 {
865 // DEBUGFLOW('4');
866 }
867 
868 /* PLL has unexpectedly unlocked */
869 ISR(TRX24_PLL_UNLOCK_vect)
870 {
871  DEBUGFLOW('5');
872 }
873 /* Flag is set by the following interrupts */
874 extern volatile uint8_t rf230_interruptwait;
875 
876 /* Wake has finished */
877 ISR(TRX24_AWAKE_vect)
878 {
879 // DEBUGFLOW('6');
880  rf230_interruptwait=0;
881 }
882 
883 /* Transmission has ended */
884 ISR(TRX24_TX_END_vect)
885 {
886 // DEBUGFLOW('7');
887  rf230_interruptwait=0;
888 }
889 
890 /* Frame address has matched ours */
891 extern volatile uint8_t rf230_pending;
892 ISR(TRX24_XAH_AMI_vect)
893 {
894 // DEBUGFLOW('8');
895  rf230_pending=1;
896 }
897 
898 /* CCAED measurement has completed */
899 ISR(TRX24_CCA_ED_DONE_vect)
900 {
901  DEBUGFLOW('4');
902  rf230_interruptwait=0;
903 }
904 
905 #else /* defined(__AVR_ATmega128RFA1__) */
906 /* Separate RF230 has a single radio interrupt and the source must be read from the IRQ_STATUS register */
908 {
909  /*The following code reads the current system time. This is done by first
910  reading the hal_system_time and then adding the 16 LSB directly from the
911  hardware counter.
912  */
913 // uint32_t isr_timestamp = hal_system_time;
914 // isr_timestamp <<= 16;
915 // isr_timestamp |= HAL_TICK_UPCNT(); // TODO: what if this wraps after reading hal_system_time?
916 
917  volatile uint8_t state;
918  uint8_t interrupt_source; /* used after HAL_SPI_TRANSFER_OPEN/CLOSE block */
919 
920  INTERRUPTDEBUG(1);
921 
922 
923  /* Using SPI bus from ISR is generally a bad idea... */
924  /* Note: all IRQ are not always automatically disabled when running in ISR */
926 
927  /*Read Interrupt source.*/
928  /*Send Register address and read register content.*/
929  HAL_SPI_TRANSFER_WRITE(0x80 | RG_IRQ_STATUS);
930 
931  /* This is the second part of the convertion of system time to a 16 us time
932  base. The division is moved here so we can spend less time waiting for SPI
933  data.
934  */
935 // isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */
936 // isr_timestamp &= HAL_SYMBOL_MASK;
937 
938  HAL_SPI_TRANSFER_WAIT(); /* AFTER possible interleaved processing */
939 
940 #if 0 //dak
941  interrupt_source = HAL_SPI_TRANSFER_READ(); /* The interrupt variable is used as a dummy read. */
942 
943  interrupt_source = HAL_SPI_TRANSFER(interrupt_source);
944 #else
945  interrupt_source = HAL_SPI_TRANSFER(0);
946 #endif
947  HAL_SPI_TRANSFER_CLOSE();
948 
949  /*Handle the incomming interrupt. Prioritized.*/
950  if ((interrupt_source & HAL_RX_START_MASK)){
951  INTERRUPTDEBUG(10);
952  /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */
953 #if !RF230_CONF_AUTOACK
954 #if 0 // 3-clock shift and add is faster on machines with no hardware multiply
955  // While the compiler should use similar code for multiply by 3 there may be a bug with -Os in avr-gcc that calls the general subroutine
956  rf230_last_rssi = hal_subregister_read(SR_RSSI);
957  rf230_last_rssi = (rf230_last_rssi <<1) + rf230_last_rssi;
958 #else // Faster with 1-clock multiply. Raven and Jackdaw have 2-clock multiply so same speed while saving 2 bytes of program memory
959  rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI);
960 #endif
961 #endif
962 // if(rx_start_callback != NULL){
963 // /* Read Frame length and call rx_start callback. */
964 // HAL_SPI_TRANSFER_OPEN();
965 // uint8_t frame_length = HAL_SPI_TRANSFER(0x20);
966 // frame_length = HAL_SPI_TRANSFER(frame_length);
967 
968 // HAL_SPI_TRANSFER_CLOSE();
969 
970 // rx_start_callback(isr_timestamp, frame_length);
971 // }
972  } else if (interrupt_source & HAL_TRX_END_MASK){
973  INTERRUPTDEBUG(11);
974 // if(trx_end_callback != NULL){
975 // trx_end_callback(isr_timestamp);
976 // }
977 
979  if((state == BUSY_RX_AACK) || (state == RX_ON) || (state == BUSY_RX) || (state == RX_AACK_ON)){
980  /* Received packet interrupt */
981  /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */
982 // if (rxframe.length) break; //toss packet if last one not processed yet
983  if (rxframe[rxframe_tail].length) INTERRUPTDEBUG(42); else INTERRUPTDEBUG(12);
984 
985 #ifdef RF230_MIN_RX_POWER
986  /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes.*/
987  /* Save the rssi for printing in the main loop */
988 #if RF230_CONF_AUTOACK
989  // rf230_last_rssi=hal_subregister_read(SR_ED_LEVEL);
990  rf230_last_rssi=hal_register_read(RG_PHY_ED_LEVEL);
991 #endif
992  if (rf230_last_rssi >= RF230_MIN_RX_POWER) {
993 #endif
994  hal_frame_read(&rxframe[rxframe_tail]);
995  rxframe_tail++;if (rxframe_tail >= RF230_CONF_RX_BUFFERS) rxframe_tail=0;
996  rf230_interrupt();
997 // trx_end_callback(isr_timestamp);
998 #ifdef RF230_MIN_RX_POWER
999  }
1000 #endif
1001 
1002  }
1003 
1004  } else if (interrupt_source & HAL_TRX_UR_MASK){
1005  INTERRUPTDEBUG(13);
1006  ;
1007  } else if (interrupt_source & HAL_PLL_UNLOCK_MASK){
1008  INTERRUPTDEBUG(14);
1009  ;
1010  } else if (interrupt_source & HAL_PLL_LOCK_MASK){
1011  INTERRUPTDEBUG(15);
1012 // hal_pll_lock_flag++;
1013  ;
1014  } else if (interrupt_source & HAL_BAT_LOW_MASK){
1015  /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */
1016  /* will continously be asserted while the supply voltage is less than the */
1017  /* user-defined voltage threshold. */
1018  uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK);
1019  trx_isr_mask &= ~HAL_BAT_LOW_MASK;
1020  hal_register_write(RG_IRQ_MASK, trx_isr_mask);
1021 // hal_bat_low_flag++; /* Increment BAT_LOW flag. */
1022  INTERRUPTDEBUG(16);
1023  ;
1024  } else {
1025  INTERRUPTDEBUG(99);
1026  ;
1027  }
1028 }
1029 #endif /* defined(__AVR_ATmega128RFA1__) */
1030 # endif /* defined(DOXYGEN) */
1031 
1032 /*----------------------------------------------------------------------------*/
1033 /* This #if compile switch is used to provide a "standard" function body for the */
1034 /* doxygen documentation. */
1035 #if defined(DOXYGEN)
1036 /** \brief Timer Overflow ISR
1037  * This is the interrupt service routine for timer1 overflow.
1038  */
1039 void TIMER1_OVF_vect(void);
1040 #else /* !DOXYGEN */
1041 HAL_TIME_ISR()
1042 {
1043  hal_system_time++;
1044 }
1045 #endif
1046 
1047 /** @} */
1048 /** @} */
1049 
1050 /*EOF*/