
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "miv_rv32_hal.h"
#include "sample_hw_platform.h"
#include "hw_reg_access.h"
#include "core_gpio.h"
#include "core_uart_apb.h"
#include "corespi_regs.h"
#include "core_spi.h"

#include "headless.h"
#include "t_mykonos.h"
#include "mykonos.h"
#include "mykonos_gpio.h"
#include "myAD9371.h"
#include "ad9528.h"


extern void delay(volatile int a);
extern unsigned int firmware_Mykonos_M3_bin_len;
extern unsigned char firmware_Mykonos_M3_bin[];

int AD9371_1_chip_calibration()
{


	const char* errorString;
	uint8_t pllLockStatus = 0;
	uint8_t errorFlag = 0;
	uint8_t errorCode = 0;
    uint32_t prbsErrorCount = 0;
	uint32_t initCalsCompleted = 0;
	uint16_t errorWord = 0,mismatch = 0;
	uint16_t statusWord = 0;
	uint8_t status = 0,test = 0;
	mykonosInitCalStatus_t initCalStatus = {0};

	uint8_t				arm_major;
	uint8_t				arm_minor;
	uint8_t				arm_release;

	uint8_t deframerStatus = 0;
	uint8_t obsFramerStatus = 0;
	uint8_t framerStatus = 0;

	uint32_t initCalMask = 0 |
      TX_BB_FILTER |
      ADC_TUNER |
      TIA_3DB_CORNER |
      DC_OFFSET |
      TX_ATTENUATION_DELAY |
      RX_GAIN_DELAY |
      FLASH_CAL |
      RX_LO_DELAY |
      RX_QEC_INIT;

	uint32_t trackingCalMask = 0 |
      TRACK_ORX1_QEC |
      TRACK_ORX2_QEC;

      mykonosErr_t mykError = MYKONOS_ERR_OK;
      mykonosGpioErr_t mykGpioErr = MYKONOS_ERR_GPIO_OK;


      /* Allocating memory for the errorString */
      errorString = (const char*) malloc(sizeof(char) * 200);
      uint8_t read_buffer;

//      printf("\r**************************************************************\n\r");
//      printf("\r********************* AD9371_1 - JESD *********************\n\r");
//      printf("\r**************************************************************\n\n\r");



	/*** < Action: Insert BBIC Initialization Code Here                     > ***/

	/*************************************************************************/
	/*****                Mykonos Initialization Sequence                *****/
	/*************************************************************************/


	/*************************************************************************/
	/*****                Mykonos CLKPLL Status Check                    *****/
	/*************************************************************************/
	if ((mykError = MYKONOS_checkPllsLockStatus(&mykDevice1, &pllLockStatus)) != MYKONOS_ERR_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
    }


	/*************************************************************************/
	/*****                Mykonos Load ARM file                          *****/
	/*************************************************************************/
	if (pllLockStatus & 0x01)
	{
		printf("\rCLKPLL locked\n\r");
		if ((mykError = MYKONOS_initArm(&mykDevice1)) != MYKONOS_ERR_OK)
        {
            /*** < Info: errorString will contain log error string in order to debug failure > ***/
		    errorString = getMykonosErrorMessage(mykError);
		     printf("\r%s\n\r",errorString);
        }

#if 1
		/*** < Action: User must load ARM binary byte array into variable binary[98304] before calling next command > ***/
		if ((mykError = MYKONOS_loadArmFromBinary(&mykDevice1, &firmware_Mykonos_M3_bin[0], firmware_Mykonos_M3_bin_len)) != MYKONOS_ERR_OK)
				{
		    /*** < Info: errorString will contain log error string in order to debug why
		     *  ARM did not load properly - check binary and device settings  > ***/
		    /*** < Action: User code > ***/
		    errorString = getMykonosErrorMessage(mykError);
		     printf("\r%s\n\r",errorString);
		}
#endif
	}
	else
	{
		printf("\rCLKPLL not locked (0x%x)\n\r", pllLockStatus);
		return -1;
	}

	/* Read back the version of the ARM binary loaded into the Mykonos ARM memory */
		if ((mykError = MYKONOS_getArmVersion(&mykDevice1, &arm_major, &arm_minor, &arm_release)) == MYKONOS_ERR_OK)
			printf("\rAD9371_1 ARM version %d.%d.%d\n\r", arm_major, arm_minor, arm_release);


	/*************************************************************************/
	/*****                Mykonos Set RF PLL Frequencies                 *****/
	/*************************************************************************/
	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice1, RX_PLL, mykDevice1.rx->rxPllLoFrequency_Hz)) != MYKONOS_ERR_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
        errorString = getMykonosErrorMessage(mykError);
         printf("\r%s\n\r",errorString);
    }

	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice1, TX_PLL, mykDevice1.tx->txPllLoFrequency_Hz)) != MYKONOS_ERR_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
    }

	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice1, SNIFFER_PLL, mykDevice1.obsRx->snifferPllLoFrequency_Hz)) != MYKONOS_ERR_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
    }

	/*** < Action: wait 200ms for PLLs to lock > ***/
	delay(200*1000);

	if ((mykError = MYKONOS_checkPllsLockStatus(&mykDevice1, &pllLockStatus)) != MYKONOS_ERR_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
    }

	if ((pllLockStatus & 0x0F) == 0x0F)
	{
			printf("PLLs locked\n\r");
	    /*** < Info: All PLLs locked > ***/
	}
	else
	{
		printf("PLLs not locked (0x%x)\n\r", pllLockStatus);
		return -1;
	    /*** < Info: PLLs not locked  > ***/
	    /*** < Action: Ensure lock before proceeding - User code here > ***/
	}

	/*************************************************************************/
	/*****                Mykonos Set GPIOs                              *****/
	/*************************************************************************/
	if ((mykGpioErr = MYKONOS_setRx1GainCtrlPin(&mykDevice1, 0, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getGpioMykonosErrorMessage(mykGpioErr);
	     printf("\r%s\n\r",errorString);
    }

	if ((mykGpioErr = MYKONOS_setRx2GainCtrlPin(&mykDevice1, 0, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getGpioMykonosErrorMessage(mykGpioErr);
	     printf("\r%s\n\r",errorString);
    }

	if ((mykGpioErr = MYKONOS_setTx1AttenCtrlPin(&mykDevice1, 0, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getGpioMykonosErrorMessage(mykGpioErr);
	     printf("\r%s\n\r",errorString);
    }

	if ((mykGpioErr = MYKONOS_setTx2AttenCtrlPin(&mykDevice1, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getGpioMykonosErrorMessage(mykGpioErr);
	     printf("\r%s\n\r",errorString);
    }

	if ((mykGpioErr = MYKONOS_setupGpio(&mykDevice1)) != MYKONOS_ERR_GPIO_OK)
    {
        /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getGpioMykonosErrorMessage(mykGpioErr);
	     printf("\r%s\n\r",errorString);
    }

	/*************************************************************************/
	/*****                Mykonos Set manual gains values                *****/
	/*************************************************************************/
	if ((mykError = MYKONOS_setRx1ManualGain(&mykDevice1, 255)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	if ((mykError = MYKONOS_setRx2ManualGain(&mykDevice1, 255)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice1, OBS_RX1_TXLO, 255)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice1, OBS_RX2_TXLO, 255)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice1, OBS_SNIFFER_A, 255)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice1, OBS_SNIFFER_B, 255)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}
	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice1, OBS_SNIFFER_C, 255)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	/*************************************************************************/
	/*****                Mykonos Initialize attenuations                *****/
	/*************************************************************************/
	if ((mykError = MYKONOS_setTx1Attenuation(&mykDevice1, 0)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	if ((mykError = MYKONOS_setTx2Attenuation(&mykDevice1, 0)) != MYKONOS_ERR_OK)
	{
	    /*** < Info: errorString will contain log error string in order to debug failure > ***/
	    errorString = getMykonosErrorMessage(mykError);
	     printf("\r%s\n\r",errorString);
	}

	/*************************************************************************/
	/*****           Mykonos ARM Initialization Calibrations             *****/
	/*************************************************************************/

    if ((mykError = MYKONOS_runInitCals(&mykDevice1, (initCalMask & ~TX_LO_LEAKAGE_EXTERNAL))) != MYKONOS_ERR_OK)
	{
		/*** < Info: errorString will contain log error string in order to debug failure > ***/
		errorString = getMykonosErrorMessage(mykError);
		 printf("\r%s\n\r",errorString);
	}

	if ((mykError = MYKONOS_waitInitCals(&mykDevice1, 60000, &errorFlag, &errorCode)) != MYKONOS_ERR_OK)
	{
		/*** < Info: errorString will contain log error string in order to debug failure > ***/
		errorString = getMykonosErrorMessage(mykError);
		 printf("\r%s\n\r",errorString);
	}

	if ((errorFlag != 0) || (errorCode != 0))
	{
		if ((mykError = MYKONOS_getInitCalStatus(&mykDevice1, &initCalStatus)) != MYKONOS_ERR_OK)
		{
			/*** < Info: errorString will contain log error string in order to debug failure > ***/
			errorString = getMykonosErrorMessage(mykError);
			 printf("\r%s\n\r",errorString);
		}

		/*** < Info: abort init cals > ***/
		if ((mykError = MYKONOS_abortInitCals(&mykDevice1, &initCalsCompleted)) != MYKONOS_ERR_OK)
		{
			/*** < Info: errorString will contain log error string in order to debug failure > ***/
			errorString = getMykonosErrorMessage(mykError);
			 printf("\r%s\n\r",errorString);
		}
		if (initCalsCompleted)
		{
			printf("Completed calibrations: %x\n", (unsigned int)initCalsCompleted);
			/*** < Info: which calls had completed, per the mask > ***/
		}

		if ((mykError = MYKONOS_readArmCmdStatus(&mykDevice1, &errorWord, &statusWord)) != MYKONOS_ERR_OK)
		{
			/*** < Info: errorString will contain log error string in order to debug failure > ***/
			errorString = getMykonosErrorMessage(mykError);
			 printf("\r%s\n\r",errorString);
		}

		if ((mykError = MYKONOS_readArmCmdStatusByte(&mykDevice1, 2, &status)) != MYKONOS_ERR_OK)
		{
			/*** < Info: errorString will contain log error string in order to debug why  failed > ***/
			errorString = getMykonosErrorMessage(mykError);
			 printf("\r%s\n\r",errorString);
		}
		if (status != 0)
		{
			/*** < Info: Arm Mailbox Status Error errorWord > ***/
			/*** < Info: Pending Flag per opcode statusWord, this follows the mask > ***/
		}
	}
	else
	{
			printf("Calibrations completed successfully\n\r");
		/*** < Info: Calibrations completed successfully  > ***/
	}

	/*************************************************************************/
	/*****  Mykonos ARM Initialization External LOL Calibrations with PA *****/
	/*************************************************************************/
	/*** < Action: Please ensure PA is enabled operational at this time > ***/
	if (initCalMask & TX_LO_LEAKAGE_EXTERNAL)
	{
		if ((mykError = MYKONOS_runInitCals(&mykDevice1, TX_LO_LEAKAGE_EXTERNAL)) != MYKONOS_ERR_OK)
		{
			/*** < Info: errorString will contain log error string in order to debug failure > ***/
			errorString = getMykonosErrorMessage(mykError);
			 printf("\r%s\n\r",errorString);
		}
		if ((mykError = MYKONOS_waitInitCals(&mykDevice1, 60000, &errorFlag, &errorCode)) != MYKONOS_ERR_OK)
		{
			/*** < Info: errorString will contain log error string in order to debug failure > ***/
			errorString = getMykonosErrorMessage(mykError);
			 printf("\r%s\n\r",errorString);
		}
		if ((errorFlag != 0) || (errorCode != 0))
		{
			if ((mykError = MYKONOS_getInitCalStatus(&mykDevice1, &initCalStatus)) != MYKONOS_ERR_OK)
			{
				/*** < Info: errorString will contain log error string in order to debug failure > ***/
				errorString = getMykonosErrorMessage(mykError);
				 printf("\r%s\n\r",errorString);
			}

			/*** < Info: abort init cals > ***/
			if ((mykError = MYKONOS_abortInitCals(&mykDevice1, &initCalsCompleted)) != MYKONOS_ERR_OK)
			{
				/*** < Info: errorString will contain log error string in order to debug failure > ***/
				errorString = getMykonosErrorMessage(mykError);
				 printf("\r%s\n\r",errorString);
			}
			if (initCalsCompleted)
			{
				/*** < Info: which calls had completed, per the mask > ***/
			}

			if ((mykError = MYKONOS_readArmCmdStatus(&mykDevice1, &errorWord, &statusWord)) != MYKONOS_ERR_OK)
			{
				/*** < Info: errorString will contain log error string in order to debug failure > ***/
				errorString = getMykonosErrorMessage(mykError);
				 printf("\r%s\n\r",errorString);
			}

			if ((mykError = MYKONOS_readArmCmdStatusByte(&mykDevice1, 2, &status)) != MYKONOS_ERR_OK)
			{
				/*** < Info: errorString will contain log error string in order to debug failure > ***/
				errorString = getMykonosErrorMessage(mykError);
				 printf("\r%s\n\r",errorString);
			}
			if (status != 0)
			{
				/*** < Info: Arm Mailbox Status Error errorWord > ***/
				/*** < Info: Pending Flag per opcode statusWord, this follows the mask > ***/
			}
		}
		else
		{
			/*** < Info: Calibrations completed successfully  > ***/
		}
	}
}
