/*
 * @Author       : stark1898y 1658608470@qq.com
 * @Date         : 2024-06-14 15:28:09
 * @LastEditors: mbw && 1600520629@qq.com
 * @LastEditTime: 2025-02-21 13:17:48
 * @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_vin_detection.c
 * @Description  :
 *
 * Copyright (c) 2024 by yzy, All Rights Reserved.
 */
#include "bsp_vin_detection.h"
#include "bsp_adc.h"
#include "bsp_rtc.h"
#include "bsp_flash.h"

#include "drv_common.h"

#include "user_sys.h"

#define LOG_TAG "bsp_vin_detection" // 该模块对应的标签。不定义时，默认：NO_TAG
#define LOG_LVL LOG_LVL_DBG         // 该模块对应的日志输出级别。不定义时，默认：调试级别
#include <ulog.h>                   // 必须在 LOG_TAG 与 LOG_LVL 下面

#if 1
// static rt_sem_t sem_vin;

ALIGN(RT_ALIGN_SIZE)
static char vin_thread_stack[VIN_THREAD_STACK_SIZE];
static struct rt_thread vin_thread;
#endif

float Get_VIN_Voltage(void)
{
    float vin_voltage = Get_ADC_Voltage(kVinAdc) * VIN_VOLTAGE_RATIO;

    //    int16_t voltage = vin_voltage * 1000;

    //    LOG_D("Get_VIN_Voltage(V): %d.%d%d%d\r\n", (voltage / 1000), ((voltage % 1000) / 100),
    //        ((voltage % 100) / 10), (voltage % 10));

    return vin_voltage;
}
#ifdef FINSH_USING_MSH
// MSH_CMD_EXPORT(Get_VIN_Voltage, "Get_VIN_Voltage(V)");
#endif // !FINSH_USING_MSH

uint16_t Get_VIN_VoltageInt1000x(void)
{
    uint16_t voltage = (Get_ADC_Average(kVinAdc) * 3.3 / 4096) * VIN_VOLTAGE_RATIO * 1000;

    // LOG_D("Get_VIN_VoltageInt1000x = %04d", voltage);
    return voltage;
}
#ifdef FINSH_USING_MSH
// MSH_CMD_EXPORT(Get_VIN_VoltageInt1000x, "Get_VIN_VoltageInt1000x");
#endif // !FINSH_USING_MSH

#if 1
static void vin_thread_entry(void *param)
{
    while (1)
    {
        // rt_sem_take(sem_vin, RT_WAITING_FOREVER);
        // 写入掉电记录
        if (Get_VIN_VoltageInt1000x() <= 10000)
        {
            if (SysControl.status != kPowerDownEvent)
            {
                LOG_D("电压低于10V");
                Send_Laser_Alarm_Event(kPowerDownEvent);
            }
        }
        rt_thread_mdelay(50);

        #if 0
        Flash_Write_Record(kRecordPowerDown);
        LOG_D("Enter AnalogWatchdog Interrupt");

        for (uint8_t i = 0; i < 30; i++)
        {
            rt_thread_mdelay(1000);
            LOG_D(" %d s", i);
        }
        for (uint16_t i = 0; i < 6000; i++)
        {
            rt_hw_us_delay(999);
            LOG_D("i = %d", i);
        }
        // 还是没断电的话就重启
        NVIC_SystemReset();
        #endif
    }
}
#endif

int BSP_VIN_Detection_Init(void)
{
    // NVIC_InitTypeDef NVIC_InitStructure = {0};

    // rt_thread_mdelay(100);

    // /* Higher Threshold: 14V, Lower Threshold: 10V */
    // ADC_AnalogWatchdogThresholdsConfig(USED_ADC, VIN_ADC_HIGH_THRESHOLD, VIN_ADC_LOW_THRESHOLD);
    // ADC_AnalogWatchdogSingleChannelConfig(USED_ADC, VIN_ADC_CHANNEL);
    // ADC_AnalogWatchdogCmd(USED_ADC, ADC_AnalogWatchdog_SingleRegEnable);

    // NVIC_InitStructure.NVIC_IRQChannel                   = ADC1_2_IRQn;
    // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    // NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    // NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    // NVIC_Init(&NVIC_InitStructure);

    // rt_thread_mdelay(50);

    // ADC_ITConfig(USED_ADC, ADC_IT_AWD, ENABLE);

#if 1
    // sem_vin = rt_sem_create("sem_vin", 0, RT_IPC_FLAG_PRIO);
    // if (sem_vin == RT_NULL)
    // {
    //     LOG_E("create sem_vin fail");
    // }

    rt_thread_init(&vin_thread,
                   "vin_thread",
                   vin_thread_entry,
                   RT_NULL,
                   &vin_thread_stack[0],
                   sizeof(vin_thread_stack),
                   VIN_THREAD_PRIORITY, VIN_THREAD_TIMESLICE);
    rt_thread_startup(&vin_thread);
#endif
    LOG_D("BSP_VIN_Detection_Init");

    return RT_EOK;
}
// #ifdef RT_USING_COMPONENTS_INIT
// INIT_APP_EXPORT(BSP_VIN_Detection_Init);
// #endif

#if 0
void ADC1_2_IRQHandler(void) __attribute__((interrupt()));
void ADC1_2_IRQHandler(void)
{
    GET_INT_SP();
    /* enter interrupt */
    rt_interrupt_enter();

    if (ADC_GetITStatus(ADC1, ADC_IT_AWD))
    {
        ADC_ClearITPendingBit(ADC1, ADC_IT_AWD);

        LOG_D("Enter AnalogWatchdog Interrupt");
        Send_Laser_Alarm_Event(kPowerDownEvent);

        ADC_ITConfig(USED_ADC, ADC_IT_AWD, DISABLE);
    }

    /* leave interrupt */
    rt_interrupt_leave();
    FREE_INT_SP();
}
#endif
