#include "uart_helper.h"
#include "elog.h"


UartHelper_TypeDef * UartHelper_Init( )
{
    UartHelper_TypeDef *Handle = (UartHelper_TypeDef *)malloc(sizeof(UartHelper_TypeDef));
    if (Handle == NULL)
    {
        return NULL;
    }
 
	// Handle->interface = UartInterface_Init();
	Handle->interface = UartInterface_Init();
	// Handle->interface_type = 0;
 
    Handle->interface_type = 0; /* 0: common, 1: 485 ,2:3160*/
	Handle->mode_232_485 = 0; /* 0: common, 1: 485  */
    Handle->trans_type = 2;   /* 0 :polling, 1: IT  2: DMA*/
    Handle->rcv_type = 2;  /* 0 :polling, 1: IT  2: DMA*/
    Handle->idle_enable_disable = 1;    /* 0 不开启空闲中断 ， 1 开启空闲中断 */
	Handle->trans_mode = 2;         /* 0 :polling, 1: IT  2: DMA*/
	Handle->status = Uart_Status_Ready;         /* 0 :polling, 1: IT  2: DMA*/
	Handle->huart = NULL;  
	Handle->obj = NULL;  
	Handle->callback = NULL;  
    // Handle->timeout_enable = 0;        
    // Handle->timeout_ms = 0;        
    // Handle->timebase_ticks = 0;        
    return Handle;

}

void UartHelper_Set_Interface( UartHelper_TypeDef *uarthelper,  UartInterface_TypeDef * interface )
{
    uarthelper->interface = interface;
}
void UartHelper_Set_Huart( UartHelper_TypeDef *uarthelper,  UART_HandleTypeDef * huart  )
{
    uarthelper->huart = huart;
}
void UartHelper_Set_Interface_Type( UartHelper_TypeDef *uarthelper,   Uart_Interface_Type_Typedef interface_type  )
{
    uarthelper->interface_type = interface_type;
}
void UartHelper_Set_Trans_Type( UartHelper_TypeDef *uarthelper,  Uart_Transmode_TypeDef trans_type  )
{
    uarthelper->trans_type = trans_type;
}
void UartHelper_Set_Rcv_Type( UartHelper_TypeDef *uarthelper,  Uart_Transmode_TypeDef rcv_type  )
{
    uarthelper->rcv_type = rcv_type;
}
void UartHelper_Set_Idle_Enable( UartHelper_TypeDef *uarthelper,  Uart_IDLE_Enable_TypeDef idle_enable_disable  )
{
    uarthelper->idle_enable_disable = idle_enable_disable;
}
void UartHelper_Set_TransMode( UartHelper_TypeDef *uarthelper,  Uart_Transmode_TypeDef trans_mode  )
{
    uarthelper->trans_mode = trans_mode;
}
void UartHelper_Set_RsMode_232_485( UartHelper_TypeDef *uarthelper,  Uart_RS_Mode_TypeDef mode_232_485  )
{
    uarthelper->mode_232_485 = mode_232_485;
    UartInterface_Setup_Mode_232_485( uarthelper->interface, uarthelper->mode_232_485);
}

// void UartHelper_Set_timeout( UartHelper_TypeDef *uarthelper,  uint32_t timeout_ms  )
// {
//     uarthelper->timeout_ms = timeout_ms;
//     uarthelper->timeout_enable = 1;
// }

int UartHelper_Set_callback_func_obj( UartHelper_TypeDef *uarthelper,   void * obj,  it_callback callback )
{
    if(uarthelper==NULL || callback==NULL || obj==NULL){
        return -1;
    }
    uarthelper->callback    =callback;
    uarthelper->obj =obj;
    return 0;
}

void UartHelper_Set_rcv_buf( UartHelper_TypeDef *uarthelper, uint8_t *buf, uint32_t buf_size )
{
    uarthelper->receive_buf = buf;
    uarthelper->receive_buf_half_len = buf_size/2;
}

void UartHelper_Set_Trans_Buf( UartHelper_TypeDef *uarthelper, uint8_t *buf, uint32_t buf_size )
{
    uarthelper->trans_buf = buf;
    uarthelper->trans_size = buf_size;
}

int UartHelper_Transmit( UartHelper_TypeDef *uarthelper,  uint8_t * buf, uint16_t size)
{
    // log_i( "SensorSend  size_   "   );
    // set gpio
    UartInterface_Set_GPIO_For_Transmit( uarthelper->interface );
    // it idle  start
    // if ( uarthelper->idle_enable_disable == 1 )    
    // {
    //     log_i( "start idle .... ");
    //     __HAL_UART_ENABLE_IT(uarthelper->huart, UART_IT_IDLE);
    // }

    /* 开启 transmit */
    if (buf!=NULL  )
    {
        uarthelper->status  = Uart_Status_Sending;
        if ( uarthelper->trans_type == 0 )
            return HAL_UART_Transmit( uarthelper->huart,  buf,  size ,0x0FFF);
        if ( uarthelper->trans_type == 1 )
            return HAL_UART_Transmit_IT( uarthelper->huart,  buf,  size );
        if ( uarthelper->trans_type == 2 )
            return HAL_UART_Transmit_DMA( uarthelper->huart,  buf,  size );
    }
    if (buf==NULL  && uarthelper->trans_buf !=NULL)
    {
        uarthelper->status  = Uart_Status_Sending;
 
        if ( uarthelper->trans_type == 0 )
            return HAL_UART_Transmit( uarthelper->huart, uarthelper->trans_buf, uarthelper->trans_size ,0x0FFF);
        if ( uarthelper->trans_type == 1 )
            return HAL_UART_Transmit_IT( uarthelper->huart, uarthelper->trans_buf, uarthelper->trans_size);
        if ( uarthelper->trans_type == 2 )
            return HAL_UART_Transmit_DMA( uarthelper->huart, uarthelper->trans_buf, uarthelper->trans_size);
    }
    return -1;
}


int UartHelper_Begin_Rcv(UartHelper_TypeDef *uarthelper,  uint8_t * buf, uint16_t size)
{
    /* 是否开启空闲中断*/
    if ( uarthelper->idle_enable_disable == 1 )
    {
        __HAL_UART_ENABLE_IT( uarthelper->huart, UART_IT_IDLE );
    }
 
    if ( uarthelper->rcv_type == 0 )
    {
        // TODO  发生错误怎么处理
        HAL_UART_Receive( uarthelper->huart,  buf,  size ,0X0FFF);
    }

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

    if ( uarthelper->rcv_type == 2 )
    {
        // log_i( "start dma rcv.... . ");
        HAL_UART_Receive_DMA( uarthelper->huart,  buf,  size);
    }
}


void UartHelper_Set_GPIO_For_Trans_Cplt(  UartHelper_TypeDef *uarthelper )
{
    uarthelper->status      = Uart_Status_Ready;
    // log_i(" UartHelper_Set_GPIO_For_Trans_Cplt ...  %d   %d", uarthelper->interface_type, uarthelper->mode_232_485);
    if (uarthelper->interface_type != Uart_Interface_Default && uarthelper->mode_232_485 ==Uart_RSMODE_485)
    {
        // log_i(" UartHelper_Set_GPIO_For_Trans_Cplt ... 111111");
        UartHelper_Set_GPIO_For_Trans_Cplt( uarthelper->interface  );
    }
}

void UartHelper_Rcv_Cplt_Callback( UartHelper_TypeDef *uarthelper  )
{
    // TODO 超时 --> 尽量用空闲中断代替  接收指定长度完成中断

    // TODO 拷贝数据
 
}

void UartHelper_Rcv_Idle_Callback( UartHelper_TypeDef *uarthelper  )
{
    /* 搬运 数据到 kfifo*/
 
        log_i("SC6....huart3 IDLE....");

        uint16_t count = __HAL_DMA_GET_COUNTER( uarthelper->huart->hdmarx );
         uint16_t data_length  = 2*uarthelper->receive_data_size - count; 

        // if (count != 0 && data_length != 0)
        if ( data_length != 0 )
        {
            // TODO 拷贝数据  最后一位  datalenth-1
            HAL_UART_DMAStop( uarthelper->huart );
            uarthelper->callback( uarthelper->obj, uarthelper->receive_buf, data_length);

        }
 
}

void UartHelper_Rcv_DMA_Half_Callback( UartHelper_TypeDef *uarthelper  )
{
    /* 循环模式才有  半满中断 */
}
 

int UartHelper_copy(UartHelper_TypeDef *uarthelper,uint8_t *buf,uint32_t buf_size)
{
    int data_len;
    if(uarthelper==NULL || buf==NULL){
        return -1;
    }
    data_len = uarthelper->receive_data_size;
    if(buf_size<data_len){
        return -2;
    }
    if(data_len!=0){
        // TODO
        // memcpy(buf,uart_get_receive_buff(uart_buf),data_len);
        uarthelper->receive_data_size=0;
    }
    return data_len;

}
int UartHelper_isbusy(UartHelper_TypeDef *uarthelper )
{
    if (uarthelper->status==Uart_Status_Sending)
        return 1;
    return 0;
}
void UartHelper_error(UartHelper_TypeDef *uarthelper )
{
     while(1);  
}

uint16_t Get_Crc16(const char *buf, uint16_t len)
{
    int crc = 0xffff;
    for (int i = 0; i < len; i++)
    {
        crc ^= buf[i];
        for (int j = 0; j < 8; j++)
        {
            if (crc & 1 == 1)
            {
                crc >>= 1;
                crc ^= 0xa001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    uint8_t cs1 = crc & 0xff; // 校验码的低字节
    uint8_t cs2 = (crc & 0xff00) >> 8; // 校验码的高字节
    return crc;
};
 

uint8_t Check_Crc16(uint8_t *buf, uint16_t length){   
    uint16_t len = length-2;
      int crc = 0xffff;
    for (int i = 0; i < len; i++)
    {
        crc ^= buf[i];
        for (int j = 0; j < 8; j++)
        {
            if (crc & 1 == 1)
            {
                crc >>= 1;
                crc ^= 0xa001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    uint8_t cs1 = crc & 0xff; // 校验码的低字节
    uint8_t cs2 = (crc & 0xff00) >> 8; // 校验码的高字节
    log_i( "  %d  %d  %d ",crc ,cs1, cs2  )  ;
    log_i( "  %d  %d  %d ",crc ,buf[length-2], buf[length-1]  )  ;

    if ( (crc & 0xff) == buf[length-2] && ((crc & 0xff00) >> 8) == buf[length-1])
    {
        return 1;
    }
    else   
    {
         return 0;       
    } 
}


        //     //  HAL_UART_DMAStop  HAL_UART_Receive_DMA 成对使用，可从指定指针开始
        //     //  HAL_UART_DMAPause HAL_UART_DMAResume 成对使用
        //     HAL_UART_DMAStop( sc6->huart );
        //     memcpy(sc6->SC6_Data_Buf, sc6->SC6_Raw_Buf, data_length);
        //     sc6->size_received = data_length;
        //     log_i("  IDLE.... count  %d   data_length %d   ",count,data_length );
        //     log_i("  IDLE....   -> %02X %02X %02X %02X ", sc6->SC6_Data_Buf[0] , sc6->SC6_Data_Buf[1], sc6->SC6_Data_Buf[2] , sc6->SC6_Data_Buf[3]);
        //     log_i("  IDLE....   -> %02X %02X %02X %02X  ",
        //          sc6->SC6_Data_Buf[data_length] , sc6->SC6_Data_Buf[data_length-1], sc6->SC6_Data_Buf[data_length-2] , sc6->SC6_Data_Buf[data_length-3]);
        //     log_i("  IDLE....   -> %s ", sc6->SC6_Data_Buf );
        //     //  TODO数据清零 DMA指针指向开始的地方  或双缓冲 
        //     // memset(sc6->SC6_Data_Buf, 0, sizeof(sc6->SC6_Data_Buf));
        //     memset(sc6->SC6_Raw_Buf, 0, sizeof(sc6->SC6_Raw_Buf));
        // // HAL_UART_DMAStop( sc6->myuart->huart );
        //             // SC6_Begin_Rcv( sc6,  sc6->SC6_Raw_Buf, sizeof(sc6->SC6_Raw_Buf));
        //         __HAL_UART_ENABLE_IT( sc6->huart, UART_IT_IDLE);
        //         HAL_UART_Receive_DMA( sc6->huart,  sc6->SC6_Raw_Buf, sizeof(sc6->SC6_Raw_Buf));
        //     // HAL_UART_DMAResume( sc6->myuart->huart );

        /* 再次开启DMA接收 重新接收 */
        // HAL_UART_Receive_DMA(&UartHandle, UartHandle.pRxBuffPtr, UartHandle.RxXferSize);