#include "bsp_wf5803.h"
#include "CONFIG.h"

typedef enum
{
    kPressIn   = 0,
    kPressOut  = 1,
    kPressAtom = 2,
    kPressMaxIndex
} TePressSensorIndex;

static tmosTaskID press_task_id = INVALID_TASK_ID;

#define PRESS_IN_CS_HIGH()   GPIOB_SetBits(GPIO_Pin_9)
#define PRESS_IN_CS_LOW()    GPIOB_ResetBits(GPIO_Pin_9)

#define PRESS_OUT_CS_HIGH()  GPIOB_SetBits(GPIO_Pin_4)
#define PRESS_OUT_CS_LOW()   GPIOB_ResetBits(GPIO_Pin_4)

#define PRESS_ATOM_CS_HIGH() GPIOB_SetBits(GPIO_Pin_17)
#define PRESS_ATOM_CS_LOW()  GPIOB_ResetBits(GPIO_Pin_17)

uint8_t volatile press_done_flag = 0;

uint8_t press_raw_data[kPressMaxIndex][5];

void PRESS_SPI_CsStart(TePressSensorIndex index)
{
    switch (index)
    {
        case kPressIn:
            PRESS_IN_CS_LOW();
            break;
        case kPressOut:
            PRESS_OUT_CS_LOW();
            break;
        case kPressAtom:
            PRESS_ATOM_CS_LOW();
            break;

        default:
            break;
    }
}

void PRESS_SPI_CsStop(TePressSensorIndex index)
{
    switch (index)
    {
        case kPressIn:
            PRESS_IN_CS_HIGH();
            break;
        case kPressOut:
            PRESS_OUT_CS_HIGH();
            break;
        case kPressAtom:
            PRESS_ATOM_CS_HIGH();
            break;

        default:
            break;
    }
}

uint8_t PRESS_SPI_SendByte(uint8_t data)
{
    R8_SPI0_BUFFER = data;
    while (!(R8_SPI0_INT_FLAG & RB_SPI_FREE));
    return (R8_SPI0_BUFFER);
}

void WF5803_WriteReg(uint8_t Address, uint8_t value, TePressSensorIndex index)
{
    PRESS_SPI_CsStart(index);
    PRESS_SPI_SendByte(0x00);
    PRESS_SPI_SendByte(Address);
    PRESS_SPI_SendByte(value);
    PRESS_SPI_CsStop(index);
}

uint8_t WF5803_ReadReg(uint8_t addr, TePressSensorIndex index)
{
    uint8_t value;
    PRESS_SPI_CsStart(index);
    PRESS_SPI_SendByte(0x80);
    PRESS_SPI_SendByte(addr);
    value = PRESS_SPI_SendByte(0xFF);
    PRESS_SPI_CsStop(index);
    return value;
}

void PRESS_IO_SPI_Init(void)
{
    /**
     * CSB: PB17
     * SCL: PA13
     * SDA: PA14
     * SDO: PA15
     */
    // SDA: MOSI
    // SDO: MISO

    // CSB1: PA3
    // GPIOA_SetBits(GPIO_Pin_3);
    // GPIOA_ModeCfg(GPIO_Pin_3, GPIO_ModeOut_PP_5mA);

    // CSB2: PB9
    GPIOB_SetBits(GPIO_Pin_9);
    GPIOB_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);

    // CSB3: PB4
    GPIOB_SetBits(GPIO_Pin_4);
    GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeOut_PP_5mA);

    // CSB4: PB17
    GPIOB_SetBits(GPIO_Pin_17);
    GPIOB_ModeCfg(GPIO_Pin_17, GPIO_ModeOut_PP_5mA);

    PRESS_SPI_CsStop(kPressIn);
    PRESS_SPI_CsStop(kPressOut);
    PRESS_SPI_CsStop(kPressAtom);

    // spi初始化，模式0
    GPIOA_ModeCfg(GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU);

    SPI0_MasterDefInit();
}

void WF5803_Init(void)
{
    PRESS_IO_SPI_Init();
    WF5803_WriteReg(0x00, 0x81, kPressIn);   // 配置spi为四线模式
    WF5803_WriteReg(0x00, 0x81, kPressOut);  // 配置spi为四线模式
    WF5803_WriteReg(0x00, 0x81, kPressAtom); // 配置spi为四线模式
}

void PRESS_LowerIO_Init(void)
{
    // WF5803默认供电时，其他IO都是高电平
    // SPI
    GPIOA_SetBits(GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
    GPIOA_ModeCfg(GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15, GPIO_ModeIN_PU);

    // CSB1: PA3
    // GPIOA_SetBits(GPIO_Pin_3);
    // GPIOA_ModeCfg(GPIO_Pin_3, GPIO_ModeIN_PU);
    // CSB1: PA3
    // GPIOA_SetBits(GPIO_Pin_3);
    // GPIOA_ModeCfg(GPIO_Pin_3, GPIO_ModeOut_PP_5mA);

    // CSB2: PB9
    GPIOB_SetBits(GPIO_Pin_9);
    GPIOB_ModeCfg(GPIO_Pin_9, GPIO_ModeIN_PU);

    // CSB3: PB4
    GPIOB_SetBits(GPIO_Pin_4);
    GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);

    // CSB4: PB17
    GPIOB_SetBits(GPIO_Pin_17);
    GPIOB_ModeCfg(GPIO_Pin_17, GPIO_ModeIN_PU);
}

void Lower_IO_Deinit(void)
{
    // LED
    GPIOA_ResetBits(GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12);
    GPIOA_ModeCfg(GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12, GPIO_ModeIN_PD);

    // KEY
    GPIOA_ResetBits(GPIO_Pin_7);
    GPIOA_ModeCfg(GPIO_Pin_7, GPIO_ModeIN_PU);

    // RESET KEY
    GPIOB_ResetBits(GPIO_Pin_7);
    GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeIN_PU);

    // motor
    GPIOB_ResetBits(GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2);
    GPIOB_ModeCfg(GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2, GPIO_ModeIN_PD);

    // COIL_ADC
    GPIOA_ResetBits(GPIO_Pin_6);
    GPIOA_ModeCfg(GPIO_Pin_6, GPIO_ModeIN_PD);

    // ADC_CTRL,ADC_VBAT
    GPIOA_ResetBits(GPIO_Pin_0 | GPIO_Pin_1);
    GPIOA_ModeCfg(GPIO_Pin_0 | GPIO_Pin_1, GPIO_ModeIN_PD);
}

void PRESS_LowPower(void)
{
    Lower_IO_Deinit();
    if (press_done_flag == 1)
    {
        PRESS_LowerIO_Init();
    }
}

uint8_t GetSensorData(TePressSensorIndex index)
{
    memset(press_raw_data[index], 0, 5);

    PRINT("Status = %02x\r\n", WF5803_ReadReg(0x02, index));

    // 气压数据
    // 温度数据
    for (uint8_t i = 0; i < 5; i++)
    {
        press_raw_data[index][i] = WF5803_ReadReg(0x06 + i, index);
    }

    return 0;
}

void SensorData_Process(TePressSensorIndex index)
{
    long reading = 0;
    float fDat   = 0;
    float press  = 0;
    float temp   = 0;

    GetSensorData(index);

    reading = press_raw_data[index][0];
    reading = reading << 8;
    reading |= press_raw_data[index][1];
    reading = reading << 8;
    reading |= press_raw_data[index][2];
    if (reading >= 8388608)
    {
        fDat = (int32_t)(reading - 16777216) / 8388608.0f;
    }
    else
    {
        fDat = reading / 8388608.0f;
    }

    press = fDat * 125 + 17.5; // WF5803_1BAR    如果是使用10m级别的深传就使用这个

    reading = press_raw_data[index][3];
    reading = reading << 8;
    reading |= press_raw_data[index][4];
    if (reading > 32768)
    {
        temp = (reading - 65844) / 256.0f;
    }
    else
    {
        temp = (reading - 308) / 256.0f;
    }

    PRINT("P[%d] = %d.%d pa\r\n", index, (int)(press * 1000), ((int)(press * 10000000.0f) % 10000));
    PRINT("T[%d] = %d.%d \r\n", index, (int)temp, ((int)(temp * 100.0f) % 100));
}

// __HIGH_CODE
// __attribute__((noinline))
uint16_t WF5803_ProcessEvent(uint8_t task_id, uint16_t events)
{
    if (events & WF5803_EVT_START)
    {
        press_done_flag = 0;

        WF5803_Init();

        WF5803_WriteReg(0x30, 0x0A, kPressIn);
        WF5803_WriteReg(0x30, 0x0A, kPressOut);
        WF5803_WriteReg(0x30, 0x0A, kPressAtom);

        tmos_start_task(press_task_id, WF5803_EVT_READ, MS1_TO_SYSTEM_TIME(5));
        return (events ^ WF5803_EVT_START);
    }
    else if (events & WF5803_EVT_READ)
    {
        SensorData_Process(kPressIn);
        SensorData_Process(kPressOut);
        SensorData_Process(kPressAtom);

        tmos_start_task(press_task_id, WF5803_EVT_START, MS1_TO_SYSTEM_TIME(800));

        press_done_flag = 1;
        return (events ^ WF5803_EVT_READ);
    }
    return 0;
}

void BSP_PRESS_Init(void)
{
    press_task_id = TMOS_ProcessEventRegister(WF5803_ProcessEvent);
    tmos_set_event(press_task_id, WF5803_EVT_START);
}
