Defines | Functions | Variables

rtc.c File Reference

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

Detailed Description

RTC implementation.


Function Documentation

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 */
}