/*
 * Copyright 2017 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#include "pin_mux.h"
#include "fsl_device_registers.h"
#include "clock_config.h"
#include "pin_mux.h"
#include "fsl_power.h"
#include "fsl_inputmux.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_gpio.h"
#include "fsl_usart.h"
#include "fsl_i2c.h"
#include "lcd.h"
#include "log.h"
#include "ov7670.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define DEMO_USART USART0
#define DEMO_USART_CLK_FREQ CLOCK_GetFlexCommClkFreq(0U)
#define PINFUNC_CAMERA		15	/* Pin function for Camera engine to be configured by ARM CPU*/
/*******************************************************************************
 * Variables
 ******************************************************************************/
/**
 * @brief	camera initialization
 * @return	Nothing
 */
extern void Camera_Init(void);
/**
 * @brief	camera start
 * @return	Nothing
 */
extern void Camera_Start(void);

volatile uint32_t DataReadyFlag;
/*******************************************************************************
 * Code
 ******************************************************************************/

void Reserved46_IRQHandler(){
	DataReadyFlag = 1; // tell ARM data is ready from Camera engine
};

/*!
 * @brief Main function
 */
int main(void) {	

    usart_config_t config;
    /* Define the init structure for the output pin*/
    gpio_pin_config_t gpio_config = {
        kGPIO_DigitalOutput,
        1,
    };	
		
    BOARD_BootClockPLL150M();//set the system clock 150MHz, camera engine will use this clock as well

    CLOCK_EnableClock(kCLOCK_InputMux);                        /* Enables the clock for the kCLOCK_InputMux block. 0 = Disable; 1 = Enable.: 0x01u */
    CLOCK_EnableClock(kCLOCK_Iocon);                           /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */
    CLOCK_EnableClock(kCLOCK_Gpio0);
    CLOCK_EnableClock(kCLOCK_Gpio1);
		
    /* attach 12 MHz clock to FLEXCOMM4 (I2C master) */
    CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4);
    GPIO_PortInit(GPIO,0);
    /* reset FLEXCOMM for I2C */
    RESET_PeripheralReset(kFC4_RST_SHIFT_RSTn);		

	/* Board pin init */
    BOARD_InitPins();
    CLOCK_AttachClk(kMAIN_CLK_to_CLKOUT);				//main clock source to clkout
    CLOCK_SetClkDiv(kCLOCK_DivClkOut,3,false);	//150MHz / 3 = 50MHz clkout to XCLK of camera module
		
    /* Connect trigger sources to camera engine */
    INPUTMUX_Init(INPUTMUX);
    INPUTMUX->CAMERA_ENGINE_INPUTMUX[0]	 =  13; // set p0_13 as VSYNC input function pin, every edge will be responded
    INPUTMUX->CAMERA_ENGINE_INPUTMUX[1]	 =  15; // set p0_15 as pixel input function pin, every edge will be responded
    /* Turnoff clock to inputmux to save power. Clock is only needed to make changes */
    INPUTMUX_Deinit(INPUTMUX);		
    // configure camera interface pins
    IOCON->PIO[0][0]  = PINFUNC_CAMERA | 1<<8|1<<10|2<<4| 1<<6;	//set p0_0 D0 on the camera port
    IOCON->PIO[0][1]  = PINFUNC_CAMERA | 1<<8|2<<4| 1<<6;				//set p0_1 D1 on the camera port
    IOCON->PIO[0][2]  = PINFUNC_CAMERA | 1<<8|2<<4| 1<<6;				//set p0_2 D2 on the camera port
    IOCON->PIO[0][3]  = PINFUNC_CAMERA | 1<<8|1<<6;							//set p0_3 D3 on the camera port
    IOCON->PIO[0][4]  = PINFUNC_CAMERA | 1<<8|1<<6;							//set p0_4 D4 on the camera port
    IOCON->PIO[0][5]  = PINFUNC_CAMERA | 1<<8|2<<4|1<<6;				//set p0_5 D5 on the camera port
    IOCON->PIO[0][6]  = PINFUNC_CAMERA | 1<<8;									//set p0_6 D6 on the camera port
    IOCON->PIO[0][7]  = PINFUNC_CAMERA | 1<<8;									//set p0_7 D7 on the camera port
    IOCON->PIO[0][18] = PINFUNC_CAMERA | 1<<8| 1<<10;						//P0_18 will toggle when camera engine receive every VSYNC dege

    /* configure P1_11 as output gpio for measuring the timing */
    GPIO_PortInit(GPIO, 1);
    GPIO_PinInit(GPIO, 1, 11, &gpio_config);	
		
	/* debug console initialization */
	BOARD_InitDebugConsole();
	Lcd_Init();			//LCD initialization
	Ov7670_Init(0); //outside camera module initialization

	DisableIRQ(Reserved46_IRQn);  // Camera engine irq NUMBER 30
	CLOCK_EnableClock(kCLOCK_CameraEngine);// enable camera engine clock
	Camera_Init();								//camera engine initialization
	Camera_Start();								//start camera engine
	EnableIRQ(Reserved46_IRQn);   // Camera engine irq NUMBER 30

	DataReadyFlag = 0;
	PRINTF("camera engine for LPC55S69 demo\r\n");

    while (1)
    {
		while(DataReadyFlag == 0);		  // Waiting for respond from EZH, the waiting time is about 7ms
		GPIO_PinWrite(GPIO, 1, 11, 0);	//toggle P1_11
		Lcd_Refresh(); 									//the refresh time is about 25ms
		DataReadyFlag = 0;              // clear the flag
		GPIO_PinWrite(GPIO, 1, 11, 1);  //toggle P1_11
    }	
}
