// 延时驱动
// 杭州秒寻科技有限公司
// 周涛
// 2023-09-14

#include "includes.h"

static flt32 g_fFactorUs = 0;  // 微秒小数因子
static uint16 g_wFactorMs = 0; // 毫秒因子

// 初始化延时模块
void driver_delay_init()
{
	// 指定滴答时钟源
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

	// 计算延时因子
	g_fFactorUs = DRIVER_DELAY_SYSTICK_CLK / 8;
	g_wFactorMs = (uint16)(g_fFactorUs * 1000);

	return;
}

// 微秒延时
// dwUs:延时微秒数，由于systick定时器重装寄存器是24位的，最大值为0xFFFFFE(16777214)，所以延时不能超过（1092266=16777214/15.36）us
// 100us以内的延时，误差较大。100us的整倍数，误差较少
void driver_delay_nxus(uint32 dwUs)
{
	uint32 dwTmp = 0;
	uint32 dwFactorUs = 0; // 微秒延时因子

	// 参数容错处理
	if (dwUs > 1092266)
	{
		return;
	}

	dwFactorUs = (uint32)(g_fFactorUs * dwUs); // 计算延时因子（丢掉小数部分）
	SysTick->LOAD = dwFactorUs;				   // 给重装寄存器赋值
	SysTick->VAL = 0;
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 使能定时器

	do
	{ // 等待
		dwTmp = SysTick->CTRL;
	} while ((dwTmp & 0x01) && !(dwTmp & (0x01 << 16)));

	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 关闭定时器
	SysTick->VAL = 0;

	return;
}

// 延时100us(1536个周期)
void driver_delay_100us()
{
	uint32 dwTmp = 0;

	SysTick->LOAD = DRIVER_DELAY_100US; // 给重装寄存器赋值
	SysTick->VAL = 0;
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 使能定时器

	do
	{ // 等待
		dwTmp = SysTick->CTRL;
	} while ((dwTmp & 0x01) && !(dwTmp & (0x01 << 16)));

	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 关闭定时器
	SysTick->VAL = 0;

	return;
}

// 延时1ms(1536000个周期)
void driver_delay_1ms()
{
	uint32 dwTmp = 0;

	SysTick->LOAD = DRIVER_DELAY_1MS; // 给重装寄存器赋值
	SysTick->VAL = 0;
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 使能定时器

	do
	{ // 等待
		dwTmp = SysTick->CTRL;
	} while ((dwTmp & 0x01) && !(dwTmp & (0x01 << 16)));

	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 关闭定时器
	SysTick->VAL = 0;

	return;
}

// 延时1s
void driver_delay_1s()
{
	for (uint16 i = 0; i < 1000; i++)
	{
		driver_delay_1ms();
	}
}

// 延时n倍100us
void driver_delay_nx100us(uint16 wNx100us)
{
	for (uint16 i = 0; i < wNx100us; i++)
	{
		driver_delay_100us();
	}

	return;
}

// 延时n毫秒
// wMs:毫秒
void driver_delay_nxms(uint16 wMs)
{
	for (uint16 i = 0; i < wMs; i++)
	{
		driver_delay_1ms();
	}

	return;
}

// 延时n秒
// wS:秒
void driver_delay_nxs(uint16 wS)
{
	for (uint16 i = 0; i < wS; i++)
	{
		driver_delay_1s();
	}

	return;
}