Contiki 2.5
hal.c
Go to the documentation of this file.
1 /* Copyright (c) 2008, 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  *
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  * $Id: hal.c,v 1.2 2008/10/14 18:37:28 c_oflynn Exp $
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  */
57 
58 
59 
60 /*============================ INCLUDE =======================================*/
61 #include <stdlib.h>
62 
63 #include "hal.h"
64 #include "at86rf230_registermap.h"
65 /*============================ MACROS ========================================*/
66 
67 /*
68  * Macros defined for the radio transceiver's access modes.
69  *
70  * These functions are implemented as macros since they are used very often.
71  */
72 #define HAL_DUMMY_READ (0x00) /**< Dummy value for the SPI. */
73 
74 #define HAL_TRX_CMD_RW (0xC0) /**< Register Write (short mode). */
75 #define HAL_TRX_CMD_RR (0x80) /**< Register Read (short mode). */
76 #define HAL_TRX_CMD_FW (0x60) /**< Frame Transmit Mode (long mode). */
77 #define HAL_TRX_CMD_FR (0x20) /**< Frame Receive Mode (long mode). */
78 #define HAL_TRX_CMD_SW (0x40) /**< SRAM Write. */
79 #define HAL_TRX_CMD_SR (0x00) /**< SRAM Read. */
80 #define HAL_TRX_CMD_RADDRM (0x7F) /**< Register Address Mask. */
81 
82 #define HAL_CALCULATED_CRC_OK (0) /**< CRC calculated over the frame including the CRC field should be 0. */
83 /*============================ TYPDEFS =======================================*/
84 /*============================ VARIABLES =====================================*/
85 /** \brief This is a file internal variable that contains the 16 MSB of the
86  * system time.
87  *
88  * The system time (32-bit) is the current time in microseconds. For the
89  * AVR microcontroller implementation this is solved by using a 16-bit
90  * timer (Timer1) with a clock frequency of 1MHz. The hal_system_time is
91  * incremented when the 16-bit timer overflows, representing the 16 MSB.
92  * The timer value it self (TCNT1) is then the 16 LSB.
93  *
94  * \see hal_get_system_time
95  */
96 static uint16_t hal_system_time = 0;
97 
98 /*Flag section.*/
99 static uint8_t volatile hal_bat_low_flag; /**< BAT_LOW flag. */
100 static uint8_t volatile hal_pll_lock_flag; /**< PLL_LOCK flag. */
101 
102 /*Callbacks.*/
103 
104 /** \brief This function is called when a rx_start interrupt is signaled.
105  *
106  * If this function pointer is set to something else than NULL, it will
107  * be called when a RX_START event is signaled. The function takes two
108  * parameters: timestamp in IEEE 802.15.4 symbols (16 us resolution) and
109  * frame length. The event handler will be called in the interrupt domain,
110  * so the function must be kept short and not be blocking! Otherwise the
111  * system performance will be greatly degraded.
112  *
113  * \see hal_set_rx_start_event_handler
114  */
115 static hal_rx_start_isr_event_handler_t rx_start_callback;
116 
117 /** \brief This function is called when a trx_end interrupt is signaled.
118  *
119  * If this function pointer is set to something else than NULL, it will
120  * be called when a TRX_END event is signaled. The function takes one
121  * parameter: timestamp in IEEE 802.15.4 symbols (16 us resolution).
122  * The event handler will be called in the interrupt domain,
123  * so the function must not block!
124  *
125  * \see hal_set_trx_end_event_handler
126  */
127 static hal_trx_end_isr_event_handler_t trx_end_callback;
128 /*============================ PROTOTYPES ====================================*/
129 /*============================ IMPLEMENTATION ================================*/
130 
131 /** \brief This function initializes the Hardware Abstraction Layer.
132  */
133 void
134 hal_init(void)
135 {
136  /*Reset variables used in file.*/
137  hal_system_time = 0;
138  hal_reset_flags();
139 
140  /*IO Specific Initialization.*/
141  DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */
142  DDR_RST |= (1 << RST); /* Enable RST as output. */
143 
144  /*SPI Specific Initialization.*/
145  /* Set SS, CLK and MOSI as output. */
146  HAL_DDR_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI);
147  HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */
148  /* Run SPI at max speed */
149  SPCR = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */
150  SPSR = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */
151 
152  /*TIMER1 Specific Initialization.*/
153  TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */
154  TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */
155  HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */
156  hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */
157 }
158 
159 /*----------------------------------------------------------------------------*/
160 /** \brief This function reset the interrupt flags and interrupt event handlers
161  * (Callbacks) to their default value.
162  */
163 void
165 {
167 
168  /* Reset Flags. */
169  hal_bat_low_flag = 0;
170  hal_pll_lock_flag = 0;
171 
172  /* Reset Associated Event Handlers. */
173  rx_start_callback = NULL;
174  trx_end_callback = NULL;
175 
177 }
178 
179 /*----------------------------------------------------------------------------*/
180 /** \brief This function returns the current value of the BAT_LOW flag.
181  *
182  * The BAT_LOW flag is incremented each time a BAT_LOW event is signaled from the
183  * radio transceiver. This way it is possible for the end user to poll the flag
184  * for new event occurances.
185  */
186 uint8_t
188 {
189  return hal_bat_low_flag;
190 }
191 
192 /*----------------------------------------------------------------------------*/
193 /** \brief This function clears the BAT_LOW flag.
194  */
195 void
197 {
199  hal_bat_low_flag = 0;
201 }
202 
203 /*----------------------------------------------------------------------------*/
204 /** \brief This function is used to set new TRX_END event handler, overriding
205  * old handler reference.
206  */
209 {
210  return trx_end_callback;
211 }
212 
213 /*----------------------------------------------------------------------------*/
214 /** \brief This function is used to set new TRX_END event handler, overriding
215  * old handler reference.
216  */
217 void
219 {
221  trx_end_callback = trx_end_callback_handle;
223 }
224 
225 /*----------------------------------------------------------------------------*/
226 /** \brief Remove event handler reference.
227  */
228 void
230 {
232  trx_end_callback = NULL;
234 }
235 
236 /*----------------------------------------------------------------------------*/
237 /** \brief This function returns the active RX_START event handler
238  *
239  * \return Current RX_START event handler registered.
240  */
243 {
244  return rx_start_callback;
245 }
246 
247 /*----------------------------------------------------------------------------*/
248 /** \brief This function is used to set new RX_START event handler, overriding
249  * old handler reference.
250  */
251 void
253 {
255  rx_start_callback = rx_start_callback_handle;
257 }
258 
259 /*----------------------------------------------------------------------------*/
260 /** \brief Remove event handler reference.
261  */
262 void
264 {
266  rx_start_callback = NULL;
268 }
269 
270 /*----------------------------------------------------------------------------*/
271 /** \brief This function returns the current value of the PLL_LOCK flag.
272  *
273  * The PLL_LOCK flag is incremented each time a PLL_LOCK event is signaled from the
274  * radio transceiver. This way it is possible for the end user to poll the flag
275  * for new event occurances.
276  */
277 uint8_t
279 {
280  return hal_pll_lock_flag;
281 }
282 
283 /*----------------------------------------------------------------------------*/
284 /** \brief This function clears the PLL_LOCK flag.
285  */
286 void
288 {
290  hal_pll_lock_flag = 0;
292 }
293 
294 /*----------------------------------------------------------------------------*/
295 /** \brief This function reads data from one of the radio transceiver's registers.
296  *
297  * \param address Register address to read from. See datasheet for register
298  * map.
299  *
300  * \see Look at the at86rf230_registermap.h file for register address definitions.
301  *
302  * \returns The actual value of the read register.
303  */
304 uint8_t
305 hal_register_read(uint8_t address)
306 {
307  /* Add the register read command to the register address. */
308  address &= HAL_TRX_CMD_RADDRM;
309  address |= HAL_TRX_CMD_RR;
310 
311  uint8_t register_value = 0;
312 
314 
315  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
316 
317  /*Send Register address and read register content.*/
318  SPDR = address;
319  while ((SPSR & (1 << SPIF)) == 0) {;}
320  register_value = SPDR;
321 
322  SPDR = register_value;
323  while ((SPSR & (1 << SPIF)) == 0) {;}
324  register_value = SPDR;
325 
326  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */
327 
329 
330  return register_value;
331 }
332 
333 /*----------------------------------------------------------------------------*/
334 /** \brief This function writes a new value to one of the radio transceiver's
335  * registers.
336  *
337  * \see Look at the at86rf230_registermap.h file for register address definitions.
338  *
339  * \param address Address of register to write.
340  * \param value Value to write.
341  */
342 void
343 hal_register_write(uint8_t address, uint8_t value)
344 {
345  /* Add the Register Write command to the address. */
346  address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address);
347 
349 
350  HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
351 
352  /*Send Register address and write register content.*/
353  SPDR = address;
354  while ((SPSR & (1 << SPIF)) == 0) {;}
355  uint8_t dummy_read = SPDR;
356 
357  SPDR = value;
358  while ((SPSR & (1 << SPIF)) == 0) {;}
359  dummy_read = SPDR;
360 
361  HAL_SS_HIGH(); /* End the transaction by pulling the Slave Slect High. */
362 
364 }
365 
366 /*----------------------------------------------------------------------------*/
367 /** \brief This function reads the value of a specific subregister.
368  *
369  * \see Look at the at86rf230_registermap.h file for register and subregister
370  * definitions.
371  *
372  * \param address Main register's address.
373  * \param mask Bit mask of the subregister.
374  * \param position Bit position of the subregister
375  * \retval Value of the read subregister.
376  */
377 uint8_t
378 hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position)
379 {
380  /* Read current register value and mask out subregister. */
381  uint8_t register_value = hal_register_read(address);
382  register_value &= mask;
383  register_value >>= position; /* Align subregister value. */
384 
385  return register_value;
386 }
387 
388 /*----------------------------------------------------------------------------*/
389 /** \brief This function writes a new value to one of the radio transceiver's
390  * subregisters.
391  *
392  * \see Look at the at86rf230_registermap.h file for register and subregister
393  * definitions.
394  *
395  * \param address Main register's address.
396  * \param mask Bit mask of the subregister.
397  * \param position Bit position of the subregister
398  * \param value Value to write into the subregister.
399  */
400 void
401 hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position,
402  uint8_t value)
403 {
404  /* Read current register value and mask area outside the subregister. */
405  uint8_t register_value = hal_register_read(address);
406  register_value &= ~mask;
407 
408  /* Start preparing the new subregister value. shift in place and mask. */
409  value <<= position;
410  value &= mask;
411 
412  value |= register_value; /* Set the new subregister value. */
413 
414  /* Write the modified register value. */
415  hal_register_write(address, value);
416 }
417 
418 /*----------------------------------------------------------------------------*/
419 /** \brief This function will upload a frame from the radio transceiver's frame
420  * buffer.
421  *
422  * If the frame currently available in the radio transceiver's frame buffer
423  * is out of the defined bounds. Then the frame length, lqi value and crc
424  * be set to zero. This is done to indicate an error.
425  *
426  * \param rx_frame Pointer to the data structure where the frame is stored.
427  * \param rx_callback Pointer to callback function for receiving one byte at a time.
428  */
429 void
430 hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback)
431 {
432  uint8_t *rx_data=0;
433 
434  /* check that we have either valid frame pointer or callback pointer */
435  if (!rx_frame && !rx_callback)
436  return;
437 
439 
440  HAL_SS_LOW();
441 
442  /*Send frame read command.*/
443  SPDR = HAL_TRX_CMD_FR;
444  while ((SPSR & (1 << SPIF)) == 0) {;}
445  uint8_t frame_length = SPDR;
446 
447  /*Read frame length.*/
448  SPDR = frame_length;
449  while ((SPSR & (1 << SPIF)) == 0) {;}
450  frame_length = SPDR;
451 
452  /*Check for correct frame length.*/
453  if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){
454  uint16_t crc = 0;
455  if (rx_frame){
456  rx_data = (rx_frame->data);
457  rx_frame->length = frame_length; /* Store frame length. */
458  } else {
459  rx_callback(frame_length);
460  }
461  /*Upload frame buffer to data pointer. Calculate CRC.*/
462  SPDR = frame_length;
463  while ((SPSR & (1 << SPIF)) == 0) {;}
464 
465  do{
466  uint8_t tempData = SPDR;
467  SPDR = 0; /* dummy write */
468 
469  if (rx_frame){
470  *rx_data++ = tempData;
471  } else {
472  rx_callback(tempData);
473  }
474 
475  crc = _crc_ccitt_update(crc, tempData);
476 
477  while ((SPSR & (1 << SPIF)) == 0) {;}
478 
479  } while (--frame_length > 0);
480 
481  /*Read LQI value for this frame.*/
482  if (rx_frame){
483  rx_frame->lqi = SPDR;
484  } else {
485  rx_callback(SPDR);
486  }
487 
488  HAL_SS_HIGH();
489 
490  /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/
491  if (rx_frame){
492  rx_frame->crc = (crc == HAL_CALCULATED_CRC_OK);
493  } else {
494  rx_callback(crc != HAL_CALCULATED_CRC_OK);
495  }
496  } else {
497  HAL_SS_HIGH();
498 
499  if (rx_frame){
500  rx_frame->length = 0;
501  rx_frame->lqi = 0;
502  rx_frame->crc = false;
503  }
504  }
505 
507 }
508 
509 /*----------------------------------------------------------------------------*/
510 /** \brief This function will download a frame to the radio transceiver's frame
511  * buffer.
512  *
513  * \param write_buffer Pointer to data that is to be written to frame buffer.
514  * \param length Length of data. The maximum length is 127 bytes.
515  */
516 void
517 hal_frame_write(uint8_t *write_buffer, uint8_t length)
518 {
519  length &= HAL_TRX_CMD_RADDRM; /* Truncate length to maximum frame length. */
520 
522 
523  HAL_SS_LOW(); /* Initiate the SPI transaction. */
524 
525  /*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/
526  SPDR = HAL_TRX_CMD_FW;
527  while ((SPSR & (1 << SPIF)) == 0) {;}
528  uint8_t dummy_read = SPDR;
529 
530  SPDR = length;
531  while ((SPSR & (1 << SPIF)) == 0) {;}
532  dummy_read = SPDR;
533 
534  /* Download to the Frame Buffer. */
535  do{
536  SPDR = *write_buffer++;
537  --length;
538 
539  while ((SPSR & (1 << SPIF)) == 0) {;}
540 
541  dummy_read = SPDR;
542  } while (length > 0);
543 
544  HAL_SS_HIGH(); /* Terminate SPI transaction. */
545 
547 }
548 
549 /*----------------------------------------------------------------------------*/
550 /** \brief Read SRAM
551  *
552  * This function reads from the SRAM of the radio transceiver.
553  *
554  * \param address Address in the TRX's SRAM where the read burst should start
555  * \param length Length of the read burst
556  * \param data Pointer to buffer where data is stored.
557  */
558 void
559 hal_sram_read(uint8_t address, uint8_t length, uint8_t *data)
560 {
562 
563  HAL_SS_LOW(); /* Initiate the SPI transaction. */
564 
565  /*Send SRAM read command.*/
566  SPDR = HAL_TRX_CMD_SR;
567  while ((SPSR & (1 << SPIF)) == 0) {;}
568  uint8_t dummy_read = SPDR;
569 
570  /*Send address where to start reading.*/
571  SPDR = address;
572  while ((SPSR & (1 << SPIF)) == 0) {;}
573 
574  dummy_read = SPDR;
575 
576  /*Upload the chosen memory area.*/
577  do{
578  SPDR = HAL_DUMMY_READ;
579  while ((SPSR & (1 << SPIF)) == 0) {;}
580  *data++ = SPDR;
581  } while (--length > 0);
582 
583  HAL_SS_HIGH();
584 
586 }
587 
588 /*----------------------------------------------------------------------------*/
589 /** \brief Write SRAM
590  *
591  * This function writes into the SRAM of the radio transceiver.
592  *
593  * \param address Address in the TRX's SRAM where the write burst should start
594  * \param length Length of the write burst
595  * \param data Pointer to an array of bytes that should be written
596  */
597 void
598 hal_sram_write(uint8_t address, uint8_t length, uint8_t *data)
599 {
601 
602  HAL_SS_LOW();
603 
604  /*Send SRAM write command.*/
605  SPDR = HAL_TRX_CMD_SW;
606  while ((SPSR & (1 << SPIF)) == 0) {;}
607  uint8_t dummy_read = SPDR;
608 
609  /*Send address where to start writing to.*/
610  SPDR = address;
611  while ((SPSR & (1 << SPIF)) == 0) {;}
612  dummy_read = SPDR;
613 
614  /*Upload the chosen memory area.*/
615  do{
616  SPDR = *data++;
617  while ((SPSR & (1 << SPIF)) == 0) {;}
618  dummy_read = SPDR;
619  } while (--length > 0);
620 
621  HAL_SS_HIGH();
622 
624 }
625 
626 /*----------------------------------------------------------------------------*/
627 /* This #if compile switch is used to provide a "standard" function body for the */
628 /* doxygen documentation. */
629 #if defined(DOXYGEN)
630 /** \brief ISR for the radio IRQ line, triggered by the input capture.
631  * This is the interrupt service routine for timer1.ICIE1 input capture.
632  * It is triggered of a rising edge on the radio transceivers IRQ line.
633  */
634 void RADIO_VECT(void);
635 #else /* !DOXYGEN */
636 ISR(RADIO_VECT)
637 {
638  /*The following code reads the current system time. This is done by first
639  reading the hal_system_time and then adding the 16 LSB directly from the
640  TCNT1 register.
641  */
642  uint32_t isr_timestamp = hal_system_time;
643  isr_timestamp <<= 16;
644  isr_timestamp |= TCNT1;
645 
646  /*Read Interrupt source.*/
647  HAL_SS_LOW();
648 
649  /*Send Register address and read register content.*/
650  SPDR = RG_IRQ_STATUS | HAL_TRX_CMD_RR;
651 
652  /* This is the second part of the convertion of system time to a 16 us time
653  base. The division is moved here so we can spend less time waiting for SPI
654  data.
655  */
656  isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */
657  isr_timestamp &= HAL_SYMBOL_MASK;
658 
659  while ((SPSR & (1 << SPIF)) == 0) {;}
660  uint8_t interrupt_source = SPDR; /* The interrupt variable is used as a dummy read. */
661 
662  SPDR = interrupt_source;
663  while ((SPSR & (1 << SPIF)) == 0) {;}
664  interrupt_source = SPDR; /* The interrupt source is read. */
665 
666  HAL_SS_HIGH();
667 
668  /*Handle the incomming interrupt. Prioritized.*/
669  if ((interrupt_source & HAL_RX_START_MASK)){
670  if(rx_start_callback != NULL){
671  /* Read Frame length and call rx_start callback. */
672  HAL_SS_LOW();
673 
674  SPDR = HAL_TRX_CMD_FR;
675  while ((SPSR & (1 << SPIF)) == 0) {;}
676  uint8_t frame_length = SPDR;
677 
678  SPDR = frame_length; /* frame_length used for dummy data */
679  while ((SPSR & (1 << SPIF)) == 0) {;}
680  frame_length = SPDR;
681 
682  HAL_SS_HIGH();
683 
684  rx_start_callback(isr_timestamp, frame_length);
685  }
686  } else if (interrupt_source & HAL_TRX_END_MASK){
687  if(trx_end_callback != NULL){
688  trx_end_callback(isr_timestamp);
689  }
690  } else if (interrupt_source & HAL_TRX_UR_MASK){
691  ;
692  } else if (interrupt_source & HAL_PLL_UNLOCK_MASK){
693  ;
694  } else if (interrupt_source & HAL_PLL_LOCK_MASK){
695  hal_pll_lock_flag++;
696  ;
697  } else if (interrupt_source & HAL_BAT_LOW_MASK){
698  /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */
699  /* will continously be asserted while the supply voltage is less than the */
700  /* user-defined voltage threshold. */
701  uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK);
702  trx_isr_mask &= ~HAL_BAT_LOW_MASK;
703  hal_register_write(RG_IRQ_MASK, trx_isr_mask);
704  hal_bat_low_flag++; /* Increment BAT_LOW flag. */
705  } else {
706  ;
707  }
708 }
709 # endif /* defined(DOXYGEN) */
710 
711 /*----------------------------------------------------------------------------*/
712 /* This #if compile switch is used to provide a "standard" function body for the */
713 /* doxygen documentation. */
714 #if defined(DOXYGEN)
715 /** \brief Timer Overflow ISR
716  * This is the interrupt service routine for timer1 overflow.
717  */
718 void TIMER1_OVF_vect(void);
719 #else /* !DOXYGEN */
720 ISR(TIMER1_OVF_vect)
721 {
722  hal_system_time++;
723 }
724 #endif
725 
726 /** @} */
727 /** @} */
728 
729 /*EOF*/