#include "systick.h"
#include "misc.h"

static u8  fac_us = 0; // us延时倍乘数
static u16 fac_ms = 0; // ms延时倍乘数

volatile uint32_t systick_ms = 0;
volatile uint32_t systick_us = 0;

volatile static uint32_t delay;
volatile uint32_t        sys_tick_u32 = 0;

void dev_systick_decrement(void)
{
    if (0u != delay)
    {
        delay--;
    }
}

void dev_systick_increase(void)
{
    sys_tick_u32++;
}

void systick_init(void)
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
    if (SysTick_Config(SystemCoreClock / 1000))
    {
        while (1)
        {
        }
    }
    NVIC_SetPriority(SysTick_IRQn, 0x00);
}

uint32_t get_systick_ms(void)
{
    uint32_t tick, tick_ms;
    __disable_irq();
    tick    = (SYSTICK_EXT_CLOCK_1MS_CNT - SysTick->VAL);
    tick_ms = tick / (SYSTICK_EXT_CLOCK_1MS_CNT);
    tick_ms = tick_ms + systick_ms;
    __enable_irq();

    return tick_ms;
}

uint32_t get_systick_us(void)
{
    uint32_t tick, tick_us;
    __disable_irq();
    tick    = (SYSTICK_EXT_CLOCK_1MS_CNT - SysTick->VAL);
    tick_us = tick / (SYSTICK_EXT_CLOCK_1MS_CNT / 1000);
    tick_us = tick_us + systick_us;
    __enable_irq();

    return tick_us;
}

void ms_delay(uint8_t ms_time)
{
    uint32_t end_count = 0, current_count = 0;

    current_count = get_systick_ms();
    end_count     = current_count + ms_time;

    if (end_count == current_count)
    {
        return;
    }
    else if (end_count > current_count)
    {
        while (get_systick_ms() < end_count)
            ;
    }
    else
    {
        while (get_systick_ms() >= current_count)
            ;
        while (get_systick_ms() < end_count)
            ;
    }
}

void us_delay(uint8_t us_time)
{
    uint32_t end_count = 0, current_count = 0;

    current_count = get_systick_us();
    end_count     = current_count + us_time;

    if (end_count == current_count)
    {
        return;
    }
    else if (end_count > current_count)
    {
        while (get_systick_us() < end_count)
            ;
    }
    else
    {
        while (get_systick_us() >= current_count)
            ;
        while (get_systick_us() < end_count)
            ;
    }
}

void systick_handler(void)
{
    __disable_irq();
    systick_ms += 1;
    systick_us += 1000;
    __enable_irq();
}