/*
 * task.c
 *
 *  Created on: 2024年6月24日
 *      Author: psx
 */

#include "task.h"


#include "tim.h"
#include "pwm.h"
#include "adc.h"
#include "rs485.h"
#include "gpio.h"
#include "flash.h"


#include "sl_protocol.h"
#include "mppt_control.h"
#include "inflash.h"
#include <stdlib.h>
#include "collect_Conversion.h"


void stop_mpptWork(void)
{
    GPIO_WriteBit(EnPowerSupply_GPIO, EnPowerSupply_PIN, SET);
    g_duty_ratio = 0.7;
    TIM_Cmd(TIM3, DISABLE);
    TIM_SetCompare4(TIM4, 0);
//    TimeSliceOffset_Register(&m_startMpptControl, Task_startMpptControl
//            , startMpptControl_reloadVal, startMpptControl_offset);
//    GPIO_WriteBit(POW_OUT_CON_GPIO, POW_OUT_CON_PIN, RESET);

}

void start_mpptWork(void)
{
//    GPIO_WriteBit(EnPowerSupply_GPIO, EnPowerSupply_PIN, RESET);
    TIM_Cmd(TIM3, ENABLE);
    g_Mppt_Para.MPPT_Mode = CONSTANTCURRENT;
//    TimeSliceOffset_Unregister(&m_startMpptControl);
//    Delay_Ms(500);
    GPIO_WriteBit(POW_OUT_CON_GPIO, POW_OUT_CON_PIN, SET);
}

/**
  * @brief  运行指示灯
  * @param
  * @retval
  */
STR_TimeSliceOffset m_runled;
void Task_RunLED(void)
{
//    uart_sendstr(g_gw485_uart4_handle, "\n\n\n\n\n");
//    uart_sendstr(g_gw485_uart4_handle, "is gw485\n");
//    uart_sendstr(g_bat485_uart3_handle, "is bat485\n");get_PV1_VOLT_IN();

    printf(" \n");
    printf(" duty_ratio : %d/1000 \n", (int)(g_duty_ratio * 1000));

    printf(" vout : %d/100 \n", (int)(g_Mppt_Para.Battery_Voltage * 100));
    printf(" Iout : %d/100 \n", (int)(g_Mppt_Para.Charg_Current * 100));
    printf(" Idisout : %d/100 \n", (int)(g_Mppt_Para.Discharg_Current * 100));
    printf(" mosT : %d/10 \n", (int)(g_Mppt_Para.HighSideMos_Temperature * 10));
    printf(" mosState : %d \n", (int)(g_Mppt_Para.DischargMos_State));
//    printf(" mosState : %d \n", GPIO_ReadOutputDataBit(POW_OUT_CON_GPIO, POW_OUT_CON_PIN));
//    printf(" mosState : %d \n", GPIO_ReadInputDataBit(DSG_PROT_GPIO, DSG_PROT_PIN));

    printf(" 0.没有工作; 1.涓流模式; 2.恒流模式; 3.恒压模式; 4.浮充模式; 5.没有电池 : %d \n", g_Mppt_Para.MPPT_Mode);

    printf(" \n");

//    printf("vout : %d/100 \n", (int)(get_capturedata(get_PV_VOLT_OUT) * 100));

//    get_CHG_CURR();

    static uint8_t flag = RESET;
    flag = !flag;
    GPIO_WriteBit(RUN_LED_GPIO, RUN_LED_PIN, flag);

//    static uint8_t num = 0;
//    if (10 == ++num) {
//        GPIO_WriteBit(POW_OUT_CON_GPIO, POW_OUT_CON_PIN, SET);
//    }

    return;
}


/**
  * @brief  启动mppt控制
  * @param
  * @retval
  */
STR_TimeSliceOffset m_startMpptControl;
void Task_startMpptControl(void)
{
    static uint16_t checkSolarOpenCircuitVTimeFlag;
    static uint8_t only_once = 1;
    if (only_once) {
        only_once = 0;
        checkSolarOpenCircuitVTimeFlag = g_slConfigInfo.checkSolarOpenCircuitVTime - 3;
    }

    if (g_slConfigInfo.checkSolarOpenCircuitVTime == ++checkSolarOpenCircuitVTimeFlag) {
        checkSolarOpenCircuitVTimeFlag = 0;
        g_Mppt_Para.Solar_Open_Circuit_Voltage = get_capturedata(get_PV1_VOLT_IN);
        printf("volt in : %d/100 \n", (int)(g_Mppt_Para.Solar_Open_Circuit_Voltage * 100));

        if (g_Mppt_Para.Solar_Open_Circuit_Voltage
             > ((float_t)g_slConfigInfo.startSolarOpenCircuitV / 100)) {
//            start_mpptWork();
            TimeSliceOffset_Register(&m_softStart, Task_softStart, softStart_reloadVal, softStart_offset);
            TimeSliceOffset_Unregister(&m_startMpptControl);
        }
    }
    return;
}

/**
  * @brief  软起动
  * @param
  * @retval
  */
STR_TimeSliceOffset m_softStart;
void Task_softStart(void)
{
    static uint16_t num = 0;
    static float_t dutyRatio = 0;

    num++;

    if (num == 1) {
        GPIO_WriteBit(EnPowerSupply_GPIO, EnPowerSupply_PIN, RESET);
    }

    if (num < 5) {
        TIM_SetCompare4(TIM4, 100);
    }

    else if (num > 70 || dutyRatio > g_duty_ratio) {
        dutyRatio = 0;
        num = 0;
        Set_duty_ratio(&g_duty_ratio);
        TimeSliceOffset_Unregister(&m_softStart);
        start_mpptWork();

        return;
    }

    else {
        dutyRatio += 0.01;
        Set_duty_ratio(&dutyRatio);
    }
}

/**
  * @brief 串口数据解析和处理
  * @param
  * @retval
  */
STR_TimeSliceOffset m_usart;
uint8_t RegistrationRequestFlag = 0;
void Task_usart(void)
{
    read_and_process_uart_data(g_gw485_uart4_handle);
//    read_and_process_uart_data(g_bat485_uart3_handle);
    return;
}

/**
  * @brief 看门狗
  * @param
  * @retval
  */
STR_TimeSliceOffset m_wdi;
void Task_wdi(void)
{
    static uint32_t temp = 0;
    if (wdi_RESET == temp++) {
        temp = 0;
        NVIC_SystemReset();
    }
    GPIO_WriteBit(WDI_INPUT_GPIO, WDI_INPUT_PIN, SET);
    GPIO_WriteBit(WDI_INPUT_GPIO, WDI_INPUT_PIN, RESET);
    return;
}

/**
  * @brief  刷新寄存器中的数据,同时确定mos管温度
  * @param
  * @retval
  */
STR_TimeSliceOffset m_refreshRegister;
uint8_t overTemperature = 0;
void Task_refreshRegister(void)
{
    static uint16_t checkRegisterRefreshTimeFlag;

    if (g_slConfigInfo.registerRefreshTime == ++checkRegisterRefreshTimeFlag) {
        checkRegisterRefreshTimeFlag = 0;
        g_Mppt_Para.Battery_Voltage = get_capturedata(get_PV_VOLT_OUT);
        g_Mppt_Para.Charg_Current = get_capturedata(get_CHG_CURR);
        g_Mppt_Para.Discharg_Current = get_capturedata(get_DSG_CURR);
        g_Mppt_Para.HighSideMos_Temperature = get_capturedata(get_MOSFET_Temper);
        g_Mppt_Para.DischargMos_State = GPIO_ReadOutputDataBit(POW_OUT_CON_GPIO, POW_OUT_CON_PIN)
                                                && GPIO_ReadInputDataBit(DSG_PROT_GPIO, DSG_PROT_PIN);
        g_Mppt_Para.Solar_Open_Circuit_Voltage = get_capturedata(get_PV1_VOLT_IN);

        if (g_Mppt_Para.HighSideMos_Temperature < g_slConfigInfo.HighSideMosTemperature_start) {
            if (overTemperature == 2) {
//                start_mpptWork();
                TimeSliceOffset_Register(&m_softStart, Task_softStart, softStart_reloadVal, softStart_offset);
            }
            overTemperature = 0;
            return;
        }

        if (g_Mppt_Para.HighSideMos_Temperature > g_slConfigInfo.HighSideMosTemperature_end) {
            g_Mppt_Para.MPPT_Mode = NoBattery;
            overTemperature = 1;
        }

        if (g_Mppt_Para.HighSideMos_Temperature > g_slConfigInfo.HighSideMosTemperature_stop) {
            overTemperature = 2;
            stop_mpptWork();
        }

    }
}

/**
  * @brief 接收到广播指令后,发送数据给网关，未接收到指令再次发送，最多三次，间隔时间3s
  * @param
  * @retval
  */
uint8_t recvbroadcast_flag = 0;
device_handle g_recvBroadcastDevice;
uint8_t g_recvBroadcastRegisterNumber;
STR_TimeSliceOffset m_recvbroadcast;
void Task_recvbroadcast(void)
{
    static uint8_t run_number = 0;
    /* 超过三次，不再发送 */
    if (run_number++ == 3 || run_number > 3) {
        RegistrationRequestFlag = 0;
        run_number = 0;
        TimeSliceOffset_Unregister(&m_recvbroadcast);
        return;
    }
//    if (g_Mppt_Para.Registration_Status == REGISTER_SUCCESS) {
//        TimeSliceOffset_Unregister(&m_recvbroadcast);
//        return;
//    }
    SL_Mppt_RegistrationRequest_pack recvpack = {0};

    /* 起始标志 */
    recvpack.start_Flag[0] = g_slConfigInfo.start_Flag[0];
    recvpack.start_Flag[1] = g_slConfigInfo.start_Flag[1];

    /* ID */
    recvpack.address[0] = 0xFF;
    recvpack.address[1] = 0xFF;
    recvpack.address[2] = 0xFF;
    recvpack.address[3] = 0xFF;
    recvpack.address[4] = 0xFF;
    recvpack.address[5] = 0xFF;
    recvpack.address[6] = 0xFF;

    /* 功能码 */
    recvpack.function_Code = SL_Function_Code_Registration_request;

    /* 寄存器长度 */
    recvpack.register_Length_H =  g_recvBroadcastRegisterNumber >> 8;
    recvpack.register_Length_L =  g_recvBroadcastRegisterNumber;

    /* 注册状态 */
    recvpack.registration_Status_H = g_Mppt_Para.Registration_Status >> 8;
    recvpack.registration_Status_L = g_Mppt_Para.Registration_Status;

    /* 接入节点ID */
    recvpack.access_Node_ID[0] = g_slConfigInfo.address[0];
    recvpack.access_Node_ID[1] = g_slConfigInfo.address[1];
    recvpack.access_Node_ID[2] = g_slConfigInfo.address[2];
    recvpack.access_Node_ID[3] = g_slConfigInfo.address[3];
    recvpack.access_Node_ID[4] = g_slConfigInfo.address[4];
    recvpack.access_Node_ID[5] = g_slConfigInfo.address[5];
    recvpack.access_Node_ID[6] = g_slConfigInfo.address[6];

    /* 接入节点类型 */
    recvpack.access_Node_Type_H = g_Mppt_Para.Access_Node_Type >> 8;
    recvpack.access_Node_Type_L = g_Mppt_Para.Access_Node_Type;

    /* 校验位 */
//    uint8_t *rpack_buf = (uint8_t *)&recvpack;
    uint16_t crc = CheckFunc((uint8_t *)&recvpack, SL_MPPT_REGISTRATIONREQUEST_PACK_SIZE - 3);

    recvpack.check_Bit_H = crc >> 8;
    recvpack.check_Bit_L = crc;
    /* 结束标志 */
    recvpack.end_Flag = g_slConfigInfo.end_Flag;
    /* 校验位 */
    for (uint8_t var = 0; var < 10; ++var) {
        Delay_Ms(randomDelay());
        if (!Check_485_bus_busy(g_recvBroadcastDevice)) {
            if (recvbroadcast_flag == 1) {
                recvbroadcast_flag = 0;
                run_number = 0;
                return;
            }
            uart_dev_write(g_recvBroadcastDevice, (uint8_t *)&recvpack, SL_MPPT_REGISTRATIONREQUEST_PACK_SIZE + 1);

            if (g_recvBroadcastDevice == g_bat485_uart3_handle) {
                USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
            } else {
                USART_ITConfig(USART4, USART_IT_RXNE, ENABLE);
            }

            break;
        }
    }
}

/**
  * @brief 阻抗计算
  * @param
  * @retval
  */
STR_TimeSliceOffset m_impedanceCalculation;
float_t g_impedance = 0;            /* 回路阻抗的值 */
float_t voltOut = 0;                /* 输出电压的值 */
void Task_impedanceCalculation(void)
{
    static uint8_t num = 0;
    static float_t currOne = 0;
    static float_t voltOne = 0;
    static float_t currTwo = 0;
    static float_t voltTwo = 0;

    if (g_Mppt_Para.MPPT_Mode == CONSTANTCURRENT
            || g_Mppt_Para.MPPT_Mode == CONSTANTVOLTAGE) {
        ++num;
    } else {
        num = 0;
    }

    if (num == 10) {
        num = 0;
        TIM_Cmd(TIM3, DISABLE);

        TIM_SetCompare4(TIM4, 420);
        Delay_Ms(5);
        currOne = get_capturedata(get_CHG_CURR) - get_capturedata(get_DSG_CURR);
        voltOne = get_capturedata(get_PV_VOLT_OUT);

        TIM_SetCompare4(TIM4, 350);
        Delay_Ms(5);
        currTwo = get_capturedata(get_CHG_CURR) - get_capturedata(get_DSG_CURR);
        voltTwo = get_capturedata(get_PV_VOLT_OUT);

        g_impedance = (voltOne - voltTwo) / (currOne - currTwo);

        printf("currOne = %d/1000, voltOne = %d/100 \n", (int)(currOne * 1000), (int)(voltOne * 100));
        printf("currTwo = %d/1000, voltTwo = %d/100 \n", (int)(currTwo * 1000), (int)(voltTwo * 100));
        printf("Res = %d/1000, E = %d/100 \n", (int)(g_impedance * 1000), (int)((voltTwo - currTwo * g_impedance) * 100));

        TIM_Cmd(TIM3, ENABLE);
    }

    return;
}

/**
  * @brief 再次打开放电端口，避免上电引起的异常波动
  * @param
  * @retval
  */
STR_TimeSliceOffset m_outputAgain;
uint8_t outputAgainFlag = 0;
void Task_outputAgain(void)
{

    if (outputAgainFlag == 1) {
        outputAgainFlag = 0;
        TimeSliceOffset_Unregister(&m_outputAgain);
    }

    if (outputAgainFlag == 2) {
        TimeSliceOffset_Unregister(&m_outputAgain);
    }

    return;
}

/**
  * @brief 设定传感器能再次注册的间隔时间
  * @param
  * @retval
  */
STR_TimeSliceOffset m_sensorEnableBroadcast;
/* 是否接收广播帧标志位 */
uint8_t run_Broadcast = 1;
void Task_sensorEnableBroadcast(void)
{
    static uint32_t enabBroadcastTimeFlag = 0;
    enabBroadcastTimeFlag++;
    run_Broadcast = 0;

    if (enabBroadcastTimeFlag == g_slConfigInfo.sensorEnableBroadcastTime) {
        enabBroadcastTimeFlag = 0;
        run_Broadcast = 1;
        TimeSliceOffset_Unregister(&m_sensorEnableBroadcast);
    }
    return;
}

/**
  * @brief  初始化各个寄存器
  * @param
  * @retval
  */
void g_Mppt_Para_Init(void)
{
    g_Mppt_Para.Registration_Status = UNREGISTER;
    g_Mppt_Para.address[0] = g_slConfigInfo.address[0];
    g_Mppt_Para.address[1] = g_slConfigInfo.address[1];
    g_Mppt_Para.address[2] = g_slConfigInfo.address[2];
    g_Mppt_Para.address[3] = g_slConfigInfo.address[3];
    g_Mppt_Para.address[4] = g_slConfigInfo.address[4];
    g_Mppt_Para.address[5] = g_slConfigInfo.address[5];
    g_Mppt_Para.address[6] = g_slConfigInfo.address[6];
    g_Mppt_Para.Access_Node_Type = defaultValue.access_Node_Type;
    g_Mppt_Para.Communication_Methods = defaultValue.communication_Methods;

    g_Mppt_Para.Battery_Voltage = get_capturedata(get_PV_VOLT_OUT);
    g_Mppt_Para.Charg_Current = get_capturedata(get_CHG_CURR);
    g_Mppt_Para.Discharg_Current = get_capturedata(get_DSG_CURR);
    g_Mppt_Para.Solar_Open_Circuit_Voltage = get_capturedata(get_PV1_VOLT_IN);
    g_Mppt_Para.HighSideMos_Temperature = get_capturedata(get_MOSFET_Temper);
    g_Mppt_Para.DischargMos_State = GPIO_ReadOutputDataBit(POW_OUT_CON_GPIO, POW_OUT_CON_PIN)
                                            && GPIO_ReadInputDataBit(DSG_PROT_GPIO, DSG_PROT_PIN);
    g_Mppt_Para.MPPT_Mode = NoWork;


//    printf("start_flag : %s \n", g_slConfigInfo.start_Flag);
//    for (int var = 0; var < 7; ++var) {
//        printf("address[%d] : %x\n", var, g_slConfigInfo.address[var]);
//    }
//    printf("end_flag : %x\n", g_slConfigInfo.end_Flag);
//    printf("access_Node_Type : %x\n", defaultValue.access_Node_Type);
//    printf("communication_Methods : %x\n", defaultValue.communication_Methods);
}

/**
  * @brief  初始化各个任务和读取配置文件等
  * @param
  * @retval
  */
void task_Init(void)
{
    read_config_info();
    g_Mppt_Para_Init();

    TimeSliceOffset_Register(&m_runled, Task_RunLED, runled_reloadVal, runled_offset);

    TimeSliceOffset_Register(&m_usart, Task_usart, usart_reloadVal, usart_offset);

    TimeSliceOffset_Register(&m_wdi, Task_wdi, wdi_reloadVal, wdi_offset);

////    TimeSliceOffset_Register(&m_impedanceCalculation, Task_impedanceCalculation
////            , impedanceCalculation_reloadVal, impedanceCalculation_reloadVal);
//
//    TimeSliceOffset_Register(&m_refreshRegister, Task_refreshRegister
//            , refreshRegister_reloadVal, refreshRegister_reloadVal);
//
//    TimeSliceOffset_Register(&m_startMpptControl, Task_startMpptControl
//            , startMpptControl_reloadVal, startMpptControl_offset);

    TimeSliceOffset_Start();    /* 启动时间片轮询 */
}


/**
  * @brief  初始化所需外设
  * @param
  * @retval
  */
void hardware_Init(void)
{
    TIM2_Init(1);
    uart_dev_init();
    PWM_TIM_Configuration();
    ADC_all_Init();
    RUN_LED_Init();
    WDI_INPUT_Init();
    SPI_Flash_Init();
    POW_OUT_CON_Init();
//    DSG_PROT_Init();
//    EnPowerSupply_Init();

    Set_duty_ratio(&g_duty_ratio);

//    TIM3_Init(1);
}

