#include "chip.h"
#include "lclock.h"

static volatile t_lclock_ticks lclock_systicks;
static uint8_t f_initialized = 0;


ISR(TIMER2_COMPA_vect) {
    lclock_systicks++;
}

#define CLOCK_IRQ_TICKS (CHIP_CLK_SYS_FREQ/LCLOCK_TICKS_PER_SECOND)

#if CLOCK_IRQ_TICKS < 256
    #define LCLOCK_SYS_CLK_DIV      1
    #define LCLOCK_TCCR0B_CS_RVAL   CHIP_REGFLDVAL_TCCR2B_CS_FSYS_1
#elif CLOCK_IRQ_TICKS/8 < 256
    #define LCLOCK_SYS_CLK_DIV      8
    #define LCLOCK_TCCR0B_CS_RVAL   CHIP_REGFLDVAL_TCCR2B_CS_FSYS_8
#elif CLOCK_IRQ_TICKS/32 < 256
    #define LCLOCK_SYS_CLK_DIV      32
    #define LCLOCK_TCCR0B_CS_RVAL   CHIP_REGFLDVAL_TCCR2B_CS_FSYS_32
#elif CLOCK_IRQ_TICKS/64 < 256
    #define LCLOCK_SYS_CLK_DIV      64
    #define LCLOCK_TCCR0B_CS_RVAL   CHIP_REGFLDVAL_TCCR2B_CS_FSYS_64
#elif CLOCK_IRQ_TICKS/128 < 256
    #define LCLOCK_SYS_CLK_DIV      128
    #define LCLOCK_TCCR0B_CS_RVAL   CHIP_REGFLDVAL_TCCR2B_CS_FSYS_128
#elif CLOCK_IRQ_TICKS/256 < 256
    #define LCLOCK_SYS_CLK_DIV      256
    #define LCLOCK_TCCR0B_CS_RVAL   CHIP_REGFLDVAL_TCCR2B_CS_FSYS_256
#elif CLOCK_IRQ_TICKS/1024 < 256
    #define LCLOCK_SYS_CLK_DIV      1024
    #define LCLOCK_TCCR0B_CS_RVAL   CHIP_REGFLDVAL_TCCR2B_CS_FSYS_1024
#else
    #error "unsupported system clock frequency"
#endif


/*************************************************************************
 * инициализация системного таймера
 * использует для этого RIT
 * ***********************************************************************/
void lclock_init_val(t_lclock_ticks init_val) {
    /* инициализируем счетчик */
    lclock_systicks = init_val;


    f_initialized = 1;

    CHIP_REG_TIMSK2 = CHIP_REGFLD_TIMSK0_OCIE0A;
    CHIP_REG_OCR2A  = ((CLOCK_IRQ_TICKS + LCLOCK_SYS_CLK_DIV/2)/LCLOCK_SYS_CLK_DIV -1);
    CHIP_REG_TCCR2A = LBITFIELD_SET(CHIP_REGFLD_TCCR0A_WGM0_01, CHIP_REGFLDVAL_TC2_WGM_CTC);
    CHIP_REG_TCCR2B = LBITFIELD_SET(CHIP_REGFLD_TCCR0B_WGM0_2, CHIP_REGFLDVAL_TC2_WGM_CTC >> 2)
            | LBITFIELD_SET(CHIP_REGFLD_TCCR0B_CS, LCLOCK_TCCR0B_CS_RVAL);
}

char lclock_is_initialized(void) {
    return f_initialized;
}


t_lclock_ticks lclock_get_ticks(void) {
    return lclock_systicks;
}

void lclock_disable(void) {
    CHIP_REG_TCCR2B = 0;
    f_initialized = 0;
}
