#include "x_parallel_bus.h"

#include "MemoryFunctions.h"
#include "Spartan2E_Adr.h"
#include "Spartan2E_Functions.h"
#include "xp_controller.h"
#include "xerror.h"


X_PARALLEL_BUS x_parallel_bus_project = X_PARALLEL_BUS_DEFAULTS;

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_run_cmd(X_PARALLEL_BUS *v)
{
	volatile unsigned int d_wr;

	d_wr = ( (v->flags.bit.cmd_start & 0x1) << 15 ) | ( (v->setup.setup_error_count_read & 0xf) << 8 ) | ((v->setup.size_table - 1) & 0xff);
	WriteMemory(ADR_PARALLEL_BUS_CMD, d_wr);

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




////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_clear_table(X_PARALLEL_BUS *v)
{
	v->setup.size_table = -1;
	v->setup.free_table = -1;

	v->flags.bit.cmd_start = 1;
	x_parallel_bus_run_cmd(v);

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
int x_parallel_bus_check_free_table(X_PARALLEL_BUS *v)
{

    if ( (v->setup.size_table + v->setup.tms_adr_data_start) <= v->setup.tms_adr_data_finish)
    {
        return 1;
    }
    return 0;

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_add_table(X_PARALLEL_BUS *v)
{
	volatile unsigned int d_wr;

	if (v->flags.bit.started)
	{
		v->stop(v);
	}

//	if (v->setup.size_table != 0)
//    v->setup.size_table++;
	if ( (v->setup.size_table + v->setup.tms_adr_data_start) > v->setup.tms_adr_data_finish)
	{
	    // ����� � ������� ����!!!
	    xerror(xparall_bus_er_ID(1),(void *)0);
	    return;
	}

	d_wr = v->setup.size_table & 0xff;
	WriteMemory(ADR_PARALLEL_BUS_ADR_TABLE, d_wr);
	d_wr =  ( (v->slave_addr & 0xf) << 12 ) | ( (v->reg_addr & 0xf) << 8 ) | (( (v->setup.tms_adr_data_start & 0xff) + v->setup.size_table) & 0xff);
	WriteMemory(ADR_PARALLEL_BUS_SET_TABLE, d_wr);

	v->setup.free_table = (v->setup.tms_adr_data_finish - v->setup.tms_adr_data_start) - v->setup.size_table;

//	x_parallel_bus_run_cmd(v);

	

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_start(X_PARALLEL_BUS *v)
{
    if (v->setup.size_table != 0)
    {
        v->flags.bit.error = 0;
        v->flags.bit.cmd_start = 1;
        v->flags.bit.was_started = 0;

        x_parallel_bus_run_cmd(v);
        v->flags.bit.started = 1;
    }
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_stop(X_PARALLEL_BUS *v)
{
	v->flags.bit.cmd_start = 0;
	x_parallel_bus_run_cmd(v);
	v->flags.bit.started = 0;

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_restart(X_PARALLEL_BUS *v)
{
	v->flags.bit.cmd_start = 0;
	x_parallel_bus_run_cmd(v);
	v->flags.bit.started = 0;

	v->flags.bit.error = 0;
	v->flags.bit.cmd_start = 1;
	x_parallel_bus_run_cmd(v);
	v->flags.bit.started = 1;

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_init(X_PARALLEL_BUS *v)
{
	if (v->flags.bit.init)
		return;

	v->setup.size_table  = 0;//-1;
	v->setup.tms_adr_data_start  = ADR_FIRST_FREE;
	v->setup.tms_adr_data_finish = ADR_LAST_FREE;
	v->setup.setup_error_count_read = MAX_WAIT_ERROR_PARALLEL_BUS;
	v->setup.free_table = v->setup.tms_adr_data_finish - v->setup.tms_adr_data_start;


	v->flags.all		 = 0;

	v->slave_addr        = 0;
	v->reg_addr			 = 0;
	v->error_count_start = 0;
	v->count_read 		 = 0;

	v->stop(v);

	v->flags.bit.init = 1;

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


////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
void x_parallel_bus_read_status(X_PARALLEL_BUS *v)
{
//	volatile unsigned int d_rd;
	static unsigned int prev_error = 0;
	T_controller_read r_c;

// check prev status? 
	if (v->flags.bit.error)
	  return;

// read status bus
	r_c.errors_buses.all = i_ReadMemory(ADR_BUS_ERROR_READ);

	v->flags.bit.count_error = r_c.errors_buses.bit.count_error_pbus;//   ((d_rd >> 8) & 0xf);
	v->flags.bit.slave_addr_error = r_c.errors_buses.bit.slave_addr_error; //   ((d_rd >> 4) & 0xf);

	if ( v->flags.bit.count_error >= v->setup.setup_error_count_read )
	{
	   v->flags.bit.error = 1;
	}
	else
	   v->flags.bit.error = 0;

	if ((prev_error != v->flags.bit.error ) && (v->flags.bit.error))
	{
	  v->error_count_start++;
	  if (v->flags.bit.started)
	  {
	    v->flags.bit.was_started = 1;
	    x_parallel_bus_stop(v);
	  }
	}

    prev_error = v->flags.bit.error;

	if ( v->flags.bit.started && (v->flags.bit.error == 0))
	  v->count_read++;


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

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////
#pragma CODE_SECTION(x_parallel_bus_read_one_data,".fast_run");
void x_parallel_bus_read_one_data(X_PARALLEL_BUS *v)
{
// read data from parallel bus
	v->data_table_read = i_ReadMemory(ADR_FIRST_FREE + v->adr_table_read);
}
////////////////////////////////////////////////////////////////