#include "soft_flash.h"
#include <string.h>
#include "main.h"
#include "soft_flow.h"
#include "soft_p_2_c.h"
#include "config.h"
#include "soft_version.h"


bool write_vol_information = false;
bool read_vol_information = false;

bool write_serial_information = false;
bool read_serial_information = false; 

bool write_uav_information = false;
bool read_uav_information = false;

bool write_aboutage_information = false;
bool read_aboutage_information = false;

short set_cali_voltage = 0;
uint32_t set_pmu_serail = 0;


/**
  * @file    ReadFlashNBtye
  * @brief   读flash
  * @param   none
  * @details 
  * @author  Zhang Sir 
 **/
void ReadFlashNBtye(uint32_t addr, uint8_t *pdata, uint16_t size)
{   
    if(addr + size >= FLSH_MAX_SIZE)
    {
        return;
    }
    
    for (size_t i = 0; i < size; i++)
    {
       *(pdata + i) = *((__IO uint8_t *)addr + i);
    }
}


/**
  * @file    WriteFlashNBtye
  * @brief   写flash
  * @param   none
  * @details 
  * @author  Zhang Sir 
 **/
HAL_StatusTypeDef WriteFlashNBtye(uint32_t addr, uint8_t *pdata, uint16_t size)
{
    HAL_StatusTypeDef write_status = HAL_OK;

    __disable_irq();
    HAL_FLASH_Unlock();

    //擦1页flash   103c8t6 1页1kb 1024字节
    FLASH_EraseInitTypeDef f;
    f.TypeErase = FLASH_TYPEERASE_PAGES;
    f.PageAddress = addr;
    f.NbPages = 1;
    uint32_t PageError = 0;
    HAL_FLASHEx_Erase(&f, &PageError);

    //写flash 每次写2字节
    uint16_t TempBuf = 0;
    for(uint16_t i = 0; i < (size % 2 == 0? size/2 : size/2 +1); i++ )
    {
        TempBuf = *(pdata + 2 * i) + (*(pdata + 2 * i + 1) << 8);
        write_status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr + i * 2, TempBuf);
    }

    HAL_FLASH_Lock();
    __enable_irq(); 

    return write_status;
}


/**
  * @file    check_flash_par_normal
  * @brief   检查flash参数是否合法
  * @param   none
  * @details 
  * @author  Zhang Sir 
 **/
short check_flash_par_normal(short par, short min_par, short max_par ,uint8_t par_or_zero)
{
    if(par >= max_par)
    {   
        if(par_or_zero == 1)
        {
            return max_par;
        }
        else
        {
            return 0;
        }
    }
    else if(par <= min_par)
    {
        if(par_or_zero == 1)
        {
            return min_par;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        return par;
    }
}




/**
  * @file    flash_read_vol_funcktion
  * @brief   从flash中读取电压校准的系数
  * @param   none
  * @details 125kb地址0x801F800
  * @author  Zhang Sir 
 **/
struct date_vol volinf;
struct uav_type uavinf;
struct pmu_serial serial;
short reset_reason_temp = 0;
void flash_read_funcktion( void )
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    ReadFlashNBtye( FLASH_SERIAL_IFO, ( uint8_t * )&serial, sizeof( serial ) );
    
    if(serial._flag != ( int16_t )0xA48A)
    {
        serial._flag = ( int16_t )0xA48A;

        serial.num = PMU_SERIAL;

        WriteFlashNBtye( FLASH_SERIAL_IFO, ( uint8_t * )&serial, sizeof( serial ) );
    }


    ReadFlashNBtye( FLASH_VOL_IFO, ( uint8_t * )&volinf, sizeof( volinf ) );

    if ( volinf._vol_flag != ( int16_t )0xA48A )
    {
        volinf._vol_flag = ( int16_t )0xA48A;
        
        volinf.cal_vol = 0;

        WriteFlashNBtye( FLASH_VOL_IFO, ( uint8_t * )&volinf, sizeof( volinf ) );
    }

    ReadFlashNBtye( FLASH_UAV_IFO, ( uint8_t * )&uavinf, sizeof( uavinf ) );

    if ( uavinf._uavtype_flag != ( int16_t )0xA48A )
    {
        uavinf._uavtype_flag = ( int16_t )0xA48A;
        
        uavinf.uavtype = 0;

        uavinf.abnormal_outage_flag = 0;
       
        uavinf.reset_reason = 0;

        WriteFlashNBtye( FLASH_UAV_IFO, ( uint8_t * )&uavinf, sizeof( uavinf ) );
    }
    reset_reason_temp = uavinf.reset_reason;

    if(uavinf.uavtype == VK_ALL_IN_ONE)
    {
        init_pwmout(VK_ALL_IN_ONE); 
        init_gpio(VK_ALL_IN_ONE);
    }
    else
    {
        //先执行上电离心喷头会转
  
        GPIO_InitStruct.Pin = EXIT_1T_Pin|EXIT_2T_Pin;
        GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;//GPIO_MODE_IT_RISING;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
        
        GPIO_InitStruct.Pin = EXIT_3T_Pin|EXIT_4T_Pin;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


        /* EXTI interrupt init*/
        HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
    }
    HAL_TIM_Base_Start_IT(&htim4);
    HAL_TIM_Base_Start(&htim4);
}

/**
  * @file    read_flash_function
  * @brief   读flash功能
  * @param   none
  * @details 
  * @author  Zhang Sir 
 **/
int write_flash_time = 0;
void read_flash_function(void)
{   
    if(HAL_GetTick() - write_flash_time < 500)
    {
        return;
    }


    if(read_serial_information == true)
    {
        ReadFlashNBtye( FLASH_SERIAL_IFO, ( uint8_t * )&serial, sizeof( serial ) );
        Int2String(serial.num,dev_pmu.sn,9);
        read_serial_information = false;
    }

    if(read_vol_information == true)
    {
        ReadFlashNBtye( FLASH_VOL_IFO, ( uint8_t * )&volinf, sizeof( volinf ) );

        read_vol_information = false;
    }

    if(read_uav_information == true)
    {
        ReadFlashNBtye( FLASH_UAV_IFO, ( uint8_t * )&uavinf, sizeof( uavinf ) );

        read_uav_information = false;
    }
}


/**
  * @file    write_flash_function
  * @brief   把参数写入内存
  * @param   none
  * @details 
  * @author  Zhang Sir 
 **/
void write_flash_function(void)
{   

    if(write_serial_information == true)
    {
        serial.num = set_pmu_serail;
        if(HAL_OK == WriteFlashNBtye( FLASH_SERIAL_IFO, ( uint8_t * )&serial, sizeof( serial ) ))
        {
            write_flash_time = HAL_GetTick();

            read_serial_information = true;
            write_serial_information = false;
        }
    }

    if(write_vol_information == true)
    {
        volinf.cal_vol = check_flash_par_normal(set_cali_voltage,-50,50,0);

        if(HAL_OK == WriteFlashNBtye(FLASH_VOL_IFO, (uint8_t *)&volinf, sizeof(volinf)))
        {
            write_flash_time = HAL_GetTick(); 

            read_vol_information = true;
            write_vol_information = false;
        }
    }

    if(write_uav_information == true)
    {
        if(planep.UAV_type != uavinf.uavtype || uavinf.abnormal_outage_flag != 0  /*uavinf.reset_reason != reset_reason_temp*/)
        {
            uavinf.uavtype = check_flash_par_normal(planep.UAV_type,0,50,0);
            reset_reason_temp = uavinf.reset_reason;
            if(HAL_OK == WriteFlashNBtye(FLASH_UAV_IFO, (uint8_t *)&uavinf, sizeof(uavinf)))
            {
                write_flash_time = HAL_GetTick();

                read_uav_information = true;
                write_uav_information = false;
            }
        }

    }
}
