#include "pH.h"
#include "elog.h"
#include "FreeRTOS.h"
#include "cmsis_os.h"
#include "stm32f4xx.h"
#include "usart.h"
#include "main.h"

 
/******           Port             ***************/
#if 1

#define  PH_Uart_IRQHandler   USART3_IRQHandler
// #define  PH_Uart_IRQHandler   USART4_IRQHandler
UART_HandleTypeDef *pPHUart = &huart3;
PH_TypeDef *ph ;

My_PH_TypeDef my_pH =
{
    PH_Init,
    PH_Port,
    PH_Test,
    PH_Start,
    PH_Stop,
    SEL_232_485_GPIO_Port,
    HDPLX_GPIO_Port, 
    DE485_GPIO_Port,
    SEL_232_485_Pin,
    HDPLX_Pin,
    DE485_Pin,
    Uart_Interface_Max3160,  /* 接口类型 0: common, 1: 485 ,2:3160*/
    Uart_RSMODE_485,  /* mode_232_485 0 commome  1:485*/
    Uart_Trans_DMA,     /* trans_type0 :polling, 1: IT  2: DMA*/
    Uart_Trans_DMA,     /* rcv_type 0 :polling, 1: IT  2: DMA*/
    Uart_IDLE_IT_ENABLE,     /* idle_enable_disable 0 :不启用空闲 , 1: 启用空闲*/
    0,      //ph
    0,      // temprature
    NULL, /* pointer huart*/
};

extern volatile uint8_t measure_flag  ;

uint8_t PH_SND_Buf[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B };
uint8_t PH_RCV_Buf[PH_Rcv_Buf_Size*2]  = { 0 };

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

void PH_Uart_IRQHandler(void)
{
    if (__HAL_UART_GET_FLAG( ph->uarthelper->huart, UART_FLAG_TC) != RESET)
    {
        // log_i("ph....huart3 TC callback ...");
        PH_Send_Cplt_Callback(   ph );
        // ph->state = PH_Status_Send_Cplt; 
        ph->uarthelper->huart->gState = HAL_UART_STATE_READY;       
        __HAL_UART_CLEAR_FLAG( ph->uarthelper->huart, UART_FLAG_TC );
    }

    if (__HAL_UART_GET_FLAG( ph->uarthelper->huart, UART_FLAG_IDLE ) != RESET)
    {
        uint16_t count = __HAL_DMA_GET_COUNTER( ph->uarthelper->huart->hdmarx );
        log_i("....huart3 IDLE.... %d   site3 == 4 %02X ", count, PH_RCV_Buf[2] );
        uint16_t data_length  = 2*PH_Rcv_Buf_Size - count; 
        if (count == PH_Rcv_Buf_Size) 
        {            
            // HAL_UART_DMAStop( ph->uarthelper->huart ); 
            ph->state = PH_Status_RCV_OK;
        }
        if (count < PH_Rcv_Buf_Size) 
        {            
            // HAL_UART_DMAStop( ph->uarthelper->huart ); 
            ph->state = PH_Status_Error;
        }
        __HAL_UART_CLEAR_IDLEFLAG( ph->uarthelper->huart );
    }
    HAL_UART_IRQHandler( ph->uarthelper->huart );
}

int PH_Init( )
{
    ph = (PH_TypeDef *)malloc(sizeof(PH_TypeDef));

    UartInterface_TypeDef *interface    = UartInterface_Init( );
    UartHelper_TypeDef *uarthelper      = UartHelper_Init();

    PH_Set_Uarthelper( ph,  uarthelper );
    PH_Set_Interface( ph,  interface );
    PH_Set_Huart( ph, pPHUart );
 
    /* set_GPIO  UartInterface */
    UartInterface_Set_Sel_GPIO_Pin( ph->uarthelper->interface, my_pH.sel_gpio, my_pH.sel_pin );
    UartInterface_Set_Dplx_GPIO_Pin( ph->uarthelper->interface, my_pH.dplx_gpio, my_pH.dplx_pin );
    UartInterface_Set_DE485_GPIO_Pin( ph->uarthelper->interface, my_pH.de_gpio, my_pH.de_pin );

    /* interface type */
    PH_Set_Interface_Type( ph, my_pH.interface_type );
    PH_Set_RsMode_232_485 ( ph, my_pH.mode_232_485 ); //  max3160 的232  485选择
    PH_Set_Trans_Type( ph, my_pH.trans_type ) ;
    PH_Set_Rcv_Type ( ph, my_pH.rcv_type ) ;
    PH_Set_Idle_Enable (ph, my_pH.idle_enable_disable ) ;
    // UartHelper_Setup_Interface_type( ph ,my_pH.interface_type); 
 
    //  check  
    if ( ph->uarthelper->huart == pPHUart ){
        log_i ( "ph set huart ok. trans_type -> %d  rcv_type -> %d  ( 0 :polling, 1: IT  2: DMA) ",ph->trans_type ,ph->rcv_type ) ;
        log_i( " interface->   %d  %d (0:default, 1:485, 2:3160) " ,ph->uarthelper->interface_type  ,ph->uarthelper->interface->interface_type );  
        log_i( "ph 232_485 ->   %d  %d (0:232 ,1: 485)   " ,ph->uarthelper->mode_232_485, ph->uarthelper->interface->mode_232_485  );  
    }else{
        log_e ( "ph set huart failure "  ) ;
    }
        
    PH_Set_Timeout( ph, 500 );
    PH_Set_Sendbuf( ph,  PH_SND_Buf, 8 );
    PH_Set_Rcvbuf(  ph,  PH_RCV_Buf, sizeof(PH_RCV_Buf) );

    // set paras;
    ph->timebase        = 0;
    // ph->timeout_ms    = 1000;
    ph->send_status     = Uart_Status_Ready;
    ph->send_flag       = 0;
    ph->command_seq     = 4;
    ph->mode            = 2;
    ph->data_begin_flag = 0;
    ph->state           = PH_Status_Waiting;
    return 0;
}


void PH_Port( )
{
    phHandle = osThreadNew( PH_Task, NULL, &PH_attributes );
}

void PH_Task( )
{
    // log_i( " ph tran mode : %d ", ph->->trans_mode );
    memset(  PH_RCV_Buf, 0, 2*PH_Rcv_Buf_Size );  /* ph*3 ph *2 否则内存泄漏 */
    uint64_t time_ticks;
    // log_i( " ph tran mode : %d    %d " , ph->trans_mode , ph->mode );
 
    for ( ; ; )
    {   
        switch (ph->state)
        {
        case PH_Status_Waiting:
            osDelay(20);
            break;
        case PH_Status_Ready:
            log_i(" pH send  .................. "); 
            my_pH.ph_val        = 0;
            my_pH.temp_val      = 0;
            memset(  ph->rcv_buf, 0, 2*PH_Rcv_Buf_Size );
            PH_Begin_Rcv( ph, ph->rcv_buf, ph->size_rcv );
            // HAL_UARTEx_ReceiveToIdle_DMA( &huart3, PH_RCV_Buf, PH_Rcv_Buf_Size );
            // HAL_UART_Receive_DMA ( &huart3, ph->rcv_buf, ph->size_rcv );
            // __HAL_UART_ENABLE_IT(  &huart3, UART_IT_IDLE );

            ph->timebase = osKernelGetTickCount( );
            // max3160_485_send_mode();
            ph->state = PH_Status_Sending ;
            PH_Send( ph, ph->send_buf, ph->size_send );
            break; 
        case PH_Status_Sending:
            time_ticks = osKernelGetTickCount() ;
            // log_i( " time_ticks :%d   %d" , time_ticks, ph->timebase);
            if ( ( time_ticks - ph->timebase ) > ph->timeout_ms) 
            {
                ph->state = PH_Status_Timeout ;
            }
            osDelay(5); 
            break;
        case PH_Status_Send_Cplt:
            time_ticks = osKernelGetTickCount() ;
            log_i( "PH_Status_Send_Cplt ..... "  );
            if ( (time_ticks - ph->timebase ) > ph->timeout_ms) 
            {
                ph->state = PH_Status_Timeout ;
            }
            osDelay(5); 
            break;
        case PH_Status_RCV_OK:
            if ( my_pH.ph_val == 0 & my_pH.temp_val==0 )
            {
                my_pH.ph_val        = ph->rcv_buf[3]*256 + ph->rcv_buf[4];
                my_pH.temp_val      = ph->rcv_buf[5]*256 + ph->rcv_buf[6];
                
                log_i( "PH_Status_RCV_OK ..... ph %d  temp  %d " , my_pH.ph_val, my_pH.temp_val);
                ph->state = PH_Status_DATA_OK ;
            }
            // TODO 停止DMA
            HAL_UART_DMAStop( ph->uarthelper->huart ); 
            osDelay(20); 
            break;
        case PH_Status_DATA_OK:
            osDelay(20); 
            break;        
        case PH_Status_Timeout:
            log_e( " pH timeout ..... "  );
            ph->state = PH_Status_Waiting ;
            HAL_UART_DMAStop( ph->uarthelper->huart ); 
            osDelay(5); 
            break;
        case PH_Status_Error:
            log_e( " pH error ..... "  );
            ph->state = PH_Status_Waiting ;
            HAL_UART_DMAStop( ph->uarthelper->huart ); 
            osDelay(5); 
            break;         
        default:
            break;
        }

        osDelay(20); 
    }   
}
 
int PH_Test( )
{
    HAL_UART_Transmit_IT( &huart3, ph->send_buf, ph->size_send   );
    osDelay(20);
    if ( HAL_UART_Receive ( &huart3, ph->rcv_buf, ph->size_rcv ,0xFF) != HAL_OK ){
        return -1;
    }
    return 0;
}
void PH_Start( )
{
    // log_e( " pH PH_Start ..... "  );
    ph->state = PH_Status_Ready; 
}
void PH_Stop( )
{
    ph->state = PH_Status_Waiting; 
}

/******************         接口           *******************/


void PH_Set_Uarthelper( PH_TypeDef *ph,  UartHelper_TypeDef * uarthelper)
{
    ph->uarthelper = uarthelper;
}
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); 
}
void PH_Set_RsMode_232_485( PH_TypeDef *ph,  Uart_RS_Mode_TypeDef rs_232_485  )
{
    ph->mode_232_485 = rs_232_485; 
    ph->uarthelper->mode_232_485 = rs_232_485; 
       UartInterface_Setup_Mode_232_485( ph->uarthelper->interface, my_pH.mode_232_485 );
 
}
void PH_Set_Trans_Type( PH_TypeDef *ph,  Uart_Transmode_TypeDef trans_type  )
{
    ph->trans_type = trans_type; 
}
void PH_Set_Rcv_Type( PH_TypeDef *ph,  Uart_Transmode_TypeDef rcv_type  )
{
    ph->rcv_type = rcv_type; 

}
void PH_Set_Idle_Enable( PH_TypeDef *ph,  Uart_IDLE_Enable_TypeDef idle_enable_disable  )
{
    ph->idle_enable_disable = idle_enable_disable; 
}

void PH_Set_TransMode( PH_TypeDef *ph,  Uart_Transmode_TypeDef trans_mode  )
{
    ph->trans_type = trans_mode; 
        ph->rcv_type = trans_mode; 
}

void PH_Set_Timeout( PH_TypeDef *ph,    uint16_t timeout_ms)
{
    ph->timeout_ms = timeout_ms;    
}
void PH_Set_Sendbuf( PH_TypeDef *ph,  uint8_t * buf, uint16_t size)
{
    ph->send_buf = buf;
    ph->size_send = size;
    // log_i( " size_send   %d", sensor->size_send);
}

void PH_Set_Rcvbuf( PH_TypeDef *ph,  uint8_t * buf, uint16_t size)
{
    ph->rcv_buf = buf;
    ph->size_rcv = size;
    // log_i( " size_rcv   %d", demo->size_rcv);
}

int PH_Send( PH_TypeDef *ph,  uint8_t * buf, uint16_t size )
{
    // log_i( "SensorSend  size_    %d", demo->size_send );
    ph->timebase    = HAL_GetTick();
    UartInterface_Set_GPIO_For_Transmit( ph->uarthelper->interface );
    // UartHelper_Send_TxPrepare_Callback( ph->uarthelper );
    // ph->send_status   = 1;
    if ( ph->trans_type == 0 )
        return HAL_UART_Transmit( ph->uarthelper->huart,  buf,  size ,0XFF);
    if ( ph->trans_type == 1 )
        return HAL_UART_Transmit_IT( ph->uarthelper->huart,  buf,  size );
    if ( ph->trans_type == 2 )
        return HAL_UART_Transmit_DMA( ph->uarthelper->huart,  buf,  size );
    return -1;
    // ph->send_flag   = 0;
}


void PH_Begin_Rcv( PH_TypeDef *ph,  uint8_t * buf, uint16_t size)
{
    /* 是否开启空闲中断*/
    if ( ph->idle_enable_disable == 1 )
    {
        // log_i(" ** idle  enable...");
        __HAL_UART_ENABLE_IT( ph->uarthelper->huart, UART_IT_IDLE );
    }
 
    if ( ph->trans_type == 0 )
    {
        // TODO  发生错误怎么处理
        HAL_UART_Receive( ph->uarthelper->huart,  buf,  size ,0X0FFF);
    }

    if ( ph->trans_type == 1 )
    {
        HAL_UART_Receive_IT( ph->uarthelper->huart,  buf,  size);
    }

    if ( ph->trans_type == 2 )
    {
        HAL_UART_Receive_DMA( ph->uarthelper->huart,  buf,  size);
    }
}

void PH_Send_Cplt_Callback( PH_TypeDef *ph )
{
    // ph->timebase    = HAL_GetTick(); 
    ph->status      = Uart_Status_Send_Cplt;
    if ( ph->interface_type != 0 )
    {
        UartInterface_Set_GPIO_For_Trans_Cplt( ph->uarthelper->interface );
        // UartHelper_Set_GPIO_For_Trans_Cplt( ph->uarthelper  );        
    }
 
}

void PH_Rcv_Idle_Callback( PH_TypeDef *ph )
{
    /* 搬运 数据到 kfifo*/
    ph->status       = 0;
    ph->send_flag    = 0;
}



void PH_Rcv_Cplt_Callback( PH_TypeDef *ph  )
{
    /* 搬运 数据到 kfifo*/
    log_i( " PH_Rcv_Cplt_Callback 1 .... " );
    ph->rcv_ok = 1 ;
    // ph->status       = 0;
    // ph->send_flag    = 1;
    // if ( ph->mode < 2 )
    //     ph->command_seq++; 
}

int PH_Get_Data_OK( PH_TypeDef *ph  )
{
    return ph->rcv_ok;
}
void PH_Set_Send_Flag( PH_TypeDef *ph  )
{
    // vPortEnterCritical();
    ph->send_flag    =   1;
    ph->command_seq  =   0;
    ph->data_ok      =   0;
    // vPortExitCritical( );
}

#endif



    // UartHelper_Set_232 485 UartInterface
    // UartInterface_Setup_Mode_232_485( ph->uarthelper->interface, my_pH.mode_232_485 );
    // if (ph->interface_type == 0)
    //     UartInterface_Set_232( ph->uarthelper->interface);
    // if (ph->interface_type == 1)
    //     UartInterface_Set_485( ph->uarthelper->interface);
    // if (ph->interface_type ==2 && my_pH.mode_232_485 ==Uart_RSMODE_232)
    //     UartInterface_Set_232( ph->uarthelper->interface);
    // if (ph->interface_type ==2 && my_pH.mode_232_485 ==Uart_RSMODE_485)
    //     UartInterface_Set_485( ph->uarthelper->interface);
    // log_i( " interface->   %d  %d (0:default, 1:485, 2:3160) " ,ph->uarthelper->interface_type  ,ph->uarthelper->interface->interface_type );  
    // log_i( "ph 232_485 ->   %d  %d (0:232 ,1: 485)   " ,ph->uarthelper->mode_232_485, ph->uarthelper->interface->mode_232_485  );  
