/*
 * Copyright 2019 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "fsl_lcdifv2.h"
#include "lcdifv2_support.h"
#include "fsl_debug_console.h"

#include "fsl_soc_src.h"
#include "pin_mux.h"
#include "board.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define DEMO_CORE_ID 0
#define DEMO_BYTE_PER_PIXEL     2U
#define DEMO_IMG_WIDTH          640
#define DEMO_IMG_HEIGHT         480

/* Use layer 0 in this example. */
#define DEMO_LCDIFV2_LAYER 0

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

static uint32_t s_frameBufferAddr[2] = {DEMO_FB0_ADDR, DEMO_FB1_ADDR};

/*******************************************************************************
 * Code
 ******************************************************************************/
static void BOARD_ResetDisplayMix(void)
{
    /*
     * Reset the displaymix, otherwise during debugging, the
     * debugger may not reset the display, then the behavior
     * is not right.
     */
    SRC_AssertSliceSoftwareReset(SRC, kSRC_DisplaySlice);
    while (kSRC_SliceResetInProcess == SRC_GetSliceResetState(SRC, kSRC_DisplaySlice))
    {
    }
}


uint32_t addr_new = 0;
#define USE_PXP
//#define PXP_BYPASS
void DEMO_LCDIFV2_IRQHandler(void)
{
    uint32_t intStatus;

    intStatus = LCDIFV2_GetInterruptStatus(DEMO_LCDIFV2, DEMO_CORE_ID);
    LCDIFV2_ClearInterruptStatus(DEMO_LCDIFV2, DEMO_CORE_ID, intStatus);

    if (0 != (intStatus & kLCDIFV2_VerticalBlankingInterrupt))
    {
    	int addr;
#ifdef USE_PXP
        int get_lcd_loaded_buf(void);
        addr = get_lcd_loaded_buf();
#else
        char * usb_pic_output(void);
        addr = (int)usb_pic_output();
#endif
        if(addr)
        {
    		LCDIFV2_SetLayerBufferAddr(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, addr);
    		LCDIFV2_TriggerLayerShadowLoad(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER);
        }
    }
    SDK_ISR_EXIT_BARRIER;
}


void DEMO_LCDIFV2_Init(void)
{
    const lcdifv2_display_config_t lcdifv2Config = {
        .panelWidth    = DEMO_PANEL_WIDTH,
        .panelHeight   = DEMO_PANEL_HEIGHT,
        .hsw           = DEMO_HSW,
        .hfp           = DEMO_HFP,
        .hbp           = DEMO_HBP,
        .vsw           = DEMO_VSW,
        .vfp           = DEMO_VFP,
        .vbp           = DEMO_VBP,
        .polarityFlags = DEMO_POL_FLAGS,
        .lineOrder     = kLCDIFV2_LineOrderRGB,
    };

    const lcdifv2_buffer_config_t fbConfig =
    {
#ifdef USE_PXP
#ifdef PXP_BYPASS
   		.strideBytes = 640 * DEMO_BYTE_PER_PIXEL,
#else
 		.strideBytes = 720 * DEMO_BYTE_PER_PIXEL,
#endif

		.pixelFormat = kLCDIFV2_PixelFormatUYVY
#else
		.strideBytes = 640 * DEMO_BYTE_PER_PIXEL,
		.pixelFormat = kLCDIFV2_PixelFormatYUYV
#endif
    };

    if (kStatus_Success != BOARD_InitDisplayInterface())
    {
        PRINTF("Display interface initialize failed\r\n");

        while (1)
        {
        }
    }

    LCDIFV2_Init(DEMO_LCDIFV2);

    LCDIFV2_SetDisplayConfig(DEMO_LCDIFV2, &lcdifv2Config);

    LCDIFV2_EnableDisplay(DEMO_LCDIFV2, true);

    LCDIFV2_SetLayerBufferConfig(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, &fbConfig);

    LCDIFV2_SetCscMode(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, kLCDIFV2_CscYCbCr2RGB);

	#ifdef USE_PXP
	#ifdef PXP_BYPASS
		LCDIFV2_SetLayerSize(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, 640, 480);
	#else
		LCDIFV2_SetLayerSize(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, 720, 1280);
	#endif
	#else
    	LCDIFV2_SetLayerSize(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, 640, 480);
	#endif

    LCDIFV2_SetLayerOffset(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, 0, 0);

    NVIC_EnableIRQ(DEMO_LCDIFV2_IRQn);
    NVIC_SetPriority(DEMO_LCDIFV2_IRQn, 0);

    LCDIFV2_EnableInterrupts(DEMO_LCDIFV2, DEMO_CORE_ID, kLCDIFV2_VerticalBlankingInterrupt);
}


/*!
 * @brief Main function
 */
int lcdif_main(void)
{
    BOARD_ResetDisplayMix();
    BOARD_InitMipiPanelPins();
    BOARD_InitLcdifClock();
    DEMO_LCDIFV2_Init();
    LCDIFV2_EnableLayer(DEMO_LCDIFV2, DEMO_LCDIFV2_LAYER, true);
}
