Defines | Functions | Variables

xpal_async32khz.c File Reference

32kHz Timer Implementation More...

#include "config.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "keys.h"
#include "xpal_power.h"
#include "xpal_async32khz.h"

Defines

#define HL_ASYN_FAST_INC   5

Functions

void hl_asyn_init_osc (void)
 Init async timer system - initiate oscillator startup.
void hl_asyn_init_timer (void)
 init async timer system - initialize timer device
void hl_asyn_init (void)
 Init async timer system.
 ISR (TIMER2_COMPB_vect)
 TIMER2_COMPB_vect used as 1sec, slow system timer.
 ISR (TIMER2_COMPA_vect)
 19,53ms timer
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.
void hl_asyn_ReportErrors (errString_t errMsg)
 Check for Error Conditions and report string for error log.

Variables

uint8_t FastTimerInc
 Async timer overflow increment storage.
cb_list_t cbListSlowFirst
 First element in slow timer callback list.
cb_list_t cbListFastFirst
 First element in fast timer callback list.
volatile uint8_t SysTimerStatus
 System Timer Call Status.

Detailed Description

32kHz Timer Implementation

Todo:
Add function to register timer callback functions for application layer

Function Documentation

void hl_asyn_init ( void   ) 

Init async timer system.

Initialize the 32kHz timer (timer2).

                       {

        // init callback lists
#if 0 /* not needed since data gets initialised to 0 by startup */
        cbListSlowFirst = NULL;

        cbListFastFirst = NULL;
#endif

          hl_asyn_init_osc ();

        // allow xtal to startup
        _delay_ms(1000);

          hl_asyn_init_timer ();
}

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 (&cbListSlowFirst, 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 (&cbListFastFirst, fkt2call, arg);
}

void hl_asyn_ReportErrors ( errString_t  errMsg  ) 

Check for Error Conditions and report string for error log.

Report error string if available.

Function will return a zero terminated string containing the async timer error msg.

                                             {

        if(SysTimerStatus & (ASYNC_SLOW_OVERRUN | ASYNC_FAST_OVERRUN)){
                
                // One of the timers has had an overrun 
                switch (SysTimerStatus & (ASYNC_SLOW_OVERRUN | ASYNC_FAST_OVERRUN)){
                
                        case(ASYNC_SLOW_OVERRUN):
                                sprintf_P(errMsg, PSTR("ERR - Asyn 1s TMR OVR"));
                                // Clear Error condition
                                SysTimerStatus &= ~(ASYNC_SLOW_OVERRUN);
                        break;          
                        case(ASYNC_FAST_OVERRUN):
                                sprintf_P(errMsg, PSTR("ERR - Asyn 20ms TMR OVR"));
                                // Clear Error condition
                                SysTimerStatus &= ~(ASYNC_FAST_OVERRUN);
                        break;
                        case(ASYNC_SLOW_OVERRUN | ASYNC_FAST_OVERRUN):
                                sprintf_P(errMsg, PSTR("ERR - Both TMR OVR"));
                                // Clear Error condition
                                SysTimerStatus &= ~(ASYNC_SLOW_OVERRUN | ASYNC_FAST_OVERRUN);
                        break;
                        default:
                                sprintf_P(errMsg, PSTR("ERR - TMR"));
                        break;          
                }
        }else{
                // No Errors detected
                errMsg[0] = 0;
        }
}

void hl_asyn_StartSysTimer ( void   ) 

Start the system Timer again.

Restart the system timer again when it was stopped to save power

                                {
        
        FastTimerInc = HL_ASYN_FAST_INC + TCNT2;        
        OCR2A = FastTimerInc;   // Compare value for next fast system timer

        // set fast timer status
        SysTimerStatus &= ~(ASYNC_FAST_STOP);

        /* Reset any pending interrupt */
        TIFR2 = _BV(OCF2A);

        /* Start System Timer if not running */
        TIMSK2 |= _BV(OCIE2A);
}

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
        SysTimerStatus |= ASYNC_FAST_STOP;
}

ISR ( TIMER2_COMPB_vect   ) 

TIMER2_COMPB_vect used as 1sec, slow system timer.

Uset to create a 1s timer thatcan be synced

{
        hl_pwr_SetWakeSource(HL_PWR_WAKE_BY_1S_TMR);

        if( (SysTimerStatus & ASYNC_SLOW_ACTIVE) == 0 ){

                // this timer is not active, set execution active and process
                SysTimerStatus |= ASYNC_SLOW_ACTIVE;

                if( (SysTimerStatus & ASYNC_FAST_ACTIVE) == 0 ){

                        // Fast timer is not active, enable other interrupts as long
                        // as slow functions get called

                        sei();
                        callback_iterate (cbListSlowFirst);
                        cli();

                }else{
                        // Fast timer is active, set block flag

                        SysTimerStatus |= ASYNC_SLOW_BLOCK;
                        // The fast timer will call the slow timer execution when done
                        // This will avoid recursive calls
                }

                // timer operation done, set inactive
                SysTimerStatus &= ~(ASYNC_SLOW_ACTIVE);

        }else{
                // this int is still in execution, set overrun
                SysTimerStatus |= ASYNC_SLOW_OVERRUN;   
        }

        // Run now fast timer calls ín case the fast timer was blocked
        // INT stays disabled for fast execution
        if (SysTimerStatus & ASYNC_FAST_BLOCK){

                callback_iterate (cbListFastFirst);

                // reset blocking state
                SysTimerStatus &= ~(ASYNC_FAST_BLOCK);
        }
}

ISR ( TIMER2_COMPA_vect   ) 

19,53ms timer

Compare value is incremented by HL_ASYN_FAST_INC during each ISR call

{
        FastTimerInc += HL_ASYN_FAST_INC;
        
        OCR2A = FastTimerInc;   // Compare value for next fast system timer

        hl_pwr_SetWakeSource(HL_PWR_WAKE_BY_SYS_TMR);

        if( (SysTimerStatus & ASYNC_FAST_ACTIVE) == 0 ){

                // no fast int execution active, activate
                SysTimerStatus |= ASYNC_FAST_ACTIVE;

                if( (SysTimerStatus & ASYNC_SLOW_ACTIVE) == 0 ){

                        // Slow timer is not active, enable other interrupts as long 
                        // as fast timer functions get called
                        sei();                                  
                        callback_iterate (cbListFastFirst);
                        cli();

                }else{
                        // Slow timer is active, set block flag
                        SysTimerStatus |= ASYNC_FAST_BLOCK;
                        // The fast timer will call the slow timer execution when done
                        // This will avoid recursive calls
                }
                // fast int execution done, set inactive
                SysTimerStatus &= ~(ASYNC_FAST_ACTIVE);
        }else{
                // Fast int still in execution, set overrun
                SysTimerStatus |= ASYNC_FAST_OVERRUN;
        }

        // Run now 1s timer calls ín case the fast timer was blocked
        // INT stays disabled for slow execution
        if (SysTimerStatus & ASYNC_SLOW_BLOCK){

                callback_iterate (cbListSlowFirst);

                // reset blocking state
                SysTimerStatus &= ~(ASYNC_SLOW_BLOCK);
        }
}


Variable Documentation

volatile uint8_t SysTimerStatus

System Timer Call Status.

This bitmap variable will mirror the current timer call and Interrupt status It will allow the recognition of overun effects and lock the recursive call of timer functions.