#include "PH.h"

osThreadId_t PH_Handle;
const osThreadAttr_t PH_attributes = {
    .name       = "PH",
    .stack_size = 1024,
    .priority   = (osPriority_t) osPriorityBelowNormal,
};

// 事件
osEventFlagsId_t PH_EventHandle;
const osEventFlagsAttr_t PH_Event_attributes = {
  .name = "PH_Event"
};

extern UART_HandleTypeDef huart1;
UART_HandleTypeDef *pPHUart = &huart1;

// uint8_t PH_TEST_BUF[8]  ={0x01, 0x03, 0x00, 0x00, 0x00, 0x04, 0x44, 0x09};
uint8_t PH_TEST_BUF[8]  ={0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B};
uint8_t PH_TRANS_BUF[8]  ={0x01, 0x03, 0x00, 0x00, 0x00, 0x04, 0x44, 0x09};
uint8_t PH_RCV_BUF[13]  ={0};

UART_HELPER_TypeDef *ph_uart_helper;

PH_TypeDef  ph ={
    PH_Init,
    PH_Port,
    PH_Test,
    PH_Start,
    PH_Stop,
    NULL,
    0,      // state
    0,      // data_ok
    {0},    // buf
    0,      // size_received
    0,      // time base
    1000,      // timeout ticks,  1000ms = 1S
    0,          // event_flag
};

int PH_Init( )
{
    ph_uart_helper = UART_HELPER_Init( );

    if (ph_uart_helper ==NULL)  return -1;

    // TODO 接口
    UART_HELPER_Set_Huart( ph_uart_helper, pPHUart );
    UART_HELPER_Set_Interface_Type(ph_uart_helper, Uart_Interface_Max3160_485);

    //  传输
    UART_HELPER_Setup_Trans_mode(  ph_uart_helper, Uart_Trans_DMA);
    // UART_HELPER_Setup_Rcv_mode( ph_uart_helper, Uart_Trans_IT );
    UART_HELPER_Set_enable_idle(  ph_uart_helper, Uart_IDLE_IT_ENABLE);

    //  回调GPIO 操作 数据操作
    UART_HELPER_Set_trans_GPIO(  ph_uart_helper, PH_Trans_GPIO );  // enbale rcv
    UART_HELPER_Set_trans_cplt_GPIO( ph_uart_helper, PH_Trans_Cplt_GPIO );

    UART_HELPER_Set_Callback( ph_uart_helper,&ph, PH_CallBack );

    // 设置 Buf
    UART_HELPER_Set_Rcv_Buf(ph_uart_helper, PH_RCV_BUF, sizeof(PH_RCV_BUF));
    UART_HELPER_Set_Trans_Buf( ph_uart_helper, PH_TRANS_BUF, sizeof(PH_TRANS_BUF) );

    //  GPIO 操作
    switch (ph_uart_helper->interface_type)
    {
        case Uart_Interface_Default:
            break;
        case Uart_Interface_485:
            usart6_send_enable();   
            break;
        case Uart_Interface_Max3160_232:
            PH_MAX3160_232();
            break;
        case Uart_Interface_Max3160_485:
            max3160_485_receive_mode();
            break;    
        default:
            break;
    }
    ph.state = PH_State_Waiting;
    ph.timebase_ticks = osKernelGetTickCount( );
}

void PH_Port( )
{
    PH_Handle = osThreadNew( PH_Task, NULL, &PH_attributes );
    // PH_EventHandle = osEventFlagsNew(&PH_Event_attributes);
}

int PH_Test( )
{
    ph.state = PH_State_Test;  // 操作状态
    return 0;
}

void PH_Start( )
{
    ph.state = PH_State_Get_DATA;  // 操作状态
 
}

void PH_Stop( )
{
    ph.state = PH_State_Stop;
    // TODO stop  task？
}

void PH_Task( )
{
   // memset(  PH_RCV_Buf, 0, 2*PH_Rcv_Buf_Size );  /* ph*3 ph *2 否则内存泄漏 */
    ph.event_flag = 0;
    uint64_t  ticks;
    int err_con = 0;
    int st;
    for ( ; ; )
    {  
        switch (ph.state)
        {
        case PH_State_Waiting:
            log_i( " ph task..... : %d    %d " , ph.state , ph.state );
            osDelay(20);
            break;
        case PH_State_Test:
            ph.state = PH_State_Test_Start;
            continue;
        case PH_State_Test_Start:
            UART_HELPER_Set_Trans_Buf( ph_uart_helper, PH_TEST_BUF, sizeof(PH_TEST_BUF) );
            // HAL_UARTEx_ReceiveToIdle_DMA(&huart1, PH_RCV_BUF,13);
            // __HAL_UART_ENABLE_IT( &huart1, UART_IT_IDLE );
            // HAL_UART_Receive_DMA( &huart1, PH_RCV_BUF, 13 );
 
            PH_Receive();
            PH_Transmit();
            ticks =  osKernelGetTickCount();
            err_con = 0;
            ph.state = PH_State_Testing;
            continue;
        case PH_State_Testing:
            if ( osKernelGetTickCount() - ticks > 2000 )
            {
                err_con++;
                if( err_con >3)
                {
                    log_w( " PH testing  ******** error "  );
                    ph.state = PH_State_Error;
                }
                ph.state = PH_State_Test;                
            }
            osDelay(1);
            continue;
        case PH_State_Test_OK:
            log_i( " ph test ok..... : %d    %d " , ph.state , ph.state );
            ph.state = PH_State_Ready;
            break;

        case PH_State_Ready:
            osDelay(1);
            continue;
        case PH_State_Get_DATA:
            ph.data_ok = 0 ;
            ph.size_received = 0 ;
            memset( ph.result_buf, 0, sizeof(ph.result_buf) );
            UART_HELPER_Set_Trans_Buf( ph_uart_helper, PH_TRANS_BUF, sizeof(PH_TRANS_BUF) );
            PH_Receive();
            PH_Transmit();
            ticks =  osKernelGetTickCount();
            err_con = 0;
            ph.state = PH_State_Get_DATA_Wait;
            continue;
        case PH_State_Get_DATA_Wait:
            if ( osKernelGetTickCount() - ticks > 2000 )
            {
                err_con++;
                if( err_con >3)
                {
                    log_w( " PH testing  ******** error "  );
                    ph.state = PH_State_Error;
                }
                ph.state = PH_State_Get_DATA;                
            }
            osDelay(1);
            continue;
        case PH_State_Get_DATA_OK:
            log_w( " PH data ok  ********  "  );
            // TODO 停止DMA
            if (ph_uart_helper->rcv_mode == Uart_Trans_DMA)
            {
                HAL_UART_DMAStop( ph_uart_helper->huart );
            }
            ph.data_ok = 1 ;
            ph.state = PH_Statee_Get_DATA_Check ;
            continue;       
        case PH_Statee_Get_DATA_Check:
            log_w( " PH data check  ********  "  );
            if(PH_Validate(   )== 0)
            {
                ph.state = PH_State_Stop; 
            }else{
                ph.state = PH_State_Error; 
            }
                           
            osDelay(10); 
            continue;
        case PH_State_Stop:
            log_d("  ph stop, aftetr deal, wait to change status....");
            osDelay(10); 
            continue;
 
        case PH_State_Timeout:
            log_e( " pH timeout ..... "  );
            ph.state = PH_State_Waiting ;
            // TODO 停止DMA
            if (ph_uart_helper->rcv_mode == Uart_Trans_DMA)
            {
            HAL_UART_DMAStop( ph_uart_helper->huart );
            }
            osDelay(5); 
            break;
        case PH_State_Error:
            log_e( " pH error ..... "  );
            ph.state = PH_State_Waiting ;
            // TODO 停止DMA
            if (ph_uart_helper->rcv_mode == Uart_Trans_DMA)
            {
            HAL_UART_DMAStop( ph_uart_helper->huart );
            }
            osDelay(5); 
            break;  
        }
        osDelay(20); 
    }
}


void PH_Trans_GPIO(void) 
{
    // HAL_GPIO_WritePin(R_W_GPIO_Port,R_W_Pin, SET);
    // HAL_GPIO_WritePin(NULL,0, SET);
    HAL_GPIO_WritePin(SEL_232_485_GPIO_Port,SEL_232_485_Pin, SET);
    HAL_GPIO_WritePin(HDPLX_GPIO_Port,HDPLX_Pin, RESET);
    HAL_GPIO_WritePin(DE485_GPIO_Port, DE485_Pin, SET);
}

void PH_Trans_Cplt_GPIO(void) 
{
    // HAL_GPIO_WritePin(R_W_GPIO_Port,R_W_Pin, RESET);
    // HAL_GPIO_WritePin(NULL,0, RESET);
    HAL_GPIO_WritePin(SEL_232_485_GPIO_Port,SEL_232_485_Pin, SET);
    HAL_GPIO_WritePin(HDPLX_GPIO_Port,HDPLX_Pin, SET);
    HAL_GPIO_WritePin(DE485_GPIO_Port, DE485_Pin, RESET);
} 

int PH_Transmit()
{
    //  TODO 结合队列
    ph.size_received =0;
    if( ph_uart_helper->transferring == 0)
    {
        return UART_HELPER_Trans(ph_uart_helper, ph_uart_helper->trans_record->buf, ph_uart_helper->trans_record->size );
    }
    return 0;
}

int PH_Receive()
{
    return UART_HELPER_Start_Rcv(ph_uart_helper, ph_uart_helper->rcv_buf, ph_uart_helper->rcv_size);
    // return UART_HELPER_Start_Rcv(ph_uart_helper, PH_RCV_BUF, 13);
    // return 0;
}

void PH_Set_Timeout_ms(    uint64_t ms_ticks )
{
    ph.timeout_ticks = ms_ticks;
}

int PH_Validate(   )
{
    return CRC16_Check(ph.result_buf ,ph.size_received);
}


int PH_CallBack( PH_TypeDef *pPH, uint8_t *buf, uint16_t size )
{
    log_i( " PH_CallBack  -- state %d " , ph.state);
    uint16_t size_tmp;
    size_tmp =size;
    switch (ph.state)
    {
        case PH_State_Testing:
            if (size>0) 
            {
                ph.state++;
            }
            break;
        case PH_State_Get_DATA_Wait:
            if (size == 0)  return 0;
            if ((size + ph.size_received) >= sizeof(ph.result_buf) )
            {
                size_tmp = sizeof(ph.result_buf) - ph.size_received;
            }
            memcpy( (uint32_t)(ph.result_buf+ph.size_received), ph_uart_helper->rcv_buf, size_tmp );
            ph.size_received += size_tmp;

            if ( ph_uart_helper->enable_idle_it == 0 )
            {
                // Modbus 长度校验，拷贝数据？
                if( ph.size_received == ( ph.result_buf[2]+ 5 ) )
                {
                    ph.state++;
                }
                return 0;
            }
            if ( ph_uart_helper->enable_idle_it == 1 )
            {
                // 长度校验，拷贝数据？
                if( ph.size_received == ( ph.result_buf[2]+ 5 ) )
                {
                    ph.state++;
                }
                return 0;
            }   
            break;  
        default:
            break;
    }
    return 0;
}

// CRCValue = HAL_CRC_Calculate(&hcrc, (uint32_t *)dataBuffer, BUFFER_SIZE);

// void PH_Set_Interface( PH_TypeDef *ph,  UartInterface_TypeDef * interface  )
// {
//     UartHelper_Set_Interface( ph.uarthelper,   interface );
// }
// void PH_Set_Huart( PH_TypeDef *ph,  UART_HandleTypeDef * huart  )
// {
//     ph.uarthelper->huart = huart;
//     // UartHelper_Set_Huart( ph.uarthelper,    huart  );
// }
// void PH_Set_Interface_Type( PH_TypeDef *ph,    Uart_Interface_Type_Typedef interface_type  )
// {
//     ph.interface_type = interface_type;  
//     ph.uarthelper->interface_type = interface_type; 
//     UartInterface_Setup_Interface_type( ph.uarthelper->interface ,ph.interface_type); 
// }