/*-------------------------------------------------------------------------------------------------
--
-- File Name    : main.c



-- Description  : This module replicates the CoaXPress Device main interface functionality.




-- Targeted device : Microchip FPGAs
-- Author          : India Solutions Team




--
-- COPYRIGHT 2023 BY MICROCHIP
-- THE INFORMATION CONTAINED IN THIS DOCUMENT IS SUBJECT TO LICENSING RESTRICTIONS
-- FROM MICROCHIP CORP.  IF YOU ARE NOT IN POSSESSION OF WRITTEN AUTHORIZATION FROM
-- MICROCHIP FOR USE OF THIS FILE, THEN THE FILE SHOULD BE IMMEDIATELY DESTROYED AND
-- NO BACK-UP OF THE FILE SHOULD BE MADE.
--



-------------------------------------------------------------------------------------------------*/


#include <stdio.h>
#include "hal/hal.h"
#include "miv_rv32_hal/miv_rv32_hal.h"
#include "drivers/fpga_ip/CoreGPIO/core_gpio.h"
#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
#include "imx334_corei2c/imx334_corei2c.h"

#include <drivers/fpga_ip/CoaXPressDevice/coaxpressDevice.h>

#define LED1 GPIO_0
#define LED2 GPIO_1
#define LED3 GPIO_2
#define LED4 GPIO_3

#define MIPI_TRNG_RST GPIO_7

volatile uint32_t g_10ms_count;
volatile uint32_t timerdone = 0;
volatile uint32_t g_10ms_count1;
volatile uint32_t g_ms_count;

i2c_instance_t g_i2c_instance_cam1;
i2c_instance_t g_i2c_instance_cam2;
volatile uint8_t irq_flag = 0;

/*-----------------------------------------------------------------------------
 * GPIO instance data.
 */
gpio_instance_t g_gpio_out;

/*-----------------------------------------------------------------------------
 *
 * Global state counter.
 */
uint32_t g_state = 1;

volatile uint32_t rx_tmr_done = 0;
volatile uint32_t rx_ms_count1;
volatile uint32_t rx_ms_count;
uint32_t t_ms_count = 0;
uint32_t process_data = 0;
uint8_t resolution[4];

void GPIO_settings();
//void resolution_setting();
void camera_init_setting();
extern void msdelay(uint32_t tms);

/*-----------------------------------------------------------------------------
 * Interrupt handlers.
 * Weakly linked default versions of all the interrupt handlers are defined
 * in miv_rv32_stubs.c.
 */

void External_IRQHandler()
{
    //GPIO_set_output(&g_gpio_out, LED3, 0);

    irq_flag = 1;
}

void MSYS_EI0_IRQHandler(void)
{
    I2C_isr(&g_i2c_instance_cam1);
}

void MSYS_EI1_IRQHandler(void)
{
    I2C_isr(&g_i2c_instance_cam2);
}

/*-------------------------------------------------------------------------//**
  main() function.
*/
int main(void)
{
    volatile  uint32_t counter;
    uint8_t state, select;

    counter    = 0;
    state      = 0;

    /* Initializing GPIOs */
    GPIO_settings();

    /* enabling local interrupts */
    MRV_enable_local_irq(MRV32_EXT_IRQn);
    MRV_enable_local_irq(MRV32_MSYS_EIE0_IRQn);
    MRV_enable_local_irq(MRV32_MSYS_EIE1_IRQn);

    /* This must be done for all Mi-V cores to enable interrupts globally. */
    HAL_enable_interrupts();

    GPIO_set_output(&g_gpio_out, MIPI_TRNG_RST, 0u);
    GPIO_set_output(&g_gpio_out, LED2, 1);

    GPIO_set_output(&g_gpio_out, CAM1_RST, 1u);
    GPIO_set_output(&g_gpio_out, CAM2_RST, 1u);
    GPIO_set_output(&g_gpio_out, CAM_CLK_EN, 0u);

    msdelay(1);

    //initializations for 4K
    width_reg_st  = WIDTH_MAX;
    height_reg_st = HEIGHT_MAX;
    resolution[0] = width_reg_st & 0xff;
    resolution[1] = (width_reg_st >> 8) & 0xff;
    resolution[2] = height_reg_st & 0xff;
    resolution[3] = (height_reg_st >> 8) & 0xff;
    
    //update_cxp_xcvr_uplink_speed(DEF_RATE);

    //default 2 cameras
    StreamIDSelect_st = DUAL_STREAM;
    /* Initialize camera */
    imx334_cam_init();
    imx334_cam_reginit(1u, resolution);

    msdelay(1000);

    GPIO_set_output(&g_gpio_out, MIPI_TRNG_RST, 1u);
    GPIO_set_output(&g_gpio_out, LED4, 1);

    msdelay(10);

    /* Initialize Coaxpress Device */
    CoaxpressDeviceInit(resolution);

    update_cxp_xcvr_uplink_speed(DEF_RATE);

    StreamIDSelect_st = STREAM0;
    /**************************************************************************
    * Loop
    *************************************************************************/
    do
    {
        if(100000u == counter)
        {
            counter = 0;
            state = !state;
            GPIO_set_output(&g_gpio_out, LED1, state);
        }
        else
        {
            counter = counter + 1;
        }

        if(irq_flag == 1)
        {
            irq_flag = 0;

            CoaxpressDeviceMain();
        }

        if(pattern_en)
        {
            pattern_en = 0;
            pattern_setting(1u, Pattern_st);
            if(Pattern_st == 0)
            {
                camera_init_setting();
                delay(1);
            }
        }

        if(gain_en)
        {
            gain_en = 0;
            gain_setting(1u, Gain_st);
            delay(1);
        }

        if(reversex_en)
        {
            reversex_en = 0;
            reverse_x_setting(1u, ReverseX_st);
            delay(1);
        }

        if(reversey_en)
        {
            reversey_en = 0;
            reverse_y_setting(1u, ReverseY_st);
            delay(1);
            if(ReverseY_st == 0)
            {
                camera_init_setting();
                delay(1);
            }
        }

        if(width_en || height_en || resolution_en)
        {
            resolution_en = 0;
            if(ResolutionSelect_st == RESOLUTION_4K)
            {
                width_reg_st  = 3840;
                height_reg_st = 2160;
            }
            else if(ResolutionSelect_st == RESOLUTION_FHD)
            {
                width_reg_st  = 1920;
                height_reg_st = 1080;
            }

            width_en = 0;
            resolution[0] = width_reg_st & 0xff;
            resolution[1] = (width_reg_st >> 8) & 0xff;

            height_en = 0;
            resolution[2] = height_reg_st & 0xff;
            resolution[3] = (height_reg_st >> 8) & 0xff;


            delay(1);
            resolution_cxp_setting(resolution);
            delay(1);
            resolution_setting(1u, resolution);
            delay(1);
        }



    } while (1);

    return 0u;
}



void camera_init_setting()
{
    delay(1);

    stream_disable();

    delay(1);
    delay(1);

    //imx334_cam_init();
    imx334_cam_reginit(1u, resolution);

    delay(1);
    delay(1);

    //stream_enable();

    delay(1);
    delay(1);
    delay(1);
}

void GPIO_settings()
{
    GPIO_init(&g_gpio_out, COREGPIO_OUT_BASE_ADDR, GPIO_APB_32_BITS_BUS);
    GPIO_config(&g_gpio_out, 0, GPIO_OUTPUT_MODE);
    GPIO_config(&g_gpio_out, 1, GPIO_OUTPUT_MODE);
	GPIO_config(&g_gpio_out, 2, GPIO_OUTPUT_MODE);
    GPIO_config(&g_gpio_out, 4, GPIO_OUTPUT_MODE);
    GPIO_config(&g_gpio_out, 5, GPIO_OUTPUT_MODE);
    GPIO_config(&g_gpio_out, 6, GPIO_OUTPUT_MODE);
    GPIO_config(&g_gpio_out, 7, GPIO_OUTPUT_MODE);
    GPIO_set_outputs(&g_gpio_out,0);
	GPIO_set_output(&g_gpio_out, GPIO_2, 0u);//1-incr data, 0-video data
}

void cxp_xcvr_uplink_lane_preemphasis(uint32_t lane_addr)

{

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + lane_addr + SER_TERM_CTRL)=0xF300;

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + lane_addr + SER_DRV_DATA_CTRL)=0x6082AA;

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + lane_addr + SER_DRV_CTRL)=0x160B9FFF;

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + lane_addr + SER_DRV_CTRL_SEL)=0xC;

}


