

/***************************** Include Files *******************************/

#include "IMX253_SPI_2.h"


/************************** Function Definitions ***************************/
unsigned int *SPI_ADDR = XPAR_IMX253_SPI_2_0_S00_AXI_BASEADDR;
#define BUFFER_SIZE 100
char write_buff[BUFFER_SIZE][4];                                    //[spi id][chip_id, register address, data, is it busy?]
int spi_enabled = 1;



void spi_set_register(imx253reg reg, int val){
	int i = 0;
	if(reg.length > (8-reg.bit)){                                     //does it lap over the other address?

		spi_write(reg.chip_id_w, reg.address, val<<reg.bit);            //first address write
		if(reg.length - (8-reg.bit) > 8){                               //does it lap over the third address?
			spi_write(reg.chip_id_w, reg.address+1,val>>(8-reg.bit));     //second address write
			spi_write(reg.chip_id_w, reg.address+2,val>>((8-reg.bit)+8)); //third address write
		}
		else //laps over to the second address
		{
			spi_write(reg.chip_id_w, reg.address+1,val>>(8-reg.bit));
		}
	}
	else //does not lap over
	{
		spi_write(reg.chip_id_w, reg.address, val<<reg.bit); 
	}
}


void spi_set_interrupt_delay(u32 delay){
	if(delay >= 0 && delay < 16000000){
	}
	else
	{
		print("Not in range (0 - 15999999)");
	}
}
int spi_write(char chip_id, char register_address, char data){ //sends SPI command
	u32 chip_id_s = chip_id;
	u32 register_address_s = register_address;
	u32 data_s = data;
	u32 communication_ok = 0;
	u32 result = 0;
	u32  mask;
	int i = 0;
	int n = 256;
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 0, 0b00100000000);
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 1, register_address_s);
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 2, data_s);
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 0, 0b11111100000000 + chip_id); //interrupt enable, data valid, zápis, 8x chip_id
	while (lock_spi == 1){	//data separation and validity check until confirmed
		}
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 0, 0b01100000000);
	lock_spi = 0;

	return 1;
}
char spi_read(char chip_id, char register_address){ //sends SPI command and read the answer
	u32 communication_ok = 0;
	u32 result = 0;
	u32  mask;
	u32 data;
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 0, 0b0000000000);
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 0, chip_id + 0x000); //+0x000 = 0b0 0000 0000 - reading
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 1, register_address);
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 2, register_address);
	IMX253_SPI_2_mWriteReg(SPI_ADDR, 0, 0b1000000000);
	while (communication_ok == 0){						      //data separation and validity check until confirmed
		result = IMX253_SPI_2_mReadReg(SPI_ADDR, 3); 	//e.g. 00011100111100011100011100011100
		mask = ((1 << 8) - 1) << 24;					        //011111111000000000000000000000000
		data = result & mask;							            //000011100000000000000000000000000
		data = data >> 24;								            //000000000000000000000000000011100
		result = IMX253_SPI_2_mReadReg(SPI_ADDR, 3);	// 00011100111100011100011100011100
		mask = ((1 << 1) - 1) << 8;			    		      // 00000000100000000000000000000000
		communication_ok = result & mask;				      // 00000000100000000000000000000000
		communication_ok = communication_ok >> 8;		  // 00000000000000000000000000000001
	}
	return (char)data;
}

int spi_add_to_write(char chip_id, char register_address, char data){ //adds SPI command to the queue

	int i = 0;
	while(write_buff[i][3]!=0){ //searches for empty space
		i ++;
		if(i == BUFFER_SIZE -1){
			return -1; //insufficient space in buffer
	    }
	}
	write_buff[i][0] = chip_id;
	write_buff[i][1] = register_address;
	write_buff[i][2] = data;
	write_buff[i][3] = 1;	//marks item as busy
	return 1;
}
void print_buff(){
	int i = 0;
	while(i < BUFFER_SIZE){ //searches for busy items in queue
		if(write_buff[i][0] == 0 && write_buff[i][1] == 0 && write_buff[i][2] == 0 && write_buff[i][3] == 0){
			i++;
		}else
				printf("%d:%d,%d,%d,%d\n",i,write_buff[i][0],write_buff[i][1],write_buff[i][2],write_buff[i][3]);
		i++;
			}
}

int spi_write_next_from_buff(){ //sends all waiting SPI from the queue
	int i = 0;
	int communication_ok = 0;
	int result = 0;
	while(i < BUFFER_SIZE){ //searches for busy items
		if(write_buff[i][3]==1){ //is item busy?
			write_buff[i][3] = 0; //unmarks item as busy (space is ready for reset)
			lock_spi = 1;
			spi_write(write_buff[i][0],write_buff[i][1],write_buff[i][2]); //sends SPI
			while(lock_spi == 1){
			}
		}
		i++;
	}
	lock_spi = 0;
	return -1;
}

void spi_write_enable(){
	spi_enabled = 1;
}
void spi_write_disable(){
	spi_enabled = 0;
}