

#include "common_include.h"
#include "s6j3360_LCDB.h"

/*****************************************************************************/
/* Local pre-processor symbols/macros ('#define')                            */
/*****************************************************************************/
//#define     WRITE(r,v) r=v
//#define     READ(r) r

volatile  INT8U     UP_VSYNC;
volatile  INT32U    UpScreenTime;
volatile  INT8U     UpScreenStep;
volatile  INT8U     LcdBusState;

extern void bsp_HDOG_Feed(void);


#define     WPREG_PPC(n,d)                          \
{                                                   \
    un_ppc_keycdr_t wk;                             \
    unsigned long adr = (unsigned long)&n;          \
    unsigned char size_key;                         \
    wk.au16Halfword[0] = adr & 0x7FFF;              \
    size_key = (sizeof(n) >> 1) << 4;               \
    wk.au8Byte[3] = size_key | (0 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    wk.au8Byte[3] = size_key | (1 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    wk.au8Byte[3] = size_key | (2 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    wk.au8Byte[3] = size_key | (3 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    n = d;                                          \
}

/*-------------------------------------------------------------------------
* Function Name  : VsyncDetectCallback
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
*
--------------------------------------------------------------------------*/
static void VsyncDetectCallBack(uint8_t channel)
{
    uint8_t   sw = 0;

    if((UpScreenStep) && (UpScreenTime > 1000))
    {
        LCDPanelUpdtCtrl.Request = 0;
        UpScreenStep = 0;
        UP_VSYNC = 0;
        LcdBusState = 1;
    }
    else
    {
        sw = (memoryVramSel + 1) % 2;
        if((g_DrawInfo.VramCalOverFlag[ sw ]) && (UP_VSYNC == 0))
        {         
             LCDPanelGraphicRAM = (uint32_t*)VRAM_BUF[ sw ];
             memoryVramSel = sw;
             UP_VSYNC = 1;
             LCD_Panel_Update_Req(96,128);
             UpScreenStep = 1;
             UpScreenTime = 0;
        }
    }
}

/*-------------------------------------------------------------------------
* Function Name  : LcdBus_Check
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
*
--------------------------------------------------------------------------*/
void LcdBus_Check(void)
{
    if(LcdBusState)
    {
         LCD_BUS_Init();
    }
}

/*-------------------------------------------------------------------------
* Function Name  : LcdBus_InstrFifo_isr
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
*
--------------------------------------------------------------------------*/
__irq __arm  void LcdBus_InstrFifo_isr(void)
{
    if((UpScreenStep) && (LcdBusState == 0))
    {
         LCD_Panel_Update_ISR(UpScreenStep);
    }
        
    LCDB_InterruptClear = 0x04;
    IRC0_IRQHC = INTERRUPTS_IRQ_NUMBER_86;
}

/*-------------------------------------------------------------------------
* Function Name  : VsyncDetectionInit
* Description    : 初始化外部中断 为了VSYNC同步
* Input          :
* Output         : None
* Return         : None
* onther         : WindowY:page Number
--------------------------------------------------------------------------*/
void VsyncDetectionInit(void)
{
    stc_port_pin_config_t stc_port_pin_config0_12= { .enOutputFunction      = PortOutputResourceGPIO,
        .enOutputDrive         = PortOutputDriveA,
        .enPullResistor        = PortPullResistorNone,
        .enInputLevel          = PortInputLevelCmosA,
        .bInputEnable          = TRUE,
        .bNoiseFilterEnable    = FALSE,
        .enGpioDirection       = PortGpioInput,
    .enGpioInitOutputLevel = PortGpioLow};
    Port_SetPinConfig( 0, 12, &stc_port_pin_config0_12 );
    
    stc_eic_config_t      stcEicConfig;
    // EIC Configuration
    stcEicConfig.enRequestEvent               = EicFallingEdge;          // Detect rising edge
    stcEicConfig.bInputNoiseFilterEnable      = TRUE;                   // Enable the noise filter
    stcEicConfig.bDmaRequestEnable            = FALSE;                  // Disable the DMA request
    stcEicConfig.pfnCallback                  = &VsyncDetectCallBack;   // using interrupts
    
    Port_SelectInputPort( &RIC.unRESIN274, PortInputPortC );
    
    Eic_Init((stc_eic00_t *) &EIC00, 23, &stcEicConfig);
    
    Eic_Enable((stc_eic00_t *) &EIC00, 23);
    
    Port_EnableInput();
}

void LCD_BUS_Init(void)
{
    un_lcdb_interfaceconfig_t                     interfaceCofigTemp      = { 0 };
    un_lcdb_writetimingconfig_t                   writeTimingCofigTemp    = { 0 };
    un_lcdb_readtimingconfig_t                    readTimingCofigTemp     = { 0 };
    un_lcdb_commandtransfermapping0_t             cmdTransMap0CofigTemp   = { 0 };
    un_lcdb_datatransfermapping0_t                dataTransMap0CofigTemp  = { 0 };
    un_lcdb_datatransfermapping1_t                dataTransMap1CofigTemp  = { 0 };
    un_lcdb_colorcomponentbits_t                  colorComponentBitsTemp  = { 0 };
    un_lcdb_colorcomponentshift_t                 colorComponentShiftTemp = { 0 };
    un_lcdb_destinationattributes_t               destAttributesTemp      = { 0 };
    un_lcdb_instructionfifoconfig_t               instructionfifoconfigTemp = { 0 };
    un_lcdb_interruptenable_t                     interruptenableTemp = { 0 };
    
    LcdBusState = 0;
    memoryVramSel = 0;
    
    //端口配置
    WPREG_PPC(PPC_PCFGR215, 0x1002);  // LCDD0  pin127
    WPREG_PPC(PPC_PCFGR216, 0x1002);  // LCDD1  pin128
    WPREG_PPC(PPC_PCFGR217, 0x1002);  // LCDD2  pin129
    WPREG_PPC(PPC_PCFGR218, 0x1002);  // LCDD3  pin130
    WPREG_PPC(PPC_PCFGR222, 0x1002);  // LCDD4  pin136
    WPREG_PPC(PPC_PCFGR223, 0x1002);  // LCDD5  pin137
    WPREG_PPC(PPC_PCFGR224, 0x1002);  // LCDD6  pin138
    WPREG_PPC(PPC_PCFGR225, 0x1002);  // LCDD7  pin139
    
    WPREG_PPC(PPC_PCFGR006, 0x1002);  // CS#    pin008
    WPREG_PPC(PPC_PCFGR007, 0x1002);  // WR#    pin011
    WPREG_PPC(PPC_PCFGR008, 0x1002);  // RD#    pin012
    WPREG_PPC(PPC_PCFGR010, 0x1002);  // RS     pin014
    WPREG_PPC(PPC_PCFGR011, 0x1002);  // RES#   pin015
    VsyncDetectionInit();//WPREG_PPC(PPC_PCFGR012, 0x1002);  // TE     pin016
    
    
    //总线配置
    //Interface Config
    LCDB_LockUnlockLcd = 0x691DB936;
    interfaceCofigTemp.stcField.u2InterfaceType       = 0;      // 0: INTEL80_TYPE1
    interfaceCofigTemp.stcField.u2InterfaceWidth      = 0;      // 0: 8bit LCDBus
    interfaceCofigTemp.stcField.u1CsPolarity          = 0;      // CS is low active
    interfaceCofigTemp.stcField.u1WrPolarity          = 0;      // WR# is default protocol
    interfaceCofigTemp.stcField.u1RdPolarity          = 0;      // RD# is default protocol
    interfaceCofigTemp.stcField.u1RsPolarity          = 0;      // RS is low signal level
    interfaceCofigTemp.stcField.u1DataPolarity        = 0;      // Data bus is used
    interfaceCofigTemp.stcField.u1TePolarity          = 0;      // TE is high active
    LCDB_InterfaceConfig = interfaceCofigTemp.u32Register;
    
    //Write Timing Config
    LCDB_LockUnlockLcd = 0x691DB936;
    writeTimingCofigTemp.u32Register                  = LCDB_WriteTimingConfig;
    writeTimingCofigTemp.stcField.u8WriteSetupCycles  = 1;
    writeTimingCofigTemp.stcField.u8WriteActiveCycles = 3;
    writeTimingCofigTemp.stcField.u8WriteHoldCycles   = 1;
    LCDB_WriteTimingConfig = writeTimingCofigTemp.u32Register;
    
    //Read Timing Config (addr: 0x0014)
    LCDB_LockUnlockLcd = 0x691DB936;
    readTimingCofigTemp.u32Register                   = LCDB_ReadTimingConfig;
    readTimingCofigTemp.stcField.u8ReadSetupCycles    = 2;
    readTimingCofigTemp.stcField.u8ReadActiveCycles   = 5;
    readTimingCofigTemp.stcField.u8ReadHoldCycles     = 2;
    LCDB_ReadTimingConfig = readTimingCofigTemp.u32Register;
    
    //Command Transfer Mapping 0
    LCDB_LockUnlockLcd = 0x691DB936;
    cmdTransMap0CofigTemp.stcField.u5CommandTransfer0Bits   = 8;    // sbits
    cmdTransMap0CofigTemp.stcField.u5CommandTransfer0SrcLsb = 0;    // slsb
    cmdTransMap0CofigTemp.stcField.u5CommandTransfer0DstLsb = 0;    // dlsb
    cmdTransMap0CofigTemp.stcField.u1CommandTransfer0Next   = 0;    // next
    LCDB_CommandTransferMapping0 = cmdTransMap0CofigTemp.u32Register;
    
    //Data Transfer Mapping 0
    LCDB_LockUnlockLcd = 0x691DB936;
    dataTransMap0CofigTemp.stcField.u5DataTransfer0Bits   = 8;      // sbits
    dataTransMap0CofigTemp.stcField.u5DataTransfer0SrcLsb = 0;      // slsb
    dataTransMap0CofigTemp.stcField.u5DataTransfer0DstLsb = 0;      // dlsb
    dataTransMap0CofigTemp.stcField.u1DataTransfer0Next   = 0;      // next
    LCDB_DataTransferMapping0 = dataTransMap0CofigTemp.u32Register;
    
    //ColorComponentBits
    LCDB_LockUnlockLcd = 0x691DB936;
    colorComponentBitsTemp.stcField.u4ComponentBitsBlue  = 0;
    colorComponentBitsTemp.stcField.u4ComponentBitsGreen = 4;
    colorComponentBitsTemp.stcField.u4ComponentBitsRed   = 0;
    LCDB_ColorComponentBits = colorComponentBitsTemp.u32Register;
    
    //ColorComponentShift
    LCDB_LockUnlockLcd = 0x691DB936;
    colorComponentShiftTemp.stcField.u5ComponentShiftBlue  = 0;
    colorComponentShiftTemp.stcField.u5ComponentShiftGreen = 0;
    colorComponentShiftTemp.stcField.u5ComponentShiftRed   = 0;
    LCDB_ColorComponentShift = colorComponentShiftTemp.u32Register;
    
    //DestinationAttributes
    LCDB_LockUnlockLcd = 0x691DB936;
    destAttributesTemp.stcField.u5BitsPerTransfer = 8;
    destAttributesTemp.stcField.u5BitsPerPixel    = 4;
    LCDB_DestinationAttributes = destAttributesTemp.u32Register;
    
    //reset and clear the content of command fifo
    LCDB_LockUnlockLcd = 0x691DB936;
    LCDB_SoftwareReset = 1;
    
    //clear the content of rxfifo
    LCDB_LockUnlockLcd = 0x691DB936;
    LCDB_RxFifoControl = 1;
    
#if 1
    LCDB_LockUnlockLcd = 0x691DB936;
    instructionfifoconfigTemp.stcField.u6InstrThresholdLow = 0;     //下限是 0
    instructionfifoconfigTemp.stcField.u6InstrThresholdHigh = 1;
    instructionfifoconfigTemp.stcField.u2InstrThresholdTrigger = 0;  //0 = LOW
    LCDB_InstructionFifoConfig = instructionfifoconfigTemp.u32Register;

    LCDB_LockUnlockLcd = 0x691DB936;
    interruptenableTemp.stcField.u1InstrFifoInterruptEnable = 1;
    LCDB_InterruptEnable = interruptenableTemp.u32Register;
#endif
}



void LCD_BUS_Panel_Reset_Ctrl(uint8_t Level)
{
    INT16U cnt = 0;
    while (LCD_BUS_Get_Status())
    {
        cnt ++;
        if(cnt > 60000)
        {
            break;
        }
    }
    
    if(Level)
    {
        LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_SET_RESET, 1);
    }
    else
    {
        LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_SET_RESET, 0);
    }
    LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_NOP, 16);
}


void LCD_BUS_Write_Cmd(uint8_t Cmd, uint8_t *pPara, uint8_t ParaLen)
{
    uint16_t i = 0;
    
    if ((ParaLen) && (pPara == NULL))
        return;
    
    while (LCD_BUS_Get_Status())
    {
        i ++;
        if(i > 800)
        {
            break;
        }
    }

    LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_IR_SET, Cmd);
    
    if(ParaLen)
    {   
        for(i = 0; i < ParaLen; i++)
        {
            LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_DR_SET, pPara[ i ]);
        }
    }
}

uint8_t LCD_BUS_Get_Status(void)
{
    if ((LCDB_InstrFifoStatus_InstrEmpty == 0) && (LCDB_SequencerStatus_LcdInterfaceState == 0))
        return 1;
    
    return 0;
}

void LCD_BUS_Write_Bus_Cmd(uint32_t Opcode, uint8_t Para)
{
    if(LCDB_InstrFifoStatus_InstrFull)
    {
        NOP();NOP();NOP();NOP();NOP();
    }
    if (LCDB_InstrFifoStatus_InstrFull == 0)
    {
        LCDB_InstructionFifo0 = (Opcode + Para);
    }
}

void LCD_BUS_Write_Bus_Fifo(uint32_t Data)
{
    if(LCDB_InstrFifoStatus_InstrFull)
    {
        NOP();NOP();NOP();NOP();NOP();
    }
    if (LCDB_InstrFifoStatus_InstrFull == 0)
    {
        LCDB_InstructionFifo0 = Data;
    }
}

