//************************************************************
//*********** Modul čtečky otisků prstů MIAXIS SM-621 ********
//------------------------------------------------------------
//********************  KNIHOVNA FUNKCÍ  *********************
//*********************** martyy 2011 ************************
//************************************************************ 


#include "SM621.h"
#include "common.h"

extern volatile unsigned int tick1ms;

 //Platform dependent functions providing UART communication
void FPR_putchar(char data){

	while(USART_GetFlagStatus(FPR_UART, USART_FLAG_TXE) == RESET)
	    {
	    }
	USART_SendData(FPR_UART,data);
}

char FPR_getchar(void){
uint32_t timeout=tick1ms;

	while(USART_GetFlagStatus(FPR_UART, USART_FLAG_RXNE) == RESET){
		if((tick1ms-timeout)>1000){
			ERR_log(ERR_FPR_TIMEOUT);
			return(0);
		}
		    }
		ERR_delete(ERR_FPR_TIMEOUT);
		return(USART_ReceiveData(FPR_UART));

}


//Interní funkce pro zasílání příkazů do FPR
char fpr_sendcmd(t_cmd * cmd,int cnt){
unsigned char i=0;
char k=0;
char j=0;
volatile int checksum=0;
FPR_Buffer[0]        = BORDER_P;				//Struktura příkazového paketu FPR
FPR_Buffer[P_FLAG]   = FLAG_P;
FPR_Buffer[P_ADDR]   = 0x00;
FPR_Buffer[P_ADDR+1] = 0x00;
FPR_Buffer[P_ADDR+2] = 0x00;
FPR_Buffer[P_ADDR+3] = 0x00;
FPR_Buffer[P_CNT]    = (char)(cnt>>8);			//Délka paketu
FPR_Buffer[P_CNT+1]  = (char)cnt;


for(i=0;i!=cnt;i++){
	k = *((char*)cmd+i);
											//zakódování části paketu s příkazem
	switch (k)	{
		case 0xC0 : {
			FPR_Buffer[P_CMDSTART+i+j]=0xDB;
			FPR_Buffer[P_CMDSTART+i+1+j]=0xDC;
			j++;
			} 
			break;

		case 0xDB : {
			FPR_Buffer[P_CMDSTART+i+j]=0xDB;
			FPR_Buffer[P_CMDSTART+i+1+j]=0xDD;
			j++;			
			}
			break;

		default : FPR_Buffer[P_CMDSTART+i+j] = k;
		break;
	}


	checksum=checksum + k;
	}

checksum = checksum + cnt + FLAG_P;					//Výpočet kontrolního součtu
FPR_Buffer[P_CMDSTART + cnt] =  (char)checksum>>8;
FPR_Buffer[P_CMDSTART + cnt +1] =  (char)checksum;
FPR_Buffer[P_CMDSTART + cnt +2] = BORDER_P;				//Zakončení paketu
cnt=cnt + FRAME_BYTES;

for(i=0;i!=cnt;i++){								//Odeslání paketů do FPR

	FPR_putchar(FPR_Buffer[(int)i]);
	
	}
k=FPR_getchar();
if(ERR_isset(ERR_FPR_TIMEOUT)){
	return(TIMEOUT_ERR);
}
if(k==0xC0){
	 i=0;  
	checksum =0;
	do {;
		k=FPR_getchar();
		if(ERR_isset(ERR_FPR_TIMEOUT)){
			return(0xDE);
		}
		switch(k){
			case 0xDC : {
				if(FPR_Buffer[i-1]==0xDB){
					i--;
					FPR_Buffer[i]=0xC0;
					checksum+=0xC0;					
						}
				else {
					FPR_Buffer[i]=k;
					checksum=checksum+k;
						}
					}
					break;

			case 0xDD : {
				if(FPR_Buffer[i-1]==0xDB){
					i--;
					checksum+=0xDB;
						}
				else {
					FPR_Buffer[i]=k;
					checksum=checksum+k;
						}
					}
					break;
			default : {
					FPR_Buffer[i]=k;
					checksum=checksum+k;
					}
					break;

				
				}

			}
			
		while(FPR_Buffer[i++]!=BORDER_P);											//Dokud není zjištěn konec paketu
		}

else return(INFRAME_ERR);

checksum=checksum-(FPR_Buffer[i-3]+FPR_Buffer[i-4]+0xC0);
if((FPR_Buffer[i-3]!=(char)checksum)||(FPR_Buffer[i-4]!=(char)(checksum>>8)))		//.Kontrola, zda souhlasí checksum
return(CHECKSUM_ERR);														//.Pokud ne, je vrácena chyba CHECKSUM_ERR

//else 																		//.Pokud ano, je vrácena hodnota dodaná FPR
return(FPR_Buffer[OPCODE]);


}

char fpr_RecvRAWData(uint8_t* buf,int count){

	int cnt = 0;
	uint8_t k;

	while(cnt<count){ 								//Prijeti vsech 278 bytu sablony
		k=FPR_getchar();

		if(k==0xDC && (buf[cnt - 1]==0xDB)){	//Je nutno vsechna prijata data dekodovat
			buf[cnt - 1] = 0xC0;
			continue;
			}

		if(k==0xDD && (buf[cnt - 1]==0xDB)){
			continue;
			}

		buf[cnt] = k;
		cnt++;
	}

	return(0);


}

char fpr_SendRAWData(uint8_t* buffer,int count){
	uint8_t k;
	int cnt=0;



while(cnt<count){														//Pokud ma sablona spravnou delku
	k=buffer[cnt];								//Nastavime index na jeji zacatek
	if(k==0xC0 && (cnt!=0)&&(cnt!=277)&&(cnt!=138)&&(cnt!=139)){	//Kodovani znaku 0xC0
		FPR_putchar(0xDB);
		FPR_putchar(0xDC);
		cnt++;
		continue;
		}

	if(k==0xDB){														//Kodovani znaku 0xDB
		FPR_putchar(0xDB);
		FPR_putchar(0xDD);
		cnt++;
		continue;
		}

		FPR_putchar(k);												//Odeslani bytu do FPR
		cnt++;

	}
return(0);
}

//************ DEFINICE FUNCÍ pro externí použití ******************

//
char fpr_CheckFinger(void){
cmd.command=1;
return(fpr_sendcmd((t_cmd*)&cmd,1));
}

char fpr_GetImage(void){
cmd.command=2; 
return(fpr_sendcmd((t_cmd*)&cmd,1));
}

char fpr_GenTemplet(char FPR_Buffer){
cmd.command=3;
cmd.preparam=FPR_Buffer;
return(fpr_sendcmd((t_cmd*)&cmd,2));
}

char fpr_Search(char FPR_Buffer, int from, int to){
cmd.command=5;
cmd.preparam=FPR_Buffer;
cmd.paramA_low=from;
cmd.paramA_high=from>>8;
cmd.paramB_low=to;
cmd.paramB_high=to>>8;
return(fpr_sendcmd((t_cmd*)&cmd,6));

}

char fpr_Merge(void){
cmd.command=6; 
return(fpr_sendcmd((t_cmd*)&cmd,1));
}

char fpr_UploadTemplate(char FPR_Buffer){
cmd.command=9;
cmd.preparam=FPR_Buffer;
return(fpr_sendcmd((t_cmd*)&cmd,2));
}

char fpr_DownloadTemplate(char FPR_Buffer){
cmd.command=0x0A;
cmd.preparam=FPR_Buffer;
return(fpr_sendcmd((t_cmd*)&cmd,2));
}

char fpr_Store(char FPR_Buffer,int pageNR){
cmd.command=0x07;
cmd.preparam=FPR_Buffer;
cmd.paramA_low=(uint8_t)(pageNR & 0x0000000FF);
cmd.paramA_high=(uint8_t)((pageNR>>8) & 0x000000FF);
return(fpr_sendcmd((t_cmd*)&cmd,4));
}

char fpr_Delete(int pageNR){
cmd.command=0x0D;
cmd.preparam=pageNR>>8;
cmd.paramA_high=pageNR;
return(fpr_sendcmd((t_cmd*)&cmd,3));
}

char fpr_CheckTemplate(int pageNR){
cmd.command=0x28;
cmd.preparam=pageNR>>8;
cmd.paramA_high=pageNR;
return(fpr_sendcmd((t_cmd*)&cmd,3));
}
