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