/*
 * driver.cpp
 *
 * Created: 4.3.2013 18:50:50
 *  Author: Jirka
 */ 

#include <avr/io.h>
#include <stdio.h>
#include "SPI.h"
#include "driver.h"

//   ---------------------------------------------
//   |  Byte_4  |  Byte_3  |  Byte_2  |  Byte_1  |
//   ---------------------------------------------

#define BYTE_4(x)	(((x) & (0xFF000000))>>24)		//MSByte
#define BYTE_3(x)	(((x) & (0x00FF0000))>>16)
#define BYTE_2(x)	(((x) & (0x0000FF00))>>8)
#define BYTE_1(x)	(((x) & (0x000000FF))>>0)		//LSByte

unsigned char Nop (void)
{
	unsigned char driver;
	driver = SPI_read();
	return driver;
}

void SetParam (reg_name set_param,long presets, long set_value1, long set_value2)
{
	unsigned char i = 0;															//pocet bajtu pro odeslani
	unsigned char j = 0;
	char reg_value [4] = {0,0,0,0};													//odesilane bajty
		
	switch (set_param)
	{
		case 0:	reg_value[0] = adr_ABS_POS;
				reg_value[1] = BYTE_3(set_value1);
				reg_value[2] = BYTE_2(set_value1);
				reg_value[3] = BYTE_1(set_value1);
				i = 4;			break;
		
		case 1:	reg_value[0] = adr_EL_POS;											//kroky, mikrokroky
				//reg_value[1] = (((set_value1)<<7 | set_value2) & 0x0000FF00)>>8;
				//reg_value[2] = (((set_value1)<<7 | set_value2) & 0x000000FF)>>0;
				reg_value[1] = BYTE_2((set_value1)<<7 | set_value2);
				reg_value[2] = BYTE_1((set_value1)<<7 | set_value2);
				i = 3;			break;
		
		case 2:	reg_value[0] = adr_MARK;
				reg_value[1] = BYTE_3(set_value1);
				reg_value[2] = BYTE_2(set_value1);
				reg_value[3] = BYTE_1(set_value1);
				i = 4;			break;

		case 3:					break;
												
		case 4:	reg_value[0] = adr_ACC;
				reg_value[1] = BYTE_2(set_value1);
				reg_value[2] = BYTE_1(set_value1);
				i = 3;			break;
					
		case 5:	reg_value[0] = adr_DEC;
				reg_value[1] = BYTE_2(set_value1);
				reg_value[2] = BYTE_1(set_value1);
				i = 3;			break;
					
		case 6:	reg_value[0] = adr_MAX_SPEED;
				reg_value[1] = BYTE_2(set_value1);
				reg_value[2] = BYTE_1(set_value1);
				i = 3;			break;
					
		case 7:	reg_value[0] = adr_MIN_SPEED;
				reg_value[1] = (BYTE_2(set_value1)) | presets;
				reg_value[2] = BYTE_1(set_value1);
				i = 3;			break;	
					
		case 8:	reg_value[0] = adr_KVAL_HOLD;
				reg_value[1] = set_value1;
				i = 2;			break;
					
		case 9: reg_value[0] = adr_KVAL_RUN;
				reg_value[1] = set_value1;	
				i = 2;			break;
					
		case 10:reg_value[0] = adr_KVAL_ACC;
				reg_value[1] = set_value1;
				i = 2;			break;
					
		case 11:reg_value[0] = adr_KVAL_DEC;
				reg_value[1] = set_value1;
				i = 2;			break;
					
		case 12:reg_value[0] = adr_INT_SPEED;
				reg_value[1] = BYTE_2(set_value1);
				reg_value[2] = BYTE_1(set_value1);
				i = 3;			break;
					
		case 13:reg_value[0] = adr_ST_SLP;
				reg_value[1] = set_value1;
				i = 2;			break;
					
		case 14:reg_value[0] = adr_FN_SLP_ACC;
				reg_value[1] = set_value1;
				i = 2;			break;
		
		case 15:reg_value[0] = adr_FN_SLP_DEC;
				reg_value[1] = set_value1;
				i = 2;			break;
				
		case 16:reg_value[0] = adr_K_THERM;
				reg_value[1] = set_value1;
				i = 2;			break;
		
		case 17:				break;					
					
		case 18:reg_value[0] = adr_OCD_TH;
				reg_value[1] = set_value1;
				i = 2;			break;
					
		case 19:reg_value[0] = adr_STALL_TH;
				reg_value[1] = set_value1;
				i = 2;			break;
					
		case 20:reg_value[0] = 	adr_FS_SPD;
				reg_value[1] = BYTE_2(set_value1);
				reg_value[2] = BYTE_1(set_value1);
				i = 3;			break;
		
		case 21:reg_value[0] = adr_STEP_MODE;
				reg_value[1] = presets;
				i = 2;			break;
					
		case 22:reg_value[0] = adr_ALARM_EN;
				reg_value[1] = presets;
				i = 2;			break;
					
		case 23:reg_value[0] = adr_CONFIG;
				reg_value[1] = BYTE_2(presets);
				reg_value[2] = BYTE_1(presets);
				i = 3;			break;
		
		case 24:				break;
		
		default:				break;
		
	}
		
	for (j=0; j<i; j++)
	{
		SPI_write(reg_value[j]);
	}
	
}

long GetParam (reg_name get_param)
{
	unsigned char i = 0;
	unsigned char j = 0;
	unsigned char address = 0;
	long reg_parameter = 0;
	char reg_value [3] = {0,0,0};
		
	switch(get_param)
	{
		case 0: address = adr_ABS_POS + 0x20;
				i = 4;		break;
				
		case 1: address = adr_EL_POS + 0x20;
				i = 3;		break;
				
		case 2: address = adr_MARK + 0x20;
				i = 4;		break;
				
		case 3: address = adr_SPEED + 0x20;
				i = 4;		break;
				
		case 4: address = adr_ACC + 0x20;
				i = 3;		break;
				
		case 5: address = adr_DEC + 0x20;
				i = 3;		break;
				
		case 6: address = adr_MAX_SPEED + 0x20;
				i = 3;		break;
				
		case 7: address = adr_MIN_SPEED + 0x20;
				i = 3;		break;
				
		case 8: address = adr_KVAL_HOLD + 0x20;
				i = 2;		break;
				
		case 9: address = adr_KVAL_RUN + 0x20;
				i = 2;		break;
				
		case 10:address = adr_KVAL_ACC + 0x20;
				i = 2;		break;
				
		case 11:address = adr_KVAL_DEC + 0x20;
				i = 2;		break;
				
		case 12:address = adr_INT_SPEED + 0x20;
				i = 3;		break;
				
		case 13:address = adr_ST_SLP + 0x20;
				i = 2;		break;
				
		case 14:address = adr_FN_SLP_ACC + 0x20;
				i = 2;		break;
				
		case 15:address = adr_FN_SLP_DEC + 0x20;
				i = 2;		break;
				
		case 16:address = adr_K_THERM + 0x20;
				i = 2;		break;
				
		case 17:address = adr_ADC_OUT + 0x20;
				i = 2;		break;
				
		case 18:address = adr_OCD_TH + 0x20;
				i = 2;		break;
				
		case 19:address = adr_STALL_TH + 0x20;
				i = 2;		break;
				
		case 20:address = adr_FS_SPD + 0x20;
				i = 3;		break;
				
		case 21:address = adr_STEP_MODE + 0x20;
				i = 2;		break;
				
		case 22:address = adr_ALARM_EN + 0x20;
				i = 2;		break;
				
		case 23:address = adr_CONFIG + 0x20;
				i = 3;		break;
				
		case 24:address = adr_STATUS + 0x20;
				i = 3;		break;
				
		default:			break;
	}
	
	SPI_write(address);
	for (j=0; j<i-1; j++)
	{
		reg_value[j] = SPI_read();
	}
		
	switch(i)
	{
		case 1:															break;
		case 2:		reg_parameter = reg_value[0];						break;
		case 3:		reg_parameter = reg_value[0];
					reg_parameter <<= 8;
					reg_parameter = reg_parameter + reg_value[1];		break;
		case 4:		reg_parameter = reg_value[0];
					reg_parameter <<= 8;
					reg_parameter = reg_parameter + reg_value[1];
					reg_parameter <<= 8;
					reg_parameter = reg_parameter + reg_value[2];		break;
		default:														break;
	}
	return(reg_parameter);	
}

void Run (direction dir, long spd)
{
	unsigned char k = 0;
	char reg[4] = {0,0,0,0};
	switch(dir)
	{
		case 0:	reg[0] = 0b01010000;	break;
		case 1: reg[0] = 0b01010001;	break;
		default:						break;
	}
	reg[1] = BYTE_3(spd);
	reg[2] = BYTE_2(spd);
	reg[3] = BYTE_1(spd);
	for (k=0; k<4; k++)
	{
		SPI_write(reg[k]);
	}
	
}

void StepClock (direction dir)
{
	switch(dir)
	{
		case 0:	SPI_write(0b01011000);		break;
		case 1: SPI_write(0b01011001);		break;
		default:							break;
	}
}

void Move (direction dir, long n_step)
{
	unsigned char k = 0;
	char reg[4] = {0,0,0,0};
	switch(dir)
	{
		case 0:	reg[0] = 0b01000000;	break;
		case 1: reg[0] = 0b01000001;	break;
		default:						break;
	}
	reg[1] = BYTE_3(n_step);
	reg[2] = BYTE_2(n_step);
	reg[3] = BYTE_1(n_step);
	for (k=0; k<4; k++)
	{
		SPI_write(reg[k]);
	}
}

void GoTo (long abs_position)
{
	unsigned char k = 0;
	char reg[4] = {0,0,0,0};
	reg[0] = 0b01100000;
	reg[1] = BYTE_3(abs_position);
	reg[2] = BYTE_2(abs_position);
	reg[3] = BYTE_1(abs_position);
	
	for (k=0; k<4; k++)
	{
		SPI_write(reg[k]);
	}
}

void GoTo_Dir (direction dir, long abs_position)
{
	unsigned char k = 0;
	char reg[4] = {0,0,0,0};
	switch (dir)
	{
		case 0: reg[0] = 0b01101000;	break;
		case 1: reg[1] = 0b01101001;	break;
		default:						break;
	}
	reg[1] = BYTE_3(abs_position);
	reg[2] = BYTE_2(abs_position);
	reg[3] = BYTE_1(abs_position);
	
	for (k=0; k<4; k++)
	{
		SPI_write(reg[k]);
	}
}

void GoUntil (action act, direction dir, long spd)
{
	unsigned char k = 0;
	char reg[4] = {0,0,0,0};
	switch(dir)
	{
		case 0:		switch(act)
					{
						case 0: reg[0] = 0b10000010;	break;
						case 1: reg[0] = 0b10001010;	break;
						default:						break;
					}
		case 1:		switch(act)
					{
						case 0: reg[0] = 0b10000011;	break;
						case 1: reg[0] = 0b10001011;	break;
						default:						break;
					}
		default:	break;
	}	
	reg[1] = BYTE_3(spd);
	reg[2] = BYTE_2(spd);
	reg[3] = BYTE_1(spd);
	for (k=0; k<4; k++)
	{
		SPI_write(reg[k]);
	}
	
}

void ReleaseSW (action act, direction dir)
{
	switch(dir)
	{
		case 0:		switch(act)
					{
						case 0: SPI_write(0b10010010);	break;
						case 1: SPI_write(0b10011010);	break;
						default:						break;
					}
		case 1:		switch(act)
					{
						case 0: SPI_write(0b10010011);	break;
						case 1: SPI_write(0b10011011);	break;
						default:						break;
					}
		default:	break;
	}
}

void GoHome (void)
{
	SPI_write(0b01110000);
}

void GoMark (void)
{
	SPI_write(0b01111000);
}

void ResetPos (void)
{
	SPI_write(0b11011000);
}

void ResetDevice (void)
{
	SPI_write(0b11000000);
}

void SoftStop (void)
{
	SPI_write(0b10110000);
}

void HardStop (void)
{
	SPI_write(0b10111000);
}

void SoftHiZ (void)
{
	SPI_write(0b10100000);
}

void HardHiZ (void)
{
	SPI_write(0b10101000);
}

int  GetStatus (void)
{
	int STATUS_reg = 0;
	char STATUS_value [2] = {0x00,0x00};
		
	SPI_write(0b11010000);				
	STATUS_value [0] = SPI_read();		//MSB 
	STATUS_value [1] = SPI_read();		//LSB
	
	STATUS_reg = STATUS_value [0];
	STATUS_reg<<=8;
	STATUS_reg = STATUS_reg + STATUS_value [1];		//MSB,LSB
	
	return STATUS_reg;
}
