/*
 * Command_proc.c
 *
 * Created: 20.3.2016 1:02:46
 *  Author: Chenda
 */ 

#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include "Common/DataOperations.h"
#include "Command_defs.h"

// Config
#include "conf/conf_brd.h"

/*  API  */
#include "modules/API_common_defs.h"
#include "modules/uart/UART_API_Layer.h"
#include "modules/usb/USB_API_layer.h"
#include "modules/usb/descriptors/usb_tmc_descriptors.h"
#include "modules/spi/SPI_API_Layer.h"

//#include "DeviceAddresses.h"
#include "DebugSettings.h"
#include "TaskExecuter.h"
#include "Command_proc.h"

#include <stdio.h>
#include <avr/io.h>
#include "modules/lcd/lcd_h.h"

/************************************************************************/
/* Global variable                                                      */
/************************************************************************/
static struct stApplicationStructure *spAPP;
static const char idn[] = {USB_MANUFACTURER_NAME_CHARS,',',USB_PRODUCT_NAME_CHARS,',',',',USB_FW_REVISION_CHARS};
static int16_t TempIntNo;	
static int16_t TempTenthNo;
	
static char buff[40];
/************************************************************************/
/* Private function prototypes                                          */
/************************************************************************/
// Device list functions
void SavePsAddress(uint8_t Address);
void DeletePsAddress(uint8_t ListIndex); 
void CheckRequiredPsAddress(void);
// Command functions
void CMD_CORE_IDN_QRY (void);
void CMD_CORE_STAT_CLR (void);
void CMD_CORE_RESET (void);
void CMD_BEEP (void);
void CMD_ERROR_QRY (void);
void CMD_VER_QRY (void);
void CMD_LOC_CTRL (void);
void CMD_REM_CTRL (void);
void CMD_RW_LOCK (void);
void CMD_DISP_STAT (void);
void CMD_DISP_STAT_QRY (void);
void CMD_DISP_TEXT (void);
void CMD_DISP_TEXT_QRY (void);
void CMD_DISP_CLR (void);
void CMD_INST_SEL (void);
void CMD_INST_SEL_QRY (void);
void CMD_INST_CONN (void);
void CMD_INST_CONN_QRY (void);
void CMD_INST_SEL_PAR_QRY (void);
void CMD_SRC_IMM_CURR (void);
void CMD_SRC_IMM_CURR_QRY (void);
void CMD_SRC_IMM_VOLT (void);
void CMD_SRC_IMM_VOLT_QRY (void);
void CMD_MEAS_CURR_QRY (void);
void CMD_MEAS_VOLT_QRY (void);
void CMD_OUT_STAT (void);
void CMD_OUT_STAT_QRY (void);
void CMD_OUT_STAT_ALL (void);
void CMD_CHECK_CONNECTED_DEV (void);
// Pass through standard command function
void PassThroughCmd_RespExpected(void);

/************************************************************************/
/* Public functions                                                     */
/************************************************************************/
void CMD_PROC_INIT(struct stApplicationStructure *spApplication)
{
	spAPP = spApplication;
	#ifdef TERMINAL_DEBUG
		SavePsAddress(DEV_ADD_PS1);
	#endif
}

void CMD_PROC_EXEC(void)
{	
	if (spAPP->CMD.CMD_No != NO_COMMAND) mStatusLed_On();
	
	if (spAPP->CMD.CMD_No == CORE_IDN_QRY) CMD_CORE_IDN_QRY();
	if (spAPP->CMD.CMD_No == CORE_STAT_CLR) CMD_CORE_STAT_CLR();
	if (spAPP->CMD.CMD_No == CORE_RESET) CMD_CORE_RESET();
	if (spAPP->CMD.CMD_No == BEEP) CMD_BEEP();
	if (spAPP->CMD.CMD_No == ERROR_QRY) CMD_ERROR_QRY();
	if (spAPP->CMD.CMD_No == VER_QRY) CMD_VER_QRY();
	if (spAPP->CMD.CMD_No == LOC_CTRL) CMD_LOC_CTRL();
	if (spAPP->CMD.CMD_No == REM_CTRL) CMD_REM_CTRL();
	if (spAPP->CMD.CMD_No == RW_LOCK) CMD_RW_LOCK();
	if (spAPP->CMD.CMD_No == DISP_STAT) CMD_DISP_STAT();
	if (spAPP->CMD.CMD_No == DISP_STAT_QRY) CMD_DISP_STAT_QRY();
	if (spAPP->CMD.CMD_No == DISP_TEXT) CMD_DISP_TEXT();
	if (spAPP->CMD.CMD_No == DISP_TEXT_QRY) CMD_DISP_TEXT_QRY();
	if (spAPP->CMD.CMD_No == DISP_CLR) CMD_DISP_CLR();
	if (spAPP->CMD.CMD_No == INST_SEL) CMD_INST_SEL();
	if (spAPP->CMD.CMD_No == INST_SEL_QRY) CMD_INST_SEL_QRY();
	if (spAPP->CMD.CMD_No == INST_CONN) CMD_INST_CONN();
	if (spAPP->CMD.CMD_No == INST_CONN_QRY) CMD_INST_CONN_QRY();
	if (spAPP->CMD.CMD_No == INST_SEL_PAR_QRY) CMD_INST_SEL_PAR_QRY();
	if (spAPP->CMD.CMD_No == SRC_IMM_CURR) CMD_SRC_IMM_CURR();
	if (spAPP->CMD.CMD_No == SRC_IMM_CURR_QRY) CMD_SRC_IMM_CURR_QRY();
	if (spAPP->CMD.CMD_No == SRC_IMM_VOLT) CMD_SRC_IMM_VOLT();
	if (spAPP->CMD.CMD_No == SRC_IMM_VOLT_QRY) CMD_SRC_IMM_VOLT_QRY();
	if (spAPP->CMD.CMD_No == MEAS_CURR_QRY) CMD_MEAS_CURR_QRY();
	if (spAPP->CMD.CMD_No == MEAS_VOLT_QRY) CMD_MEAS_VOLT_QRY();
	if (spAPP->CMD.CMD_No == OUT_STAT) CMD_OUT_STAT();
	if (spAPP->CMD.CMD_No == OUT_STAT_QRY) CMD_OUT_STAT_QRY();
	if (spAPP->CMD.CMD_No == OUT_STAT_ALL) CMD_OUT_STAT_ALL();
	if (spAPP->CMD.CMD_No == CHECK_CONNECTED_DEV) CMD_CHECK_CONNECTED_DEV();

	if (spAPP->CMD.CMD_No && spAPP->CMD.CMD_phase == DEF_CMD_START_PHASE) {
		// Unknown command
		spAPP->ERROR.ERROR_No = APP_E_UNKNOWN_CMD;
		spAPP->ERROR.DATA_cmd = spAPP->CMD.CMD_No;
		spAPP->ERROR.ERROR_src = spAPP->CMD.SrcAPI->RX.SourceAdd;
		spAPP->ERROR.DATA_len = spAPP->CMD.DATA_len;
		DAT_OPS_MoveData(spAPP->CMD.DATA_buff,spAPP->ERROR.DATA_buff,spAPP->ERROR.DATA_len,true);
		CMD_PROC_CLR();
		lcd_putc('9');
	}
	
	// command was finished -> clear command structure
	if (spAPP->CMD.CMD_phase == DEF_CMD_LAST_PHASE) {
		CMD_PROC_CLR();
		mStatusLed_Off();
	}
}

void CMD_PROC_CHECK(void)
{
	// check periphery incoming commands, execution start on next main loop
	if (spAPP->API.USB->RX.Event == API_PRIVATE_MESS &&
	spAPP->CMD.CMD_No == NO_COMMAND &&
	spAPP->API.USB->RX.CmdAckNack_type == API_CMD_MESS) {
		// SCPI CMD received - copy data to cmd
		spAPP->CMD.CMD_No = spAPP->API.USB->RX.Command;
		spAPP->CMD.CMD_src = spAPP->API.USB->RX.SourceAdd;
		spAPP->CMD.CMD_trg = spAPP->API.USB->RX.TargetAdd;
		spAPP->CMD.DATA_len = spAPP->API.USB->RX.DataLength;
		DAT_OPS_MoveData(spAPP->API.USB->RX.Data,spAPP->CMD.DATA_buff,spAPP->CMD.DATA_len,false);
		spAPP->CMD.DATA_buff[spAPP->CMD.DATA_len] = 0;
		spAPP->CMD.SrcAPI = spAPP->API.USB;
		spAPP->AV_DEVICE.Rem_Ctrl_present = true;
	}
	if (spAPP->API.SPI->RX.Event > API_RECEIVING &&
	spAPP->API.SPI->RX.Event != API_ERROR &&
	spAPP->CMD.CMD_No == NO_COMMAND &&
	spAPP->API.SPI->RX.CmdAckNack_type == API_CMD_MESS) {
		// SPI CMD received - copy data to cmd
		spAPP->CMD.CMD_No = spAPP->API.SPI->RX.Command;
		spAPP->CMD.CMD_src = spAPP->API.SPI->RX.SourceAdd;
		spAPP->CMD.CMD_trg = spAPP->API.SPI->RX.TargetAdd;
		spAPP->CMD.DATA_len = spAPP->API.SPI->RX.DataLength;
		DAT_OPS_MoveData(spAPP->API.SPI->RX.Data,spAPP->CMD.DATA_buff,spAPP->CMD.DATA_len,false);
		spAPP->CMD.DATA_buff[spAPP->CMD.DATA_len] = 0;
		spAPP->CMD.SrcAPI = spAPP->API.SPI;
		spAPP->AV_DEVICE.Loc_Ctrl_present = true;
	}
	
	if (spAPP->CMD.CMD_No && spAPP->CMD.CMD_phase == DEF_CMD_START_PHASE) {
		lcd_clrscr();
		//DAT_OPS_GetNumber(spAPP->CMD.SrcAPI->RX.Data,&IntNo,&TenthNo);
		sprintf(buff,"c%03d|",spAPP->CMD.CMD_No);
		//sprintf(buff,"c%03d_%03d %d.%d %d",spAPP->CMD.CMD_No,spAPP->CMD.CMD_phase,IntNo,TenthNo,spAPP->CMD.SrcAPI->RX.Data[4]);
		lcd_puts(buff);
		lcd_secondline();
	}
}

void CMD_PROC_CLR(void)
{
	spAPP->CMD.CMD_No = NO_COMMAND;
	spAPP->CMD.CMD_phase = DEF_CMD_START_PHASE;
	spAPP->CMD.CMD_src = 0;
	spAPP->CMD.SrcAPI = 0;
	spAPP->CMD.CMD_trg = 0;
	spAPP->CMD.TrgAPI = 0;
	spAPP->CMD.DATA_len = 0;
}

/************************************************************************/
/* PRIVATE - Device list functions                                      */
/************************************************************************/
void SavePsAddress(uint8_t Address)
{
	uint8_t ListIndex;
	if (Address > DEV_ADD_PS_BASE && Address < (DEV_ADD_PS1 + DEV_ADD_MAX_PS)) {
		ListIndex = Address - DEV_ADD_PS1;
		spAPP->AV_DEVICE.PS_list[ListIndex] = Address;	
	}
	else {
		// error in address number
	}
}

void DeletePsAddress(uint8_t Address)
{
	uint8_t ListIndex;
	if (Address > DEV_ADD_PS_BASE && Address < (DEV_ADD_PS1 + DEV_ADD_MAX_PS)) {
		ListIndex = Address - DEV_ADD_PS1;
		spAPP->AV_DEVICE.PS_list[ListIndex] = 0;
	}
	else {
		// error in address number
	}
}

void CheckRequiredPsAddress(void)
{
	// according source API translate and check or only check the PS address exists
	if (spAPP->CMD.CMD_src == DEV_ADD_USB_REM_CTRL) {
		spAPP->CMD.CMD_trg = spAPP->AV_DEVICE.PS_list[spAPP->AV_DEVICE.PS_selected - 1];
	}
	if (spAPP->CMD.CMD_trg > DEV_ADD_PS_BASE && spAPP->CMD.CMD_trg < (DEV_ADD_PS1 + DEV_ADD_MAX_PS)) {
		// Check OK
	}
	else {
		// device is not 
		spAPP->CMD.CMD_trg = 0;
	}
}

/************************************************************************/
/* PRIVATE - Command function                                           */
/************************************************************************/
/*
- number
DAT_OPS_GetNumber(spAPP->CMD.DATA_buff,&TempIntNo,&TempTenthNo);
// DEBUG START
sprintf(buff," %d.%d %d",TempIntNo,TempTenthNo,spAPP->CMD.DATA_buff[4]);
lcd_puts(buff);
// DEBUG END

-text
// DEBUG START
sprintf(buff," %s",spAPP->CMD.DATA_buff);
lcd_puts(buff);
// DEBUG END
*/

void CMD_CORE_IDN_QRY (void)		// DONE
{
	sprintf((char*)spAPP->CMD.SrcAPI->TX.Data,"%s",idn);
	spAPP->CMD.SrcAPI->TX.DataLength = sizeof(idn);
	
	// generate ACK respond 
	spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
	spAPP->CMD.SrcAPI->TX.Event = API_SEND;
	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
}

void CMD_CORE_STAT_CLR (void)		// NOT STARTED
{
	
}

void CMD_CORE_RESET (void)			// DONE
{
	switch(spAPP->CMD.CMD_phase) {
		case DEF_CMD_START_PHASE:
			if (spAPP->CMD.SrcAPI != 0) {
				// generate ACK respond
				spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
				spAPP->CMD.SrcAPI->TX.Event = API_SEND_ACK_NACK;
				spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
				if (spAPP->CMD.SrcAPI->RX.SourceAdd == DEV_ADD_USB_REM_CTRL) {
					// necessary to send reset also to local control
					spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_1;
					spAPP->CMD.MPC0 = 0;
				}
				else {
					// local control send the command
					spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_3;
				}
			}
			else {
				// self initiated command - necessary to send reset also to local control
				spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_1;
			}
			break;
		case DEF_CMD_EXEC_PHASE_1:
			if (spAPP->AV_DEVICE.Loc_Ctrl_present) {
				// sending RST to local control
				spAPP->API.SPI->TX.Event = API_SEND;
				spAPP->API.SPI->TX.CmdAckNack_type = API_CMD_MESS;
				spAPP->API.SPI->TX.Command = CORE_RESET;
				spAPP->API.SPI->TX.DataLength = 0;
				spAPP->API.SPI->TX.ExpectRespond = true; 
				spAPP->API.SPI->TX.SourceAdd = DEV_ADD_USBTMC_INT;
				spAPP->API.SPI->TX.TargetAdd = DEV_ADD_LOC_CTRL;
				spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_2;
			}
			else {
				// local control isn't presented - skip action
				spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_3;	
			}
			break;
		case DEF_CMD_EXEC_PHASE_2:
			// waiting for local control ACK
			if(spAPP->API.SPI->RX.Event == API_PRIVATE_MESS && (spAPP->API.SPI->RX.CmdAckNack_type == API_ACK_MESS || spAPP->CMD.MPC0 > 2)) {
				// command accepted
				spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_3;
			}
			else if (spAPP->CMD.TrgAPI->RX.Event > API_RECEIVING) {
				// API error 
				spAPP->CMD.MPC0++;
				spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_2;
			}
			if (spAPP->CMD.TrgAPI->RX.Event > API_RECEIVING) {
				spAPP->API.SPI->RX.Event = API_NO_ACTION;
			}
			break;
		case DEF_CMD_EXEC_PHASE_3:
			// sending reset to PS
			if(spAPP->API.UART1->TX.Event == API_NO_ACTION) {
				spAPP->API.UART1->TX.Event = API_SEND;
				spAPP->API.UART1->TX.CmdAckNack_type = API_CMD_MESS;
				spAPP->API.UART1->TX.Command = CORE_RESET;
				spAPP->API.UART1->TX.DataLength = 0;
				spAPP->API.UART1->TX.ExpectRespond = false;
				spAPP->API.UART1->TX.SourceAdd = DEV_ADD_USBTMC_INT;
				spAPP->API.UART1->TX.TargetAdd = DEV_ADD_PS_BASE;
				spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_4;
			}
			break;
		case DEF_CMD_EXEC_PHASE_4:
			if(spAPP->API.UART1->TX.Event == API_NO_ACTION) {
				// sending finished
				spAPP->ERROR.InitiateReset = true;
				spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			}
			break;
		default:
			spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			break;
	}
}

void CMD_BEEP (void)				// DONE
{
	switch(spAPP->CMD.CMD_phase) {
		case DEF_CMD_START_PHASE:
			spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
			mBuzzer_On();
			spAPP->CMD.MPC0 = 0;
			spAPP->CMD.MPC1 = 0;
			spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_1;
			break;
		case DEF_CMD_EXEC_PHASE_1:
			spAPP->CMD.MPC0++;
			if (spAPP->CMD.MPC0 > 254) spAPP->CMD.MPC1++;  
			if (spAPP->CMD.MPC1 > 20) {
				mBuzzer_Off();
				spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			}
			break;
		default:
			spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			break;
	}	
}

void CMD_ERROR_QRY (void)			// DONE
{
	TempIntNo = (int16_t) spAPP->SCPI_StatStr->ErrEvent.ErrorEvent[spAPP->SCPI_StatStr->ErrEvent.ReadPointer];
	spAPP->CMD.SrcAPI->TX.DataLength = DAT_OPS_PutNumber(spAPP->CMD.SrcAPI->TX.Data,&TempIntNo,NULL);
	if (TempIntNo == 0) {
		// no error put read pointer on the same place as write pointer
		spAPP->SCPI_StatStr->ErrEvent.ReadPointer = spAPP->SCPI_StatStr->ErrEvent.WritePointer;
	}
	else {
		spAPP->SCPI_StatStr->ErrEvent.ErrorEvent[spAPP->SCPI_StatStr->ErrEvent.ReadPointer] = 0;
		mSRS_ERREV_INC_R_PTR(spAPP->SCPI_StatStr);
	}	
	
	// generate ACK respond 
	spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
	spAPP->CMD.SrcAPI->TX.Event = API_SEND;
	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
}
	
void CMD_VER_QRY (void)				// DONE
{
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
	sprintf((char*)spAPP->CMD.SrcAPI->TX.Data,"%s",(char[]){USB_FW_REVISION_CHARS});
	spAPP->CMD.SrcAPI->TX.DataLength = 7;	//sizeof(USB_FW_REVISION_CHARS);
	
	// generate ACK respond 
	spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
	spAPP->CMD.SrcAPI->TX.Event = API_SEND;
	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
}

void CMD_LOC_CTRL (void)			// NOT STARTED
{
	
}

void CMD_REM_CTRL (void)			// NOT STARTED
{
		
}

void CMD_RW_LOCK (void)				// NOT STARTED
{
	
}
	
void CMD_DISP_STAT (void)			// NOT STARTED
{
	
}
	
void CMD_DISP_STAT_QRY (void)		// NOT STARTED
{
	
}
	
void CMD_DISP_TEXT (void)			// DEBUG
{
	lcd_secondline();
	lcd_puts((char*)spAPP->CMD.DATA_buff);

	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
}
	
void CMD_DISP_TEXT_QRY (void)		// NOT STARTED
{
	
}
	
void CMD_DISP_CLR (void)			// DEBUG
{
	lcd_clrscr();
	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
}

void CMD_INST_SEL (void)			// DONE
{
	DAT_OPS_GetNumber(spAPP->CMD.DATA_buff,&TempIntNo,&TempTenthNo);
	// DEBUG START
	sprintf(buff," %d.%d %d",TempIntNo,TempTenthNo,spAPP->CMD.DATA_buff[4]);
	lcd_puts(buff);
	// DEBUG END
	
	if (TempIntNo > 16) {
		TempIntNo = 16;
	}
	if (TempIntNo < 1) {
		TempIntNo = 1;
	}
	spAPP->AV_DEVICE.PS_selected = (uint8_t)TempIntNo; // lower byte of integer number
	
	// generate ACK respond 
	spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
	spAPP->CMD.SrcAPI->TX.Event = API_SEND_ACK_NACK;
	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
	
}
	
void CMD_INST_SEL_QRY (void)		// DONE
{
	TempIntNo = (int16_t)spAPP->AV_DEVICE.PS_selected;
	spAPP->CMD.SrcAPI->TX.Command = spAPP->CMD.CMD_No;
	spAPP->CMD.SrcAPI->TX.DataLength = DAT_OPS_PutNumber(spAPP->CMD.SrcAPI->TX.Data,&TempIntNo,NULL);
	
	// generate ACK respond 
	spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
	spAPP->CMD.SrcAPI->TX.Event = API_SEND;
	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
}

void CMD_INST_CONN (void)			// DONE
{
	switch(spAPP->CMD.CMD_phase) {
		case DEF_CMD_START_PHASE:
			spAPP->CMD.MPC0 = 0;
			spAPP->CMD.TrgAPI = spAPP->API.UART1;
			if (spAPP->CMD.SrcAPI != 0) {
				// generate ACK respond
				spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
				spAPP->CMD.SrcAPI->TX.Event = API_SEND_ACK_NACK;
				spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
			}
			spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_1;
			break;
		case DEF_CMD_EXEC_PHASE_1:
			if (spAPP->CMD.TrgAPI->TX.Event == API_NO_ACTION) {
				spAPP->CMD.TrgAPI->TX.Command = NONSCPI_PING_QRY;
				spAPP->CMD.TrgAPI->TX.DataLength = 0;
				spAPP->CMD.TrgAPI->TX.CmdAckNack_type = API_CMD_MESS;
				spAPP->CMD.TrgAPI->TX.ExpectRespond = true;
				spAPP->CMD.TrgAPI->TX.SourceAdd = DEV_ADD_USBTMC_INT;
				spAPP->CMD.TrgAPI->TX.TargetAdd = DEV_ADD_PS1 + spAPP->CMD.MPC0;
				spAPP->CMD.TrgAPI->TX.Event = API_SEND;
				spAPP->CMD.CMD_phase = DEF_CMD_RESP_WAIT_PHASE;
			}
			break;
		case DEF_CMD_RESP_WAIT_PHASE:
			if(spAPP->CMD.TrgAPI->RX.Event == API_PRIVATE_MESS && spAPP->CMD.TrgAPI->RX.CmdAckNack_type == API_ACK_MESS) {
				// PING successful - save address
				SavePsAddress(DEV_ADD_PS1 + spAPP->CMD.MPC0);
			}
			else if (spAPP->CMD.TrgAPI->RX.Event > API_RECEIVING) {
				// PING unsuccessful - delete address
				DeletePsAddress(DEV_ADD_PS1 + spAPP->CMD.MPC0);
			}
			if (spAPP->CMD.TrgAPI->RX.Event > API_RECEIVING) {
				spAPP->CMD.MPC0++;
				spAPP->CMD.TrgAPI->RX.Event = API_NO_ACTION;
				if (spAPP->CMD.MPC0 >= DEV_ADD_MAX_PS) spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
				else spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_1;
			}
			break;
		default:
			spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			break;
	}
	
	/*
	$AB$02$05$08$FE$00$00$F4$FC$BA
	$AB$02$08$20$FE$00$00$DC$F9$BA
	*/
}
	
void CMD_INST_CONN_QRY (void)		// DONE
{
	spAPP->CMD.SrcAPI->TX.Command = spAPP->CMD.CMD_No;
	if (spAPP->CMD.CMD_src == DEV_ADD_USB_REM_CTRL) {
		// convert into the text
		spAPP->CMD.MPC0 = 0;
		sprintf((char*)spAPP->CMD.SrcAPI->TX.Data,";");
		while(spAPP->AV_DEVICE.PS_list[spAPP->CMD.MPC0] == 0 && spAPP->CMD.MPC0 < DEV_ADD_MAX_PS) spAPP->CMD.MPC0++;
		if (spAPP->AV_DEVICE.PS_list[spAPP->CMD.MPC0]) {
			sprintf((char*)spAPP->CMD.SrcAPI->TX.Data,"%d",(spAPP->AV_DEVICE.PS_list[spAPP->CMD.MPC0++]-DEV_ADD_PS_BASE));
		}
		for (;spAPP->CMD.MPC0 < DEV_ADD_MAX_PS;spAPP->CMD.MPC0++) {
			if (spAPP->AV_DEVICE.PS_list[spAPP->CMD.MPC0]) {
				sprintf((char*)spAPP->CMD.SrcAPI->TX.Data,"%s;%d",(char*)spAPP->CMD.SrcAPI->TX.Data,(spAPP->AV_DEVICE.PS_list[spAPP->CMD.MPC0++]-DEV_ADD_PS_BASE));
			}
		}
		spAPP->CMD.MPC0 = 0;
		while(spAPP->CMD.SrcAPI->TX.Data[spAPP->CMD.MPC0]) spAPP->CMD.MPC0++;
		if (spAPP->CMD.MPC0) {
			spAPP->CMD.SrcAPI->TX.DataLength = spAPP->CMD.MPC0;
		}
		else {
			spAPP->CMD.SrcAPI->TX.DataLength = 1;
		}
	}
	else {
		spAPP->CMD.SrcAPI->TX.DataLength = DEV_ADD_MAX_PS;
		DAT_OPS_MoveData(spAPP->AV_DEVICE.PS_list,spAPP->CMD.SrcAPI->TX.Data,spAPP->CMD.SrcAPI->TX.DataLength,false);
	}
	
	// generate ACK respond
	spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
	spAPP->CMD.SrcAPI->TX.Event = API_SEND;
	// command finishing
	spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
	spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
}
	
void CMD_INST_SEL_PAR_QRY (void)	// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:
	PS RESPOND:	$AB$05$01$08$FE$04$41$48$4F$4A$00$5B$70$BA
	*/
}
	
void CMD_SRC_IMM_CURR (void)		// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 40 05 00 05 00 00 00 E8 BE BA
	PS RESPOND:	$AB$01$05$08$FE$00$00$F5$FC$BA
	*/
}
	
void CMD_SRC_IMM_CURR_QRY (void)	// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 41 00 00 F2 BD BA
	PS RESPOND:	$AB$01$05$08$FE$05$00$05$00$00$00$EB$FC$BA
	*/
}

void CMD_SRC_IMM_VOLT (void)		// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 42 05 00 0A 00 00 00 E3 BC BA
	PS RESPOND:	$AB$01$05$08$FE$00$00$F5$FC$BA	
	*/
}
	
void CMD_SRC_IMM_VOLT_QRY (void)	// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 43 00 00 F2 BB BA
	PS RESPOND:	$AB$01$05$08$FE$05$00$05$00$00$00$EB$FC$BA
	*/
}

void CMD_MEAS_CURR_QRY (void)		// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 50 00 00 F2 AE BA
	PS RESPOND:	$AB$01$05$08$FE$05$00$05$00$00$00$EB$FC$BA
	*/
}
	
void CMD_MEAS_VOLT_QRY (void)		// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 51 00 00 F2 AD BA
	PS RESPOND:	$AB$01$05$08$FE$05$00$05$00$00$00$EB$FC$BA
	*/
}

void CMD_OUT_STAT (void)			// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 60 05 00 01 00 00 00 EC 9E BA
	PS RESPOND:	$AB$01$05$08$FE$00$00$F5$FC$BA	
	*/
}
	
void CMD_OUT_STAT_QRY (void)		// DONE
{
	PassThroughCmd_RespExpected();
	
	/*
	TERMINAL DEBUG:
	USB CMD:	AB 05 01 08 61 00 00 F2 9D BA
	PS RESPOND:	$AB$01$05$08$FE$05$00$01$00$00$00$EF$FC$BA
	*/
}
	
void CMD_OUT_STAT_ALL (void)		// DONE
{
	switch(spAPP->CMD.CMD_phase) {
		case DEF_CMD_START_PHASE:
			spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
			spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_1;
			spAPP->CMD.TrgAPI = spAPP->API.UART1;
			break;
		case DEF_CMD_EXEC_PHASE_1:
			if(spAPP->CMD.TrgAPI->TX.Event == API_NO_ACTION) {
				spAPP->CMD.TrgAPI->TX.Event = API_SEND;
				spAPP->CMD.TrgAPI->TX.CmdAckNack_type = API_CMD_MESS;
				spAPP->CMD.TrgAPI->TX.Command = spAPP->CMD.CMD_No;
				spAPP->CMD.TrgAPI->TX.DataLength = spAPP->CMD.DATA_len;
				DAT_OPS_MoveData(spAPP->CMD.DATA_buff,spAPP->CMD.TrgAPI->TX.Data,spAPP->CMD.TrgAPI->TX.DataLength,false);
				spAPP->CMD.TrgAPI->TX.ExpectRespond = false;
				spAPP->CMD.TrgAPI->TX.SourceAdd = spAPP->CMD.CMD_src;
				spAPP->CMD.TrgAPI->TX.TargetAdd = DEV_ADD_PS_BASE;
				spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_2;
			}
			break;
		case DEF_CMD_EXEC_PHASE_2:
			if(spAPP->API.UART1->TX.Event == API_NO_ACTION) {
				// sending finished
				if(spAPP->CMD.SrcAPI->TX.Event == API_NO_ACTION) {
					spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_ACK_MESS;
					spAPP->CMD.SrcAPI->TX.Event = API_SEND_ACK_NACK;
					spAPP->CMD.CMD_phase = DEF_CMD_EXEC_PHASE_3;
				}
			}
			break;
		case DEF_CMD_EXEC_PHASE_3:
			// waiting for finishing ACK respond
			if (spAPP->CMD.SrcAPI->TX.Event == API_NO_ACTION) {
				spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			}
			break;
		default:
			spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			break;
	}
}
	
void CMD_CHECK_CONNECTED_DEV (void)
{
	// ???
}

/************************************************************************/
/* pass through standard command execution                              */
/************************************************************************/
void PassThroughCmd_RespExpected(void)
{
	// pass command to target PS, expect respond
	switch(spAPP->CMD.CMD_phase) {
		case DEF_CMD_START_PHASE:
		CheckRequiredPsAddress();		// check target PS address - if address not exist, TargAdd = 0
		if (spAPP->CMD.CMD_trg != 0) {
			spAPP->CMD.TrgAPI = spAPP->API.UART1;
			spAPP->CMD.CMD_phase = DEF_CMD_PASS_TO_TRG;
		}
		else {
			spAPP->CMD.CMD_phase = DEF_CMD_SEND_NACK_TO_SRC;
			spAPP->CMD.DATA_buff[0] = APP_E_DEVICE_NOT_FOUND;
			lcd_puts("Add. not found");
		}
		spAPP->CMD.SrcAPI->RX.Event = API_NO_ACTION;
		break;
		case DEF_CMD_PASS_TO_TRG:
		if(spAPP->CMD.TrgAPI->TX.Event == API_NO_ACTION) {
			spAPP->CMD.TrgAPI->TX.CmdAckNack_type = API_CMD_MESS;
			spAPP->CMD.TrgAPI->TX.Command = spAPP->CMD.CMD_No;
			spAPP->CMD.TrgAPI->TX.DataLength = spAPP->CMD.DATA_len;
			DAT_OPS_MoveData(spAPP->CMD.DATA_buff,spAPP->CMD.TrgAPI->TX.Data,spAPP->CMD.TrgAPI->TX.DataLength,false);
			spAPP->CMD.TrgAPI->TX.ExpectRespond = true;
			spAPP->CMD.TrgAPI->TX.SourceAdd = spAPP->CMD.CMD_src;
			spAPP->CMD.TrgAPI->TX.TargetAdd = spAPP->CMD.CMD_trg;
			spAPP->CMD.TrgAPI->TX.Event = API_SEND;
			spAPP->CMD.CMD_phase = DEF_CMD_PASS_WAIT_TRG_RESP;
		}
		break;
		case DEF_CMD_PASS_WAIT_TRG_RESP:
		if (spAPP->CMD.TrgAPI->RX.Event > API_RECEIVING && spAPP->CMD.TrgAPI->RX.Event != API_ERROR) {
			// respond was received
			spAPP->CMD.CMD_phase = DEF_CMD_PASS_TO_SRC;
		}
		else if (spAPP->CMD.TrgAPI->RX.Event == API_ERROR) {
			// error happened
			spAPP->CMD.DATA_buff[0] = spAPP->CMD.TrgAPI->RX.ErrorNumber;
			spAPP->CMD.CMD_phase = DEF_CMD_SEND_NACK_TO_SRC;
			lcd_puts("Targ. Rx Error");
		}
		if (spAPP->CMD.TrgAPI->RX.Event > API_RECEIVING) {
			spAPP->CMD.TrgAPI->RX.Event = API_NO_ACTION;
		}
		break;
		case DEF_CMD_PASS_TO_SRC:
		if(spAPP->CMD.SrcAPI->TX.Event == API_NO_ACTION) {
			if (spAPP->CMD.TrgAPI->RX.CmdAckNack_type == API_NACK_MESS) {
				// store error into status register
				mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->CMD.TrgAPI->RX.Data[0]);
				// for NACK respond don't send to USB host
				spAPP->CMD.SrcAPI->TX.Event = API_SEND_ACK_NACK;
				lcd_puts("NACK");
			}
			else {
				// ACK successful data handover
				lcd_puts("ACK");
				spAPP->CMD.SrcAPI->TX.Event = API_SEND;
			}
			spAPP->CMD.SrcAPI->TX.CmdAckNack_type = spAPP->CMD.TrgAPI->RX.CmdAckNack_type;
			spAPP->CMD.SrcAPI->TX.DataLength = spAPP->CMD.TrgAPI->RX.DataLength;
			DAT_OPS_MoveData(spAPP->CMD.TrgAPI->RX.Data,spAPP->CMD.SrcAPI->TX.Data,spAPP->CMD.SrcAPI->TX.DataLength,false);
			spAPP->CMD.SrcAPI->TX.SourceAdd = spAPP->CMD.TrgAPI->RX.SourceAdd;
			spAPP->CMD.SrcAPI->TX.TargetAdd = spAPP->CMD.TrgAPI->RX.TargetAdd;
			spAPP->CMD.SrcAPI->TX.ExpectRespond = false;
			
			spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
		}
		break;
		case DEF_CMD_SEND_NACK_TO_SRC:
		// only local control is handled, remote will receive empty message
		if (spAPP->CMD.SrcAPI->TX.Event == API_NO_ACTION) {
			spAPP->CMD.SrcAPI->TX.CmdAckNack_type = API_NACK_MESS;
			spAPP->CMD.SrcAPI->TX.Data[0] = spAPP->CMD.DATA_buff[0];
			spAPP->CMD.SrcAPI->TX.DataLength = 1;
			spAPP->CMD.SrcAPI->TX.Event = API_SEND_ACK_NACK;
			spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
			
			// store error into status register
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->CMD.DATA_buff[0]);
		}
		break;
		default:
		spAPP->CMD.CMD_phase = DEF_CMD_LAST_PHASE;
		break;
	}
}
