/******************************************************************************
*
* Copyright (C) 2009 - 2014 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/

/*
 * helloworld.c: simple test application
 *
 * This application configures UART 16550 to baud rate 9600.
 * PS7 UART (Zynq) is not initialized by this application, since
 * bootrom/bsp configures it to baud rate 115200
 *
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */

#include <stdio.h>
//#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xspi.h"
#include "xil_io.h"


XSpi spi;
int32_t spi_init(uint32_t device_id,XSpi *InstancePtr);
uint8_t spi_read_data(uint16_t addr);
int spi_write_data(uint32_t addr, uint8_t value);


#define CFG_RDY_REG 0x25     // 4th bit should be read -- if 1 power supply seq and reset seq is good  dev ready
#define RESET_REG 0x100    // 0th bit should be write in order to set all the internal re
#define GLOBAL_PLW_DWN 0x101  // 4th bit powerdowns entire ADC chip
#define CH_TERM  0x104 //1st bit chb-term  0th bit CHA -term . default 100ohm

#define LVDS_SETTINGS 0x110 // 1st bit channel swap
#define CUSTOM_PATTERN_LSB 0x14B
#define CUSTOM_PATTERN_MSB 0x14C
#define CUSTOM_PATTERNM_MSB 0x14D

#define TEST_PATTERN 0x14A
#define LVDS_BITS_SWAP 0x116

#define DDC_MODE_SEL 0x162
#define DDC_BYPASS 0x167
#define DDC_DEC_MODE_SEL0 0x168
#define DDC_DEC_MODE_SEL1  0x169
#define CLOCK_DEV_ENABLE_REG 0x590

#define FCLK_EN_REG 0x115
#define DDC_SEL 0x163
#define DIGITAL_GAIN_CHA  0x15B
#define DIGITAL_GAIN_CHB  0x15C
#define DATA_FORMAT 0x162

#define NCO_REG_0 0x200
#define NCO_REG_1 0x201
#define NCO_REG_2 0x202
#define NCO_REG_3 0x203
#define NCO_REG_4 0x204
#define NCO_REG_5 0x205

#define NCO_TOGGLE 0x165
#define NCO_ENABLE_REG 0x166
#define SYS_REF_MASK 0x161
#define SYS_REF_MODE 0x160
#define NCO_INDV_CH 0x164

/// threshold and testing functionality registors to be added

#define QSPI_CR_REG 0x60
#define UNITRAMP
#define CUSTOM_PATTERN_TOGGLE
#define CH_TERM_ENABLE
#define CH_SWAP
#define bits_swap
#define GAIN_INC
#define DATA_FORMAT_ENABLE
#define NCO_ENABLE
#define CUSTOM_PATTERN_STATIC
#define CUSTOM_PATTERN_RAMP
#define COMPLEX_R_REAL_DDC
#define DECIMATION_ENABLE


int main()
{
    init_platform();

	uint8_t data;
	spi_init(XPAR_AXI_QUAD_SPI_0_DEVICE_ID,&spi);

	Xil_Out32(XPAR_AXI_QUAD_SPI_0_BASEADDR + 0x60,0x186);
	int CR_REG = Xil_In32(XPAR_AXI_QUAD_SPI_0_BASEADDR + 0x60);



	spi_read_data(CFG_RDY_REG);
	usleep(1);


   while(1){
	   data=spi_read_data(CFG_RDY_REG);
	   xil_printf("CFG_READY_REG:%d\n",data);

	   data=spi_read_data(DDC_SEL);
	   xil_printf("DDC_SEL:%d\n",data);
	   usleep(10);

	   spi_write_data(RESET_REG,1);
	   usleep(1);

#ifndef COMPLEX_R_REAL_DDC
	   data=spi_read_data(DDC_SEL);
	   xil_printf("DDC_SEL:%d\n",data);
	   usleep(10);
	   spi_write_data(DDC_MODE_SEL,0);
	   usleep(1);
	   data=spi_read_data(DDC_MODE_SEL);
	   xil_printf("DDC_MODE_SEL:%d\n",data);
#endif



#ifndef DATA_FORMAT_ENABLE
	   spi_write_data(DATA_FORMAT,1);
	   usleep(1);
	   data=spi_read_data(DATA_FORMAT);
	   xil_printf("DATA_FORMAT:%d\n",data);
#endif

#ifndef bits_swap
	   spi_write_data(LVDS_BITS_SWAP,64);
	   usleep(1);
	   data=spi_read_data(LVDS_BITS_SWAP);
	   xil_printf("LVDS_BITS_SWAP:%d\n",data);

#endif


#ifndef CH_SWAP
	   data=spi_read_data(LVDS_SETTINGS);
	   xil_printf("LVDS_SETTINGS:%d\n",data);
	   spi_write_data(LVDS_SETTINGS,2);
	   usleep(1);
	   data=spi_read_data(LVDS_SETTINGS);
	   xil_printf("LVDS_SETTINGS:%d\n",data);

#endif

#ifdef NCO_ENABLE
	   spi_write_data(NCO_ENABLE_REG,0xFF);
	   usleep(1);
	   data=spi_read_data(NCO_ENABLE_REG);
//	   xil_printf("NCO_REG_0:%d\n",data);

	   spi_write_data(NCO_TOGGLE,2);
	   usleep(1);


	   spi_write_data(NCO_REG_0,0x55);
	   usleep(1);
	   data=spi_read_data(NCO_REG_0);
	   xil_printf("NCO_REG_0:%d\n",data);
	   spi_write_data(NCO_REG_1,0x55);
	   usleep(1);
	   data=spi_read_data(NCO_REG_1);
	   xil_printf("NCO_REG_1:%d\n",data);
	   spi_write_data(NCO_REG_2,0x55);
	   usleep(1);
	   data=spi_read_data(NCO_REG_2);
	   xil_printf("NCO_REG_2:%d\n",data);
	   spi_write_data(NCO_REG_3,0x55);
	   usleep(1);
	   data=spi_read_data(NCO_REG_3);
	   xil_printf("NCO_REG_3:%d\n",data);
	   spi_write_data(NCO_REG_4,0x55);
	   usleep(1);
	   data=spi_read_data(NCO_REG_4);
	   xil_printf("NCO_REG_4:%d\n",data);
	   spi_write_data(NCO_REG_5,0x15);
	   usleep(1);
	   data=spi_read_data(NCO_REG_5);
	   xil_printf("NCO_REG_5:%d\n",data);


	   //NCO2
	   spi_write_data(0x206,0x55);
	   usleep(1);
	   data=spi_read_data(0x206);
	   xil_printf("NCO_REG_0:%d\n",data);
	   spi_write_data(0x207,0x55);
	   usleep(1);
	   data=spi_read_data(0x207);
	   xil_printf("NCO_REG_1:%d\n",data);
	   spi_write_data(0x208,0x55);
	   usleep(1);
	   data=spi_read_data(0x208);
	   xil_printf("NCO_REG_2:%d\n",data);
	   spi_write_data(0x209,0x55);
	   usleep(1);
	   data=spi_read_data(0x209);
	   xil_printf("NCO_REG_3:%d\n",data);
	   spi_write_data(0x20A,0x55);
	   usleep(1);
	   data=spi_read_data(0x20A);
//	   xil_printf("NCO_REG_4:%d\n",data);
	   spi_write_data(0x20B,0x15);
	   usleep(1);
	   data=spi_read_data(0x20B);
//	   xil_printf("NCO_REG_5:%d\n",data);
//
//	   //NCO3
//
	   spi_write_data(0x20C,0x55);
	   usleep(1);
	   data=spi_read_data(0x20C);
//	   xil_printf("NCO_REG_0:%d\n",data);
	   spi_write_data(0x20D,0x55);
	   usleep(1);
	   data=spi_read_data(0x20D);
//	   xil_printf("NCO_REG_1:%d\n",data);
	   spi_write_data(0x20E,0x55);
	   usleep(1);
	   data=spi_read_data(0x20E);
//	   xil_printf("NCO_REG_2:%d\n",data);
	   spi_write_data(0x20F,0x55);
	   usleep(1);
	   data=spi_read_data(0x20F);
//	   xil_printf("NCO_REG_3:%d\n",data);
	   spi_write_data(0x210,0x55);
	   usleep(1);
//	   data=spi_read_data(0x210);
//	   xil_printf("NCO_REG_4:%d\n",data);
	   spi_write_data(0x211,0x15);
	   usleep(1);
//	   data=spi_read_data(0x211);
//	   xil_printf("NCO_REG_5:%d\n",data);
//
//	   //NCO4
//
//
	   spi_write_data(0x212,0x55);
	   usleep(1);
	   data=spi_read_data(0x212);
//	   xil_printf("NCO_REG_0:%d\n",data);
	   spi_write_data(0x213,0x55);
	   usleep(1);
	   data=spi_read_data(0x213);
//	   xil_printf("NCO_REG_1:%d\n",data);
	   spi_write_data(0x214,0x55);
	   usleep(1);
	   data=spi_read_data(0x214);
//	   xil_printf("NCO_REG_2:%d\n",data);
	   spi_write_data(0x215,0x55);
	   usleep(1);
	   data=spi_read_data(0x215);
//	   xil_printf("NCO_REG_3:%d\n",data);
	   spi_write_data(0x216,0x55);
//	   usleep(1);
	   data=spi_read_data(0x216);
//	   xil_printf("NCO_REG_4:%d\n",data);
	   spi_write_data(0x217,0x15);
//	   usleep(1);
	   data=spi_read_data(0x217);
//	   xil_printf("NCO_REG_5:%d\n",data);

	   spi_write_data(NCO_INDV_CH,0xF0);
	   usleep(100);
	   spi_write_data(NCO_INDV_CH,0x00);
//	   usleep(100);

	   spi_write_data(NCO_TOGGLE,3);
	   usleep(100);
	   spi_write_data(NCO_TOGGLE,2);
//	   usleep(100);

	   spi_write_data(SYS_REF_MASK,0x82);  //Mask Timer and LVDS block so sysref pulse only goes to DDC and NCO
	   usleep(1);
	   spi_write_data(SYS_REF_MODE,0x3);  // # Pulse Sysref (to synchronize DDCs on 0 - 1 transition)
	   usleep(1);
	   spi_write_data(SYS_REF_MODE,0x0);  // # (set back to zero)
	   usleep(1);

	   data=spi_read_data(0x164);
	   data=spi_read_data(0x165);
	   data=spi_read_data(0x166);


#endif
#ifdef DECIMATION_ENABLE


//	   spi_write_data(DDC_BYPASS,0x1);
//	   usleep(1);

	   spi_write_data(DDC_DEC_MODE_SEL1,0x1);
	   usleep(1);
	   data=spi_read_data(DDC_DEC_MODE_SEL1);
	   xil_printf("DDC_DEC_MODE_SEL1:%d\n",data);
#endif

#ifndef GAIN_INC
	   usleep(1);
	   data=spi_read_data(DIGITAL_GAIN_CHA);
	   xil_printf("DIGITAL_GAIN_CHA:%d\n",data);


	   spi_write_data(DIGITAL_GAIN_CHA,127);
	   usleep(1);
	   data=spi_read_data(DIGITAL_GAIN_CHA);
	   xil_printf("DIGITAL_GAIN_CHA:%d\n",data);

	   usleep(1);
	   data=spi_read_data(DIGITAL_GAIN_CHB);
	   xil_printf("DIGITAL_GAIN_CHB:%d\n",data);

	   spi_write_data(DIGITAL_GAIN_CHB,127);
	   usleep(1);
	   data=spi_read_data(DIGITAL_GAIN_CHB);
	   xil_printf("DIGITAL_GAIN_CHB:%d\n",data);
#endif

#ifndef CH_TERM_ENABLE   // this will enable 200 ohm termination instead of 100 ohm
	   spi_write_data(CH_TERM,3);
	   usleep(1);
	   data=spi_read_data(CH_TERM);
	   xil_printf("CH_TERM_enabled:%d\n",data);
#endif

#ifndef UNITRAMP
	   spi_write_data(CUSTOM_PATTERN_LSB,0x10);
	   usleep(1);
	   data=spi_read_data(CUSTOM_PATTERN_LSB);
	   xil_printf("CUSTOM_PATTERN_LSB:%d\n",data);
	   usleep(1);
	   spi_write_data(TEST_PATTERN,2);      // test pattern = 2 and custom test pattern LSB = 0x10 then UNIT RAMP
	   usleep(1);
	   data=spi_read_data(TEST_PATTERN);
	   xil_printf("TEST_PATTERN:%d\n",data);
#endif

#ifndef CUSTOM_PATTERN_STATIC      // upper 8 bits will be on rising edge lower 8 bits on falling edge  for dec 2
	   spi_write_data(CUSTOM_PATTERN_LSB,0xF0);    // upper 4 bits valid
	   usleep(1);
	   data=spi_read_data(CUSTOM_PATTERN_LSB);
	   xil_printf("CUSTOM_PATTERN_LSB:%d\n",data);
	   usleep(1);
	   spi_write_data(CUSTOM_PATTERN_MSB,0x0F);   // t0tal 8 bits valid
	   usleep(1);
	   data=spi_read_data(CUSTOM_PATTERN_MSB);
	   xil_printf("CUSTOM_PATTERN_MSB:%d\n",data);
	   usleep(1);
	   spi_write_data(CUSTOM_PATTERNM_MSB,0x00);  // lower 4 bits valid
	   usleep(1);
	   data=spi_read_data(CUSTOM_PATTERNM_MSB);
	   xil_printf("CUSTOM_PATTERNM_MSB:%d\n",data);
	   usleep(1);
	   spi_write_data(TEST_PATTERN,4);      // test pattern = 2 and custom test pattern LSB = 0x10 then UNIT RAMP
	   usleep(1);
	   data=spi_read_data(TEST_PATTERN);
	   xil_printf("TEST_PATTERN:%d\n",data);
#endif

#ifndef CUSTOM_PATTERN_RAMP
	   spi_write_data(CUSTOM_PATTERN_LSB,0x10);
	   usleep(1);
	   data=spi_read_data(CUSTOM_PATTERN_LSB);
	   xil_printf("CUSTOM_PATTERN_LSB:%d\n",data);

	   spi_write_data(TEST_PATTERN,0x2);      // test pattern = 2 and custom test pattern LSB = 0x10 then UNIT RAMP
	   usleep(1);
	   data=spi_read_data(TEST_PATTERN);
	   xil_printf("TEST_PATTERN:%d\n",data);
#endif

//	   usleep(100);

    }
    return 0;

//    print("Hello -World\n\r");
//    print("Successfully ran Hello World application");
    cleanup_platform();
    return 0;
}



int32_t spi_init(uint32_t device_id,XSpi *InstancePtr)

{
	uint32_t base_addr	 = 0;
	uint32_t spi_options = 0;
	XSpi_Config *spi_config;

	XSpi_Initialize(InstancePtr, device_id);
	XSpi_Stop(InstancePtr);
	spi_options = XSP_MASTER_OPTION |
				  XSP_CLK_PHASE_1_OPTION |
				  XSP_MANUAL_SSELECT_OPTION;
	XSpi_SetOptions(InstancePtr, spi_options);
	XSpi_Start(InstancePtr);
	XSpi_IntrGlobalDisable(InstancePtr);
	XSpi_SetSlaveSelect(InstancePtr, 1);

	return 1;
}

uint8_t spi_read_data(uint16_t addr)
{
	uint8_t send_buffer[2];
	uint32_t data1;

	int value=1;    // spi read bit
	int length = 0;
	int bytes_number = 3;
	value = (value << 23);
//	value = value|(length <<20);
	value = value|(addr <<8);
	send_buffer[2] = value ;
	send_buffer[1] = value >> 8 ;
	send_buffer[0] = value >> 16 ;
	XSpi_Transfer(&spi, send_buffer, &data1, bytes_number);
	return (data1 >> 16);
}

int spi_write_data(uint32_t addr,uint8_t value)
{
	uint8_t send_buffer[3];
	uint8_t recv_buffer[3];

	uint32_t value1=0;   // spi write bit
	uint32_t length = 0;
	int bytes_number = 3;
	value1 = (value1 << 23);
//	value1 = value1|(length <<20);
	value1 = value1|(addr <<8);
	value1= value1| (value);
	send_buffer[2] = value1 ;
	send_buffer[1] = value1 >> 8 ;
	send_buffer[0] = value1 >> 16 ;
	XSpi_Transfer(&spi, send_buffer, recv_buffer, bytes_number);
	return 1;

}
