RTC implementation. More...
#include "config.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include "rtc.h"
#include "cb_list.h"
Defines | |
#define | TIM1_PRESCALE (256) |
#define | RTC_SCALE (80) |
#define | RTC_PRESCALE (8) |
#define | RTC_PRESCALER_CONTROL (0*_BV(CS22)|_BV(CS21)|0*_BV(CS20)) |
#define | Ux (4L) |
#define | UxSEC_HZ (Ux*1000000) |
#define | UxSEC_PER_TICK (UxSEC_HZ*RTC_SCALE/(F_RTC_OSC/RTC_PRESCALE)) |
Functions | |
void | hl_rtc_init_osc (void) |
activate low-frequency oscillator | |
void | hl_rtc_init (void) |
initialize low-frequency timer | |
ISR (TIMER2_COMPA_vect) | |
void | hl_asyn_Register1sTimer (cb_function_t fkt2call, void *arg) |
Register a call back function for the slow timer. | |
void | hl_asyn_RegisterFastTimer (cb_function_t fkt2call, void *arg) |
Register a call back function for the fast timer. | |
void | hl_asyn_StartSysTimer (void) |
Start the system Timer again. | |
void | hl_asyn_StopSysTimer (void) |
Stop the system Timer. | |
hl_time_t | hl_get_current_time (void) |
return current time | |
uint16_t | hl_get_timer_ticks (void) |
return current tick value | |
void | hl_sleep_for_tick (uint16_t ms) |
enter power-save mode until next timer overflow or other wake-up event | |
Variables | |
cb_list_t | rtc_1s_list |
cb_list_t | rtc_fast_list |
RTC implementation.
void hl_asyn_Register1sTimer | ( | cb_function_t | fkt2call, | |
void * | arg | |||
) |
Register a call back function for the slow timer.
The function will add an entry to the list of functions to be called when the 1sec timer expires
The new entry is added to the front of the list.
{ cb_register_call (&rtc_1s_list, fkt2call, arg); }
void hl_asyn_RegisterFastTimer | ( | cb_function_t | fkt2call, | |
void * | arg | |||
) |
Register a call back function for the fast timer.
The function will add an entry to the list of functions to be called when the 19,53ms timer expires
The new entry is added to the front of the list.
{ cb_register_call (&rtc_1s_list, fkt2call, arg); }
void hl_asyn_StartSysTimer | ( | void | ) |
Start the system Timer again.
Restart the system timer again when it was stopped to save power
{ /* Start System Timer if not running */ TIMSK2 |= _BV(OCIE2A); // set fast timer status #if 0 SysTimerStatus &= ~(ASYNC_FAST_STOP); #endif }
void hl_asyn_StopSysTimer | ( | void | ) |
Stop the system Timer.
Stop the system timer to save power
{ /* Start System Timer if not running */ TIMSK2 &= ~(_BV(OCIE2A)); // set fast timer status #if 0 SysTimerStatus |= ASYNC_FAST_STOP; #endif }
void hl_rtc_init | ( | void | ) |
initialize low-frequency timer
hl_rtc_init() blocks as long as timer1 indicates that the necessary time for oscillator start-up has not elapsed.
{ /* await Overflow Compare on Timer1 - one second has elapsed */ while ((TIFR1 & _BV(OCF1A)) == 0); /* stop timer1 */ TCCR1B = 0; /* reset OCF1A */ TIFR1 = _BV(OCF1A); /* power down timer1 */ power_timer1_disable (); /* wait until previous TCCR2x updates finish */ while (ASSR & (_BV(TCN2UB)|_BV(OCR2AUB)|_BV(TCR2AUB)|_BV(TCR2BUB))); /* set counter register to known state */ TCNT2 = 0; OCR2A = RTC_SCALE-1; TCCR2A = 0 /* | _BV(COM2A1) | _BV(COM2A0) */ /* disconnect OC2A */ /* | _BV(COM2B1) | _BV(COM2B0) */ /* disconnect OC2B */ | _BV(WGM21) /* | _BV(WGM20) */ /* CTC mode */ ; TCCR2B = 0 /* | _BV(FOC2A) | _BV(FOC2B) */ /* no Force Output Compare */ /* | _BV(WGM22) */ /* CTC mode */ | RTC_PRESCALER_CONTROL ; TIFR2 = _BV(OCF2A); /* clear OV interrupt flag */ TIMSK2 = 0 /* | _BV(OCIE2B) */ | _BV(OCIE2A) /* | _BV(TOIE2) */ ; }
void hl_rtc_init_osc | ( | void | ) |
activate low-frequency oscillator
After calling this function, wait at least one second before starting to use the timer, as this is the time the oscillator needs to stabilize.
hl_rtc_init_osc() also starts timer1 to measure the elapsed time since startup of the oscillator. The idea is to be able to do some other initialization tasks which do not need the asynchronous oscillator.
{ power_timer2_enable (); /* disable interrupts from timer during start-up */ TIMSK2 = 0; /* stop timer before enabling asynchronous operation */ TCCR2B &= ~(_BV(CS22)|_BV(CS21)|_BV(CS20)); while (ASSR & _BV(TCR2BUB)); /* enable asynchronous operation with quartz oscillator */ ASSR = _BV(AS2); /* wait until previous TCNT update finishes */ while (ASSR & _BV(TCN2UB)); /* reset counter */ TCNT2 = 0; /* initialize Timer1 */ power_timer1_enable (); /* reset counter */ TCNT1 = 0; /* OC1A/B/C disconnected; WGM: normal mode */ TCCR1A = 0; #define TIM1_PRESCALE (256) /* set compare value (round up to be on safe side) */ OCR1A = F_CPU/TIM1_PRESCALE+1; /* do not generate interrupt */ TIMSK1 = 0; /* reset interrupt flag */ TIFR1 = _BV(OCF1A); /* input capture off; WGM: normal mode; prescaler 1:256 */ TCCR1B = _BV(CS12); /* this starts the timer */ }