#include "x_serial_bus.h"

#include "DSP281x_Examples.h"
#include "DSP281x_Device.h"
#include "MemoryFunctions.h"
#include "Spartan2E_Adr.h"
#include "Spartan2E_Functions.h"
#include "TuneUpPlane.h"
#include "x_parallel_bus.h"
#include "xp_controller.h"



X_SERIAL_BUS x_serial_bus_project = X_SERIAL_BUS_DEFAULTS;
T_controller_read r_c_sbus;

static unsigned int counterSBWriteErrors = 0;

///////////////////////////////////////////////////////
//
//
//	Example use:
//
//  x_serial_bus_project.init(&x_serial_bus_project);
//	
//	x_serial_bus_project.reg_addr = 1;   // adr memory in plate
//	x_serial_bus_project.slave_addr = 6; // number plate
//
//	x_serial_bus_project.read(&x_serial_bus_project); // read
//
//	if (x_serial_bus_project.flags.bit.read_error==0) // check error
//	{
//		x_serial_bus_project.write_data = 1000; // write data 
//	    x_serial_bus_project.write(&x_serial_bus_project); // make write	  
//	}
//
//  check return data:
//   
//    x_serial_bus_project.flags.bit.read_error - error 
//    x_serial_bus_project.flags.bit.write_error - error
//    x_serial_bus_project.error_count_read - sum count read
//    x_serial_bus_project.error_count_write - sum count write
///////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// Read from serial bus
////////////////////////////////////////////////////////////////
int x_serial_bus_read(X_SERIAL_BUS *v)
{
	volatile unsigned int d_rd, d_wr;
	unsigned int time_out = 0;
	int err = 0;

	if (v->slave_addr>0xf)
// overfull adr - error?
	   return 1;
// check bus hold?
	if (v->flags.bit.count_hold_bus) 
	// bus hold - error?
	  return 1;

// test hold bus
	v->flags.bit.count_hold_bus++;
	if (v->flags.bit.count_hold_bus>1)
	{
	// parallel hold - error?
	  v->error_count_hold++;
	  return 1;
	}

// clear bus flags
    d_rd = i_ReadMemory(ADR_SERIAL_BUS_DATA_READ);

// read status bus
//    d_rd = i_ReadMemory(ADR_BUS_ERROR_READ);
	r_c_sbus.errors_buses.all = i_ReadMemory(ADR_BUS_ERROR_READ);
	v->flags.bit.error = r_c_sbus.errors_buses.bit.err_sbus;//  ((d_rd >> 14) & 0x1);
	v->flags.bit.trans_compl = r_c_sbus.errors_buses.bit.sbus_updated;//((d_rd >> 15) & 0x1);
	
// check status bits - all clear?
//	if (v->flags.bit.error || v->flags.bit.trans_compl)
	if (v->flags.bit.trans_compl)
	{
		v->flags.bit.read_error = 2;
	    v->error_count_read++;
		return 1;
	}
	 
// write cmd
	d_wr = CMD_SERIAL_BUS_READ | ( (v->slave_addr & 0xf) << 4 ) | (v->reg_addr & 0xf);
	WriteMemory(ADR_SERIAL_BUS_CMD, d_wr); 

// wait transmited data
	v->flags.bit.trans_compl   = 0;
	v->flags.bit.error_timeout = 0;
	time_out = 0;

	DELAY_US(200);
	while (!v->flags.bit.trans_compl)
	{		
// read status bus
//		d_rd = i_ReadMemory(ADR_BUS_ERROR_READ);
     	r_c_sbus.errors_buses.all = i_ReadMemory(ADR_BUS_ERROR_READ);
		v->flags.bit.error = r_c_sbus.errors_buses.bit.err_sbus;//((d_rd >> 14) & 0x1);
		v->flags.bit.trans_compl = r_c_sbus.errors_buses.bit.sbus_updated; //((d_rd >> 15) & 0x1);

//check timeout		 		
		time_out++;
		if (time_out>TIME_OUT_SERIAL_BUS)
		{
// time out - error!
		  v->flags.bit.error_timeout = 1;
		  break;
		}

		if (v->flags.bit.trans_compl)
		{
// check error
		  if (v->flags.bit.error==0)
		  {
// data ready - read it!
	        d_rd = i_ReadMemory(ADR_SERIAL_BUS_DATA_READ);
		    v->read_data = d_rd;
		  }
		}
	}
// clear bus flags
	d_rd = i_ReadMemory(ADR_SERIAL_BUS_DATA_READ);
	if (v->flags.bit.error_timeout || v->flags.bit.error)
	{
	  v->flags.bit.read_error = 1;
	  v->error_count_read++;
	  err = 1;
	}
	else
	{
      v->flags.bit.read_error = 0;
	  v->ok_count_read++;
	}

// unhold bus
	v->flags.bit.count_hold_bus = 0;
	v->count_timer = time_out;


	return err;
}


////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// Write to serial bus
////////////////////////////////////////////////////////////////
int x_serial_bus_write(X_SERIAL_BUS *v)
{
	volatile unsigned int d_rd, d_wr;
	unsigned int time_out = 0;
	int err = 0;

	if (v->slave_addr>0xf)
// overfull adr - error?
       return 1;

// check bus hold?
	if (v->flags.bit.count_hold_bus) 
	  return 1;

// test hold bus
	if (v->flags.bit.count_hold_bus<8)
	  v->flags.bit.count_hold_bus++;

	if (v->flags.bit.count_hold_bus>1)
	{
	// parallel hold - error?
	  v->error_count_hold++;
	  v->flags.bit.count_hold_bus = 0;
	  return 1;
	}


	//cycle to write several times if there was some errors
    counterSBWriteErrors = 0;
	do{

// clear bus flags
    d_rd = i_ReadMemory(ADR_SERIAL_BUS_DATA_READ);

// read status bus
//    d_rd = i_ReadMemory(ADR_BUS_ERROR_READ);
   	r_c_sbus.errors_buses.all = i_ReadMemory(ADR_BUS_ERROR_READ);
	v->flags.bit.error = r_c_sbus.errors_buses.bit.err_sbus;//((d_rd >> 14) & 0x1);
	v->flags.bit.trans_compl = r_c_sbus.errors_buses.bit.sbus_updated; //((d_rd >> 15) & 0x1);

// check status bits - all clear?
//	if (v->flags.bit.error || v->flags.bit.trans_compl)
	if (v->flags.bit.trans_compl)
	{
		v->flags.bit.read_error = 2;
	    v->error_count_write++;
		v->flags.bit.count_hold_bus = 0;
		return 1;
	}

// write data
	WriteMemory(ADR_SERIAL_BUS_DATA_WRITE, v->write_data); 

// write cmd
	d_wr = CMD_SERIAL_BUS_WRITE | ( (v->slave_addr & 0xf) << 4 ) | (v->reg_addr & 0xf);
	WriteMemory(ADR_SERIAL_BUS_CMD, d_wr); 

// wait transmited data
	v->flags.bit.trans_compl   = 0;
	v->flags.bit.error_timeout = 0;
	time_out = 0;

	while (!v->flags.bit.trans_compl)
	{		
// read status bus
		d_rd = i_ReadMemory(ADR_BUS_ERROR_READ);
		v->flags.bit.error = ((d_rd >> 14) & 0x1);
		v->flags.bit.trans_compl = ((d_rd >> 15) & 0x1);
		
//check timeout		 		
		time_out++;
		if (time_out>TIME_OUT_SERIAL_BUS)
		{
// time out - error!
		  v->flags.bit.error_timeout = 1;
		  break;
		}

		if (v->flags.bit.trans_compl)
		{
//	      d_rd = i_ReadMemory(ADR_BUS_ERROR_READ);
//		  if (v->flags.bit.error==0)
//		  {
//		  }
   		  break;
		}

	}

		if (v->flags.bit.error)
		{
			counterSBWriteErrors++;  // ���� ������ ���� � ���� �����, �� ��������� ��������
		} 
		else
		{
			break;	// ���� ��� ������ ���, �� ��������� ���� � ���� ������
		}


	}while(counterSBWriteErrors <= SB_ERROR_REPEATS);

		
// clear bus flags
	d_rd = i_ReadMemory(ADR_SERIAL_BUS_DATA_READ);

	if (v->flags.bit.error_timeout || v->flags.bit.error)
	{
	  v->flags.bit.write_error = 1;
	  v->error_count_write++;
	  err = 1;
	}
	else
	 v->ok_count_write++;

	v->count_timer = time_out;

// unhold bus
	v->flags.bit.count_hold_bus = 0;
	return err;

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
void x_serial_bus_check(X_SERIAL_BUS *v)
{

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

void x_serial_bus_init(X_SERIAL_BUS *v)
{
	v->flags.all   = 0;

	v->count_timer = 0;
	v->read_data   = 0x0;
	v->write_data  = 0x0;
	v->reg_addr    = 0;
	v->slave_addr  = 0;

    v->error_count_read  = 0;
	v->error_count_write = 0;
	v->error_count_hold  = 0;
    v->ok_count_read  = 0;
	v->ok_count_write = 0;
}

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

void x_serial_bus_clear_stat_error(X_SERIAL_BUS *v)
{
    v->error_count_read  = 0;
	v->error_count_write = 0;
	v->error_count_hold  = 0;
	v->count_timer       = 0;

    v->ok_count_read  = 0;
	v->ok_count_write = 0;

}