/***************************************************************************//**
  @ingroup ltimer_port_wch32v307
  @file ports/wch32v307/lclock.c
  Файл содержит реализацию порта для конроллера ch32v307 с использованием
  системного счетчика SysTick.
  Порт использует определения от Gigadevice
  
  @author Руслан Кяргин <kyargin@lcard.ru>
 ******************************************************************************/
#include "lclock.h"
#include "ltimer.h"
/* файл должен определять LPC_SYSCLK и включать cmsis.h */
#include "chip.h"
#include "ch32v30x.h"

#ifndef LCLOCK_IN_CLK_FREQ
    #ifdef CHIP_CLK_SYSTICK_FREQ
        /* используем частоту SysTick, если она определена в chip */
        #define LCLOCK_IN_CLK_FREQ CHIP_CLK_SYSTICK_FREQ
    #elif defined LPC_SYSCLK
        /* для совместимости с версией chip, где определялось только значение LPC_SYSCLK */
        #define LCLOCK_IN_CLK_FREQ LPC_SYSCLK
    #else
        /* если другие варианты не определены, то используем вариант с внешней
         * переменной, который в частности используется в lpcopen */
        extern uint32_t SystemCoreClock;
        #define LCLOCK_IN_CLK_FREQ SystemCoreClock
    #endif
#endif

volatile t_lclock_ticks lclock_systicks;
static char f_initialized = 0;

#if 0
void Delay_Us (uint32_t n) {
    t_ltimer tmr;
    //     -
    ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(n*1));
    while (!ltimer_expired(&tmr)) {
        //
    }
}
void Delay_Ms (uint32_t n) {
    t_ltimer tmr;
    //     -
    ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(n));
    while (!ltimer_expired(&tmr)) {
        //
    }
}
#endif

#define STK_CTLR_STCLK (1 << 2)
#define STK_CTLR_STE (1)

/*************************************************************************
 * инициализация системного таймера
 * ***********************************************************************/
void lclock_init_val(t_lclock_ticks init_val) {
    /* инициализируем счетчик */
    lclock_systicks = init_val;
    SysTick->CTLR= 0;
    SysTick->SR  = 0;
    SysTick->cnt.CNT = 0;

#if 0
    SysTick->CMP = (SystemCoreClock / LCLOCK_TICKS_PER_SECOND);
    SysTick->CTLR = (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
    NVIC_EnableIRQ(SysTicK_IRQn);
#else
    SysTick->CMP = 0;

    //SysTick = HCLK/8
    SysTick->CTLR = 0;//STK_CTLR_STCLK;
    SysTick->CTLR |= STK_CTLR_STE;
#endif
    f_initialized = 1;
}

char lclock_is_initialized(void) {
    return f_initialized;
}

void lclock_disable(void) {
    NVIC_DisableIRQ(SysTicK_IRQn);
    SysTick->CTLR = 0;
    f_initialized = 0;
}

/* обработка прерывания от системного таймера - обновление числа тиков */
#include "lcspec_interrupt.h"
void SysTick_Handler(void) __attribute__((interrupt()));
void SysTick_Handler( void )
{
    lclock_systicks++;
    SysTick->SR = 0;
}
