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  *
5  * Colin O'Flynn coflynn@newae.com
6  * Eric Gnoske egnoske@gmail.com
7  * Blake Leverett bleverett@gmail.com
8  * Mike Vidales mavida404@gmail.com
9  * Kevin Brown kbrown3@uccs.edu
10  * Nate Bohlmann nate@elfwerks.com
11  * David Kopf dak664@embarqmail.com
12  *
13  * All rights reserved.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions are met:
17  *
18  * * Redistributions of source code must retain the above copyright
19  * notice, this list of conditions and the following disclaimer.
20  * * Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in
22  * the documentation and/or other materials provided with the
23  * distribution.
24  * * Neither the name of the copyright holders nor the names of
25  * contributors may be used to endorse or promote products derived
26  * from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  *
41  */
42 
43 /**
44  * \addtogroup wireless
45  * @{
46  */
47 
48 /**
49  * \defgroup hal RF230 hardware level drivers
50  * @{
51  */
52 
53 /**
54  * \file
55  * This file contains low-level radio driver code.
56  * This version is optimized for use with the "barebones" RF230bb driver,
57  * which communicates directly with the contiki core MAC layer.
58  * It is optimized for speed at the expense of generality.
59  */
60 /* #include "contiki-conf.h" */
61 
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 /*============================ INCLUDE =======================================*/
70 #include <stdlib.h>
71 
72 #include "hal.h"
73 
74 #include "at86rf230_registermap.h"
75 
76 #include "stdio.h"
77 
78 /*============================ MACROS ========================================*/
79 
80 /*
81  * Macros defined for the radio transceiver's access modes.
82  *
83  * These functions are implemented as macros since they are used very often.
84  */
85 #define HAL_DUMMY_READ (0x00) /**< Dummy value for the SPI. */
86 
87 #define HAL_TRX_CMD_RW (0xC0) /**< Register Write (short mode). */
88 #define HAL_TRX_CMD_RR (0x80) /**< Register Read (short mode). */
89 #define HAL_TRX_CMD_FW (0x60) /**< Frame Transmit Mode (long mode). */
90 #define HAL_TRX_CMD_FR (0x20) /**< Frame Receive Mode (long mode). */
91 #define HAL_TRX_CMD_SW (0x40) /**< SRAM Write. */
92 #define HAL_TRX_CMD_SR (0x00) /**< SRAM Read. */
93 #define HAL_TRX_CMD_RADDRM (0x7F) /**< Register Address Mask. */
94 
95 #define HAL_CALCULATED_CRC_OK (0) /**< CRC calculated over the frame including the CRC field should be 0. */
96 
97 /*============================ VARIABLES =====================================*/
98 /** \brief This is a file internal variable that contains the 16 MSB of the
99  * system time.
100  *
101  * The system time (32-bit) is the current time in microseconds. For the
102  * AVR microcontroller implementation this is solved by using a 16-bit
103  * timer (Timer1) with a clock frequency of 1MHz. The hal_system_time is
104  * incremented when the 16-bit timer overflows, representing the 16 MSB.
105  * The timer value it self (TCNT1) is then the 16 LSB.
106  *
107  * \see hal_get_system_time
108  */
109 volatile extern signed char rf230_last_rssi;
110 
111 /*============================ CALLBACKS =====================================*/
112 
113 /** \brief This function is called when a rx_start interrupt is signaled.
114  *
115  * If this function pointer is set to something else than NULL, it will
116  * be called when a RX_START event is signaled. The function takes two
117  * parameters: timestamp in IEEE 802.15.4 symbols (16 us resolution) and
118  * frame length. The event handler will be called in the interrupt domain,
119  * so the function must be kept short and not be blocking! Otherwise the
120  * system performance will be greatly degraded.
121  *
122  * \see hal_set_rx_start_event_handler
123  */
124 /* static hal_rx_start_isr_event_handler_t rx_start_callback; */
125 
126 /** \brief This function is called when a trx_end interrupt is signaled.
127  *
128  * If this function pointer is set to something else than NULL, it will
129  * be called when a TRX_END event is signaled. The function takes one
130  * parameter: timestamp in IEEE 802.15.4 symbols (16 us resolution).
131  * The event handler will be called in the interrupt domain,
132  * so the function must not block!
133  *
134  * \see hal_set_trx_end_event_handler
135  */
136 /* static hal_trx_end_isr_event_handler_t trx_end_callback; */
137 
138 /*============================ IMPLEMENTATION ================================*/
139 #if 0 /* defined(__AVR_ATmega128RFA1__) */
140 /* #include <avr/io.h> */
141 #include <avr/interrupt.h>
142 /* AVR1281 with internal RF231 radio */
143 #define HAL_SPI_TRANSFER_OPEN()
144 /* #define HAL_SPI_TRANSFER_WRITE(to_write) (SPDR = (to_write)) */
145 #define HAL_SPI_TRANSFER_WAIT()
146 #define HAL_SPI_TRANSFER_READ() (SPDR)
147 #define HAL_SPI_TRANSFER_CLOSE()
148 #if 0
149 #define HAL_SPI_TRANSFER(to_write) ( \
150  HAL_SPI_TRANSFER_WRITE(to_write), \
151  HAL_SPI_TRANSFER_WAIT(), \
152  HAL_SPI_TRANSFER_READ())
153 #endif
154 #elif defined(__AVR__)
155 /*
156  * AVR with hardware SPI tranfers (TODO: move to hw spi hal for avr cpu)
157  */
158 #include <avr/io.h>
159 #include <avr/interrupt.h>
160 
161 #define HAL_SPI_TRANSFER_OPEN() { \
162  HAL_ENTER_CRITICAL_REGION(); \
163  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
164 #define HAL_SPI_TRANSFER_WRITE(to_write) (SPDR = (to_write))
165 #define HAL_SPI_TRANSFER_WAIT() ({ while((SPSR & (1 << SPIF)) == 0) {; } }) /* gcc extension, alternative inline function */
166 #define HAL_SPI_TRANSFER_READ() (SPDR)
167 #define HAL_SPI_TRANSFER_CLOSE() \
168  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
169  HAL_LEAVE_CRITICAL_REGION(); \
170  }
171 #define HAL_SPI_TRANSFER(to_write) ( \
172  HAL_SPI_TRANSFER_WRITE(to_write), \
173  HAL_SPI_TRANSFER_WAIT(), \
174  HAL_SPI_TRANSFER_READ())
175 #endif
176 #if 0
177 /*
178  * Other SPI architecture (parts to core, parts to m16c6Xp
179  */
180 #include "contiki-mulle.h" /* MULLE_ENTER_CRITICAL_REGION */
181 
182 /* Software SPI transfers */
183 #define HAL_SPI_TRANSFER_OPEN() { uint8_t spiTemp; \
184  HAL_ENTER_CRITICAL_REGION(); \
185  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
186 #define HAL_SPI_TRANSFER_WRITE(to_write) (spiTemp = spiWrite(to_write))
187 #define HAL_SPI_TRANSFER_WAIT() ({ 0; })
188 #define HAL_SPI_TRANSFER_READ() (spiTemp)
189 #define HAL_SPI_TRANSFER_CLOSE() \
190  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
191  HAL_LEAVE_CRITICAL_REGION(); \
192  }
193 #define HAL_SPI_TRANSFER(to_write) (spiTemp = spiWrite(to_write))
194 
195 inline uint8_t
196 spiWrite(uint8_t byte)
197 {
198  uint8_t data = 0;
199  uint8_t mask = 0x80;
200  do {
201  if((byte & mask) != 0) {
202  HAL_PORT_MOSI |= (1 << HAL_MOSI_PIN); /* call MOSI.set(); */
203  } else {
204  HAL_PORT_MOSI &= ~(1 << HAL_MOSI_PIN); /* call MOSI.clr(); */
205  }
206  if((HAL_PORT_MISO & (1 << HAL_MISO_PIN)) > 0) { /* call MISO.get() ) */
207  data |= mask;
208  }
209 
210  HAL_PORT_SCK &= ~(1 << HAL_SCK_PIN); /* call SCLK.clr(); */
211  HAL_PORT_SCK |= (1 << HAL_SCK_PIN); /* call SCLK.set(); */
212  } while((mask >>= 1) != 0);
213  return data;
214 }
215 #endif /* !__AVR__ */
216 
217 /* #include "MK60DZ10.h" */
218 
219 /* K60: TODO */
220 #define HAL_SPI_TRANSFER_OPEN() HAL_ENTER_CRITICAL_REGION();
221 /* #define HAL_SPI_TRANSFER_WRITE(data) */
222 /* #define HAL_SPI_TRANSFER_WAIT() */
223 /* #define HAL_SPI_TRANSFER_READ() */
224 #define HAL_SPI_TRANSFER_CLOSE() HAL_LEAVE_CRITICAL_REGION();
225 #include "K60.h"
226 #include "llwu.h"
227 
228 static inline void
229 hal_spi_send(uint8_t data, int cont)
230 {
231  /* Send data */
232  if(cont) {
233  SPI0->PUSHR = SPI_PUSHR_PCS((1 << HAL_SS_PIN)) | SPI_PUSHR_CONT_MASK | data;
234  } else {
235  SPI0->PUSHR = SPI_PUSHR_PCS((1 << HAL_SS_PIN)) | data;
236  }
237  SPI0->SR |= SPI_SR_TCF_MASK;
238  while(!(SPI0->SR & SPI_SR_TCF_MASK)) ;
239 
240  /* Dummy read */
241  SPI0->SR |= SPI_SR_TCF_MASK;
242  data = (0xFF & SPI0->POPR);
243 }
244 
245 static inline uint8_t
246 hal_spi_receive(int cont)
247 {
248  /* Dummy write */
249  if(cont) {
250  SPI0->PUSHR = SPI_PUSHR_PCS((1 << HAL_SS_PIN)) | SPI_PUSHR_CONT_MASK;
251  } else {
252  SPI0->PUSHR = SPI_PUSHR_PCS((1 << HAL_SS_PIN));
253  }
254  SPI0->SR |= SPI_SR_TCF_MASK;
255  while(!(SPI0->SR & SPI_SR_TCF_MASK)) ;
256 
257  /* Read data */
258  SPI0->SR |= SPI_SR_TCF_MASK;
259  return 0xFF & SPI0->POPR;
260 }
261 #ifdef MULLE_IRQ_PATCH
262 #define HAL_RF230_ISR() void __attribute__((interrupt)) _isr_portc_pin_detect(void)
263 #else
264 #define HAL_RF230_ISR() void __attribute__((interrupt)) _isr_portb_pin_detect(void)
265 #endif
266 
267 /** \brief This function initializes the Hardware Abstraction Layer.
268  */
269 void
270 hal_init(void)
271 {
272  /*** IO Specific Initialization.****/
273 
274  /* Enable PORTC clock gate */
275  SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
276  SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK;
277 
278  PORTE->PCR[6] |= 0x0100; /* Sleep */
279  PORTD->PCR[7] |= 0x0100; /* Vp */
280 
281  PTE->PDDR |= 0x0040; /* Setup PTE6 (Sleep) as output */
282  PTD->PDDR |= 0x0080; /* Setup PTD7 (Vp) as output */
283 
284 #ifdef MULLE_IRQ_PATCH
285  SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
286  PORTC->PCR[1] |= 0x00090100;
287  llwu_enable_wakeup_source(LLWU_WAKEUP_SOURCE_P6_RISING);
288 #else
289  SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
290  PORTB->PCR[9] |= 0x00090100; /* Set PTB9 (IRQ) as GPIO with active high interrupt */
291 #endif
292  /* Enable power switch to radio */
294 
295  /*** SPI Specific Initialization.****/
296 
297  /* Mux SPI0 on port B */
298  PORTD->PCR[4] |= 0x0200; /* SPI0_PCS1 */
299  PORTD->PCR[2] |= 0x0200; /* SPI0_MOSI */
300  PORTD->PCR[1] |= 0x0200; /* SPI0_SCLK */
301  PORTD->PCR[3] |= 0x0200; /* SPI0_MISO */
302 
303  /* Enable clock gate for SPI0 module */
304  SIM->SCGC6 |= SIM_SCGC6_SPI0_MASK;
305 
306  /* Configure SPI1 */
307  SPI0->MCR = 0x803F3000;
308  SPI0->CTAR[0] = 0x38002224; /* TODO: Should be able to speed up */
309 
310  /*** Enable interrupts from the radio transceiver. ***/
312 }
313 /*----------------------------------------------------------------------------*/
314 /** \brief This function reads data from one of the radio transceiver's registers.
315  *
316  * \param address Register address to read from. See datasheet for register
317  * map.
318  *
319  * \see Look at the at86rf230_registermap.h file for register address definitions.
320  *
321  * \returns The actual value of the read register.
322  */
323 uint8_t
324 hal_register_read(uint8_t address)
325 {
326  uint8_t register_value = 0;
327 
328  /* Add the register read command to the register address. */
329  address &= HAL_TRX_CMD_RADDRM;
330  address |= HAL_TRX_CMD_RR;
331 
333 
334  /*** Send Register address and read register content. ***/
335  hal_spi_send(address, true); /* Write address */
336  register_value = hal_spi_receive(false); /* Read register */
337 
339 
340  return register_value;
341 }
342 /*----------------------------------------------------------------------------*/
343 /** \brief This function writes a new value to one of the radio transceiver's
344  * registers.
345  *
346  * \see Look at the at86rf230_registermap.h file for register address definitions.
347  *
348  * \param address Address of register to write.
349  * \param value Value to write.
350  */
351 void
352 hal_register_write(uint8_t address, uint8_t value) /* K60: OK, tested */
353 {
354  /* Add the Register Write command to the address. */
355  address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address);
356 
358 
359  /*** Send Register address and write register content. ***/
360  hal_spi_send(address, true); /* Write address */
361  hal_spi_send(value, false); /* Write data */
362 
364 }
365 /*----------------------------------------------------------------------------*/
366 /** \brief This function reads the value of a specific subregister.
367  *
368  * \see Look at the at86rf230_registermap.h file for register and subregister
369  * definitions.
370  *
371  * \param address Main register's address.
372  * \param mask Bit mask of the subregister.
373  * \param position Bit position of the subregister
374  * \retval Value of the read subregister.
375  */
376 uint8_t
377 hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position)
378 {
379  /* Read current register value and mask out subregister. */
380  uint8_t register_value = hal_register_read(address);
381  register_value &= mask;
382  register_value >>= position; /* Align subregister value. */
383 
384  return register_value;
385 }
386 /*----------------------------------------------------------------------------*/
387 /** \brief This function writes a new value to one of the radio transceiver's
388  * subregisters.
389  *
390  * \see Look at the at86rf230_registermap.h file for register and subregister
391  * definitions.
392  *
393  * \param address Main register's address.
394  * \param mask Bit mask of the subregister.
395  * \param position Bit position of the subregister
396  * \param value Value to write into the subregister.
397  */
398 void
399 hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position,
400  uint8_t value)
401 {
402  /* Read current register value and mask area outside the subregister. */
403  uint8_t register_value = hal_register_read(address);
404  register_value &= ~mask;
405 
406  /* Start preparing the new subregister value. shift in place and mask. */
407  value <<= position;
408  value &= mask;
409 
410  value |= register_value; /* Set the new subregister value. */
411 
412  /* Write the modified register value. */
413  hal_register_write(address, value);
414 }
415 /*----------------------------------------------------------------------------*/
416 /** \brief Transfer a frame from the radio transceiver to a RAM buffer
417  *
418  * This version is optimized for use with contiki RF230BB driver.
419  * The callback routine and CRC are left out for speed in reading the rx buffer.
420  * Any delays here can lead to overwrites by the next packet!
421  *
422  * If the frame length is out of the defined bounds, the length, lqi and crc
423  * are set to zero.
424  *
425  * \param rx_frame Pointer to the data structure where the frame is stored.
426  */
427 void
428 hal_frame_read(hal_rx_frame_t *rx_frame) /* TODO: Make sure this is working */
429 {
430  uint8_t *rx_data;
431  uint8_t frame_length;
432 
434 
435  /*Send frame read (long mode) command.*/
436  hal_spi_send(HAL_TRX_CMD_FR, true);
437 
438  /*Read frame length. This includes the checksum. */
439  frame_length = hal_spi_receive(true);
440 
441  /*Check for correct frame length. Bypassing this test can result in a buffer overrun! */
442  if((frame_length < HAL_MIN_FRAME_LENGTH) || (frame_length > HAL_MAX_FRAME_LENGTH)) {
443  /* Length test failed */
444  rx_frame->length = 0;
445  rx_frame->lqi = 0;
446  rx_frame->crc = false;
447  } else {
448  rx_data = (rx_frame->data);
449  rx_frame->length = frame_length;
450  /*Transfer frame buffer to RAM buffer */
451 
452  do {
453  *rx_data++ = hal_spi_receive(true);
454  } while(--frame_length > 0);
455 
456  /*Read LQI value for this frame.*/
457  rx_frame->lqi = *rx_data++ = hal_spi_receive(false);
458 
459  /* If crc was calculated set crc field in hal_rx_frame_t accordingly.
460  * Else show the crc has passed the hardware check.
461  */
462  rx_frame->crc = true;
463  }
464 
466 #if 0
467  uint8_t frame_length, *rx_data;
468 
469  /*Send frame read (long mode) command.*/
471  HAL_SPI_TRANSFER(0x20);
472 
473  /*Read frame length. This includes the checksum. */
474  frame_length = HAL_SPI_TRANSFER(0);
475 
476  /*Check for correct frame length. Bypassing this test can result in a buffer overrun! */
477  if((frame_length < HAL_MIN_FRAME_LENGTH) || (frame_length > HAL_MAX_FRAME_LENGTH)) {
478  /* Length test failed */
479  rx_frame->length = 0;
480  rx_frame->lqi = 0;
481  rx_frame->crc = false;
482  } else {
483  rx_data = (rx_frame->data);
484  rx_frame->length = frame_length;
485 
486  /*Transfer frame buffer to RAM buffer */
487 
488  HAL_SPI_TRANSFER_WRITE(0);
489  HAL_SPI_TRANSFER_WAIT();
490  do {
491  *rx_data++ = HAL_SPI_TRANSFER_READ();
492  HAL_SPI_TRANSFER_WRITE(0);
493 
494  /* CRC was checked in hardware, but redoing the checksum here ensures the rx buffer
495  * is not being overwritten by the next packet. Since that lengthy computation makes
496  * such overwrites more likely, we skip it and hope for the best.
497  * Without the check a full buffer is read in 320us at 2x spi clocking.
498  * The 802.15.4 standard requires 640us after a greater than 18 byte frame.
499  * With a low interrupt latency overwrites should never occur.
500  */
501  /* crc = _crc_ccitt_update(crc, tempData); */
502 
503  HAL_SPI_TRANSFER_WAIT();
504  } while(--frame_length > 0);
505 
506  /*Read LQI value for this frame.*/
507  rx_frame->lqi = HAL_SPI_TRANSFER_READ();
508 
509  /* If crc was calculated set crc field in hal_rx_frame_t accordingly.
510  * Else show the crc has passed the hardware check.
511  */
512  rx_frame->crc = true;
513  }
514 
515  HAL_SPI_TRANSFER_CLOSE();
516 
517 #endif /* defined(__AVR_ATmega128RFA1__) */
518 }
519 /*----------------------------------------------------------------------------*/
520 /** \brief This function will download a frame to the radio transceiver's frame
521  * buffer.
522  *
523  * \param write_buffer Pointer to data that is to be written to frame buffer.
524  * \param length Length of data. The maximum length is 127 bytes.
525  */
526 void
527 hal_frame_write(uint8_t *write_buffer, uint8_t length) /* TODO: Make sure this is working */
528 {
529 #if 0 /* Print frame to uart */
530  {
531  int i;
532  for(i = 0; i < length; i++) {
533  printf("%02x ", write_buffer[i]);
534  if((i + 1) % 16 == 0) {
535  printf("\r\n");
536  }
537  }
538  printf("\r\n");
539  }
540 #endif
542 
543  /* Send frame transmitt (long mode) command. */
544  hal_spi_send(HAL_TRX_CMD_FW, true);
545 
546  /* Sendframe length. */
547  hal_spi_send(length, true);
548 
549  /* Download to the Frame Buffer.
550  * When the FCS is autogenerated there is no need to transfer the last two bytes
551  * since they will be overwritten.
552  */
553 #if !RF230_CONF_CHECKSUM
554  length -= 2;
555 #endif
556 
557  do {
558  if(length == 1) { /* Do not assert) CS on last byte */
559  hal_spi_send(*write_buffer++, false);
560  } else {
561  hal_spi_send(*write_buffer++, true);
562  }
563  } while(--length);
564 
566 }
567 /*----------------------------------------------------------------------------*/
568 /* This #if compile switch is used to provide a "standard" function body for the */
569 /* doxygen documentation. */
570 #if defined(DOXYGEN)
571 /** \brief ISR for the radio IRQ line, triggered by the input capture.
572  * This is the interrupt service routine for timer1.ICIE1 input capture.
573  * It is triggered of a rising edge on the radio transceivers IRQ line.
574  */
575 void RADIO_VECT(void);
576 #else /* !DOXYGEN */
577 /* These link to the RF230BB driver in rf230.c */
578 void rf230_interrupt(void);
579 
580 extern hal_rx_frame_t rxframe[RF230_CONF_RX_BUFFERS];
581 extern uint8_t rxframe_head, rxframe_tail;
582 
583 /* rf230interruptflag can be printed in the main idle loop for debugging */
584 #define DEBUG 0
585 #if DEBUG
586 volatile char rf230interruptflag;
587 #define INTERRUPTDEBUG(arg) rf230interruptflag = arg
588 #else
589 #define INTERRUPTDEBUG(arg)
590 #endif
591 
592 /* Separate RF230 has a single radio interrupt and the source must be read from the IRQ_STATUS register */
594 {
595  volatile uint8_t state;
596  uint8_t interrupt_source; /* used after HAL_SPI_TRANSFER_OPEN/CLOSE block */
597 
598  /* Clear Interrupt Status Flag */
599 #ifdef MULLE_IRQ_PATCH
600  PORTC->PCR[1] |= 0x01000000; /* Clear interrupt */
602 #else
603  PORTB->PCR[9] |= 0x01000000; /* Clear interrupt */
605 #endif
606 
607  INTERRUPTDEBUG(1);
608 
609  /*Read Interrupt source.*/
610  interrupt_source = hal_register_read(RG_IRQ_STATUS); /* K60: OK, tested */
611 
612  /*Handle the incomming interrupt. Prioritized.*/
613  if((interrupt_source & HAL_RX_START_MASK)) {
614  INTERRUPTDEBUG(10);
615  /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */
616 #if !RF230_CONF_AUTOACK
617  rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI);
618 #endif
619  } else if(interrupt_source & HAL_TRX_END_MASK) {
620  INTERRUPTDEBUG(11);
621 
623  if((state == BUSY_RX_AACK) || (state == RX_ON) || (state == BUSY_RX) || (state == RX_AACK_ON)) {
624  /* Received packet interrupt */
625  /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */
626  if(rxframe[rxframe_tail].length) {
627  INTERRUPTDEBUG(42);
628  } else { INTERRUPTDEBUG(12);
629  }
630 
631 #ifdef RF230_MIN_RX_POWER
632  /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes.*/
633  /* Save the rssi for printing in the main loop */
634 #if RF230_CONF_AUTOACK
635  rf230_last_rssi = hal_register_read(RG_PHY_ED_LEVEL);
636 #endif
637  if(rf230_last_rssi >= RF230_MIN_RX_POWER) {
638 #endif
639  hal_frame_read(&rxframe[rxframe_tail]);
640  rxframe[rxframe_tail].rssi = rf230_last_rssi;
641  rxframe_tail++;
642  if(rxframe_tail >= RF230_CONF_RX_BUFFERS) {
643  rxframe_tail = 0;
644  }
645  rf230_interrupt();
646 #ifdef RF230_MIN_RX_POWER
647  }
648 #endif
649  }
650  } else if(interrupt_source & HAL_TRX_UR_MASK) {
651  INTERRUPTDEBUG(13);
652  } else if(interrupt_source & HAL_PLL_UNLOCK_MASK) {
653  INTERRUPTDEBUG(14);
654  } else if(interrupt_source & HAL_PLL_LOCK_MASK) {
655  INTERRUPTDEBUG(15);
656  } else if(interrupt_source & HAL_BAT_LOW_MASK) {
657  /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */
658  /* will continously be asserted while the supply voltage is less than the */
659  /* user-defined voltage threshold. */
660  uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK);
661  trx_isr_mask &= ~HAL_BAT_LOW_MASK;
662  hal_register_write(RG_IRQ_MASK, trx_isr_mask);
663  INTERRUPTDEBUG(16);
664  } else {
665  INTERRUPTDEBUG(99);
666  }
667 }
668 
669 #if 0
670 /* Separate RF230 has a single radio interrupt and the source must be read from the IRQ_STATUS register */
672 {
673  /*The following code reads the current system time. This is done by first
674  reading the hal_system_time and then adding the 16 LSB directly from the
675  hardware counter.
676  */
677 /* uint32_t isr_timestamp = hal_system_time; */
678 /* isr_timestamp <<= 16; */
679 /* isr_timestamp |= HAL_TICK_UPCNT(); */
680 
681  volatile uint8_t state;
682  uint8_t interrupt_source; /* used after HAL_SPI_TRANSFER_OPEN/CLOSE block */
683 
684  INTERRUPTDEBUG(1);
685 
686  /* Using SPI bus from ISR is generally a bad idea... */
687  /* Note: all IRQ are not always automatically disabled when running in ISR */
689 
690  /*Read Interrupt source.*/
691  /*Send Register address and read register content.*/
692  HAL_SPI_TRANSFER_WRITE(0x80 | RG_IRQ_STATUS);
693 
694  /* This is the second part of the convertion of system time to a 16 us time
695  base. The division is moved here so we can spend less time waiting for SPI
696  data.
697  */
698 /* isr_timestamp /= HAL_US_PER_SYMBOL; / * Divide so that we get time in 16us resolution. * / */
699 /* isr_timestamp &= HAL_SYMBOL_MASK; */
700 
701  HAL_SPI_TRANSFER_WAIT(); /* AFTER possible interleaved processing */
702 
703 #if 0 /* dak */
704  interrupt_source = HAL_SPI_TRANSFER_READ(); /* The interrupt variable is used as a dummy read. */
705 
706  interrupt_source = HAL_SPI_TRANSFER(interrupt_source);
707 #else
708  interrupt_source = HAL_SPI_TRANSFER(0);
709 #endif
710  HAL_SPI_TRANSFER_CLOSE();
711 
712  /*Handle the incomming interrupt. Prioritized.*/
713  if((interrupt_source & HAL_RX_START_MASK)) {
714  INTERRUPTDEBUG(10);
715  /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */
716 #if !RF230_CONF_AUTOACK
717 #if 0 /* 3-clock shift and add is faster on machines with no hardware multiply */
718  /* With -Os avr-gcc saves a byte by using the general routine for multiply by 3 */
719  rf230_last_rssi = hal_subregister_read(SR_RSSI);
720  rf230_last_rssi = (rf230_last_rssi << 1) + rf230_last_rssi;
721 #else /* Faster with 1-clock multiply. Raven and Jackdaw have 2-clock multiply so same speed while saving 2 bytes of program memory */
722  rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI);
723 #endif
724 #endif
725 /* if(rx_start_callback != NULL){ */
726 /* / * Read Frame length and call rx_start callback. * / */
727 /* HAL_SPI_TRANSFER_OPEN(); */
728 /* uint8_t frame_length = HAL_SPI_TRANSFER(0x20); */
729 /* frame_length = HAL_SPI_TRANSFER(frame_length); */
730 
731 /* HAL_SPI_TRANSFER_CLOSE(); */
732 
733 /* rx_start_callback(isr_timestamp, frame_length); */
734 /* } */
735  } else if(interrupt_source & HAL_TRX_END_MASK) {
736  INTERRUPTDEBUG(11);
737 /* if(trx_end_callback != NULL){ */
738 /* trx_end_callback(isr_timestamp); */
739 /* } */
740 
742  if((state == BUSY_RX_AACK) || (state == RX_ON) || (state == BUSY_RX) || (state == RX_AACK_ON)) {
743  /* Received packet interrupt */
744  /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */
745 /* if (rxframe.length) break; //toss packet if last one not processed yet */
746  if(rxframe[rxframe_tail].length) {
747  INTERRUPTDEBUG(42);
748  } else { INTERRUPTDEBUG(12);
749  }
750 
751 #ifdef RF230_MIN_RX_POWER
752  /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes.*/
753  /* Save the rssi for printing in the main loop */
754 #if RF230_CONF_AUTOACK
755  /* rf230_last_rssi=hal_subregister_read(SR_ED_LEVEL); */
756  rf230_last_rssi = hal_register_read(RG_PHY_ED_LEVEL);
757 #endif
758  if(rf230_last_rssi >= RF230_MIN_RX_POWER) {
759 #endif
760  hal_frame_read(&rxframe[rxframe_tail]);
761  rxframe_tail++;
762  if(rxframe_tail >= RF230_CONF_RX_BUFFERS) {
763  rxframe_tail = 0;
764  }
765  rf230_interrupt();
766 /* trx_end_callback(isr_timestamp); */
767 #ifdef RF230_MIN_RX_POWER
768  }
769 #endif
770  }
771  } else if(interrupt_source & HAL_TRX_UR_MASK) {
772  INTERRUPTDEBUG(13);
773  } else if(interrupt_source & HAL_PLL_UNLOCK_MASK) {
774  INTERRUPTDEBUG(14);
775  } else if(interrupt_source & HAL_PLL_LOCK_MASK) {
776  INTERRUPTDEBUG(15);
777 /* hal_pll_lock_flag++; */
778  } else if(interrupt_source & HAL_BAT_LOW_MASK) {
779  /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */
780  /* will continously be asserted while the supply voltage is less than the */
781  /* user-defined voltage threshold. */
782  uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK);
783  trx_isr_mask &= ~HAL_BAT_LOW_MASK;
784  hal_register_write(RG_IRQ_MASK, trx_isr_mask);
785 /* hal_bat_low_flag++; / * Increment BAT_LOW flag. * / */
786  INTERRUPTDEBUG(16);
787  } else {
788  INTERRUPTDEBUG(99);
789  }
790 }
791 #endif /* defined(__AVR_ATmega128RFA1__) */
792 #endif /* defined(DOXYGEN) */
793 
794 /** @} */
795 /** @} */
796 
797 /*EOF*/
#define RX_ON
Constant RX_ON for sub-register SR_TRX_STATUS.
#define SR_TRX_STATUS
Access parameters for sub-register TRX_STATUS in register RG_TRX_STATUS.
#define HAL_TRX_CMD_FW
Frame Transmit Mode (long mode).
Definition: halbb.c:89
uint8_t lqi
LQI value for received frame.
Definition: hal.h:354
#define RG_IRQ_MASK
Offset for register IRQ_MASK.
#define hal_enable_trx_interrupt()
Enable the interrupt from the radio transceiver.
Definition: hal.h:322
uint8_t hal_register_read(uint8_t address)
This function reads data from one of the radio transceiver&#39;s registers.
Definition: hal.c:304
#define HAL_PORT_MOSI
The SPI module uses GPIO might be split on different ports.
Definition: hal.h:266
#define RG_IRQ_STATUS
Offset for register IRQ_STATUS.
#define HAL_BAT_LOW_MASK
Mask for the BAT_LOW interrupt.
Definition: hal.h:335
#define RX_AACK_ON
Constant RX_AACK_ON for sub-register SR_TRX_STATUS.
#define PORTE
Peripheral PORTE base pointer.
Definition: MK60D10.h:6431
#define PTD
Peripheral PTD base pointer.
Definition: MK60D10.h:4669
Port C interrupt.
Definition: MK60D10.h:185
#define RG_PHY_ED_LEVEL
Offset for register PHY_ED_LEVEL.
#define HAL_SS_PIN
The slave select pin.
Definition: hal.h:258
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
Clear Pending Interrupt.
Definition: core_cm0.h:587
#define PORTB
Peripheral PORTB base pointer.
Definition: MK60D10.h:6419
uint8_t length
Length of frame.
Definition: hal.h:352
#define hal_set_pwr_high()
This macro pulls the RST pin high.
Definition: hal.h:88
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 hal_init(void)
This function initializes the Hardware Abstraction Layer.
Definition: hal.c:133
This struct defines the rx data container.
Definition: hal.h:351
#define SIM
Peripheral SIM base pointer.
Definition: MK60D10.h:7650
#define SPI0
Peripheral SPI0 base pointer.
Definition: MK60D10.h:7984
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&#39;s subregisters.
Definition: hal.c:400
uint8_t data[HAL_MAX_FRAME_LENGTH]
Actual frame data.
Definition: hal.h:353
#define PTE
Peripheral PTE base pointer.
Definition: MK60D10.h:4673
#define BUSY_RX
Constant BUSY_RX for sub-register SR_TRX_STATUS.
This file contains low-level radio driver code.
bool crc
Flag - did CRC pass for received frame?
Definition: hal.h:355
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&#39;s frame buffer.
Definition: hal.c:429
#define HAL_TRX_CMD_RR
Register Read (short mode).
Definition: halbb.c:88
K60 hardware register header wrapper.
#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:322
#define HAL_PLL_LOCK_MASK
Mask for the PLL_LOCK interrupt.
Definition: hal.h:340
#define HAL_RX_START_MASK
Mask for the RX_START interrupt.
Definition: hal.h:338
#define HAL_SPI_TRANSFER_OPEN()
This function is called when a rx_start interrupt is signaled.
Definition: halbb.c:220
#define HAL_TRX_UR_MASK
Mask for the TRX_UR interrupt.
Definition: hal.h:336
#define HAL_TRX_CMD_RADDRM
Register Address Mask.
Definition: halbb.c:93
#define HAL_PORT_MISO
The SPI module uses GPIO might be split on different ports.
Definition: hal.h:267
#define SR_RSSI
Access parameters for sub-register RSSI in register RG_PHY_RSSI.
void hal_frame_write(uint8_t *write_buffer, uint8_t length)
This function will download a frame to the radio transceiver&#39;s frame buffer.
Definition: hal.c:516
#define HAL_RF230_ISR()
This function initializes the Hardware Abstraction Layer.
Definition: halbb.c:203
Provide common UART routines for MK60DZ10.
#define BUSY_RX_AACK
Constant BUSY_RX_AACK for sub-register SR_TRX_STATUS.
#define HAL_TRX_CMD_RW
Register Write (short mode).
Definition: halbb.c:87
#define HAL_PLL_UNLOCK_MASK
Mask for the PLL_UNLOCK interrupt.
Definition: hal.h:339
void RADIO_VECT(void)
ISR for the radio IRQ line, triggered by the input capture.
#define PORTC
Peripheral PORTC base pointer.
Definition: MK60D10.h:6423
#define HAL_ENTER_CRITICAL_REGION()
This macro will protect the following code from interrupts.
Definition: hal.h:318
#define HAL_MAX_FRAME_LENGTH
A frame should no more than 127 bytes.
Definition: hal.h:343
Port B interrupt.
Definition: MK60D10.h:184
#define HAL_TRX_CMD_FR
Frame Receive Mode (long mode).
Definition: halbb.c:90
void hal_register_write(uint8_t address, uint8_t value)
This function writes a new value to one of the radio transceiver&#39;s registers.
Definition: hal.c:342
#define HAL_SCK_PIN
Data bit for SCK.
Definition: hal.h:260
#define PORTD
Peripheral PORTD base pointer.
Definition: MK60D10.h:6427
#define HAL_MIN_FRAME_LENGTH
A frame should be at least 3 bytes.
Definition: hal.h:342
#define HAL_TRX_END_MASK
Mask for the TRX_END interrupt.
Definition: hal.h:337
This file contains the register definitions for the AT86RF230.