#include <al_swtimer.h>
#include <al_common.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint16_t	swtimer_vector[SWTIMER_COUNT];

#if defined(SWTIMER_0)
SIGNAL(SIG_OVERFLOW0)
#elif defined(SWTIMER_1)
SIGNAL(SIG_OVERFLOW1)
#elif defined(SWTIMER_2)
SIGNAL(SIG_OVERFLOW2)
#endif
{
    uint8_t	i;

#if defined(SWTIMER_0)
    TCNT0=0x100-(CLOCK_FREQ/SWTIMER_DIV*SWTIMER_RESOLUTION/1000000);
#elif defined(SWTIMER_1)
    TCNT1H=HBYTE(0x10000-(CLOCK_FREQ/SWTIMER_DIV*SWTIMER_RESOLUTION/1000000));
    TCNT1L=LBYTE(0x10000-(CLOCK_FREQ/SWTIMER_DIV*SWTIMER_RESOLUTION/1000000));
#elif defined(SWTIMER_2)
    TCNT2=0x100-(CLOCK_FREQ/SWTIMER_DIV*SWTIMER_RESOLUTION/1000000);
#endif

    for (i=0;i<SWTIMER_COUNT;i++)
	if (swtimer_vector[i]>0)
	    swtimer_vector[i]--;
}


void swtimer_init()
{
#if defined(SWTIMER_0)
    uint8_t	b;
#if SWTIMER_DIV==8
    b=_BV(CS01);
#elif SWTIMER_DIV==64
    b=_BV(CS01) | _BV(CS00);
#elif SWTIMER_DIV==256
    b=_BV(CS02);
#else
#error Invalid value of SWTIMER_DIV
#endif
#ifdef TCCR0B
    TCCR0B=b;
#else
    TCCR0=b;
#endif
#ifdef TIMSK0
    sbi(TIMSK0,TOIE0);
#else
    sbi(TIMSK,TOIE0);
#endif
#elif defined(SWTIMER_1)
    TCCR1A=0;
    TCCR1B=_BV(CS10);					// Normal mode, no prescale
#ifdef TIMSK1
    sbi(TIMSK1,TOIE1);
#else
    sbi(TIMSK,TOIE1);
#endif
#elif defined(SWTIMER_2)
    uint8_t	b;
#if SWTIMER_DIV==8
    b=_BV(CS21);
#elif SWTIMER_DIV==64
    b=_BV(CS22);
#elif SWTIMER_DIV==256
    b=_BV(CS22) | _BV(CS21);
#else
#error Invalid value of SWTIMER_DIV
#endif
#ifdef TCCR2B
    TCCR2B=b;
#else
    TCCR2=b;
#endif
#ifdef TIMSK2
    sbi(TIMSK2,TOIE2);
#else
    sbi(TIMSK,TOIE2);
#endif
#endif

    memset(&swtimer_vector,0,sizeof(swtimer_vector));
}


uint16_t swtimer_get(uint8_t id_)
{
    return swtimer_vector[id_];
}


void swtimer_set(uint8_t id_,uint16_t value_)
{
    swtimer_vector[id_]=value_;
}


uint8_t swtimer_is_expired(uint8_t id_)
{
    return swtimer_vector[id_]==0;
}


void swtimer_delay(uint8_t id_,uint16_t value_)
{
    swtimer_set(id_,value_);
    while (!swtimer_is_expired(id_));
}
