/*
 * TaskExecuter.c
 *
 * Created: 22.2.2016 23:04:31
 *  Author: Chenda
 */ 

#include "config.h"
#include "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/spi/SPI_API_Layer.h"

#include <util/delay.h>
#include <stdint.h>
#include <stdbool.h>
#include "Common/PeipherialFunctions.h"

#include "DebugSettings.h"
#include "Command_defs.h"
#include "TaskExecuter.h"
#include "Command_proc.h"

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

/************************************************************************/
/* Global variable declaration                                          */
/************************************************************************/
//static volatile U8 cpt_sof;
//static volatile bool Next100ms;

static struct stApplicationStructure stAppStruct;
static struct stApplicationStructure *spAPP = &stAppStruct;
/************************************************************************/
/* Private functions                                                    */
/************************************************************************/
// API routines
void API_init(void);
void API_tasks(void);
// Timer events routines
void T_EV_tasks(void);
void T_EV_tick(void);
// CMD routines
void CMD_tasks(void);

// Respond processing routines
void RESP_tasks(void);

// Error processing
void ERROR_tasks(void);

// Debug function
void Debug(void);

/************************************************************************/
/* Public functions                                                     */
/************************************************************************/
void TE_INIT(void)  
{
	mBuzzer_Enab();
	mBuzzer_On();
	mStatusLed_Enab();
	mStatusLed_On();
	lcd_init();
	lcd_clrscr();
	lcd_blk_on();
	lcd_puts("  USBTMC DC PS  ");
	lcd_puts((char[]){' ',' ',' ',' ','V',V_major,'.',V_minor,'.',V_build100,V_build10,V_build1,' ',' ',' ',' '});
	_delay_ms(50);
	mBuzzer_Off();
	_delay_ms(700);
	mStatusLed_Off();
	/*  Main initialization  */
	spAPP->AV_DEVICE.PS_selected = 1;
	API_init();
	CMD_PROC_INIT(spAPP);
	
	// creating first command - refresh PS connection
	#ifndef TERMINAL_DEBUG
		spAPP->CMD.CMD_No = INST_CONN;
		spAPP->CMD.CMD_src = DEV_ADD_USBTMC_INT;
		spAPP->CMD.DATA_len = 0;
		spAPP->CMD.SrcAPI = 0;
	#endif
}

void TE (void)
{
	API_tasks();		// DONE - API tasks routine
	CMD_tasks();		// CMD executing - continue in long term CMD & process new CMD & responds for long term CMD	
	RESP_tasks();		// Respond processing - probably only unexpected	
	
	// dodelat - kvuli postupnemu pingovani zdroju, popripade aji lokalniho ovladani
	// - zavest casovac preruseni
	//T_EV_tasks();		// Timer event tasks routine works only if USB host is connected
	
	ERROR_tasks();		// Error handling - must be at the end of the loop	
}

/************************************************************************/
/* Private functions                                                    */
/************************************************************************/
void Debug(void)
{
	static uint8_t OldTick = 0;
	if (spAPP->T_EVENTS.Tick100ms != OldTick) {
		OldTick = spAPP->T_EVENTS.Tick100ms;
		//lcd_blk_togle();
	}
}

// Error processing
void ERROR_tasks(void)
{
	// catching unhandled errors
	if (!spAPP->ERROR.InitiateReset) {
		// checking API errors	
		if (spAPP->API.USB->RX.Event == API_ERROR) {
			spAPP->API.USB->RX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->API.USB->RX.ErrorNumber);
		}
		if (spAPP->API.USB->TX.Event == API_ERROR) {
			spAPP->API.USB->TX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->API.USB->TX.ErrorNumber);
		}
		if (spAPP->API.SPI->RX.Event == API_ERROR) {
			spAPP->API.SPI->RX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->API.SPI->RX.ErrorNumber);
		}
		if (spAPP->API.SPI->TX.Event == API_ERROR) {
			spAPP->API.SPI->TX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->API.SPI->TX.ErrorNumber);
		}
		if (spAPP->API.UART1->RX.Event == API_ERROR) {
			spAPP->API.UART1->RX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->API.UART1->RX.ErrorNumber);
		}
		if (spAPP->API.UART1->TX.Event == API_ERROR) {
			spAPP->API.UART1->TX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,spAPP->API.UART1->TX.ErrorNumber);
		}
		// checking application errors
		
	}
	if (spAPP->ERROR.InitiateReset) {
		// enabling WDT to initiate error
		soft_reset();
	}
}

// Respond processing
void RESP_tasks(void)
{
	if (spAPP->CMD.CMD_No != NO_COMMAND) {
		// unexpected respond handling
		if(spAPP->API.SPI->RX.Event > API_RECEIVING && spAPP->API.SPI->RX.Event != API_ERROR && spAPP->API.SPI->RX.CmdAckNack_type != API_CMD_MESS)	{
			spAPP->API.SPI->RX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,APP_E_UNEXPECTED_RESP);
			
		}
		if(spAPP->API.UART1->RX.Event > API_RECEIVING && spAPP->API.UART1->RX.Event != API_ERROR && spAPP->API.UART1->RX.CmdAckNack_type != API_CMD_MESS)	{
			spAPP->API.UART1->RX.Event = API_NO_ACTION;
			mSRS_ERREV_QUEUE_WR(spAPP->SCPI_StatStr,APP_E_UNEXPECTED_RESP);
		}
	}
}

// Command routines
void CMD_tasks(void)
{
	if (spAPP->CMD.CMD_No == NO_COMMAND) {
		// no ongoing command execution so check for new command
		CMD_PROC_CHECK();
	}
	if (spAPP->CMD.CMD_No) {
		// command execution ongoing
		CMD_PROC_EXEC();		
	}
}

// Timer events routines
void T_EV_tasks(void)
{
	//T_EV_tick();
}

void T_EV_tick(void)
{
	/*
	if (Next100ms) {
		// next 100ms
		Next100ms = false;
		spAPP->T_EVENTS.Tick100ms++;
	}
	*/
}

// API routines
void API_init(void)
{
	spAPP->API.USB = USB_API_INIT();
	spAPP->API.UART1 = UART_API_U1_INIT();
	spAPP->API.SPI = SPI_API_INIT();
}

void API_tasks(void)
{
	USB_API();
	UART_API_U1();
	SPI_API();		// empty routine - SPI API not started yet
}

