#include "hostcom.h"

uint8_t Host_Rx_Buffer[HOST_MAX_PACKET_SIZE];
uint8_t Host_Tx_Buffer[HOST_MAX_PACKET_SIZE];

extern unsigned char ledstat;

void HOST_putchar(char data){

	while(USART_GetFlagStatus(HOST_UART, USART_FLAG_TXE) == RESET)
	    {
	    }
	  HOST_UART->DR = (data & (uint16_t)0x00FF);
}

uint8_t Host_send(uint8_t* data, uint16_t length){

	uint16_t checksum=0;
    uint16_t i;

	HOST_putchar(BORDER_P);
	HOST_putchar((uint8_t)((length+2)>>8));
	HOST_putchar((uint8_t)((length+2)));

	for(i=0;i<length;i++){
		HOST_putchar(data[i]);
		checksum += data[i];
	}

	HOST_putchar((uint8_t)(checksum>>8));
	HOST_putchar((uint8_t)(checksum));

	return (1);

}

int Host_Process(void){
	void (*SysMemBootJump)(void);
	uint8_t k;

	uint8_t command = Host_Rx_Buffer[HOST_COMMAND_OFFSET];

	switch (command){

	case HOSTIN_ECHO_REQUEST_CMD :
		Host_Send_Echo();
	break;

	case HOSTIN_FPR_SWITCH_CMD :
		if(Host_Rx_Buffer[HOST_PARAMETER_OFFSET])
			FPR_ON();
		else
			FPR_OFF();
		Host_Send_Ack(HOSTIN_FPR_SWITCH_CMD);
	break;

	case HOSTIN_KEYB_MODE_CMD :
		if(Host_Rx_Buffer[HOST_PARAMETER_OFFSET])
			KEYB_SetMode(keybmode_alpha);
		else
			KEYB_SetMode(keybmode_numeric);
		Host_Send_Ack(HOSTIN_FPR_SWITCH_CMD);
	break;

	case HOSTIN_BOOTLOAD_RESET_CMD :

			SysMemBootJump = (void (*)(void))(*((u32 *) 0x1ffff004));
			Host_Send_Ack(HOSTIN_BOOTLOAD_RESET_CMD);
			RCC_DeInit();
			USART_DeInit(USART1);

			Delay_ms(20);
			SysTick->CTRL=0;
			SysTick->LOAD=0;
			SysTick->VAL=0;


			__set_PRIMASK(1);
			__set_MSP(0x20000200) ;

			SysMemBootJump();

			while(1);


	break;

	case HOSTIN_FPR_SCAN_CMD :
	RED_LED_BLFAST();
		Host_Send_ScanProgress(SCANPROGRESS_PUT1);
		while(fpr_CheckFinger());
		Host_Send_ScanProgress(SCANPROGRESS_PROCESSING1);
	RED_LED_OFF();
		Delay_ms(1000);

		k=fpr_GetImage();
		if(k){
			Host_Send_Err(HOSTIN_FPR_SCAN_CMD,k);
			return(1);
		}										//Sejmuti obrazu prstu


		k=fpr_GenTemplet(BUFFER_A);
		if(k){
			Host_Send_Err(HOSTIN_FPR_SCAN_CMD,k);
			return(1);
		}

		RED_LED_ON();
		Host_Send_ScanProgress(SCANPROGRESS_RELEASE1);
		while(!fpr_CheckFinger());

		Delay_ms(1000);
		RED_LED_BLFAST();
		Host_Send_ScanProgress(SCANPROGRESS_PUT2);
		while(fpr_CheckFinger());  							//Cekani na prilozeny prst
		RED_LED_OFF();
		Host_Send_ScanProgress(SCANPROGRESS_PROCESSING2);
		Delay_ms(1000); 									//Prodleva pro "usazeni" prstu na hranolu
		k=fpr_GetImage(); 									//Sejmuti obrazu prstu
		if(k){
			Host_Send_Err(HOSTIN_FPR_SCAN_CMD,k);
			return(1);
		}
		k=fpr_GenTemplet(BUFFER_B);
		if(k){
			Host_Send_Err(HOSTIN_FPR_SCAN_CMD,k);
			return(1);
		}
		Host_Send_ScanProgress(SCANPROGRESS_RELEASE2);
		while(!fpr_CheckFinger());
		if(fpr_Merge()){
			Host_Send_Err(HOSTIN_FPR_SCAN_CMD,k);
			return(1);
		}

		fpr_UploadTemplate(3);
		fpr_RecvRAWData(Host_Tx_Buffer,FPR_TEMPLATE_OVERALL_LEN);
		Host_send(Host_Tx_Buffer,FPR_TEMPLATE_OVERALL_LEN);


	break;

	case HOSTIN_FPR_DOWNLOAD_CMD :

		k=fpr_DownloadTemplate(BUFFER_MODEL);
		if(k){																	//Pokud FPR odpovi chybou pri zadosti o download
			Host_Send_Err(HOSTIN_FPR_DOWNLOAD_CMD,k);
			return(1);
			}

		fpr_SendRAWData(&(Host_Rx_Buffer[HOST_PARAMETER_OFFSET+2]),FPR_TEMPLATE_OVERALL_LEN);

		k=fpr_Store(BUFFER_MODEL,(Host_Rx_Buffer[HOST_PARAMETER_OFFSET]<<8)|(Host_Rx_Buffer[HOST_PARAMETER_OFFSET+1]));					//Prevod parametru prikazu - pozice pro ulozeni sablony
		if(k){
			Host_Send_Err(HOSTIN_FPR_DOWNLOAD_CMD,k);
			return(1);
		}
		Host_Send_Ack(HOSTIN_FPR_DOWNLOAD_CMD);

	break;

	case HOSTIN_FPR_DELETE_CMD :

			k=fpr_Delete(CHARSTOINT(Host_Rx_Buffer[HOST_PARAMETER_OFFSET],Host_Rx_Buffer[HOST_PARAMETER_OFFSET+1]));
			if(k){																	//Pokud FPR odpovi chybou pri zadosti o download
				Host_Send_Err(HOSTIN_FPR_DELETE_CMD,k);
				return(1);		//A prerusime proces
				}

			Host_Send_Ack(HOSTIN_FPR_DELETE_CMD);

		break;

	case HOSTIN_AMP_SWITCH_CMD:

		if(Host_Rx_Buffer[HOST_PARAMETER_OFFSET]){
			AMP_ON();
			STATUS_SET(STAT_AMP_PERMANENT_ACTIVE);
		}
		else{
			FPR_OFF();
			STATUS_RESET(STAT_AMP_PERMANENT_ACTIVE);
		}
		Host_Send_Ack(HOSTIN_AMP_SWITCH_CMD);

	break;
	case HOSTIN_WRITE_BINARY :
		k=Host_Rx_Buffer[HOST_PARAMETER_OFFSET];
		if(k&(1)) EXT_OUT1_PORT->BSRR = EXT_OUT1_PIN;
		if(k&(1<<1)) EXT_OUT1_PORT->BRR = EXT_OUT1_PIN;
		if(k&(1<<2))EXT_OUT2_PORT->BSRR = EXT_OUT2_PIN;
		if(k&(1<<3))EXT_OUT2_PORT->BSRR = EXT_OUT2_PIN;
		Host_Send_Ack(HOSTIN_AMP_SWITCH_CMD);
	break;

	}


return(0);
}

uint8_t Host_Send_ScannedFPR(uint16_t fpr_no){


		Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_SCANNED_FPR_CMD;
		Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = (uint8_t)(fpr_no >> 8);
		Host_Tx_Buffer[HOST_PARAMETER_OFFSET+1] = (uint8_t)(fpr_no & 0x00FF);
		Host_send(Host_Tx_Buffer,3);

		return(0);

}

uint8_t Host_Send_ReadRFID(uint8_t* cardNo){

	uint8_t i;

	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_CARD_READ;
	for(i=0;i<12;i++){
		Host_Tx_Buffer[HOST_PARAMETER_OFFSET + i] = cardNo[i];
	}
	Host_send(Host_Tx_Buffer,13);

	return(0);
}

uint8_t Host_Send_ActiveMode(uint8_t state){
	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_ACTIVE_MODE_CMD;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = state;
	Host_send(Host_Tx_Buffer,2);

	return(0);
}

uint8_t Host_Send_PWRChange(uint8_t source){
	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_PWRCHANGE;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = source;
	Host_send(Host_Tx_Buffer,2);

	return(0);
}

uint8_t Host_Send_ScanProgress(uint8_t progress){
	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_SCAN_PROGRESS;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] =progress;
	Host_send(Host_Tx_Buffer,2);

	return(0);

}

uint8_t Host_Send_Echo(void){

	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_ECHO_REPLY_CMD;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = HIGHBYTE(Statusword);
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET+1] = LOWBYTE(Statusword);
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET+2]	= FW_WER_MAJOR;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET+3]	= '.';
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET+4]	= FW_WER_MINOR;
	Host_send(Host_Tx_Buffer,6);

	return(0);
}

uint8_t Host_Send_PressedKey(uint8_t key){

	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_KEY_PRESSED_CMD;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = KEYB_GetMode();
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET+1] = key;
	Host_send(Host_Tx_Buffer,3);

	return(0);
}


uint8_t Host_Send_Ack(uint8_t cmd){

	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_ACK;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = cmd;
	Host_send(Host_Tx_Buffer,2);

	return(0);
}

uint8_t Host_Send_Err(uint8_t cmd,uint8_t errcode){
  Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_ERR;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = cmd;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET+1] = errcode;
	Host_send(Host_Tx_Buffer,3);

	return(0);
}

uint8_t Host_Send_Binary(uint8_t cmd){

	Host_Tx_Buffer[HOST_COMMAND_OFFSET] = HOSTOUT_SEND_ACK;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET] = HOSTIN_READ_BINARY;
	Host_Tx_Buffer[HOST_PARAMETER_OFFSET+1] = (uint8_t)(GPIO_ReadInputData(GPIOC));
	Host_send(Host_Tx_Buffer,3);

	return(0);
}


