#include "HvDefine.h"
#include "HvPlatform.h"

#include "hv_vos_Comm.h"

#include "hv_comm_DataType.h"
#include "hv_comm_Define.h"
#include "hv_comm_MemParser.h"
#include "hv_comm_Event.h"
#include "hv_comm_Assert.h"
#include "hv_mw_Audio.h"
#include "hv_mw_SystemManager.h"
#include "hv_mw_Video.h"
#include "hv_mw_PanelManager.h"
#include "hv_mw_EventHub.h"
#include "hv_chip_Driver.h"
#include "hv_drv_Mailbox.h"
#include "hv_mw_PQ.h"
#include "hv_drv_Ktx.h"
#include "hv_drv_Uart.h"
#include "hv_chip_Irq.h"

#define UART_TASK_STACK_SIZE             512 /*2K*/
#define UART_TASK_PRIORITY               4

#define RX_BUF_SIZE     64
#define CMD_BUF_SIZE    4

#define CMD_LENTH  0x04
#define MAGIC_NUM0 0x52
#define MAGIC_NUM2 0x00
#define MAGIC_DIFF 0x51

/* buf for uart task to receive data from uart interrupt. */
static UCHAR8 aucUartRcvBuff[RX_BUF_SIZE]   = {0};
/* buf for uart task to send data for ops fd. */
static UCHAR8 aucUartSendBuff[CMD_BUF_SIZE]  = {0};
/* uart task rx buf index. */
static USHORT16 s_ucRxSize = 0;
/* uart task rd buf index. */
static USHORT16 s_ucRdSize = 0;
/* semaphore for uart receive process. */
static HV_VOS_SEMAPHORE_S*  pstUartRxSema = NULL;


VOID Hv_Mw_Uart_MsgProc(UCHAR8 ucCmd)
{
    HV_LOGI("get uart msg code %x\n", ucCmd);
    switch (ucCmd)
    {
        case 0:
        {
            break;
        }
        case 1:
        {
            break;
        }
        case 2:
        {
            break;
        }
        case 3:
        {
            break;
        }
        case 4:
        {
            break;
        }
        case 5:
        {
            break;
        }
        case 6:
        {
            break;
        }
        case 7:
        {
            break;
        }
        case 8:
        {
            break;
        }
        case 9:
        {
            break;
        }
        case 0xa:
        {
            break;
        }
        case 0xb:
        {
            break;
        }
        case 0xc:
        {
            break;
        }
        case 0xd:
        {
            break;
        }
        case 0xe:
        {
            break;
        }
        default:
        {
            break;
        }
    }
    return;
}


/* callback from uart interrupt. */
VOID uart_callback(UartCallbackType enType, VOID *pArg, UCHAR8 ucSize)
{
    if (enType == UART_INT_RX_COMPLETE)
    {
        HV_LOGV("rx int %d + %d.\n", s_ucRxSize, ucSize);
        while (ucSize--)
        {
            aucUartRcvBuff[(s_ucRxSize++)%RX_BUF_SIZE] = *(UCHAR8*)pArg++;
        }

        if (s_ucRxSize >= RX_BUF_SIZE)
        {
            s_ucRxSize -= RX_BUF_SIZE;
        }

        Hv_Vos_ReleaseSemaphoreFromISR(pstUartRxSema);
    }
    else
    {
        ;
    }
    return;
}

VOID Hv_Mw_InitUart(VOID)
{
    UartSelf *pstSelf = NULL;
    UartInitParam stInit;
    memset(&stInit, 0, sizeof(stInit));

    pstUartRxSema = Hv_Vos_InitSemaphore(1, 0);

    stInit.enPort       = UART_PORT_1;
    stInit.uiBaudrate   = 115200;
    stInit.enParity     = UART_PARITY_NONE;
    stInit.enStopbit    = UART_STOPBIT_1;
    stInit.enWordlen    = UART_WORDLEN_8;
    stInit.b9BitMode    = HV_FALSE;
    stInit.bFifoEnable  = HV_TRUE;
    stInit.enRxFiFoTrig = UART_RX_FIFO_CHAR_1;
    stInit.bNewInterface    = HV_TRUE;
    stInit.fCallback        = uart_callback;

    pstSelf = Hv_Drv_Uart_Init(&stInit);
    Hv_Drv_Uart_EnableReceive(stInit.enPort);

    return;
}


VOID Hv_Mw_Uart_MsgDecode(VOID)
{
    USHORT16 usLenth    = 0;
    USHORT16 usIndex    = 0;
    USHORT16 usRcvSize  = 0;
    USHORT16 usSize     = 0;

    if (s_ucRdSize >= RX_BUF_SIZE)
    {
        s_ucRdSize -= RX_BUF_SIZE;
    }
    if (s_ucRdSize > s_ucRxSize)
    {
        usRcvSize = s_ucRxSize + RX_BUF_SIZE;
    }
    else
    {
        usRcvSize = s_ucRxSize;
    }

    HV_LOGV("size now %d - %d.\n", s_ucRdSize, usRcvSize);
    for (usSize = s_ucRdSize; usSize < usRcvSize; usSize++)
    {
        if (usSize + CMD_LENTH > usRcvSize)
        {
            s_ucRdSize = usSize;
            HV_LOGV("size not enough now %d.\n",s_ucRdSize);
            return;
        }

        if ((aucUartRcvBuff[usSize%RX_BUF_SIZE] != MAGIC_NUM0) || (aucUartRcvBuff[(usSize + 2)%RX_BUF_SIZE] != MAGIC_NUM2))
        {
            HV_LOGV("not alligned1.\n");
            continue;
        }
        if ((aucUartRcvBuff[(usSize+1)%RX_BUF_SIZE] + MAGIC_DIFF) != (aucUartRcvBuff[(usSize + 3)%RX_BUF_SIZE]))
        {
            HV_LOGV("not alligned2.\n");
            continue;
        }
        HV_LOGV("get cmd.\n");
        Hv_Mw_Uart_MsgProc(aucUartRcvBuff[(usSize+1)%RX_BUF_SIZE]);
        usSize += CMD_LENTH - 1;
        s_ucRdSize = usSize;
        //return;
    }

    //s_ucRdSize = usRcvSize;

    return;
}


VOID Hv_Uart_taskHandle(VOID* arg)
{
    Hv_Mw_InitUart();
    for (;;)
    {
        Hv_Vos_AcquireSemaphore(pstUartRxSema);
        Hv_Mw_Uart_MsgDecode();
        Hv_Vos_TaskYield();
    }
    return;
}

VOID Hv_User_AddPlatformTask(VOID)
{
    HV_LOG_DEBUG(SYSTEM, "Hv_User_AddPlatformTask!");
    Hv_Vos_TASK_INIT_PARAMS param = {0};
    param.arg = NULL;

    param.entry = Hv_Uart_taskHandle;
    param.name = "uart task";
    param.priority = UART_TASK_PRIORITY;
    param.stackSize = UART_TASK_STACK_SIZE;
    Hv_Vos_TaskInit(&param);
}
VOID Hv_User_InitPlatform(VOID)
{

    return;
}

