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



-- Description  : This module replicates the CoaXPress Host GUI modules.



-- 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 "hal/hal.h"

#include "drivers/fpga_ip/CoaXPressHost/coaxpressBootstrapReg.h"
#include "drivers/fpga_ip/CoaXPressHost/coaxpressXcvrSpeed.h"
#include "drivers/fpga_ip/CoaXPressHost/coaxpressHost.h"
#include "coaxpressHostGUI.h"

#define NEW_RATE RATE_6DOT25G    //RATE_5DOT0G

extern volatile uint8_t irq_flag_device;
extern volatile uint8_t irq_flag_gui;
extern volatile uint32_t DIP_SW_status;

uint32_t cont_cnt = 0;
uint32_t xml_cont[32];
uint32_t xml_file[32];
uint8_t  xml_name_buff[32];
uint32_t rd_pkt[MAX_CHUNK_SIZE];

uint32_t crc_buffer[16];
uint8_t  crc_buffer_8bit[64];
uint32_t crc_value       = 0;
volatile uint8_t tag     = 0;

uint32_t host_cmd_sel;
uint32_t host_command;
uint32_t prev_host_command;
uint32_t host_cmd_address;
uint32_t streaming_address;

uint8_t xml_cmd_sel          = WAIT_FOR_NODATA;
uint32_t xml_url_address     = 0x7000;
static int xml_address       = 0x8100;
static int xml_start_address = 0x8100;
int xml_size                 = 0x100;
int rem_data                 = 0;
int chunk_size               = MAX_CHUNK_SIZE;

volatile uint8_t wait_for_data = 0;
volatile uint8_t host_wait_cmd_sel;

uint8_t xml_name[9] = {"zippedxml"};  //fixed name indication for letting the host GUI to know when to read zipped xml file
uint32_t xml_size_ascii = 0;
uint32_t xml_name_ascii = 0;
uint32_t file_index     = 0;

uint32_t video_start_reg;
uint8_t uplinkspeed_update = 0;
uint32_t reset_status;

uint8_t reset_en = 0;
uint8_t device_to_host_connection_test_en = 0;
uint8_t host_to_device_connection_test_en = 0;
void msdelay(uint32_t tms)
{
    int i = 0;
    //g_ms_count = tms;
    //g_10ms_count1 = 0;
    //timerdone = 1;
    for(i = 0; i < 50000; i++);
    //    while(timerdone != 0)
    //  {
    //      //busy wait loop
    //  }

}

void delay()
{
    for(uint32_t i=0; i<50; i++)
    {
        for(uint32_t j=0; j<50000; j++);
    }
}

void CoaxpressHostGUIMain()
{

    volatile uint32_t  *host_cmd_sel_addr;
    volatile uint32_t  *host_cmd_addr_value;
    volatile uint32_t  *host_cmd_wdata_addr;

    host_cmd_sel_addr   = (uint32_t*)HOST_CMD_SEL_ADDR;
    host_cmd_addr_value = (uint32_t*)HOST_CMD_ADDR_ADDR;
    host_cmd_wdata_addr = (uint32_t*)HOST_CMD_WDATA_ADDR;

    uint32_t host_cmd_wdata;
    uint32_t count;
    uint32_t size;

    uint8_t index;

    irq_flag_gui     = 0;
    host_cmd_sel     = *host_cmd_sel_addr;
    host_cmd_address = *host_cmd_addr_value;
    host_cmd_wdata   = *host_cmd_wdata_addr;
    count = 0;

    switch(host_cmd_sel)
    {
    case READ_XML: //Send command for xml read
    {
        tag = tag + 1 ;
        host_wait_cmd_sel = WAIT_FOR_NODATA;

        switch(xml_cmd_sel)
        {
        case XML_REG_ADDRESS_FETCH:
        {
            host_cmd_address    = XmlUrlAddress;
            size                = FOUR_BYTES;
            tag                 = 0;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        }
        break;

        case XML_URL_FETCH:
        {
            host_cmd_address    = xml_url_address;
            size                = FOUR_BYTES;
            tag                 = 0;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        }
        break;

        case XML_ZIP_FILE_FETCH:
        {
            if(rem_data <= chunk_size)
            {
                chunk_size = rem_data;
            }

            host_cmd_address    = xml_address;
            size                = chunk_size;
            tag                 = 0;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);

            xml_address = xml_address + chunk_size;
            rem_data = rem_data - chunk_size;
        }
        break;

        }

        msdelay(10);
        host_wait_cmd_sel = WAIT_FOR_DATA;

    }
    break;

    case REG_READ: //Send command for Boot strap read
    {
        host_wait_cmd_sel   = WAIT_READ_ACK;
        size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);

        // reading address from bootstrap address registers
        if((host_cmd_address >= WidthAddress) && (host_cmd_address <= ImagenStreamIDAddress))
        {   receive_resp_cmd(rd_pkt);
        host_cmd_address = rd_pkt[5];
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        }
        break;
    }

    case REG_WRITE: //Send command for Boot strap write
    {
        // reading address from bootstrap address registers
        if((host_cmd_address >= WidthAddress) && (host_cmd_address <= ImagenStreamIDAddress))
        {
            host_wait_cmd_sel   = WAIT_READ_ACK;
            size                = FOUR_BYTES;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);
            receive_resp_cmd(rd_pkt);
            host_cmd_address = rd_pkt[5];
        }

        host_wait_cmd_sel   = WAIT_WRITE_ACK;
        size                = FOUR_BYTES;
        //send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        if(host_cmd_address == ConnectionReset)
        {
            reset_en = 1;
        }
        else
        {
            uint8_t status;
            uint32_t rd_data = 0;
            tag              = 0;

            do
            {
                send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
                status = receive_resp_cmd(rd_pkt);
                msdelay(10);
            }while(status == 0);

            if(host_cmd_address == ConnectionConfig)
            {
                uint8_t host_cmd_wdata_8bit = host_cmd_wdata & 0xFF;
                update_cxp_xcvr_uplink_speed(host_cmd_wdata_8bit);
                wait_for_pll_lock();

                //wait for word alignment
                while(rd_data == 0)
                {
                    //delay();
                    msdelay(10);
                    rd_data = *(volatile int*) HSDC_RX_SW_PKT_VAL;
                    rd_data = rd_data & 0x4;
                }
            }
            status = 0;
            do
            {
                //read response
                send_read_cmd(crc_buffer, host_cmd_address, tag, size);
                status = receive_resp_cmd(rd_pkt);
            }while(status == 0);

        }
        //resolution
        if(host_cmd_address == RESOLUTION_SELECT)
        {
            if(host_cmd_wdata == 1 && (DIP_SW_status && 0x00000001)) //4k stream and FHD display
            {
                *(volatile int*) HPAN_C1 = 0x3C0;
                *(volatile int*) VPAN_C1 = 0x21C;
                *(volatile int*) HPAN_C2 = 0x3C0;
                *(volatile int*) VPAN_C2 = 0x21C;
            }
            else
            {
                *(volatile int*) HPAN_C1 = 0;
                *(volatile int*) VPAN_C1 = 0;
                *(volatile int*) HPAN_C2 = 0;
                *(volatile int*) VPAN_C2 = 0;

            }
        }
        break;
    }

    case READ_MAGIC ://Send command to read Magic number
    {
        host_cmd_address    = Standard;
        host_wait_cmd_sel   = WAIT_READ_ACK;
        size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        break;
    }


    case START_VIDEO ://Send command to start video streaming
    {
        //read StartVideo Address
        tag                 = 0;
        host_wait_cmd_sel   = WAIT_READ_ACK;
        host_cmd_address    = AcquistionStartAddress;
        size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);

        streaming_address = rd_pkt[5];

        host_wait_cmd_sel   = WAIT_WRITE_ACK;
        host_cmd_address    = streaming_address;
        host_cmd_wdata      = 1;
        size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        break;
    }

    case STOP_VIDEO ://Send command to stop video streaming
    {
        //read StartVideo Address
        tag                 = 0;
        host_wait_cmd_sel   = WAIT_READ_ACK;
        host_cmd_address    = AcquistionStopAddress;
        size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);

        streaming_address = rd_pkt[5];

        host_wait_cmd_sel   = WAIT_WRITE_ACK;
        host_cmd_address    = streaming_address;
        host_cmd_wdata      = 0;
        size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        break;
    }

#if 0
    case DEVICE_TO_HOST_CONNECTION_TEST :
    {
        host_wait_cmd_sel   = WAIT_WRITE_ACK;
        host_cmd_address    = DeviceToHostConnectionTest;
        size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        device_to_host_connection_test_en = 1;
        break;
    }


    case HOST_TO_DEVICE_CONNECTION_TEST :
    {
        host_wait_cmd_sel   = WAIT_WRITE_ACK;
        host_cmd_address    = HostToDeviceConnectionTest;
        size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        host_to_device_connection_test_en = 1;
        break;
    }
#endif
    } //switch(host_cmd_sel)

}


void read_resp1()
{
    uint32_t i;

    for(i=0; i<10; i++)
    {
        rd_pkt[i] = 0;
    }

    rd_pkt[0] = *(volatile int*) RD_ACK_ADDRESS;  //length of read
    if(rd_pkt[0] > 128)
    {
        rd_pkt[0] = 0;   //if size is more than 128, exception will come
    }
    for(i=1; i<=rd_pkt[0]; i++)
    {
        rd_pkt[i] = *(volatile int*) RD_ACK_ADDRESS;
    }
}


void CoaxpressDeviceToHostMain()
{

    msdelay(10);
    irq_flag_device = 0;
    //receive_resp_cmd(rd_pkt);
    //wait_for_deviceirq();
    read_resp1();
    msdelay(10);
    CoaxpressHostWaitCommand();

}

void CoaxpressHostWaitCommand()
{

    volatile uint32_t  *uart_write_addr;
    volatile uint32_t  *uart_ready_addr;

    uart_write_addr = (uint32_t*)UART_WRITE_ADDRESS;
    uart_ready_addr = (uint32_t*)UART_READY_ADDRESS;

    uint32_t num_loc;
    uint8_t index;

    switch(host_wait_cmd_sel)
    {

    case WAIT_FOR_DATA:
    {
        reading_xml_from_device();
    }
    break;

    case WAIT_FOR_XML:
    {
        *uart_ready_addr   = WRITE_DISABLE;
        num_loc           = rd_pkt[0];

        for (index=5; index <= num_loc-2; index++)
        {
            *uart_write_addr = rd_pkt[index];
        }
        *uart_ready_addr   = WRITE_ENABLE;
    }
    break;

    case WAIT_READ_ACK:
    {
        *uart_ready_addr  = WRITE_DISABLE;
        num_loc          = rd_pkt[0];
        cont_cnt         = 0;
        for (index=5; index <= num_loc-2; index++)
        {
            *uart_write_addr     = rd_pkt[index];
            xml_cont[cont_cnt++] = rd_pkt[index];
        }

        *uart_ready_addr  = WRITE_ENABLE;
    }
    break;

    case WAIT_WRITE_ACK:
    {
        *uart_ready_addr = WRITE_DISABLE;
        *uart_write_addr = ACK_CMD_EXEC_OK;
        *uart_write_addr = rd_pkt[3];
        *uart_ready_addr = WRITE_ENABLE;
    }
    break;

    default:
    {
        host_wait_cmd_sel = WAIT_FOR_NODATA;
    }
    break;

    } //switch(host_wait_cmd_sel)

    host_wait_cmd_sel = WAIT_FOR_NODATA;

}



void finding_xml_details()
{

    volatile uint32_t  *uart_write_addr;
    volatile uint32_t  *uart_ready_addr;

    uart_write_addr = (uint32_t*)UART_WRITE_ADDRESS;
    uart_ready_addr = (uint32_t*)UART_READY_ADDRESS;

    uint8_t xml1_char[FOUR_BYTES];
    uint32_t xml1 = xml_cont[cont_cnt-1];
    xml1_char[0]  = xml1 >> 0;
    xml1_char[1]  = (xml1 >> 8)  & 0xFF;
    xml1_char[2]  = (xml1 >> 16) & 0xFF;
    xml1_char[3]  = (xml1 >> 24) & 0xFF;

    if((xml1_char[0] == 0) | (xml1_char[1] == 0) | (xml1_char[2] == 0) | (xml1_char[3] == 0))
    {
        parse_xml_url(xml_cont, cont_cnt);

        xml_address = xml_start_address;
        rem_data    = xml_size;
        file_index  = 0;
        cont_cnt    = 0;

        *uart_ready_addr = WRITE_DISABLE;
        *uart_write_addr = NEW_LINE;
        *uart_ready_addr = WRITE_ENABLE;

        *uart_ready_addr = WRITE_DISABLE;

        uint32_t xml1   = (xml_name[0] << 24) | (xml_name[1] << 16) | (xml_name[2] << 8) | xml_name[3];
        *uart_write_addr = xml1;
        xml1            = (xml_name[4] << 24) | (xml_name[5] << 16) | (xml_name[6] << 8) | xml_name[7];
        *uart_write_addr = xml1;
        xml1            = (xml_name[8] << 24);
        *uart_write_addr = xml1;
        *uart_write_addr = NEW_LINE;

        *uart_write_addr = xml_size_ascii;
        *uart_write_addr = NEW_LINE;

        *uart_ready_addr = WRITE_ENABLE;

        xml_cmd_sel     = XML_ZIP_FILE_FETCH;

    }

}


void reading_xml_from_device()
{
    volatile uint32_t  *uart_write_addr;
    volatile uint32_t  *uart_ready_addr;
    uint32_t num_loc;

    uart_write_addr = (uint32_t*)UART_WRITE_ADDRESS;
    uart_ready_addr = (uint32_t*)UART_READY_ADDRESS;

    switch(xml_cmd_sel)
    {
    case XML_REG_ADDRESS_FETCH:
    {
        *uart_ready_addr = WRITE_DISABLE;
        xml_url_address = rd_pkt[5];
        xml_cmd_sel     = XML_URL_FETCH;
        cont_cnt        = 0;
        *uart_write_addr = rd_pkt[5];
        *uart_ready_addr = WRITE_ENABLE;
        //msdelay(10);
        host_cmd_sel    = READ_XML;
        irq_flag_gui    = 1;
    }
    break;

    case XML_URL_FETCH:
    {
        *uart_ready_addr = WRITE_DISABLE;
        //cont_cnt = 0;
        num_loc = rd_pkt[0];
        for (uint32_t index=5; index <= num_loc-2; index++)
        {
            *uart_write_addr     = rd_pkt[index];
            xml_cont[cont_cnt]  = rd_pkt[index];
            cont_cnt            = cont_cnt + 1;
        }
        *uart_write_addr = NEW_LINE;
        *uart_ready_addr = WRITE_ENABLE;

        xml_url_address = xml_url_address + FOUR_BYTES;

        finding_xml_details();

        msdelay(10);
        host_cmd_sel = READ_XML;
        irq_flag_gui = 1;
    }
    break;

    case XML_ZIP_FILE_FETCH:
    {
        *uart_ready_addr = WRITE_DISABLE;
        num_loc          = rd_pkt[0];
        for (uint32_t index=5; index <= num_loc-2; index++)
        {
            *uart_write_addr      = rd_pkt[index];
            //xml_file[file_index]  = rd_pkt[index];
            file_index            = file_index + 1;
        }
        host_wait_cmd_sel = WAIT_FOR_NODATA;
        *uart_ready_addr  = WRITE_ENABLE;

        msdelay(10);

        if(rem_data == 0)
        {
            irq_flag_gui = 0;
            rem_data     = xml_size;
            file_index   = 0;
            chunk_size   = MAX_CHUNK_SIZE;
            xml_cmd_sel  = XML_REG_ADDRESS_FETCH;
            xml_address  = xml_start_address;
            tag          = 0;
            msdelay(10);
        }
        else
        {
            host_cmd_sel = READ_XML;
            irq_flag_gui = 1;
        }
    }
    break;
    } //switch(xml_cmd_sel)
}

uint8_t get_num(uint8_t ch1)
{
    uint8_t ch = 0;
    if(ch1 >= '0' && ch1 <='9')
    {
        ch = ch1 - '0';
    }
    else
    {
        ch = (ch1 -'a') + 10;
    }
    return ch;
}


uint32_t send_decimal_number(uint8_t *src) //8100:08a8
{
    uint32_t num = 0;
    num = get_num(src[0])*16*16*16;
    num = num + get_num(src[1])*16*16;
    num = num + get_num(src[2])*16;
    num = num + get_num(src[3]);
    return num;
}


// steps: send XmlUrlAddress from GUI, get the string filename;adress;size;schema version # get xml from the sting adress chunk by chunk till size gets 0.
void parse_xml_url(uint32_t crc_buffer1[], uint8_t cont_count)
{
    int crc_cnt_ind  = 0;
    uint8_t term_ind = 0;
    int terminator_index[10];
    uint8_t xml_start_add_buff[2*FOUR_BYTES];
    uint8_t xml_size_buff[FOUR_BYTES];


    for (int ind1=0; ind1<cont_count*FOUR_BYTES; ind1=ind1+FOUR_BYTES)
    {
        crc_buffer_8bit[ind1]   = ((crc_buffer1[crc_cnt_ind] & 0xFF000000) >> 24) & 0xFF;
        crc_buffer_8bit[ind1+1] = ((crc_buffer1[crc_cnt_ind] & 0x00FF0000) >> 16) & 0xFF;
        crc_buffer_8bit[ind1+2] = ((crc_buffer1[crc_cnt_ind] & 0x0000FF00) >> 8) & 0xFF;
        crc_buffer_8bit[ind1+3] = ((crc_buffer1[crc_cnt_ind] & 0x000000FF) >> 0) & 0xFF;
        crc_cnt_ind++;

        for(uint8_t ind2=0; ind2<FOUR_BYTES; ind2++)
        {
            if(crc_buffer_8bit[ind1+ind2] == 58)  //":"
            {
                terminator_index[term_ind++] = ind1 + ind2;
            }

            if(crc_buffer_8bit[ind1+ind2] == 59)  //";"
            {
                terminator_index[term_ind++] = ind1 + ind2;
            }

            if(crc_buffer_8bit[ind1+ind2] == 63)  //"?"
            {
                terminator_index[term_ind++] = ind1 + ind2;
            }

            if(crc_buffer_8bit[ind1+ind2] == 0)  //"\0"
            {
                terminator_index[term_ind++] = ind1 + ind2;
            }
        }
    }

    //read xml name
    term_ind = 0;
    uint8_t prev_ind = terminator_index[term_ind++] + 1;  //+1 for skipping the teminator ;, :, ?
    uint8_t end_ind  = terminator_index[term_ind++];
    uint8_t ind3 = 0;
    for(uint8_t ind2=prev_ind; ind2<end_ind; ind2++)
    {
        xml_name_buff[ind3++] = crc_buffer_8bit[ind2];
    }

    //read xml start address
    prev_ind = end_ind + 1;
    end_ind  = terminator_index[term_ind++];
    ind3 = 0;

    for(uint8_t ind2=prev_ind; ind2<end_ind; ind2++)
    {
        xml_start_add_buff[ind3++] = crc_buffer_8bit[ind2];
    }
    uint8_t add_count = ind3;

    //read xml size
    prev_ind = end_ind + 1;
    end_ind  = terminator_index[term_ind++];
    ind3 = 0;
    for(uint8_t ind2=prev_ind; ind2<end_ind; ind2++)
    {
        xml_size_buff[ind3++] = crc_buffer_8bit[ind2];
    }
    uint8_t size_count = ind3;

    //start address in hex
    xml_start_address = 0;
    uint32_t mult_factor = 0;
    for(uint8_t ind2=0; ind2<add_count; ind2++)
    {
        mult_factor = (1 << (add_count-ind2-1)*4);
        xml_start_address = xml_start_address + get_num(xml_start_add_buff[ind2]) * mult_factor;
    }

    //size in hex
    xml_size = 0;
    for(uint8_t ind2=0; ind2<size_count; ind2++)
    {
        mult_factor = (1 << (size_count-ind2-1)*4);
        xml_size = xml_size + get_num(xml_size_buff[ind2]) * mult_factor;
    }

    //size in ascii
    xml_size_ascii = (xml_size_buff[0] << 24) | (xml_size_buff[1] << 16) | (xml_size_buff[2] << 8) | xml_size_buff[3];
}


void device_reset()
{
    //uint32_t host_cmd_address;
    uint32_t host_cmd_wdata;
    uint32_t size;

    tag = 0;
    do
    {
        //device reset
        tag                 = 0;
        host_cmd_address    = ConnectionReset;
        host_cmd_wdata      = 0x00000001;
        size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //reset_status = receive_resp_cmd(rd_pkt);   //For Basler camera reset command response is not coming
        reset_status = 1;
    }while(reset_status == 0);

}

void start_video_stream()
{
    //uint32_t host_cmd_address;
    uint32_t host_cmd_wdata;
    uint32_t size, status,model;

    //read standard
    tag                 = 0;
    host_cmd_address    = Standard;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    //read model name
    tag                 = 0;
    host_cmd_address    = DeviceModelName;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    model = rd_pkt[5];

    //write master connection ID
    tag                 = 0;
    host_cmd_address    = MasterHostConnectionID;
    host_cmd_wdata      = 0x00000002;
    size                = FOUR_BYTES;
    send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
    receive_resp_cmd(rd_pkt);

    //read ConnectionConfig
    tag                 = 0;
    host_cmd_address    = ConnectionConfig;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    //read ConnectionConfigDefault
    tag                 = 0;
    host_cmd_address    = ConnectionConfigDefault;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    //write ConnectionConfig
    tag                 = 0;
    host_cmd_address    = ConnectionConfig;
    host_cmd_wdata      = 0x00010000 | NEW_RATE;
    size                = FOUR_BYTES;
    send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
    receive_resp_cmd(rd_pkt);

    update_cxp_xcvr_uplink_speed(NEW_RATE);// RATE_12DOT5G

    wait_for_pll_lock();
    delay();
    delay();

    //read ConnectionConfig
    tag                 = 0;
    host_cmd_address    = ConnectionConfig;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    //write StreamPacketSizeMax
    tag                 = 0;
    host_cmd_address    = StreamPacketSizeMax;
    host_cmd_wdata      = 0x00001000;
    size                = FOUR_BYTES;
    send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
    receive_resp_cmd(rd_pkt);

    //write XmlManifestSelector
    tag                 = 0;
    host_cmd_address    = XmlManifestSelector;
    host_cmd_wdata      = 0x00000000;
    size                = FOUR_BYTES;
    send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
    receive_resp_cmd(rd_pkt);

    //write VersionUsed
    tag                 = 0;
    host_cmd_address    = VersionUsed;
    host_cmd_wdata      = 0x00020000;
    size                = FOUR_BYTES;
    send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
    receive_resp_cmd(rd_pkt);

    //default FHD settings
    *(volatile int*) HPAN_C1 = 0;
    *(volatile int*) VPAN_C1 = 0;
    *(volatile int*) HPAN_C2 = 0;
    *(volatile int*) VPAN_C2 = 0;

    if(DIP_SW_status && 0x00000001) //4k stream and FHD display
    {
        *(volatile int*) HPAN_C1 = 0x3C0;
        *(volatile int*) VPAN_C1 = 0x21C;
        *(volatile int*) HPAN_C2 = 0x3C0;
        *(volatile int*) VPAN_C2 = 0x21C;
    }

    delay();

    //Making PAN variables zero if width is FHD dimension
    tag                 = 0;
    host_cmd_address    = WidthAddress;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    streaming_address = rd_pkt[5];

    host_cmd_address    = streaming_address;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    streaming_address = rd_pkt[5];
    if(streaming_address == FHD_WIDTH) //4k stream and FHD display
    {
        *(volatile int*) HPAN_C1 = 0;
        *(volatile int*) VPAN_C1 = 0;
        *(volatile int*) HPAN_C2 = 0;
        *(volatile int*) VPAN_C2 = 0;
    }

#if 1 //default stream enable

    //For Basler Camera - make alpha as 255 in GUI (Basler default streams Stream 1)
    if(model == 0x49726f6e)
    {
        //write PixelFormatAddress
        host_cmd_address    = 0x10040;
        host_cmd_wdata      = 0x09000801;
        size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        receive_resp_cmd(rd_pkt);
    }

    //start stream
    //read StartVideo Address
    status              = 0;
    tag                 = 0;
    host_cmd_address    = AcquistionStartAddress;
    size                = FOUR_BYTES;
    send_read_cmd(crc_buffer, host_cmd_address, tag, size);
    receive_resp_cmd(rd_pkt);

    streaming_address = rd_pkt[5];

    status              = 0;
    tag                 = 0;
    host_cmd_address    = streaming_address;
    host_cmd_wdata      = 0x00000001;
    size                = FOUR_BYTES;
    do{
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        status = receive_resp_cmd(rd_pkt);
        delay();
    } while(status==0);
#endif
}

#if 0
  uint32_t TestModeValue[5];
  uint32_t TestErrorCountValue[5];
  uint32_t TestPacketCountTxValue[5];
  uint32_t TestPacketCountRxValue[5];
  uint8_t testcount = 0;
    void coaxpress_device_to_host_connection_test()
    {
        //uint32_t host_cmd_address;
        uint32_t host_cmd_wdata;
        uint32_t size;

        volatile uint32_t  *uart_write_addr;
        volatile uint32_t  *uart_ready_addr;

        uart_write_addr = (uint32_t*)UART_WRITE_ADDRESS;
        uart_ready_addr = (uint32_t*)UART_READY_ADDRESS;

        //*uart_ready_addr = WRITE_DISABLE;
        //*uart_write_addr = 0x00000000;
        //*uart_ready_addr = WRITE_ENABLE;

        //stop image acquisition
        tag                 = 0;
        host_cmd_address    = 0x100100;//AcquistionStartAddress;//streaming_address;
        host_cmd_wdata      = 0x00000000;
        size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //receive_resp_cmd(rd_pkt);

        //Reset the Error Counters and Packet Counters at the Host receivers
        //Reset the Device Packet Counters by writing the value 0 to TestPacketCountTx[m] registers
        //Read TestPacketCountTx APB address
#if 0
        tag                 = 0;
        host_cmd_address    = TestPacketCountTx;
        size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);
        TestPacketCountTxAddress = rd_pkt[5];
#endif

        ///tag                 = 0;
        host_cmd_address    = TestPacketCountTx;//Reg;
        host_cmd_wdata      = 0x00000000;
        //size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //receive_resp_cmd(rd_pkt);

        *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestErrorCountReg) = 0;
        *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestPacketCountRxReg) = 0;

        //*uart_ready_addr = WRITE_DISABLE;
        //*uart_write_addr = 0x00000001;
        //*uart_ready_addr = WRITE_ENABLE;

        //Put the Device in Test Mode by writing 1 to the TestMode
        //tag                 = 0;
        host_cmd_address    = TestMode;//Reg;
        host_cmd_wdata      = 0x00000001;
        //size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //receive_resp_cmd(rd_pkt);

        delay();

        //tag                 = 0;
        host_cmd_address    = TestPacketCountTx;//Reg;
        //size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);
        TestPacketCountTxValue[0] = rd_pkt[5];
        delay();

        TestErrorCountValue[0]    = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestErrorCountReg);
        TestPacketCountRxValue[0] = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestPacketCountRxReg);

        *uart_ready_addr = WRITE_DISABLE;
        *uart_write_addr = 0x00000002;
        //*uart_ready_addr = WRITE_ENABLE;

        //Restore normal Device operation by writing 0 to the TestMode bootstrap register
        //tag                 = 0;
        host_cmd_address    = TestMode;//Reg;
        host_cmd_wdata      = 0x00000000;
        //size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //receive_resp_cmd(rd_pkt);

        delay();
#if 0
        tag                 = 0;
        host_cmd_address    = TestMode;//Reg;
        size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);
        TestModeValue[0] = rd_pkt[5];
#endif
        //*uart_ready_addr = WRITE_DISABLE;
        *uart_write_addr = 0x00000003;
        //*uart_ready_addr = WRITE_ENABLE;

        for(unsigned char i=1; i<5; i++)
        {
#if 0
            //Repeat reading counters after making TestMode as zero
            delay();
            tag                 = 0;
            host_cmd_address    = TestMode;//Reg;
            size                = FOUR_BYTES;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);
            receive_resp_cmd(rd_pkt);
            TestModeValue[i] = rd_pkt[5];
#endif

            delay();
#if 0
            tag                 = 0;
            host_cmd_address    = TestPacketCountTx;//Reg;
            size                = FOUR_BYTES;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);
            receive_resp_cmd(rd_pkt);
            TestPacketCountTxValue[i] = rd_pkt[5];

            delay();
#endif
            TestErrorCountValue[i]    = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestErrorCountReg);
            TestPacketCountRxValue[i] = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestPacketCountRxReg);

            testcount = i;

            //*uart_ready_addr = WRITE_DISABLE;
            *uart_write_addr = i;
            //*uart_ready_addr = WRITE_ENABLE;
        }

        //*uart_ready_addr = WRITE_DISABLE;
        if(TestErrorCountValue[4] == 0x0)
        {
            *uart_write_addr = 0x11111111;
        }
        else
        {
            *uart_write_addr = 0xffffffff;
        }
        *uart_ready_addr = WRITE_ENABLE;

        //start image acquisition
        //tag                 = 0;
        host_cmd_address    = 0x100100;//AcquistionStartAddress;//streaming_address;
        host_cmd_wdata      = 0x00000001;
        //size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        receive_resp_cmd(rd_pkt);

    }
#endif

#if 0
    void coaxpress_host_to_device_connection_test()
    {
        //uint32_t host_cmd_address;
        uint32_t host_cmd_wdata;
        uint32_t size;

        volatile uint32_t  *uart_write_addr;
        volatile uint32_t  *uart_ready_addr;

        uart_write_addr = (uint32_t*)UART_WRITE_ADDRESS;
        uart_ready_addr = (uint32_t*)UART_READY_ADDRESS;

        *uart_ready_addr = WRITE_DISABLE;
        tag                 = 0;
        size                = FOUR_BYTES;

#if 0
        //stop image acquisition
        host_cmd_address    = 0x100100;//streaming_address;
        host_cmd_wdata      = 0x00000000;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //receive_resp_cmd(rd_pkt);
#endif
        *uart_write_addr = 0x00000001;
        //*uart_write_addr = "Testing";
        *uart_ready_addr = WRITE_ENABLE;
        *uart_ready_addr = WRITE_DISABLE;

        //Reset the Error Counters and Packet Counters at the Host receivers
        //Reset the Device Packet Counters by writing the value 0 to TestPacketCountTx[m] registers
        //Read TestPacketCountTx APB address
#if 0
        tag                 = 0;
        host_cmd_address    = TestPacketCountTx;
        size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);
        TestPacketCountTxAddress = rd_pkt[5];
#endif

        //tag                 = 0;
        host_cmd_address    = TestErrorCount;//Reg;
        host_cmd_wdata      = 0x00000000;
        //size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //receive_resp_cmd(rd_pkt);

        *uart_write_addr = 0x00000003;

        //tag                 = 0;
        host_cmd_address    = TestPacketCountRx;//Reg;
        host_cmd_wdata      = 0x00000000;
        //size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        //receive_resp_cmd(rd_pkt);


        *uart_write_addr = 0x00000004;

        *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestPacketCountTxReg) = 0;

        *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestModeReg) = 0;

        //start the test
        *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestModeReg) = 1;

        delay();

        *uart_write_addr = 0x00000005;

        delay();
        //tag                 = 0;
        host_cmd_address    = TestErrorCount;//Reg;
        //size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);
        TestErrorCountValue[0] = rd_pkt[5];

        delay();
        //tag                 = 0;
        host_cmd_address    = TestPacketCountRx;//Reg;
        //size                = FOUR_BYTES;
        send_read_cmd(crc_buffer, host_cmd_address, tag, size);
        receive_resp_cmd(rd_pkt);
        TestPacketCountRxValue[0] = rd_pkt[5];
        delay();

        TestModeValue[0]          = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestModeReg);
        TestPacketCountTxValue[0] = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestPacketCountTxReg);

        //stop the test
        *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestModeReg) = 0;

        delay();

        for(unsigned char i=1; i<5; i++)
        {
            //Repeat reading counters after making TestMode as zero
            //delay();
            //tag                 = 0;
            host_cmd_address    = TestErrorCount;//Reg;
            //size                = FOUR_BYTES;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);
            receive_resp_cmd(rd_pkt);
            TestErrorCountValue[i] = rd_pkt[5];

            delay();
            //tag                 = 0;
            host_cmd_address    = TestPacketCountRx;//Reg;
            //size                = FOUR_BYTES;
            send_read_cmd(crc_buffer, host_cmd_address, tag, size);
            receive_resp_cmd(rd_pkt);
            TestPacketCountRxValue[i] = rd_pkt[5];

            delay();

            TestModeValue[i]          = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestModeReg);
            TestPacketCountTxValue[i] = *(volatile unsigned int *)(COAXPRESS_HOST_APB_BASE_ADDRESS + TestPacketCountTxReg);

            testcount = i;
            *uart_write_addr = i;
            delay();
        }

        //*uart_ready_addr = WRITE_DISABLE;
        if(TestErrorCountValue[4] == 0x0)
        {
            *uart_write_addr = 0x11111111;
        }
        else
        {
            *uart_write_addr = 0xffffffff;
        }
        *uart_ready_addr = WRITE_ENABLE;

#if 0
        //start image acquisition
        //tag                 = 0;
        host_cmd_address    = 0x100100;//AcquistionStartAddress;//streaming_address;
        host_cmd_wdata      = 0x00000001;
        //size                = FOUR_BYTES;
        send_write_cmd(crc_buffer, host_cmd_address, host_cmd_wdata, tag, size);
        receive_resp_cmd(rd_pkt);
#endif
    }
#endif
