/**
 * @file hv_pm51_app_Mailbox.c
 * @brief Implemented mailbox communication with SoC
 * @details 
 * @author HiView SoC Software Team
 * @version 0.0.1
 * @date 20230301
 * @copyright Copyright(c),2023-3, Hiview Software. All rights reserved.
 * @par History: 
 * <table>
 * <tr><th>author                     <th>date           <th>description
 * <tr><td>HiView SoC Software Team   <td>20230301       <td>Create and first Version.
 * </table>
**/

#include "HS_PAGE_HT7315_8051_reg.h"
#include "hv_pm51_Setting.h"
#include "hv_pm51_driver_Reg.h"
#include "hv_pm51_driver_UART.h"
#include "hv_pm51_app_Sys.h"
#include "hv_pm51_app_PM.h"
#include "hv_pm51_app_Key.h"
#include "hv_pm51_driver_Timer.h"
#include "hv_pm51_app_Mailbox.h"
#include "KeyboardConfig.h"

#define MAILBOX_MSG_POOL_SIZE         8

static xdata MsgPoolItem s_astSendMsgPool[MAILBOX_MSG_POOL_SIZE] = {0};
static xdata SendMsgPoolMgr s_stSendMsgPoolMgr;

extern xUCHAR8 ucACBootFlag;
extern UCHAR8 ucPmLedMode;
extern UCHAR8 ucPmFixMode;
extern UCHAR8 ucPmCurMainChannel;
extern UCHAR8 ucPmCurSubChannel;
extern xUCHAR8 ucFactoyMode;
extern UCHAR8 ucPowerState;

BOOL Hv_PM51_Mailbox_MsgPoolIsEmpty(void)
{
    if(s_stSendMsgPoolMgr.u16NumOfFreeItems == s_stSendMsgPoolMgr.u16TotalNumOfItems)
    {
        return HV_TRUE;
    }
    else
    {
        return HV_FALSE;
    }
}

void Hv_PM51_Mailbox_Init(void)
{
    s_stSendMsgPoolMgr.pStMsgPool = s_astSendMsgPool;
    s_stSendMsgPoolMgr.u16TotalNumOfItems = sizeof(s_astSendMsgPool)/sizeof(MsgPoolItem);
    s_stSendMsgPoolMgr.u16NumOfFreeItems = s_stSendMsgPoolMgr.u16TotalNumOfItems;
    s_stSendMsgPoolMgr.u16CurSendingItem = s_stSendMsgPoolMgr.u16TotalNumOfItems;
    s_stSendMsgPoolMgr.u16CurWritableItem = s_stSendMsgPoolMgr.u16TotalNumOfItems;

    //Hv_PM51_Reg_Write(REG_STBY_INTERRUPT, 0x00000912);
}

xUCHAR8 Hv_PM51_Mailbox_Send(Msg *pstMsg)
{
    xUSHORT16 usCount = 0;

    if (pstMsg == NULL)
        return HV_FALSE;
    if (s_stSendMsgPoolMgr.u16NumOfFreeItems <= 0)
    {
        //s_astSendMsgPool's space have exhausted.
        return HV_FALSE;
    }

    for (usCount = 0; usCount < s_stSendMsgPoolMgr.u16TotalNumOfItems; usCount++)
    {
        s_stSendMsgPoolMgr.u16CurWritableItem++;
        if(s_stSendMsgPoolMgr.u16CurWritableItem >= s_stSendMsgPoolMgr.u16TotalNumOfItems)
            s_stSendMsgPoolMgr.u16CurWritableItem = 0;
        
        if(s_astSendMsgPool[s_stSendMsgPoolMgr.u16CurWritableItem].bIsUsed == HV_FALSE)
        {
            s_astSendMsgPool[s_stSendMsgPoolMgr.u16CurWritableItem].bIsUsed = HV_TRUE;
            s_stSendMsgPoolMgr.u16NumOfFreeItems--;
            s_astSendMsgPool[s_stSendMsgPoolMgr.u16CurWritableItem].stMsg = *pstMsg;
            break;
        }
    }

    if(usCount == s_stSendMsgPoolMgr.u16TotalNumOfItems)
        return HV_FALSE;
    else
        return HV_TRUE;
}

void Hv_PM51_Mailbox_SendHandler(void)
{
    xdata MsgHeader *pstMsgHeader = NULL;
    xUSHORT16 usCount   = 0;
    xULONG32 ulRegVal   = 0;
    xUCHAR8  *pstMsg    = NULL;
    xUCHAR8 u8LoopCnt   = 0;
    xUCHAR8 u8Retry     = 10;
    xULONG32 ulRegtemp  = 0;

    if (s_stSendMsgPoolMgr.u16NumOfFreeItems == s_stSendMsgPoolMgr.u16TotalNumOfItems)
    {
        /* no msg need to send in s_astSendMsgPool */
        return;
    }

    u8LoopCnt = 0;
    while((s_stSendMsgPoolMgr.u16NumOfFreeItems < s_stSendMsgPoolMgr.u16TotalNumOfItems) && (u8LoopCnt < 10))
    {
        EI1 = 0xDF; /* disable int 11 better to disable ADC wake up en? */
        for (usCount = 0; usCount < s_stSendMsgPoolMgr.u16TotalNumOfItems;)
        {
            ulRegVal = Hv_PM51_Reg_ReadArray(HS_Standby__standby_mcu_reg__reg_stby_reg0_ADDR);
            pstMsgHeader = (MsgHeader *)&ulRegVal;
            if (pstMsgHeader->u8MsgType != E_MAILBOX_CMD_NULL)  /* E_MAILBOX_CMD_NULL means that the RISC have read the previous msg. */
            {
                if (u8Retry--)
                {
                    Hv_PM51_Sys_DelayMs(50);
                    //Hv_PM51_Uart_Print("wait!\r\n ");
                    continue;
                    //break;
                }
                else
                {
                    //Hv_PM51_Uart_Print("timeout!\r\n ");
                } 
            }

            u8Retry = 3;
            s_stSendMsgPoolMgr.u16CurSendingItem++;
            if (s_stSendMsgPoolMgr.u16CurSendingItem >= s_stSendMsgPoolMgr.u16TotalNumOfItems)
                s_stSendMsgPoolMgr.u16CurSendingItem = 0;

            if (s_astSendMsgPool[s_stSendMsgPoolMgr.u16CurSendingItem].bIsUsed == HV_TRUE)
            {
                pstMsg = (UCHAR8 *)&s_astSendMsgPool[s_stSendMsgPoolMgr.u16CurSendingItem].stMsg;
                Hv_PM51_Reg_WriteArray(HS_Standby__standby_mcu_reg__reg_stby_reg1_ADDR, *(ULONG32 *)&pstMsg[4]);
                Hv_PM51_Reg_WriteArray(HS_Standby__standby_mcu_reg__reg_stby_reg2_ADDR, *(ULONG32 *)&pstMsg[8]);
                Hv_PM51_Reg_WriteArray(HS_Standby__standby_mcu_reg__reg_stby_reg3_ADDR, *(ULONG32 *)&pstMsg[12]);
                Hv_PM51_Reg_WriteArray(HS_Standby__standby_mcu_reg__reg_stby_reg0_ADDR, *(ULONG32 *)pstMsg);    //note that REG_STBY_MBX_REG0 must be wrote at the end.
                s_astSendMsgPool[s_stSendMsgPoolMgr.u16CurSendingItem].bIsUsed = HV_FALSE;
                s_stSendMsgPoolMgr.u16NumOfFreeItems++;
                Hv_PM51_Sys_DelayMs(50);
                break;
            }
            usCount++;
        }
        EI1 = 0xFF; //enable int 11
        u8LoopCnt++;
        Hv_PM51_Sys_DelayMs(25);
    }

}

void Hv_PM51_Mailbox_RecvHandler(void)
{
    xULONG32 ulRegVal = 0;
    xdata MsgHeader *pstMsgHeader;

    ulRegVal = Hv_PM51_Reg_ReadArray(HS_Standby__standby_mcu_reg__reg_stby_reg4_ADDR);
    pstMsgHeader = (MsgHeader *)&ulRegVal;
    switch(pstMsgHeader->u8MsgType)
    {
        case E_MAILBOX_CMD_RISC_TO_PM_POWER_OFF_ACK:
            Hv_PM51_Uart_Print("Received poweroff ack message from MIPS.\r\n");
            ucPowerState = POWER_STATE_OFF;
            Hv_PM51_Timer_Clear(EXTIMER1);
#if PM51_CONFIG_FAKE_DC
            ucACBootFlag = 0x0;
            Hv_PM51_PM_EnterStandBy();
            Hv_PM51_PM_SetHpdLow();
#else
            Hv_PM51_PM_EnterPowerOff();
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_STAND_BY:
            Hv_PM51_Uart_Print("Received standby message from MIPS.\r\n");
            ucPowerState = POWER_STATE_STANDBY;
#ifdef HV_PROJECT_CONFIG_AUTO_POWEROFF_MINUTES
            ulRegVal =  Hv_PM51_Reg_ReadByte(HS_Standby__standby_mcu_reg__reg_stby_reg5_ADDR);
            if (0xaa == (ulRegVal & 0xff))
            {
                Hv_PM51_Sys_SetStandby2DCTimerState(HV_TRUE);
                Hv_PM51_Timer_Clear(EXTIMER1);
                Hv_PM51_Timer_Set(EXTIMER1, STANDBY_TIMEOUT);
            }
#endif
            Hv_PM51_PM_EnterStandBy();
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_NORMAL:
            Hv_PM51_Uart_Print("Received bootup normally message from MIPS.\r\n");
            Hv_PM51_Sys_SetMipsBootState(HV_TRUE);
            ucPowerState = POWER_STATE_NORMAL;

            Hv_PM51_Key_Handler(PM51_CONFIG_MENU_KEY_WITH_ADC_INDEX);
            {
                /* if factory mode key is pressed */
                if(PM51_Key_FactoryModeJudgeMenuSts())
                {
                    xdata Msg stMsg;
                    if (ucACBootFlag == 1)
                    {
                        stMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_PM_TO_RISC_FACTORY_MODE;
                        stMsg.stMsgHeader.pu8MsgLen[0] = 0;
                        Hv_PM51_Mailbox_Send(&stMsg);
                        Hv_PM51_Uart_Print("Factory mode !\r\n");
                    }
                    else if (ucACBootFlag == 0)
                    {
                        stMsg.stMsgHeader.u8MsgType = E_MAILBOX_CMD_PM_TO_RISC_LOCK_MODE;
                        stMsg.stMsgHeader.pu8MsgLen[0] = 0;
                        Hv_PM51_Mailbox_Send(&stMsg);
                    }
                    else
                    {
                    }
                    #if PM51_CONFIG_FAKE_DC
                    ucACBootFlag = 0xaa;
                    #endif
                }
            }
            /* set KEY working */
            Hv_PM51_Sys_SetKeyState(HV_TRUE);
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_LED_MODE_OFF:
            Hv_PM51_Uart_Print("Received led mode off message from MIPS.\r\n");
            ucPmLedMode = HV_MODE_OFF;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_LED_MODE_ADDR, PM51_DEBUG_LED_MODE_OFF);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_LED_MODE_ON:
            Hv_PM51_Uart_Print("Received led mode on message from MIPS.\r\n");
            ucPmLedMode = HV_MODE_ON;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_LED_MODE_ADDR, PM51_DEBUG_LED_MODE_ON);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_FIX_MODE_OFF:
            ucPmFixMode = HV_MODE_OFF;
            Hv_PM51_Uart_Print("Received Fix mode off message from MIPS.\r\n");
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_AUTO_SEARCH_ADDR, PM51_DEBUG_AUTO_SEARCH_ON);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_FIX_MODE_ON:
            Hv_PM51_Uart_Print("Received Fix mode on message from MIPS.\r\n");
            ucPmFixMode = HV_MODE_ON;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_AUTO_SEARCH_ADDR, PM51_DEBUG_AUTO_SEARCH_OFF);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_MAIN_CHANNEL_HDMI0:
            Hv_PM51_Uart_Print("Received current main channel HDMI0 message from MIPS.\r\n");
            ucPmCurMainChannel = CUR_CHANNEL_HDMI0;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_MAIN_CHANNEL_ADDR, PM51_DEBUG_MAIN_CHANNEL_HDMI0);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_MAIN_CHANNEL_HDMI1:
            Hv_PM51_Uart_Print("Received current main channel HDMI1 message from MIPS.\r\n");
            ucPmCurMainChannel = CUR_CHANNEL_HDMI1;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_MAIN_CHANNEL_ADDR, PM51_DEBUG_MAIN_CHANNEL_HDMI1);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_MAIN_CHANNEL_DP0:
            Hv_PM51_Uart_Print("Received current main channel DP0 message from MIPS.\r\n");
            ucPmCurMainChannel = CUR_CHANNEL_DP0;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_MAIN_CHANNEL_ADDR, PM51_DEBUG_MAIN_CHANNEL_DP0);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_MAIN_CHANNEL_DP1:
            Hv_PM51_Uart_Print("Received current main channel DP1 message from MIPS.\r\n");
            ucPmCurMainChannel = CUR_CHANNEL_DP1;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_MAIN_CHANNEL_ADDR, PM51_DEBUG_MAIN_CHANNEL_DP1);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_SUB_CHANNEL_HDMI0:
            Hv_PM51_Uart_Print("Received current sub channel HDMI0 message from MIPS.\r\n");
            ucPmCurSubChannel = CUR_CHANNEL_HDMI0;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_SUB_CHANNEL_ADDR, PM51_DEBUG_SUB_CHANNEL_HDMI0);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_SUB_CHANNEL_HDMI1:
            Hv_PM51_Uart_Print("Received current sub channel HDMI1 message from MIPS.\r\n");
            ucPmCurSubChannel = CUR_CHANNEL_HDMI1;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_SUB_CHANNEL_ADDR, PM51_DEBUG_SUB_CHANNEL_HDMI1);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_SUB_CHANNEL_DP0:
            Hv_PM51_Uart_Print("Received current sub channel DP0 message from MIPS.\r\n");
            ucPmCurSubChannel = CUR_CHANNEL_DP0;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_SUB_CHANNEL_ADDR, PM51_DEBUG_SUB_CHANNEL_DP0);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_CUR_SUB_CHANNEL_DP1:
            Hv_PM51_Uart_Print("Received current sub channel DP1 message from MIPS.\r\n");
            ucPmCurSubChannel = CUR_CHANNEL_DP1;
#if PM51_DEBUG_DUMMY_REGS
            Hv_PM51_Reg_WriteByte(PM51_DEBUG_SUB_CHANNEL_ADDR, PM51_DEBUG_SUB_CHANNEL_DP1);
#endif
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_SET_LED_OFF:
            Hv_PM51_Uart_Print("Received set LED off message from MIPS.\r\n");
            PM51_Key_SetLed(E_KEY_LED_OFF);
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON:
            Hv_PM51_Uart_Print("Received set LED on message from MIPS.\r\n");
            PM51_Key_SetLed(E_KEY_LED_ON);
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_SET_LED_BREATH:
            Hv_PM51_Uart_Print("Received set LED breath message from MIPS.\r\n");
            PM51_Key_SetLed(E_KEY_LED_BREATH);
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON1:
            Hv_PM51_Uart_Print("Received set LED on1 message from MIPS.\r\n");
            PM51_Key_SetLed(E_KEY_LED_ON1);
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON2:
            Hv_PM51_Uart_Print("Received set LED on2 message from MIPS.\r\n");
            PM51_Key_SetLed(E_KEY_LED_ON2);
            break;
        case E_MAILBOX_CMD_RISC_TO_PM_SET_LED_ON3:
            Hv_PM51_Uart_Print("Received set LED on3 message from MIPS.\r\n");
            PM51_Key_SetLed(E_KEY_LED_ON3);
            break;
        default:
            break;
    }

    /* notify the RISC that PM51 have received the msg. */
    Hv_PM51_Reg_WriteArray(HS_Standby__standby_mcu_reg__reg_stby_reg4_ADDR, 0);
}
