text: /*
   * Copyright  2017-2019 NXP
   * All rights reserved.
   *
   *
   * SPDX-License-Identifier: BSD-3-Clause
   */
  
  #include "fsl_common.h"
  #include "fsl_elcdif.h"
  #include "fsl_debug_console.h"
  
  #include "fsl_gpio.h"
  #include "pin_mux.h"
  #include "clock_config.h"
  #include "board.h"
  /*******************************************************************************
   * Definitions
   ******************************************************************************/
  #define APP_ELCDIF LCDIF
  
  #define APP_IMG_HEIGHT 272
  #define APP_IMG_WIDTH  480
  #define APP_HSW        41
  #define APP_HFP        4
  #define APP_HBP        8
  #define APP_VSW        10
  #define APP_VFP        4
  #define APP_VBP        2
  #define APP_POL_FLAGS \
      (kELCDIF_DataEnableActiveHigh | kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DriveDataOnRisingClkEdge)
  
  /* Display. */
  #define LCD_DISP_GPIO     GPIO1
  #define LCD_DISP_GPIO_PIN 2
  /* Back light. */
  #define LCD_BL_GPIO     GPIO2
  #define LCD_BL_GPIO_PIN 31
  
  /* Frame buffer data alignment, for better performance, the LCDIF frame buffer should be 64B align. */
  #define FRAME_BUFFER_ALIGN 64
  
  #ifndef APP_LCDIF_DATA_BUS
  #define APP_LCDIF_DATA_BUS kELCDIF_DataBus24Bit
  #endif
  
  /*******************************************************************************
   * Prototypes
   ******************************************************************************/
  void BOARD_EnableLcdInterrupt(void);
  
  /*******************************************************************************
   * Variables
   ******************************************************************************/
  static volatile bool s_frameDone = false;
  
  AT_NONCACHEABLE_SECTION_ALIGN(static uint32_t s_frameBuffer[2][APP_IMG_HEIGHT][APP_IMG_WIDTH], FRAME_BUFFER_ALIGN);
  
  /*******************************************************************************
   * Code
   ******************************************************************************/
  extern void APP_LCDIF_IRQHandler(void);
  
  void LCDIF_IRQHandler(void)
  {
      APP_LCDIF_IRQHandler();
  }
  
  /* Enable interrupt. */
  void BOARD_EnableLcdInterrupt(void)
  {
      EnableIRQ(LCDIF_IRQn);
  }
  
  /* Initialize the LCD_DISP. */
  void BOARD_InitLcd(void)
  {
      volatile uint32_t i = 0x1000U;
  
      gpio_pin_config_t config = {
          kGPIO_DigitalOutput,
          0,
          kGPIO_NoIntmode,
      };
  
      /* Reset the LCD. */
      GPIO_PinInit(LCD_DISP_GPIO, LCD_DISP_GPIO_PIN, &config);
  
      GPIO_PinWrite(LCD_DISP_GPIO, LCD_DISP_GPIO_PIN, 0);
  
      while (i--)
      {
      }
  
      GPIO_PinWrite(LCD_DISP_GPIO, LCD_DISP_GPIO_PIN, 1);
  
      /* Backlight. */
      config.outputLogic = 1;
      GPIO_PinInit(LCD_BL_GPIO, LCD_BL_GPIO_PIN, &config);
  }
  
  void BOARD_InitLcdifPixelClock(void)
  {
      /*
       * The desired output frame rate is 60Hz. So the pixel clock frequency is:
       * (480 + 41 + 4 + 18) * (272 + 10 + 4 + 2) * 60 = 9.2M.
       * Here set the LCDIF pixel clock to 9.3M.
       */
  
      /*
       * Initialize the Video PLL.
       * Video PLL output clock is OSC24M * (loopDivider + (denominator / numerator)) / postDivider = 93MHz.
       */
      clock_video_pll_config_t config = {
          .loopDivider = 31,
          .postDivider = 8,
          .numerator   = 0,
          .denominator = 0,
      };
  
      CLOCK_InitVideoPll(&config);
  
      /*
       * 000 derive clock from PLL2
       * 001 derive clock from PLL3 PFD3
       * 010 derive clock from PLL5
       * 011 derive clock from PLL2 PFD0
       * 100 derive clock from PLL2 PFD1
       * 101 derive clock from PLL3 PFD1
       */
      CLOCK_SetMux(kCLOCK_LcdifPreMux, 2);
  
      CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 4);
  
      CLOCK_SetDiv(kCLOCK_LcdifDiv, 1);
  }
  
  
  void APP_LCDIF_IRQHandler(void)
  {
      uint32_t intStatus;
  
      intStatus = ELCDIF_GetInterruptStatus(APP_ELCDIF);
  
      ELCDIF_ClearInterruptStatus(APP_ELCDIF, intStatus);
  
      if (intStatus & kELCDIF_CurFrameDone)
      {
          s_frameDone = true;
      }
      SDK_ISR_EXIT_BARRIER;
  }
  
  void APP_ELCDIF_Init(void)
  {
      const elcdif_rgb_mode_config_t config = {
          .panelWidth    = APP_IMG_WIDTH,
          .panelHeight   = APP_IMG_HEIGHT,
          .hsw           = APP_HSW,
          .hfp           = APP_HFP,
          .hbp           = APP_HBP,
          .vsw           = APP_VSW,
          .vfp           = APP_VFP,
          .vbp           = APP_VBP,
          .polarityFlags = APP_POL_FLAGS,
          .bufferAddr    = (uint32_t)s_frameBuffer[0],
          .pixelFormat   = kELCDIF_PixelFormatXRGB8888,
          .dataBus       = APP_LCDIF_DATA_BUS,
      };
  
  #if (defined(APP_ELCDIF_HAS_DISPLAY_INTERFACE) && APP_ELCDIF_HAS_DISPLAY_INTERFACE)
      BOARD_InitDisplayInterface();
  #endif
      ELCDIF_RgbModeInit(APP_ELCDIF, &config);
  }
  
  void APP_FillFrameBuffer(uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH])
  {
      /* Background color. */
      static const uint32_t bgColor = 0U;
      /* Foreground color. */
      static uint8_t fgColorIndex          = 0U;
      static const uint32_t fgColorTable[] = {0x000000FFU, 0x0000FF00U, 0x0000FFFFU, 0x00FF0000U,
                                              0x00FF00FFU, 0x00FFFF00U, 0x00FFFFFFU};
      uint32_t fgColor                     = fgColorTable[fgColorIndex];
  
      /* Position of the foreground rectangle. */
      static uint16_t upperLeftX  = 0U;
      static uint16_t upperLeftY  = 0U;
      static uint16_t lowerRightX = (APP_IMG_WIDTH - 1U) / 2U;
      static uint16_t lowerRightY = (APP_IMG_HEIGHT - 1U) / 2U;
  
      static int8_t incX = 1;
      static int8_t incY = 1;
  
      /* Change color in next forame or not. */
      static bool changeColor = false;
  
      uint32_t i, j;
  
      /* Background color. */
      for (i = 0; i < APP_IMG_HEIGHT; i++)
      {
          for (j = 0; j < APP_IMG_WIDTH; j++)
          {
              frameBuffer[i][j] = bgColor;
          }
      }
  
      /* Foreground color. */
      for (i = upperLeftY; i < lowerRightY; i++)
      {
          for (j = upperLeftX; j < lowerRightX; j++)
          {
              frameBuffer[i][j] = fgColor;
          }
      }
  
      /* Update the format: color and rectangle position. */
      upperLeftX += incX;
      upperLeftY += incY;
      lowerRightX += incX;
      lowerRightY += incY;
  
      changeColor = false;
  
      if (0U == upperLeftX)
      {
          incX        = 1;
          changeColor = true;
      }
      else if (APP_IMG_WIDTH - 1 == lowerRightX)
      {
          incX        = -1;
          changeColor = true;
      }
  
      if (0U == upperLeftY)
      {
          incY        = 1;
          changeColor = true;
      }
      else if (APP_IMG_HEIGHT - 1 == lowerRightY)
      {
          incY        = -1;
          changeColor = true;
      }
  
      if (changeColor)
      {
          fgColorIndex++;
  
          if (ARRAY_SIZE(fgColorTable) == fgColorIndex)
          {
              fgColorIndex = 0U;
          }
      }
  }
  
  /*!
   * @brief Main function
   */
  int main(void)
  {
      uint32_t frameBufferIndex = 0;
  
      BOARD_ConfigMPU();
      BOARD_InitPins();
      BOARD_InitSemcPins();
      BOARD_BootClockRUN();
      BOARD_InitLcdifPixelClock();
      BOARD_InitDebugConsole();
      BOARD_InitLcd();
  
      PRINTF("LCDIF RGB example start...\r\n");
  
      APP_ELCDIF_Init();
  
      BOARD_EnableLcdInterrupt();
  
      /* Clear the frame buffer. */
      memset(s_frameBuffer, 0, sizeof(s_frameBuffer));
  
      APP_FillFrameBuffer(s_frameBuffer[frameBufferIndex]);
  
      ELCDIF_EnableInterrupts(APP_ELCDIF, kELCDIF_CurFrameDoneInterruptEnable);
      ELCDIF_RgbModeStart(APP_ELCDIF);
  
      while (1)
      {
          frameBufferIndex ^= 1U;
  
          APP_FillFrameBuffer(s_frameBuffer[frameBufferIndex]);
  
          ELCDIF_SetNextBufferAddr(APP_ELCDIF, (uint32_t)s_frameBuffer[frameBufferIndex]);
  
          s_frameDone = false;
          /* Wait for previous frame complete. */
          while (!s_frameDone)
          {
          }
      }
  }
  