Contiki 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__)
78 #elif defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__)
80 #else
81 #include "at86rf230_registermap.h"
82 #endif
83 
84 /*============================ VARIABLES =====================================*/
85 
86 volatile extern signed char rf230_last_rssi;
87 
88 /*============================ CALLBACKS =====================================*/
89 
90 
91 /*============================ IMPLEMENTATION ================================*/
92 #if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__)
93 
94 /* AVR1281 with internal RF231 radio */
95 #include <avr/interrupt.h>
96 
97 #elif defined(__AVR__)
98 /*
99  * AVR with hardware SPI tranfers (TODO: move to hw spi hal for avr cpu)
100  */
101 #include <avr/io.h>
102 #include <avr/interrupt.h>
103 
104 #define HAL_SPI_TRANSFER_OPEN() { \
105  HAL_ENTER_CRITICAL_REGION(); \
106  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
107 #define HAL_SPI_TRANSFER_WRITE(to_write) (SPDR = (to_write))
108 #define HAL_SPI_TRANSFER_WAIT() ({while ((SPSR & (1 << SPIF)) == 0) {;}}) /* gcc extension, alternative inline function */
109 #define HAL_SPI_TRANSFER_READ() (SPDR)
110 #define HAL_SPI_TRANSFER_CLOSE() \
111  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
112  HAL_LEAVE_CRITICAL_REGION(); \
113  }
114 #define HAL_SPI_TRANSFER(to_write) ( \
115  HAL_SPI_TRANSFER_WRITE(to_write), \
116  HAL_SPI_TRANSFER_WAIT(), \
117  HAL_SPI_TRANSFER_READ() )
118 
119 #else /* __AVR__ */
120 /*
121  * Other SPI architecture (parts to core, parts to m16c6Xp
122  */
123 #include "contiki-mulle.h" // MULLE_ENTER_CRITICAL_REGION
124 
125 // Software SPI transfers
126 #define HAL_SPI_TRANSFER_OPEN() { uint8_t spiTemp; \
127  HAL_ENTER_CRITICAL_REGION(); \
128  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
129 #define HAL_SPI_TRANSFER_WRITE(to_write) (spiTemp = spiWrite(to_write))
130 #define HAL_SPI_TRANSFER_WAIT() ({0;})
131 #define HAL_SPI_TRANSFER_READ() (spiTemp)
132 #define HAL_SPI_TRANSFER_CLOSE() \
133  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
134  HAL_LEAVE_CRITICAL_REGION(); \
135  }
136 #define HAL_SPI_TRANSFER(to_write) (spiTemp = spiWrite(to_write))
137 
138 inline uint8_t spiWrite(uint8_t byte)
139 {
140  uint8_t data = 0;
141  uint8_t mask = 0x80;
142  do
143  {
144  if( (byte & mask) != 0 )
145  HAL_PORT_MOSI |= (1 << HAL_MOSI_PIN); //call MOSI.set();
146  else
147  HAL_PORT_MOSI &= ~(1 << HAL_MOSI_PIN); //call MOSI.clr();
148 
149  if( (HAL_PORT_MISO & (1 << HAL_MISO_PIN)) > 0) //call MISO.get() )
150  data |= mask;
151 
152  HAL_PORT_SCK &= ~(1 << HAL_SCK_PIN); //call SCLK.clr();
153  HAL_PORT_SCK |= (1 << HAL_SCK_PIN); //call SCLK.set();
154  } while( (mask >>= 1) != 0 );
155  return data;
156 }
157 
158 #endif /* !__AVR__ */
159 
160 /** \brief This function initializes the Hardware Abstraction Layer.
161  */
162 #if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__)
163 void
164 hal_init(void)
165 {
166  /*Reset variables used in file.*/
167  /* (none at the moment) */
168 }
169 
170 #elif defined(__AVR__)
171 
172 #define HAL_RF230_ISR() ISR(RADIO_VECT)
173 
174 void
175 hal_init(void)
176 {
177  /*Reset variables used in file.*/
178 
179  /*IO Specific Initialization - sleep and reset pins. */
180  /* Set pins low before they are initialized as output? Does not seem to matter */
181 // hal_set_rst_low();
182 // hal_set_slptr_low();
183  DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */
184  DDR_RST |= (1 << RST); /* Enable RST as output. */
185 
186  /*SPI Specific Initialization.*/
187  /* Set SS, CLK and MOSI as output. */
188  /* To avoid a SPI glitch, the port register shall be set before the DDR register */
189  HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */
190  HAL_DDR_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI);
191  HAL_DDR_SPI &=~ (1<< HAL_DD_MISO); /* MISO input */
192 
193  /* Run SPI at max speed */
194  SPCR = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */
195  SPSR = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */
196 
197  /* Enable interrupts from the radio transceiver. */
199 }
200 
201 #else /* __AVR__ */
202 
203 #define HAL_RF230_ISR() M16C_INTERRUPT(M16C_INT1)
204 #define HAL_TIME_ISR() M16C_INTERRUPT(M16C_TMRB4)
205 #define HAL_TICK_UPCNT() (0xFFFF-TB4) // TB4 counts down so we need to convert it to upcounting
206 
207 void
208 hal_init(void)
209 {
210  /*Reset variables used in file.*/
211 
212  /*IO Specific Initialization - sleep and reset pins. */
213  DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */
214  DDR_RST |= (1 << RST); /* Enable RST as output. */
215 
216  /*SPI Specific Initialization.*/
217  /* Set SS, CLK and MOSI as output. */
218  HAL_DDR_SS |= (1 << HAL_SS_PIN);
219  HAL_DDR_SCK |= (1 << HAL_SCK_PIN);
220  HAL_DDR_MOSI |= (1 << HAL_MOSI_PIN);
221  HAL_DDR_MISO &= ~(1 << HAL_MISO_PIN);
222 
223  /* Set SS */
224  HAL_PORT_SS |= (1 << HAL_SS_PIN); // HAL_SS_HIGH()
225  HAL_PORT_SCK &= ~(1 << HAL_SCK_PIN); // SCLK.clr()
226 
227  /*TIMER Specific Initialization.*/
228  // Init count source (Timer B3)
229  TB3 = ((16*10) - 1); // 16 us ticks
230  TB3MR.BYTE = 0b00000000; // Timer mode, F1
231  TBSR.BIT.TB3S = 1; // Start Timer B3
232 
233  TB4 = 0xFFFF; //
234  TB4MR.BYTE = 0b10000001; // Counter mode, count TB3
235  TBSR.BIT.TB4S = 1; // Start Timer B4
236  INT1IC.BIT.POL = 1; // Select rising edge
237  HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer overflow interrupt. */
238 
239  /* Enable interrupts from the radio transceiver. */
241 }
242 #endif /* !__AVR__ */
243 
244 #if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__)
245 /* Hack for internal radio registers. hal_register_read and hal_register_write are
246  handled through defines, but the preprocesser can't parse a macro containing
247  another #define with multiple arguments, e.g. using
248  #define hal_subregister_read( address, mask, position ) (address&mask)>>position
249  #define SR_TRX_STATUS TRX_STATUS, 0x1f, 0
250  the following only sees 1 argument to the macro
251  return hal_subregister_read(SR_TRX_STATUS);
252 
253  Possible fix is through two defines:
254  #define x_hal_subregister_read(x) hal_subregister_read(x);
255  #define hal_subregister_read( address, mask, position ) (address&mask)>>position
256  but the subregister defines in atmega128rfa1_registermap.h are currently set up without
257  the _SFR_MEM8 attribute, for use by hal_subregister_write.
258 
259  */
260 uint8_t
261 hal_subregister_read(uint16_t address, uint8_t mask, uint8_t position)
262 {
263  return (_SFR_MEM8(address)&mask)>>position;
264 }
265 void
266 hal_subregister_write(uint16_t address, uint8_t mask, uint8_t position,
267  uint8_t value)
268 {
270 
271  uint8_t register_value = _SFR_MEM8(address);
272  register_value &= ~mask;
273  value <<= position;
274  value &= mask;
275  value |= register_value;
276  _SFR_MEM8(address) = value;
277 
279 }
280 
281 #else /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */
282 /*----------------------------------------------------------------------------*/
283 /** \brief This function reads data from one of the radio transceiver's registers.
284  *
285  * \param address Register address to read from. See datasheet for register
286  * map.
287  *
288  * \see Look at the at86rf230_registermap.h file for register address definitions.
289  *
290  * \returns The actual value of the read register.
291  */
292 uint8_t
293 hal_register_read(uint8_t address)
294 {
295  uint8_t register_value;
296  /* Add the register read command to the register address. */
297  /* Address should be < 0x2f so no need to mask */
298 // address &= 0x3f;
299  address |= 0x80;
300 
301  HAL_SPI_TRANSFER_OPEN();
302 
303  /*Send Register address and read register content.*/
304  HAL_SPI_TRANSFER(address);
305  register_value = HAL_SPI_TRANSFER(0);
306 
307  HAL_SPI_TRANSFER_CLOSE();
308 
309  return register_value;
310 }
311 
312 /*----------------------------------------------------------------------------*/
313 /** \brief This function writes a new value to one of the radio transceiver's
314  * registers.
315  *
316  * \see Look at the at86rf230_registermap.h file for register address definitions.
317  *
318  * \param address Address of register to write.
319  * \param value Value to write.
320  */
321 void
322 hal_register_write(uint8_t address, uint8_t value)
323 {
324  /* Add the Register Write (short mode) command to the address. */
325  address = 0xc0 | address;
326 
327  HAL_SPI_TRANSFER_OPEN();
328 
329  /*Send Register address and write register content.*/
330  HAL_SPI_TRANSFER(address);
331  HAL_SPI_TRANSFER(value);
332 
333  HAL_SPI_TRANSFER_CLOSE();
334 }
335 /*----------------------------------------------------------------------------*/
336 /** \brief This function reads the value of a specific subregister.
337  *
338  * \see Look at the at86rf230_registermap.h file for register and subregister
339  * definitions.
340  *
341  * \param address Main register's address.
342  * \param mask Bit mask of the subregister.
343  * \param position Bit position of the subregister
344  * \retval Value of the read subregister.
345  */
346 uint8_t
347 hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position)
348 {
349  /* Read current register value and mask out subregister. */
350  uint8_t register_value = hal_register_read(address);
351  register_value &= mask;
352  register_value >>= position; /* Align subregister value. */
353 
354  return register_value;
355 }
356 /*----------------------------------------------------------------------------*/
357 /** \brief This function writes a new value to one of the radio transceiver's
358  * subregisters.
359  *
360  * \see Look at the at86rf230_registermap.h file for register and subregister
361  * definitions.
362  *
363  * \param address Main register's address.
364  * \param mask Bit mask of the subregister.
365  * \param position Bit position of the subregister
366  * \param value Value to write into the subregister.
367  */
368 void
369 hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position,
370  uint8_t value)
371 {
372  /* Read current register value and mask area outside the subregister. */
373  volatile uint8_t register_value = hal_register_read(address);
374  register_value &= ~mask;
375 
376  /* Start preparing the new subregister value. shift in place and mask. */
377  value <<= position;
378  value &= mask;
379 
380  value |= register_value; /* Set the new subregister value. */
381 
382  /* Write the modified register value. */
383  hal_register_write(address, value);
384 }
385 #endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */
386 /*----------------------------------------------------------------------------*/
387 /** \brief Transfer a frame from the radio transceiver to a RAM buffer
388  *
389  * This version is optimized for use with contiki RF230BB driver.
390  * The callback routine and CRC are left out for speed in reading the rx buffer.
391  * Any delays here can lead to overwrites by the next packet!
392  *
393  * If the frame length is out of the defined bounds, the length, lqi and crc
394  * are set to zero.
395  *
396  * \param rx_frame Pointer to the data structure where the frame is stored.
397  */
398 void
400 {
401 #if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__)
402 
403  uint8_t frame_length,*rx_data,*rx_buffer;
404 
405  /* Get length from the TXT_RX_LENGTH register, not including LQI
406  * Bypassing the length check can result in overrun if buffer is < 256 bytes.
407  */
408  frame_length = TST_RX_LENGTH;
409  if ((frame_length < HAL_MIN_FRAME_LENGTH) || (frame_length > HAL_MAX_FRAME_LENGTH)) {
410  /* Length test failed */
411  rx_frame->length = 0;
412  rx_frame->lqi = 0;
413  rx_frame->crc = false;
414  return;
415  }
416  rx_frame->length = frame_length;
417 
418  /* Start of buffer in I/O space, pointer to RAM buffer */
419  rx_buffer=(uint8_t *)0x180;
420  rx_data = (rx_frame->data);
421 
422  do{
423  *rx_data++ = _SFR_MEM8(rx_buffer++);
424  } while (--frame_length > 0);
425 
426  /*Read LQI value for this frame.*/
427  rx_frame->lqi = *rx_buffer;
428 
429  /* If crc was calculated set crc field in hal_rx_frame_t accordingly.
430  * Else show the crc has passed the hardware check.
431  */
432  rx_frame->crc = true;
433 
434 #else /* */
435 
436  uint8_t frame_length, *rx_data;
437 
438  /*Send frame read (long mode) command.*/
439  HAL_SPI_TRANSFER_OPEN();
440  HAL_SPI_TRANSFER(0x20);
441 
442  /*Read frame length. This includes the checksum. */
443  frame_length = HAL_SPI_TRANSFER(0);
444 
445  /*Check for correct frame length. Bypassing this test can result in a buffer overrun! */
446  if ((frame_length < HAL_MIN_FRAME_LENGTH) || (frame_length > HAL_MAX_FRAME_LENGTH)) {
447  /* Length test failed */
448  rx_frame->length = 0;
449  rx_frame->lqi = 0;
450  rx_frame->crc = false;
451  }
452  else {
453  rx_data = (rx_frame->data);
454  rx_frame->length = frame_length;
455 
456  /*Transfer frame buffer to RAM buffer */
457 
458  HAL_SPI_TRANSFER_WRITE(0);
459  HAL_SPI_TRANSFER_WAIT();
460  do{
461  *rx_data++ = HAL_SPI_TRANSFER_READ();
462  HAL_SPI_TRANSFER_WRITE(0);
463 
464  /* CRC was checked in hardware, but redoing the checksum here ensures the rx buffer
465  * is not being overwritten by the next packet. Since that lengthy computation makes
466  * such overwrites more likely, we skip it and hope for the best.
467  * Without the check a full buffer is read in 320us at 2x spi clocking.
468  * The 802.15.4 standard requires 640us after a greater than 18 byte frame.
469  * With a low interrupt latency overwrites should never occur.
470  */
471  // crc = _crc_ccitt_update(crc, tempData);
472 
473  HAL_SPI_TRANSFER_WAIT();
474 
475  } while (--frame_length > 0);
476 
477 
478  /*Read LQI value for this frame.*/
479  rx_frame->lqi = HAL_SPI_TRANSFER_READ();
480 
481  /* If crc was calculated set crc field in hal_rx_frame_t accordingly.
482  * Else show the crc has passed the hardware check.
483  */
484  rx_frame->crc = true;
485  }
486 
487  HAL_SPI_TRANSFER_CLOSE();
488 
489 #endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */
490 }
491 
492 /*----------------------------------------------------------------------------*/
493 /** \brief This function will download a frame to the radio transceiver's frame
494  * buffer.
495  *
496  * \param write_buffer Pointer to data that is to be written to frame buffer.
497  * \param length Length of data. The maximum length is 127 bytes.
498  */
499 void
500 hal_frame_write(uint8_t *write_buffer, uint8_t length)
501 {
502 #if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__)
503  uint8_t *tx_buffer;
504  tx_buffer=(uint8_t *)0x180; //start of fifo in i/o space
505  /* Write frame length, including the two byte checksum */
506  /* The top bit of the length field shall be set to 0 for IEEE 802.15.4 compliant frames */
507  /* It should already be clear, so bypassing the masking is sanity check of the uip stack */
508 // length &= 0x7f;
509  _SFR_MEM8(tx_buffer++) = length;
510 
511  /* Download to the Frame Buffer.
512  * When the FCS is autogenerated there is no need to transfer the last two bytes
513  * since they will be overwritten.
514  */
515 #if !RF230_CONF_CHECKSUM
516  length -= 2;
517 #endif
518  do _SFR_MEM8(tx_buffer++)= *write_buffer++; while (--length);
519 
520 #else /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */
521  /* Optionally truncate length to maximum frame length.
522  * Not doing this is a fast way to know when the application needs fixing!
523  */
524 // length &= 0x7f;
525 
526  HAL_SPI_TRANSFER_OPEN();
527 
528  /* Send Frame Transmit (long mode) command and frame length */
529  HAL_SPI_TRANSFER(0x60);
530  HAL_SPI_TRANSFER(length);
531 
532  /* Download to the Frame Buffer.
533  * When the FCS is autogenerated there is no need to transfer the last two bytes
534  * since they will be overwritten.
535  */
536 #if !RF230_CONF_CHECKSUM
537  length -= 2;
538 #endif
539  do HAL_SPI_TRANSFER(*write_buffer++); while (--length);
540 
541  HAL_SPI_TRANSFER_CLOSE();
542 #endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */
543 }
544 
545 /*----------------------------------------------------------------------------*/
546 #if 0 //Uses 80 bytes (on Raven) omit unless needed
547 /** \brief Read SRAM
548  *
549  * This function reads from the SRAM of the radio transceiver.
550  *
551  * \param address Address in the TRX's SRAM where the read burst should start
552  * \param length Length of the read burst
553  * \param data Pointer to buffer where data is stored.
554  */
555 void
556 hal_sram_read(uint8_t address, uint8_t length, uint8_t *data)
557 {
558  HAL_SPI_TRANSFER_OPEN();
559 
560  /*Send SRAM read command and address to start*/
561  HAL_SPI_TRANSFER(0x00);
562  HAL_SPI_TRANSFER(address);
563 
564  HAL_SPI_TRANSFER_WRITE(0);
565  HAL_SPI_TRANSFER_WAIT();
566 
567  /*Upload the chosen memory area.*/
568  do{
569  *data++ = HAL_SPI_TRANSFER_READ();
570  HAL_SPI_TRANSFER_WRITE(0);
571  HAL_SPI_TRANSFER_WAIT();
572  } while (--length > 0);
573 
574  HAL_SPI_TRANSFER_CLOSE();
575 }
576 #endif
577 /*----------------------------------------------------------------------------*/
578 #if 0 //omit unless needed
579 /** \brief Write SRAM
580  *
581  * This function writes into the SRAM of the radio transceiver. It can reduce
582  * SPI transfers if only part of a frame is to be changed before retransmission.
583  *
584  * \param address Address in the TRX's SRAM where the write burst should start
585  * \param length Length of the write burst
586  * \param data Pointer to an array of bytes that should be written
587  */
588 void
589 hal_sram_write(uint8_t address, uint8_t length, uint8_t *data)
590 {
591  HAL_SPI_TRANSFER_OPEN();
592 
593  /*Send SRAM write command.*/
594  HAL_SPI_TRANSFER(0x40);
595 
596  /*Send address where to start writing to.*/
597  HAL_SPI_TRANSFER(address);
598 
599  /*Upload the chosen memory area.*/
600  do{
601  HAL_SPI_TRANSFER(*data++);
602  } while (--length > 0);
603 
604  HAL_SPI_TRANSFER_CLOSE();
605 
606 }
607 #endif
608 
609 /*----------------------------------------------------------------------------*/
610 /* This #if compile switch is used to provide a "standard" function body for the */
611 /* doxygen documentation. */
612 #if defined(DOXYGEN)
613 /** \brief ISR for the radio IRQ line, triggered by the input capture.
614  * This is the interrupt service routine for timer1.ICIE1 input capture.
615  * It is triggered of a rising edge on the radio transceivers IRQ line.
616  */
617 void RADIO_VECT(void);
618 #else /* !DOXYGEN */
619 /* These link to the RF230BB driver in rf230.c */
620 void rf230_interrupt(void);
621 
622 extern hal_rx_frame_t rxframe[RF230_CONF_RX_BUFFERS];
623 extern uint8_t rxframe_head,rxframe_tail;
624 
625 /* rf230interruptflag can be printed in the main idle loop for debugging */
626 #define DEBUG 0
627 #if DEBUG
628 volatile char rf230interruptflag;
629 #define INTERRUPTDEBUG(arg) rf230interruptflag=arg
630 #else
631 #define INTERRUPTDEBUG(arg)
632 #endif
633 
634 #if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__)
635 /* The atmega128rfa1 has individual interrupts for the integrated radio'
636  * Whichever are enabled by the RF230 driver must be present even if not used!
637  */
638 /* Received packet interrupt */
639 ISR(TRX24_RX_END_vect)
640 {
641 /* Get the rssi from ED if extended mode */
642 #if RF230_CONF_AUTOACK
643  rf230_last_rssi=hal_register_read(RG_PHY_ED_LEVEL);
644 #endif
645 
646 /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */
647 /* Is a ram buffer available? */
648  if (rxframe[rxframe_tail].length) {DEBUGFLOW('0');} else /*DEBUGFLOW('1')*/;
649 
650 #ifdef RF230_MIN_RX_POWER
651 /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes */
652 /* This does not prevent an autoack. TODO:rfa1 radio can be set up to not autoack weak packets */
653  if (rf230_last_rssi >= RF230_MIN_RX_POWER) {
654 #else
655  if (1) {
656 #endif
657 // DEBUGFLOW('2');
658  hal_frame_read(&rxframe[rxframe_tail]);
659  rxframe_tail++;if (rxframe_tail >= RF230_CONF_RX_BUFFERS) rxframe_tail=0;
660  rf230_interrupt();
661  }
662 }
663 /* Preamble detected, starting frame reception */
664 ISR(TRX24_RX_START_vect)
665 {
666 // DEBUGFLOW('3');
667 /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */
668 #if !RF230_CONF_AUTOACK
669  rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI);
670 #endif
671 
672 }
673 
674 /* PLL has locked, either from a transition out of TRX_OFF or a channel change while on */
675 ISR(TRX24_PLL_LOCK_vect)
676 {
677 // DEBUGFLOW('4');
678 }
679 
680 /* PLL has unexpectedly unlocked */
681 ISR(TRX24_PLL_UNLOCK_vect)
682 {
683  DEBUGFLOW('5');
684 }
685 /* Flag is set by the following interrupts */
686 extern volatile uint8_t rf230_wakewait, rf230_txendwait,rf230_ccawait;
687 
688 /* Wake has finished */
689 ISR(TRX24_AWAKE_vect)
690 {
691 // DEBUGFLOW('6');
692  rf230_wakewait=0;
693 }
694 
695 /* Transmission has ended */
696 ISR(TRX24_TX_END_vect)
697 {
698 // DEBUGFLOW('7');
699  rf230_txendwait=0;
700 }
701 
702 /* Frame address has matched ours */
703 ISR(TRX24_XAH_AMI_vect)
704 {
705 // DEBUGFLOW('8');
706 }
707 
708 /* CCAED measurement has completed */
709 ISR(TRX24_CCA_ED_DONE_vect)
710 {
711  DEBUGFLOW('4');
712  rf230_ccawait=0;
713 }
714 
715 #else /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */
716 /* Separate RF230 has a single radio interrupt and the source must be read from the IRQ_STATUS register */
718 {
719  volatile uint8_t state;
720  uint8_t interrupt_source; /* used after HAL_SPI_TRANSFER_OPEN/CLOSE block */
721 
722  INTERRUPTDEBUG(1);
723 
724 
725  /* Using SPI bus from ISR is generally a bad idea... */
726  /* Note: all IRQ are not always automatically disabled when running in ISR */
727  HAL_SPI_TRANSFER_OPEN();
728 
729  /*Read Interrupt source.*/
730  /*Send Register address and read register content.*/
731  HAL_SPI_TRANSFER_WRITE(0x80 | RG_IRQ_STATUS);
732 
733  HAL_SPI_TRANSFER_WAIT(); /* AFTER possible interleaved processing */
734 
735  interrupt_source = HAL_SPI_TRANSFER(0);
736 
737  HAL_SPI_TRANSFER_CLOSE();
738 
739  /*Handle the incomming interrupt. Prioritized.*/
740  if ((interrupt_source & HAL_RX_START_MASK)){
741  INTERRUPTDEBUG(10);
742  /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */
743 #if !RF230_CONF_AUTOACK
744 #if 0 // 3-clock shift and add is faster on machines with no hardware multiply
745  // With -Os avr-gcc saves a byte by using the general routine for multiply by 3
746  rf230_last_rssi = hal_subregister_read(SR_RSSI);
747  rf230_last_rssi = (rf230_last_rssi <<1) + rf230_last_rssi;
748 #else // Faster with 1-clock multiply. Raven and Jackdaw have 2-clock multiply so same speed while saving 2 bytes of program memory
749  rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI);
750 #endif
751 #endif
752 
753  }
754  if (interrupt_source & HAL_TRX_END_MASK){
755  INTERRUPTDEBUG(11);
756 
758  if((state == BUSY_RX_AACK) || (state == RX_ON) || (state == BUSY_RX) || (state == RX_AACK_ON)){
759  /* Received packet interrupt */
760  /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */
761  if (rxframe[rxframe_tail].length) INTERRUPTDEBUG(42); else INTERRUPTDEBUG(12);
762 
763 #ifdef RF230_MIN_RX_POWER
764  /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes.*/
765  /* Save the rssi for printing in the main loop */
766 #if RF230_CONF_AUTOACK
767  //rf230_last_rssi=hal_subregister_read(SR_ED_LEVEL);
768  rf230_last_rssi=hal_register_read(RG_PHY_ED_LEVEL);
769 #endif
770  if (rf230_last_rssi >= RF230_MIN_RX_POWER) {
771 #endif
772  hal_frame_read(&rxframe[rxframe_tail]);
773  rxframe_tail++;if (rxframe_tail >= RF230_CONF_RX_BUFFERS) rxframe_tail=0;
774  rf230_interrupt();
775 #ifdef RF230_MIN_RX_POWER
776  }
777 #endif
778 
779  }
780 
781  }
782  if (interrupt_source & HAL_TRX_UR_MASK){
783  INTERRUPTDEBUG(13);
784  ;
785  }
786  if (interrupt_source & HAL_PLL_UNLOCK_MASK){
787  INTERRUPTDEBUG(14);
788  ;
789  }
790  if (interrupt_source & HAL_PLL_LOCK_MASK){
791  INTERRUPTDEBUG(15);
792  ;
793  }
794  if (interrupt_source & HAL_BAT_LOW_MASK){
795  /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */
796  /* will continously be asserted while the supply voltage is less than the */
797  /* user-defined voltage threshold. */
798  uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK);
799  trx_isr_mask &= ~HAL_BAT_LOW_MASK;
800  hal_register_write(RG_IRQ_MASK, trx_isr_mask);
801  INTERRUPTDEBUG(16);
802  ;
803  }
804 }
805 #endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */
806 # endif /* defined(DOXYGEN) */
807 
808 /** @} */
809 /** @} */
810 
811 /*EOF*/
void hal_init(void)
This function initializes the Hardware Abstraction Layer.
Definition: hal.c:133
void hal_register_write(uint8_t address, uint8_t value)
This function writes a new value to one of the radio transceiver's registers.
Definition: hal.c:342
#define HAL_PORT_SPI
The SPI module is located on PORTB.
Definition: hal.h:259
#define RG_IRQ_MASK
Offset for register IRQ_MASK.
#define HAL_RF230_ISR()
This function initializes the Hardware Abstraction Layer.
Definition: halbb.c:203
#define HAL_DD_SS
Data Direction bit for SS.
Definition: hal.h:261
This file contains RF230-formatted register definitions for the atmega128rfa1.
#define HAL_SS_PIN
The slave select pin.
Definition: hal.h:258
#define HAL_SCK_PIN
Data bit for SCK.
Definition: hal.h:266
uint8_t hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position)
This function reads the value of a specific subregister.
Definition: hal.c:377
void RADIO_VECT(void)
ISR for the radio IRQ line, triggered by the input capture.
#define SR_RSSI
Access parameters for sub-register RSSI in register RG_PHY_RSSI.
#define HAL_LEAVE_CRITICAL_REGION()
This macro must always be used in conjunction with HAL_ENTER_CRITICAL_REGION so that interrupts are e...
Definition: hal.h:328
#define hal_enable_trx_interrupt()
Enable the interrupt from the radio transceiver.
Definition: hal.h:322
#define BUSY_RX
Constant BUSY_RX for sub-register SR_TRX_STATUS.
#define HAL_DDR_MOSI
Data Direction Register for MISO GPIO pin.
Definition: hal.h:277
#define HAL_PLL_UNLOCK_MASK
Mask for the PLL_UNLOCK interrupt.
Definition: hal.h:339
uint8_t length
Length of frame.
Definition: hal.h:352
#define HAL_DD_SCK
Data Direction bit for SCK.
Definition: hal.h:262
#define DDR_SLP_TR
Data Direction Register that corresponds to the port where SLP_TR is connected.
Definition: hal.h:245
#define HAL_PORT_MISO
The SPI module uses GPIO might be split on different ports.
Definition: hal.h:273
void hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback)
This function will upload a frame from the radio transceiver's frame buffer.
Definition: hal.c:429
#define HAL_PLL_LOCK_MASK
Mask for the PLL_LOCK interrupt.
Definition: hal.h:340
void hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position, uint8_t value)
This function writes a new value to one of the radio transceiver's subregisters.
Definition: hal.c:400
#define HAL_TRX_UR_MASK
Mask for the TRX_UR interrupt.
Definition: hal.h:336
#define HAL_MAX_FRAME_LENGTH
A frame should no more than 127 bytes.
Definition: hal.h:343
#define SR_TRX_STATUS
Access parameters for sub-register TRX_STATUS in register RG_TRX_STATUS.
#define HAL_PORT_MOSI
The SPI module uses GPIO might be split on different ports.
Definition: hal.h:272
This file contains low-level radio driver code.
uint8_t hal_register_read(uint8_t address)
This function reads data from one of the radio transceiver's registers.
Definition: hal.c:304
bool crc
Flag - did CRC pass for received frame?
Definition: hal.h:355
#define DDR_RST
Data Direction Register that corresponds to the port where RST is.
Definition: hal.h:252
#define HAL_MIN_FRAME_LENGTH
A frame should be at least 3 bytes.
Definition: hal.h:342
#define RG_IRQ_STATUS
Offset for register IRQ_STATUS.
#define RST
Pin number that corresponds to the RST pin.
Definition: hal.h:251
#define HAL_DD_MOSI
Data Direction bit for MOSI.
Definition: hal.h:263
#define BUSY_RX_AACK
Constant BUSY_RX_AACK for sub-register SR_TRX_STATUS.
uint8_t lqi
LQI value for received frame.
Definition: hal.h:354
void hal_sram_write(uint8_t address, uint8_t length, uint8_t *data)
Write SRAM.
Definition: hal.c:597
#define HAL_DDR_SS
Data Direction Register for MISO GPIO pin.
Definition: hal.h:275
#define HAL_ENTER_CRITICAL_REGION()
This macro will protect the following code from interrupts.
Definition: hal.h:324
#define HAL_DDR_SPI
Data Direction Register for PORTB.
Definition: hal.h:260
#define HAL_DD_MISO
Data Direction bit for MISO.
Definition: hal.h:264
#define RX_AACK_ON
Constant RX_AACK_ON for sub-register SR_TRX_STATUS.
#define RX_ON
Constant RX_ON for sub-register SR_TRX_STATUS.
#define HAL_BAT_LOW_MASK
Mask for the BAT_LOW interrupt.
Definition: hal.h:335
#define SLP_TR
Pin number that corresponds to the SLP_TR pin.
Definition: hal.h:244
void hal_frame_write(uint8_t *write_buffer, uint8_t length)
This function will download a frame to the radio transceiver's frame buffer.
Definition: hal.c:516
#define HAL_RX_START_MASK
Mask for the RX_START interrupt.
Definition: hal.h:338
This file contains RF230-formatted register definitions for the atmega128rfa1.
#define HAL_DDR_SCK
Data Direction Register for MISO GPIO pin.
Definition: hal.h:276
void hal_sram_read(uint8_t address, uint8_t length, uint8_t *data)
Read SRAM.
Definition: hal.c:558
uint8_t data[HAL_MAX_FRAME_LENGTH]
Actual frame data.
Definition: hal.h:353
#define RG_PHY_ED_LEVEL
Offset for register PHY_ED_LEVEL.
#define HAL_TRX_END_MASK
Mask for the TRX_END interrupt.
Definition: hal.h:337
This file contains the register definitions for the AT86RF230.
#define HAL_DDR_MISO
Data Direction Register for MOSI GPIO pin.
Definition: hal.h:278
This struct defines the rx data container.
Definition: hal.h:351