/*
 * cc_iuc_asynchpos.c
 *
 * Created: 21.11.2017 16:36:28
 *  Author: Matthias
 */

#include "cc_iuc_asynchpos.h"
#include "aes128.h"

#include <QByteArray>
#include <QDebug>

//#include <log.h>

uint32_t iuc_asynchpos_sub_updateCRC(uint32_t crc, char* pData, size_t len) {
    // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

    QByteArray a(pData, len);
    qCritical() << "updateCRC" << a.toHex(' ');
    qCritical() << "updateCRC" << len;

    int i = 0;
    int j = 0;
//	unsigned long rem;
//	unsigned char octet;
//	UCHAR *p, *q;
    unsigned char ucCarry = 0x00;

    crc = ~crc;
    while (len > 0) {
        crc ^= (uint32_t) pData[i];
        ++i;

        for (j = 0; j < 8; ++j) {
            ucCarry = crc & 1;
            crc >>= 1;

            if (ucCarry) {
                crc ^= IUC_ASYNCHPOS_POLYNOME;
            }
        }
        --len;
    }

    return ~crc;

}

#if 0

#include <buf.h>

extern struct   T_CONF          eeprom Conf;
extern	struct  T_dynamicData GWglobTime;
extern	struct	T_vend Vend;
static struct billAsynchData asynchBill;
extern struct   T_GWstate GWstate;
//extern UCHAR    GWstate.VendRequest;

unsigned static char messageData[IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE];

ULONG com_totalSecSince1jan2017(void)
{
	// eine Zahl erzeugen die sich jede sec ändert und nicht 2x vorkommen darf
	// Zeit und Datum in Sekunden umrechnen. Beginne bei 1.1.2017 um 0:00Uhr
	// die nächsten Schaltjahre: 2020, 2024, 2028...
	// Der Wert wird sich in den nächsten 130 Jahren nicht gleichen/wiederholen

	UINT    uitmp;
	ULONG   ultmp;

	//uitmp=com_totalDaysSince1Jan2017(GlobTime.Year, GlobTime.Month, GlobTime.Day);
	uitmp= ((UINT)GWglobTime.dayOfMon) + ((UINT)GWglobTime.month) * 30;
	ultmp=(ULONG)uitmp;
	ultmp*=1440L;       // Tage--->min
	ultmp+=(ULONG) (GWglobTime.MinOfDay);//GlobTime.MinOfDay;    // min von heute drauf
	ultmp*=60L;
	return ultmp;
}

void generate_UniqueTransNr(UCHAR *buf)
{
	// buf>=20 bytes!
	UCHAR  tmp12[12];
	ULONG ultmp = 0;
	ULONG transID = com_totalSecSince1jan2017();

	// a) Transaction ID, max 19 chars
	//      ab April 2017: TID muss über alle Automaten und über alle Zeiten eindeutig sein,
	//      sonst gibt SessionBase keine Antwort.
	//uitmp=VKdata.TransID;  sub_BufferNummEntry(ultmp);      // einfache Version bis März 2017
	biox_ClearMem(buf, '0', 19);
	biox_ClearMem(tmp12, 0, 12);
	//VdKdata.TransID = com_totalSecSince1jan2017();
	//biox_ultoa(VKdata.TransID, tmp12);
	biox_ultoa(transID, tmp12);
	biox_MemCpPos(tmp12, buf, 1);

	// Automaten-nr auch rein, sonst können versch. Automaten die gleiche Nummer haben!
	biox_ClearMem(tmp12, 0, 12);
	ultmp=(ULONG) Conf.MachNr; //.MachineID;
	biox_ultoa(ultmp, tmp12);
	biox_MemCpPos(tmp12, buf, 11);

	biox_ClearMem(tmp12, 0, 12);
	ultmp=(ULONG)Conf.CustomNr; //.CustID;
	biox_ultoa(ultmp, tmp12);
	biox_MemCpPos(tmp12, buf, 16);
	buf[19]=0;
}

void iuc_asynchpos_sub_initArray(unsigned char* pArray, int length) {
	unsigned int uitemp = 0;

	for (uitemp = 0; uitemp < length; ++uitemp)
		pArray[uitemp] = 0x00;
}

void iuc_asynchpos_setTerminalID(unsigned char *pID, unsigned int length) {
	unsigned int uctemp = 0;

	if (!biox_StrComp(pID,terminalID,length)) {
		for (uctemp = 0; uctemp < length; ++uctemp) {
			terminalID[uctemp] = pID[uctemp];
		}
	}
}

void iuc_asynchpos_setTerminalAPAK(unsigned char *pAPAK, unsigned int length) {
	unsigned char uctemp = 0;

	if (!biox_StrComp(pAPAK,terminalAPAK,length)) {
		for (uctemp = 0; uctemp < length; ++uctemp) {
			terminalAPAK[uctemp] = pAPAK[uctemp];
			Conf.APAK_backup[uctemp] = pAPAK[uctemp];
		}
	}
}

ULONG iuc_asynchpos_sub_updateCRC(ULONG crc, UCHAR* pData, UINT len)	//TODO
{
    // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

    int i = 0;
	int j = 0;
//	unsigned long rem;
//	unsigned char octet;
//	UCHAR *p, *q;
	unsigned char ucCarry = 0x00;

	crc = ~crc;
	while (len > 0) {
		crc ^= (ULONG) pData[i];
		++i;

		for (j = 0; j < 8; ++j) {
			ucCarry = crc & 1;
			crc >>= 1;

			if (ucCarry) {
				crc ^= IUC_ASYNCHPOS_POLYNOME;
			}
		}
		--len;
	}

	return ~crc;
}

unsigned char iuc_asynchpos_rts() {
	unsigned char timeOut = 0x00;
	unsigned char uctmp = 0x00;

	brd_switch_RS3(RS3SW2IUC);
	biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none);
	uctmp = EOT;
	biox_Usart3_ClearRecBuffer();
	biox_Usart3_SendBlock(&uctmp,1);

	while (timeOut < 0x06 && uctmp != ENQ) {
		biox_delay_ms(400);
		if (biox_Usart3_NewTelegram()) {
			brd_SendDiagStr("->IUC ASYNCHPOS 0x05 (ENQ) received. RTS.",1);
			biox_Usart3_GetRecBuffer(&uctmp,1);
			biox_Usart3_ClearRecBuffer();
			iucAsynchpoxDataContext = 0x00;
		} else {
			brd_SendDiagStr("->IUC ASYNCHPOS waiting for 0x05 (ENQ).",1);
			biox_Usart3_ClearRecBuffer();
			biox_Usart3_SendBlock(&uctmp,1);
		}
		++timeOut;
	}

	if (uctmp == ENQ)
		return 0;

	return 1;
}

unsigned char iuc_asynchpos_cts() {
	unsigned int recLength;
	unsigned char uctmp = ENQ;

	recLength = biox_Usart3BuffSize();

	if (recLength > 0) {
		biox_Usart3_GetRecBuffer(&uctmp,1);

		if (uctmp == EOT) {	//The terminal is trying to send us data
			uctmp = ENQ;
			biox_Usart3_ClearRecBuffer();
			biox_Usart3_SendBlock(&uctmp,1);
			biox_delay_ms(10);
			return 1;
		}
	}

	return 0;
}

unsigned char iuc_asynchpos_waitforACK() {
	//unsigned char timeOut = 0x00;
	unsigned char retVal = 0x00;
	unsigned char rxData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE];
	unsigned int uitmp = 0;

	uitmp = biox_Usart3BuffSize();

	if (uitmp > 1) {
		//iuc_asynchpos_sub_initArray(rxData_,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
		biox_Usart3_GetRecBuffer(rxData_,uitmp);
		if (GWstate.DebugLevel & 0x10)
		{
			brd_SendDiagStr("->IUC ASYNCHPOS (ACK/NACK) rx data: ",0);
			brd_SendDiagBlock(rxData_,1,uitmp);
		}

		retVal = rxData_[0];

		for (;uitmp > 0;--uitmp) {
			if (rxData_[uitmp] == 0x0A) {
				retVal |= 0xA0;
			}

			if (rxData_[uitmp] == 0x0F) {
				retVal |= 0xF0;
			}
		}
	} else {

	//if (uitmp == 1)
		biox_Usart3_GetRecBuffer(&retVal,1);
	}

	biox_Usart3_ClearRecBuffer();
	return retVal;
}

unsigned char iuc_asynchpos_send_serial(unsigned char* pData, unsigned int length, unsigned char needRTS, unsigned char overrideACK) {
	unsigned int uitmp = 0;
	unsigned int uitmp2 = 0;
	unsigned int uitmp3 = 0;
	unsigned int txCounter = 0;
	unsigned int dxCounter = 0;
	unsigned char uctmp = 0x00;
//	unsigned char uctmp2 =0x00;
	unsigned char chksum = 0x00;
	//unsigned char dataContext = 0x00;
	unsigned int retryCount = 0;
	unsigned long lastRetry = 0;
	unsigned int dxLength;
//	unsigned int dx = biox_StrLen(pData) + 1;
	unsigned char rxBuf[8];
	//unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE];
//	unsigned int loopCount = 1000;
//	unsigned char retVal = 0x01;

	//preparing to send
    if (needRTS) {
		brd_SendDiagStr("->IUC ASYNCHPOS sending 0x04 (EOT).",1);
	    uctmp = iuc_asynchpos_rts();
	}

	//sending data
	if (!uctmp) {
		brd_SendDiagStr("----->IUC ASYNCHPOS",1);
		iuc_asynchpos_sub_initArray(txAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
		//iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);

		//biox_CopyBlock(pData,0,pData_,0,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);

		/*dxCounter = 0;
		for (uitmp = 0; uitmp < dx + dxCounter; ++uitmp) {
			if ((pData[uitmp] >= STX  && pData[uitmp] <= ACK2)
				|| (pData[uitmp] == DLE) || (pData[uitmp] == NAK)) {

				pData[uitmp] = (pData[uitmp] + 0x30);

				for (uitmp2 = uitmp; uitmp2 < dx + dxCounter; ++uitmp2) {
					pData[uitmp2 + 1] = pData[uitmp2];
				}

				pData[uitmp] = DLE;
				++dxCounter;
			}
		}

		dxCounter = 0;*/

		for (uitmp = 0; uitmp < length; uitmp += IUC_ASYNCHPOS_MIN_PACKET_SIZE) {

			//if (dxCounter > 0)
				//uitmp -= dxCounter;

			uctmp = 0x00;
			dxCounter = 0;
			chksum = 0x00;
			dxLength = IUC_ASYNCHPOS_MIN_PACKET_SIZE;

			if (length - uitmp <= IUC_ASYNCHPOS_MIN_PACKET_SIZE)
				dxLength = 2 + length - uitmp;

			iuc_asynchpos_sub_initArray(txAsynchData, 3 + IUC_ASYNCHPOS_MIN_PACKET_SIZE);

			//Packet structure is STX <packet_data> ETX1|ETX2 {LRC}
			txAsynchData[0] = STX;

			for (txCounter = 0; (txCounter/* + dxCounter*/) < dxLength; ++txCounter) {
			//for (txCounter = 0; txCounter < dxLength; ++txCounter) {

				/*if ((pData[uitmp + txCounter] >= STX  && pData[uitmp + txCounter] <= ACK2)
					|| (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) {
					txAsynchData[1 + txCounter + dxCounter] = DLE;
					uctmp = (pData[uitmp + txCounter] + 0x30);
					++dxCounter;
					txAsynchData[1 + txCounter + dxCounter] = uctmp; //(pData[uitmp + txCounter] + 0x30);
				} else {*/
					txAsynchData[1 + txCounter/* + dxCounter*/] = pData[uitmp + txCounter];

				if ((pData[uitmp + txCounter] >= STX  && pData[uitmp + txCounter] <= ACK2)
				|| (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) {
					++dxCounter;
				}
			}

			for (uitmp2 = 1; uitmp2 < dxLength + dxCounter; ++uitmp2) {
				if ((txAsynchData[uitmp2] >= STX  && txAsynchData[uitmp2] <= ACK2)
				|| (txAsynchData[uitmp2] == DLE) || (txAsynchData[uitmp2] == NAK)) {
					for (uitmp3 = dxLength + dxCounter; uitmp3 > uitmp2; --uitmp3) {
						txAsynchData[uitmp3] = txAsynchData[uitmp3 - 1];
					}
					txAsynchData[uitmp2 + 1] = (txAsynchData[uitmp2 + 1] + 0x30);
					txAsynchData[uitmp2] = DLE;
				}
			}

			/*if (dxLength < IUC_ASYNCHPOS_MIN_PACKET_SIZE && txAsynchData[txCounter + dxCounter] != 0x00) {
				++dxCounter;
			}*/

			for (uitmp2 = 1; uitmp2 <= (txCounter + dxCounter); ++uitmp2) {
				chksum ^= txAsynchData[uitmp2];
			}

			if (!iucAsynchpoxDataContext) {
				txAsynchData[1 + txCounter + dxCounter] = ETX1;
				chksum ^= ETX1;
			} else {
				txAsynchData[1 + txCounter + dxCounter] = ETX2;
				chksum ^= ETX2;
			}

			txAsynchData[2 + txCounter + dxCounter] = chksum;

			//Check if the terminal has decided, that our gateway is gone and is frantically sending us EOTs all the time
			//iuc_asynchpos_cts();

			//send packet
			biox_Usart3_ClearRecBuffer();
			biox_Usart3_SendBlock(txAsynchData,3 + txCounter + dxCounter);
			biox_delay_ms(1);

			iuc_asynchpos_sub_initArray(rxBuf,8);
			biox_itoa(3 + txCounter + dxCounter,rxBuf);
			
			if (GWstate.DebugLevel & 0x10)
			{	
				brd_SendDiagStr("->IUC ASYNCHPOS Packetlength: ",0);
				brd_SendDiagBlock(rxBuf,1,8);
				brd_SendDiagStr("->IUC ASYNCHPOS send package: ",0);
				brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter);
			}
			//brd_SendDiagStr("->IUC ASYNCHPOS Send: ",0);
			//brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter);

			//wait for ACK
			uctmp = 0x00;
			lastRetry = 0;
			retryCount = 0;

			brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1);
			do {
				uctmp = iuc_asynchpos_waitforACK();
				//uctmp2 = uctmp;
				uctmp &= 0x0F;
				//if (!(lastRetry % 10)) {
				//}

				if ((uctmp == NAK) || ((lastRetry >= 100) && (uctmp == 0x00))) {
					brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1);
					if (uctmp == NAK)
						brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1);
					biox_Usart3_SendBlock(txAsynchData,3 + txCounter + dxCounter);
					biox_delay_ms(1);
					++retryCount;
					uctmp = 0x00;
					lastRetry = 0;
				} else {
					++lastRetry;
					biox_delay_ms(1);
				}
			} while (retryCount < 25 && uctmp == 0x00);	//Entweder Timeout, keine neuen Versuche oder ein ACK1/ACK2 holen uns hier raus

			/*while (retryCount < 5 && (uctmp == 0x00 || uctmp == NAK)) {
				uctmp = iuc_asynchpos_waitforACK();
				++lastRetry;

//				if (uitmp == 0)
//					biox_delay_ms(100);

				if ((uctmp == NAK) || (uctmp == 0x00 && (lastRetry % 10 == 0x00))) {
					biox_Usart2_ClearRecBuffer();
					brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1);
					biox_Usart2_SendBlock(txAsynchData,3 + txCounter + dxCounter);
					biox_delay_ms(10);
					brd_SendDiagStr("->IUC ASYNCHPOS resend: ",0);
					brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter);
					++retryCount;
				} else if (uctmp == ETX1 || uctmp == ETX2) {
					biox_Usart2_ClearRecBuffer();
					uctmp = NAK;
					biox_Usart2_SendBlock(&uctmp,1);
				}
			}*/

			if (!uctmp) {
				brd_SendDiagStr("->IUC ASYNCHPOS Terminal did not reply.",1);
				return 1;	//sending failed
			}

			//iuc_asynchpos_sub_initArray(txAsynchData, 3 + txCounter + dxCounter);

			if (uctmp == ACK1) {
				brd_SendDiagStr("->IUC ASYNCHPOS ACK 1 (serial)",1);
				//dataContext = 0x01;
				iucAsynchpoxDataContext = 0x01;
			}

			if (uctmp == ACK2) {
				brd_SendDiagStr("->IUC ASYNCHPOS ACK 2 (serial)",1);
				//dataContext = 0x00;
				iucAsynchpoxDataContext = 0x00;
			}

			if (retryCount >= 5) {
				brd_SendDiagStr("->IUC ASYNCHPOS Too much NACKs, giving up.",1);
				return 2;	//too much NACKs, giving up
			}
		}

		/*uctmp2 &= 0xF0;

		if (uctmp2 == 0xA0) {
			retVal = 1;
		}

		if (uctmp2 == 0xF0) {
			retVal = 0;
		}*/

		/*if (!overrideACK) {
			brd_SendDiagStr("->IUC ASYNCHPOS Retrieving.",1);
			retVal = 0x01;
			uitmp = 0x01;
			while(uitmp > 0 && loopCount > 0) {
				uitmp = iuc_asynchpos_recieve_serial(0x01);
				biox_delay_ms(1);
				--loopCount;
				biox_Usart2_ClearRecBuffer();
			}

			if (loopCount == 0) {
				brd_SendDiagStr("->IUC ASYNCHPOS Retrieving timeout!",1);
				retVal = 0x00;
			}
			brd_SendDiagStr("->IUC ASYNCHPOS Retrieving ended.",1);
		}*/

		return 1;//retVal;//(UCHAR) uitmp;
	} else {
		brd_SendDiagStr("->IUC ASYNCHPOS Not ready to send to POS, giving up.",1);
	}

	return 2;
}

unsigned int iuc_asynchpos_send(unsigned char packetType, unsigned char* pData, unsigned int length, unsigned char needRTS) {
	unsigned char txData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE];
	unsigned char tempID [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE];
	unsigned char tempID_ [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE];
	unsigned char tempAPAK [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE];
	unsigned long uitmp = 0;
	unsigned int posID = 0;
	unsigned long chksum = 0;
	unsigned int messageLength = length + 1;
	unsigned int length_ = length + 1;
	unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE];
	unsigned char uctemp = 0;
//	unsigned char retries = 4;
	unsigned char rxBuf[8];

	iuc_asynchpos_crc_old = 0;
	iuc_asynchpos_sub_initArray(rxBuf, 8);
	iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
	biox_CopyBlock(pData,0,pData_,0,length_);

	iuc_asynchpos_sub_initArray(txData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
	iuc_asynchpos_sub_initArray(tempID, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE);
	iuc_asynchpos_sub_initArray(tempID_, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE);
	iuc_asynchpos_sub_initArray(tempAPAK, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE);

	//header
	/*
	The header of the message is composed of:
	?  1 byte packet Type, which indicates the type of the packet;
	?  8 bytes Packet ID, a unique ID to achieve maximum security (for information on forming
	Packet ID see chapter 3.4 Communication security);
	?  1 byte P.O.S. ID length;
	?  ASCII encoded P.O.S. ID (up to 255 bytes);	((gemeint ist Terminal ID)
	*/

	txData_[2] = packetType;

	//1 byte P.O.S. ID length
	/*for (uitmp = 0; uitmp < 32 && terminalID[uitmp] != 0x00; ++uitmp) {
		++posID; // -= uitmp;
	}*/

	posID = biox_StrLen(terminalID)/* + 1*/;

	//++posID;
	txData_[11] = (UCHAR) posID;

	messageLength += (10 + posID);	//Added header
	txData_[0] = (messageLength) & 0xFF00;	//high byte
	txData_[1] = (messageLength) & 0x00FF;	//low byte

	//8 byte Packet ID
	/*
	Apak: 9D547268976ADE1BBB39DE90F3A449E5
	Terminal id: T-LT-OPT-01
	*/

	//calculate CRC32
	uctemp = (UCHAR) posID;
	chksum = IUC_ASYNCHPOS_POLYNOME_INITIAL;
	chksum = iuc_asynchpos_sub_updateCRC(chksum,&uctemp,1);
	chksum = iuc_asynchpos_sub_updateCRC(chksum,terminalID,posID);
	//for (uitmp = 0; uitmp < length_; ++uitmp) {
	chksum = iuc_asynchpos_sub_updateCRC(chksum,pData_/*[uitmp]*/,length_);
	//}

	//XOR crc value with APAK
	//chksum = 2502456899;	//HACK FOR TESTING, REMOVE LATER!
	for(uitmp = 0; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) {
		tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[uitmp * 2]) << 4;
		tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[(uitmp * 2) + 1]);
		//tempAPAK[uitmp] = (terminalAPAK[uitmp * 2] << 8) | (terminalAPAK[(uitmp * 2) + 1]);
	}

	tempID[0] = (chksum >> 24) & 0xFF;
	tempID[1] = (chksum >> 16) & 0xFF;
	tempID[2] = (chksum >> 8) & 0xFF;
	tempID[3] = chksum & 0xFF;

	for (uitmp = 0; uitmp < 4; ++uitmp) {
		tempID[uitmp] ^= tempAPAK[uitmp]; //terminalAPAK[uitmp];
	}

	for (uitmp = 4; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) {
		tempID[uitmp] = tempAPAK[uitmp]; //terminalAPAK[uitmp];
	}

	//Eyncrypt result with APAK, according to AES128
	aes_encrypt(tempID,tempID_,tempAPAK);

	//get the leftmost 8 byte of that value and set then as Packet ID
	for (uitmp = 0; uitmp < 8; ++uitmp)
		txData_[3 + uitmp] = tempID_[uitmp];

	//P.O.S.ID
	for (uitmp = 0; uitmp < posID; ++uitmp) {
		txData_[12 + uitmp] = terminalID[uitmp];
	}

	//Message
	//1 byte - marker
	//0 . 7F bytes - tag name
	//2 + N bytes - data
	for (uitmp = 0; uitmp < length_; ++uitmp) {
		txData_[12 + posID + uitmp] = pData_[uitmp];
	}

    brd_SendDiagStr("->IUC ASYNCHPOS send message: ",0);
	brd_SendDiagBlock(txData_,1,messageLength);

	//Message compiled, now send it via serial
	uitmp = 1;
	//while (retries > 0 && uitmp > 0) {
		//uitmp = iuc_asynchpos_send_serial(txData_, (messageLength + 1));
		//--retries;
		if (iuc_asynchpos_send_serial(txData_, (messageLength/* + 1*/),needRTS,0x00)) {
			//brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1);
			//TODO Message sending failed -> Error handling here
			//return 1;
			uitmp = 0x00;
			brd_SendDiagStr("->IUC ASYNCHPOS Message NOT send",1);
		} else {
			brd_SendDiagStr("->IUC ASYNCHPOS Message send",1);
		} /*else {
			--retries;
		}
	}*/

	//if (!uitmp)
		//return 1;

	/*if (retries == 0) {
		brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1);
		rxBuf[0] = 0x45;
		rxBuf[1] = 0x00;
		rxBuf[2] = 0xFF;
		vmc_SendWithBuffer(rxBuf,20,0x69,0);
		return 1;
	}

	rxBuf[0] = 0x45;
	rxBuf[1] = 0x00;
	rxBuf[2] = 0x00;
	vmc_SendWithBuffer(rxBuf,20,0x69,0);*/

	//brd_SendDiagStr("->IUC ASYNCHPOS Message send",1);
	//while(iuc_asynchpos_recieve_serial());

	return 0;
}

/*
Let us assume that a client wants to purchase items and he wants to pay for these items with his
bank card. When the client is ready to authorize the transaction, the ECR needs to send [Authorize]
request for the operations to start. Within the request, the ECR must include:
?  An [Amount] sub tag with the tender amount in minor currency;
?  A [Currency] sub tag with a three digit currency code;
?  A [DocNr] sub tag with the number referencing the current receipt;
?  [Time] – the time of the transaction;
?  A [Lang] sub tag specifying a language code;
As a result, the P.O.S. will reply by an [AuthorizationResult] device event with an [ID], [DocNr],
[Result] sub tags. When ECR closes/finalizes its receipt, ECR must send [DocClosed] event to
finalize bank operation of in this receipt. A successful authorization Id from [AuthorizationResult]
must be included in [DocClosed] message. Only Id of successful authorization has to be included,
other Ids has to be omitted from message.
Depending on the configuration, and requirements, the ECR may receive a [PrintReceipt] event
(though some models of P.O.S. could as well print the receipt itself), with an [ID], [DocNr], and the
[ReceiptText], to be printed out. The [PrintReceipt] event may occur at any time of the operation,
whenever the P.O.S. needs to print something, and it should be printed as soon as possible. ECR
may be occupied during the event, so it may start printing when no more operations are waiting to
be processed. After the receipt has been printed, the ECR has to send a [PrintResult] to P.O.S. to
confirm the successful action. P.O.S. may send [GetMessageBoxInput] message to ECR if signature
of Client needed. ECR must send [InputResult] message to POS. This message informs about sign
status.
During bank card authorization [PrintReceipt] messages usually are sent before
[AuthorizationResult] event.
POS could send additional [DisplayText] message(s) to ECR to inform about process steps.
*/

void iuc_asynchpos_sub_initZero(unsigned char* pArray, int length) {
	unsigned int uitemp = 0;

	for (uitemp = 0; uitemp < (length - 1); ++uitemp)
		pArray[uitemp] = 0x30;

	pArray[length - 1] = 0x00;
}

void iuc_asynchpos_sub_clear_message(unsigned char fillwithZero) {
	if (fillwithZero) {
		iuc_asynchpos_sub_initZero(asynchBill.id,37);
		iuc_asynchpos_sub_initZero(asynchBill.docNr,33);
		/*iuc_asynchpos_sub_initZero(asynchBill.token,25);
		iuc_asynchpos_sub_initZero(asynchBill.result,8);
		iuc_asynchpos_sub_initZero(asynchBill.amount,10);
		iuc_asynchpos_sub_initZero(asynchBill.authCode,7);
		iuc_asynchpos_sub_initZero(asynchBill.rrn,13);
		iuc_asynchpos_sub_initZero(asynchBill.stan,7);
		iuc_asynchpos_sub_initZero(asynchBill.cardtype,33);*/
		//iuc_asynchpos_sub_initZero(asynchBill.errCode,17);
	} else {
		iuc_asynchpos_sub_initArray(asynchBill.id,37);
		iuc_asynchpos_sub_initArray(asynchBill.docNr,33);
		/*iuc_asynchpos_sub_initArray(asynchBill.token,25);
		iuc_asynchpos_sub_initArray(asynchBill.result,8);
		iuc_asynchpos_sub_initArray(asynchBill.amount,10);
		iuc_asynchpos_sub_initArray(asynchBill.authCode,7);
		iuc_asynchpos_sub_initArray(asynchBill.rrn,13);
		iuc_asynchpos_sub_initArray(asynchBill.stan,7);
		iuc_asynchpos_sub_initArray(asynchBill.cardtype,33);*/
		//iuc_asynchpos_sub_initArray(asynchBill.errCode,17);
	}
}

void iuc_asynchpos_sub_sendACK(unsigned char switchPrint) {
	unsigned char messageReturnData[100];
	unsigned int uitemp = 0;
	unsigned int uitemp2 = 0;
	unsigned int uitemp3 = 0;
	unsigned char uctmp = 0;
	unsigned int lastRetry = 0;
	unsigned int retryCount = 0;

	iuc_asynchpos_sub_initArray(messageReturnData, 100); //iuc_asynchpos_sub_initArray(messageData, messageLength + 1);//iuc_asynchpos_sub_initArray(messageReturnData, IUC_ASYNCHPOS_MAX_MESSAGE_SIZE);
	switch (switchPrint) {
		case 1:
		for (uitemp = 0; uitemp < 8; ++uitemp) {
			messageReturnData[uitemp + 3] = terminalSignature[uitemp];
		}
		messageReturnData[uitemp + 3] = (UCHAR) biox_StrLen(terminalID);

		for (uitemp = 0; uitemp < biox_StrLen(terminalID); ++uitemp) {
			messageReturnData[uitemp + 12] = terminalID[uitemp];
		}
		uitemp += 10;
		break;
		case 2:
		for (uitemp = 0; uitemp < 8; ++uitemp) {
			messageReturnData[uitemp + 3] = terminalSignature[uitemp + 8];
		}
		messageReturnData[uitemp + 3] = biox_StrLen(terminalID);

		for (uitemp = 0; uitemp < biox_StrLen(terminalID); ++uitemp) {
			messageReturnData[uitemp + 12] = terminalID[uitemp];
		}
		uitemp += 10;
		break;
		case 0:
		default:
		for (uitemp = 0; uitemp < rxAsynchData[11] + 9; ++uitemp) {
			messageReturnData[uitemp + 3] = rxAsynchData[uitemp + 3];
		}
		++uitemp;
		break;
	}

	messageReturnData[0] = uitemp & (0xFF00);
	messageReturnData[1] = uitemp & (0x00FF);
	messageReturnData[2] = 0x0A;
	//iuc_asynchpos_send_serial(messageReturnData,uitemp/* + 1*/,0x00,0x01);

	for (uitemp2 = uitemp + 2; uitemp2 > 0; --uitemp2) {
		messageReturnData[uitemp2] = messageReturnData[uitemp2 - 1];
	}
	uitemp += 2;

	messageReturnData[0] = 0x01;

	//convert characters
	for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) {
		if ((messageReturnData[uitemp2] >= STX  && messageReturnData[uitemp2] <= ACK2)
				|| (messageReturnData[uitemp2] == DLE) || (messageReturnData[uitemp2] == NAK)) {
					++uitemp;
					for (uitemp3 = uitemp + 1; uitemp3 > uitemp2; --uitemp3) {
						messageReturnData[uitemp3] = messageReturnData[uitemp3 - 1];
					}
					messageReturnData[uitemp2 + 1] = messageReturnData[uitemp2 + 1] + 0x30;
					messageReturnData[uitemp2] = DLE;
		}
	}

	messageReturnData[uitemp + 1] = ETX1;

	//calculate chksum
	for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) {
		messageReturnData[uitemp + 2] ^= messageReturnData[uitemp2];
	}

	biox_Usart3_SendBlock(messageReturnData,uitemp2+1);

	//wait for ACK
	uctmp = 0x00;
	lastRetry = 1;
	retryCount = 0;

	brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1);
	do {
		uctmp = iuc_asynchpos_waitforACK();
				//if (!(lastRetry % 10)) {
				//}

		if (uctmp == NAK || ((lastRetry % 500 == 0) && (uctmp == 0x00))) {
			brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1);
			if (uctmp == NAK)
				brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1);
			biox_Usart3_SendBlock(messageReturnData,uitemp2+1);
			biox_delay_ms(1);
			++retryCount;
			uctmp = 0x00;
			lastRetry = 1;
		} else {
			++lastRetry;
			biox_delay_ms(1);
		}
	} while (retryCount < 5 && uctmp == 0x00);	//Entweder Timeout, keine neuen Versuche oder ein ACK1/ACK2 holen uns hier raus

	if (!uctmp) {
		brd_SendDiagStr("->IUC ASYNCHPOS Terminal did not reply.",1);
		//return 1;	//sending failed
	}

	if (uctmp == ACK1) {
		brd_SendDiagStr("->IUC ASYNCHPOS ACK 1 (ACK serial)",1);
		//dataContext = 0x01;
		iucAsynchpoxDataContext = 0x01;
	}

	if (uctmp == ACK2) {
		brd_SendDiagStr("->IUC ASYNCHPOS ACK 2 (ACK serial)",1);
		//dataContext = 0x00;
		iucAsynchpoxDataContext = 0x00;
	}

	if (retryCount >= 5) {
		brd_SendDiagStr("->IUC ASYNCHPOS (ACK serial) Too much NACKs, giving up.",1);
		//return 2;	//too much NACKs, giving up
	}
}

void iuc_asynchpos_resetBuffers(unsigned char sendENQ) {
	unsigned char uctmp = ENQ;
	unsigned char rxBuf[8];

	if (sendENQ != 0x02) {
		rxCounter = 0;
		messageLength = 0;
		iuc_asynchpos_sub_initArray(rxAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
		iuc_asynchpos_sub_initArray(txAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
	}

	if (sendENQ) {
		iucAsynchpoxDataContext = 0x00;
		ENQrecieved = 1;
        brd_SendDiagStr("->IUC ASYNCHPOS 0x04 (EOT) received.",1);
		brd_switch_RS3(RS3SW2IUC);
		biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none);
		biox_delay_ms(1);
		biox_Usart3_ClearRecBuffer();
        brd_SendDiagStr("->IUC ASYNCHPOS send 0x05 (ENQ). CTS",1);
		biox_Usart3_SendBlock(&uctmp,1);

		if (asynchState <= 0x03)
		{
			brd_SendDiagStr("->IUC ASYNCHPOS sending an error to the VMC",1);
			iuc_asynchpos_sub_initArray(rxBuf,8);
			rxBuf[0] = 0x45;
			rxBuf[1] = 0x00;
			rxBuf[2] = 0xFF;
			vmc_SendWithBuffer(rxBuf,8,0x69,0);
		}
	}
}

//46
void iuc_asynchpos_command_print_Result(unsigned char status) { //Finalize sale
	UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE];
	UCHAR packetType = 0x00;
	UINT uitemp = 0;
	UCHAR command[] = "PrintResult";
	UCHAR tagName[] = "DocNr";
	UCHAR tag2Name[] = "Result";
	UCHAR tag3Name[] = "ID";
	UCHAR tag2ValueO[] = "OK";
	UCHAR tag2ValueE[] = "ERROR";
	unsigned char uctmp = status;

	//Constructing the message
	iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);

	uitemp = biox_StrLen(command);
	message[0] = (UCHAR) uitemp + 0x80;					//constructed element, tag name length
	biox_CopyBlock(command,0,message,1,uitemp);	//tag name
	++uitemp;

	//ID
	message[uitemp] = (UCHAR) biox_StrLen(tag3Name);
	++uitemp;
	biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));
	uitemp += (1 + biox_StrLen(tag3Name));

	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.printId);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.printId,0,message,uitemp, biox_StrLen(asynchBill.printId));//value
	uitemp += biox_StrLen(asynchBill.printId);

	//DocNr
	message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name
	uitemp += (1 + biox_StrLen(tagName));

	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value
	uitemp += biox_StrLen(asynchBill.docNr);

	//Result
	message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name
	uitemp += (1 + biox_StrLen(tag2Name));

	if (!uctmp) {
		message[uitemp] = (UCHAR) biox_StrLen(tag2ValueE);//value length
		++uitemp;
		biox_CopyBlock(tag2ValueE,0,message,uitemp, biox_StrLen(tag2ValueE));//value
		uitemp += biox_StrLen(tag2ValueE)/* + 1*/;
	} else {
		message[uitemp] = (UCHAR) biox_StrLen(tag2ValueO);//value length
		++uitemp;
		biox_CopyBlock(tag2ValueO,0,message,uitemp, biox_StrLen(tag2ValueO));//value
		uitemp += biox_StrLen(tag2ValueO)/* + 1*/;
	}

	iuc_asynchpos_send(packetType,message,uitemp,0x00);
}

void iuc_asynchpos_handleMessage(unsigned char* pData) {
	//unsigned char marker = pData[0];
//	unsigned int tagNameLength = pData[1];
	unsigned char tagName[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE];
//	unsigned int curElementLength = 0;
	//unsigned char curElement[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE];
	//unsigned char receiptData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1];
	unsigned char rxBuf[20];
//	unsigned char flags[129];
//	unsigned char docNr[32];
	//unsigned char messageType = pData[1];

	unsigned int uitmp = 0;
	unsigned int uitmp2 = 0;

	iuc_asynchpos_sub_initArray(tagName, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE);
	//iuc_asynchpos_sub_initArray(curElement, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE);

	uitmp = biox_FindStrInBufferInt("LoginResult",pData) | biox_FindStrInBuffer("LOGINRESULT",pData);
	if (uitmp) {
		asynchState = 0x02;	//eingeloggt
		/*rxBuf[0] = 0x45;
		rxBuf[1] = 0x00;
		rxBuf[2] = 0x00;
		vmc_SendWithBuffer(rxBuf,40,0x69,0);*/
	}

	uitmp = biox_FindStrInBufferInt("AuthorizationStarted",pData) | biox_FindStrInBuffer("AUTHORIZATIONSTARTED",pData);
	if (uitmp) {
		iuc_asynchpos_sub_initArray(rxBuf,5);
		rxBuf[0] = 0x53;
		rxBuf[1] = 0x00;
		rxBuf[2] = 0x00;
		vmc_SendWithBuffer(rxBuf,5,0x69,0);
	}

	uitmp = biox_FindStrInBufferInt("AuthorizationResult",pData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",pData);
	if (uitmp) {
		asynchState = 0x03; //successfully authorized
		iuc_asynchpos_sub_clear_message(0x00);
		uitmp = biox_FindStrInBufferInt("ID",pData);
		biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]);
		uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData);
		biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]);
		//uitmp = biox_FindStrInBuffer("Result",pData) | biox_FindStrInBuffer("RESULT",pData);
		//biox_CopyBlock(pData, uitmp + 2, asynchBill.result, 0, pData[uitmp + 1]);

		brd_SendDiagStr("->IUC ASYNCHPOS message ID: ",0);
		brd_SendDiagBlock(asynchBill.id,1,36);

        /*if (iuc_asynch_PrintControl) {
            brd_SendDiagStr("->IUC ASYNCHPOS print data send AUTH: ",1);
			vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0);
            iuc_asynch_PrintControl = 0x00;
            //biox_delay_ms(750);
		}   else {
            brd_SendDiagStr("->IUC ASYNCHPOS sending authorization: ",1);
            iuc_asynch_PrintControl = 0x01;
        }*/

		uitmp = biox_FindStrInBufferInt("ERROR",pData);
		if (!uitmp/*biox_FindStrInBuffer("OK",pData) | biox_FindStrInBuffer("Approved",pData) | biox_FindStrInBuffer("APPROVED",asynchBill.result)*/) {
			iuc_asynch_PrintControl |= 0xF0;
			/*uitmp = biox_FindStrInBufferInt("Amount",pData) | biox_FindStrInBufferInt("AMOUNT",pData);
			//if (pData[uitmp + 1] <= 10) {
				biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, pData[uitmp + 1]);
			//} else {
				//biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, 10);
			//}*/

			//uitmp = biox_FindStrInBuffer("Token",pData);
			//biox_CopyBlock(pData, uitmp + 2, asynchBill.token, 0, pData[uitmp + 1]);
			/*uitmp = biox_FindStrInBufferInt("Authcode",pData) | biox_FindStrInBufferInt("AUTHCODE",pData);
			biox_CopyBlock(pData, uitmp + 2, asynchBill.authCode, 0, pData[uitmp + 1]);
			uitmp = biox_FindStrInBufferInt("RRN",pData);
			biox_CopyBlock(pData, uitmp + 2, asynchBill.rrn, 0, pData[uitmp + 1]);
			uitmp = biox_FindStrInBufferInt("STAN",pData);
			biox_CopyBlock(pData, uitmp + 2, asynchBill.stan, 0, pData[uitmp + 1]);
			uitmp = biox_FindStrInBufferInt("CardType",pData) | biox_FindStrInBufferInt("CARDTYPE",pData);
			biox_CopyBlock(pData, uitmp + 2, asynchBill.cardtype, 0, pData[uitmp + 1]);*/
			asynchState = 0x04;

            brd_SendDiagStr("->IUC ASYNCHPOS authorization confirmed.",1);

            /*iuc_asynchpos_sub_initArray(rxBuf,20);
			rxBuf[0] = 0x45;
			rxBuf[1] = 0x00;
			rxBuf[2] = 0x00;
			vmc_SendWithBuffer(rxBuf,20,0x69,0);*/

			//iuc_asynchpos_resetBuffers(0x01);
			//iuc_asynchpos_command_close_Document();
		} else {
			iuc_asynch_PrintControl |= 0xF0;
			//uitmp = biox_FindStrInBufferInt("ErrCode",pData) | biox_FindStrInBufferInt("ERRCODE",pData);
			//biox_CopyBlock(pData, uitmp + 2, asynchBill.errCode, 0, pData[uitmp + 1]);

            brd_SendDiagStr("->IUC ASYNCHPOS authorization failed.",1);

            /*iuc_asynchpos_sub_initArray(rxBuf,20);
			rxBuf[0] = 0x45;
            rxBuf[1] = 0xFF;
			biox_CopyBlock(pData, uitmp + 2, rxBuf, 2, pData[uitmp + 1]);
			vmc_SendWithBuffer(rxBuf,20,0x69,0);*/
			iuc_asynch_keepAlive = 0x00;
			//VendRequest=0;
		}
	}

	uitmp = biox_FindStrInBufferInt("PrintReceipt",pData) | biox_FindStrInBufferInt("PRINTRECEIPT",pData);
	if (uitmp) {
		asynchState = 0x03; //Customer receipt recieved
		//iuc_asynchpos_sub_initArray(flags,129);
		//uitmp = biox_FindStrInBufferInt("Flag",pData) | biox_FindStrInBufferInt("FLAG",pData) | biox_FindStrInBufferInt("Flags",pData) | biox_FindStrInBufferInt("FLAGS",pData);
		/*if (uitmp) {
			biox_CopyBlock(pData, uitmp + 2, flags, 0, pData[uitmp + 1]);
			uitmp = biox_FindStrInBufferInt("CD",flags) | biox_FindStrInBufferInt("LR",flags);
		}*/

        /*iuc_asynchpos_sub_clear_message(0x00);
		uitmp = biox_FindStrInBufferInt("ID",pData);
		biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]);
		uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData);
		biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]);*/
		iuc_asynchpos_sub_initArray(asynchBill.printId,129);
		uitmp = biox_FindStrInBufferInt("ID",pData);
		biox_CopyBlock(pData, uitmp + 2, asynchBill.printId, 0, pData[uitmp + 1]);

		//if(asynchState == 0x02/* && uitmp biox_FindStrInBufferInt("CD",flags) || biox_FindStrInBufferInt("LR",flags)*/) {
		if((!iuc_asynch_PRNrecieved) && (biox_FindStrInBufferInt("CD",pData) || biox_FindStrInBufferInt("LR",pData)) )	{
			iuc_asynch_PRNrecieved = 0x01;
			iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1);
			uitmp = /*biox_FindStrInBuffer("ReceiptText",pData) | */biox_FindStrInBufferInt("RECEIPTTEXT",pData);
			uitmp2 = (pData[uitmp] * 256) + pData[uitmp + 1];

			//if (uitmp2 <= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) {
			if (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) {
				uitmp2 = IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
				brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large! Cutting off.",1);
				/*receiptData[0] = 0x50;
				biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*);
				//uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
				//uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE;

				brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0);
				brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
				iuc_asynch_PrintControl |= 0x0F;*/

				/*if (iuc_asynch_PrintControl) {
                    brd_SendDiagStr("->IUC ASYNCHPOS print data send: ",1);
					vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0);
                    iuc_asynch_PrintControl = 0x00;
				} else {
                    brd_SendDiagStr("->IUC ASYNCHPOS print data stored: ",1);
                    iuc_asynch_PrintControl = 0x01;
                }*/
				//biox_delay_ms(750);

				//iuc_asynchpos_resetBuffers(0x01);
				//iuc_asynchpos_command_close_Document();

				//iuc_asynchpos_resetBuffers(0x02);
				//iuc_asynchpos_command_print_Result(0x01);
			}

			receiptData[0] = 0x50;
			biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*/);

			brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0);
			brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
			iuc_asynch_PrintControl |= 0x0F;

			/* else {
				//receiptData[0] = 0x50;
				//iuc_asynchpos_sub_initZero(receiptData,1);
				brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large!",1);
				iuc_asynch_PrintControl |= 0x0E;
			} */
			/* else {
				//iuc_asynchpos_resetBuffers(0x02);
				iuc_asynchpos_command_print_Result(0x00);
			}*/
		}

        //++iuc_print_counter;

		//if(asynchState == 0x04 && iuc_asynch_PrintControl == 0) {
			//iuc_asynchpos_resetBuffers(0x01);
            //iuc_asynchpos_resetBuffers(0x00);
			//iuc_asynchpos_command_print_Result(0x01);
		/*} /else {
			//iuc_asynchpos_resetBuffers(0x02);
			iuc_asynchpos_command_print_Result(0x01);
		}*/
			//iuc_asynchpos_command_print_Result(0x01);

		/*while (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) {
			biox_CopyBlock(pData, uitmp + 2, receiptData, 0, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
			uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
			uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
			vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0);
		}

		//Rest des Packets
		biox_CopyBlock(pData, uitmp + 2, receiptData, 0, uitmp2);
		vmc_SendWithBuffer(receiptData,uitmp2,0x69,0);

		//iuc_asynchpos_resetBuffers(0x02);
		iuc_asynchpos_command_print_Result(0x01);*/
	}

	uitmp = biox_FindStrInBufferInt("VoidResult",pData) | biox_FindStrInBufferInt("VOIDRESULT",pData);
	if (uitmp) {
		asynchState = 0x01; //There was a cancel. Relogin and try again.
		uitmp = biox_FindStrInBufferInt("ERROR",pData);
		if (uitmp) {
			rxBuf[0] = 0x45;
			rxBuf[1] = 0x56;
			rxBuf[2] = 0x45;
			vmc_SendWithBuffer(rxBuf,3,0x69,0);
		}

		uitmp = biox_FindStrInBufferInt("REFUND",pData);
		if (uitmp) {
			rxBuf[0] = 0x45;
			rxBuf[1] = 0x56;
			rxBuf[2] = 0x52;
			vmc_SendWithBuffer(rxBuf,3,0x69,0);
			//TODO refund bill here. Should not trigger, but it might.
		}
	}

	uitmp = biox_FindStrInBufferInt("DocClosed",pData);
	if (uitmp) {
		asynchState = 0x01; //Transaction successful

		//if (VendRequest)
			GWstate.VendRequest=0;
	}


	/*while (pData[uitmp] != 0x00) {	//0x00 is the end marker
		if (tagNameLength > 0x7F) {
			//tagNameLength -= 0x80;

			for (uitmp2 = 0; uitmp2 < (tagNameLength - 0x80); ++uitmp2) {
				tagName[uitmp2] = pData[uitmp + 1 + uitmp2];
			}

			//TODO Do something with the name here

			uitmp = uitmp2 + 1;
			tagNameLength = pData[uitmp];

		} else {
			for (uitmp2 = 0; uitmp2 < tagNameLength; ++uitmp2) {
				tagName[uitmp2] = pData[uitmp + 1 + uitmp2];
			}

			//TODO Do something with the name here

			uitmp = uitmp2 + 1;

			curElementLength = ((UINT) pData[uitmp] << 8) | pData[uitmp];

			for (uitmp2 = 0; uitmp2 < curElementLength; ++uitmp2) {
				curElement[uitmp2] = pData[uitmp + 1 + uitmp2];
			}

			//TODO Do something with the data here

			uitmp = uitmp2 + 1;
			tagNameLength = pData[uitmp];
		}
	}*/

}

void iuc_asynchpos_startCommunication() {
	unsigned char uctmp = EOT;

	biox_Usart3_ClearRecBuffer();
	biox_Usart3_SendBlock(&uctmp,1);
}

void iuc_asynchpos_init() {
	//TODO: CHANGE THIS LATER ON! TEST ONLY!
	#ifdef IUC_ASYCHNPOS_TESTMODE
	unsigned char APAK[] = "9D547268976ADE1BBB39DE90F3A449E5"; //9D547268976ADE1BBB39DE90F3A449E5
	unsigned char TID[] = "T-LT-OPT-01";
	#endif
	unsigned char timeStart[] = "2018-01-01 00:00:00";
	unsigned int uitmp = 0;

	iuc_asynchpos_sub_initArray(asynchBill.time,20);
	biox_CopyBlock(timeStart,0,asynchBill.time,0,biox_StrLen(timeStart));
	//iuc_asynchpos_sub_initArray(asynchBill.id,20);
	//iuc_asynchpos_sub_initArray(asynchBill.docNr,32);
	iuc_asynchpos_sub_clear_message(0x01);
	asynchState = 0;
	iuc_asynch_keepAlive = 0x00;
	iuc_asynch_PrintControl = 0x00;

	tableCreated = 0x00;

	#ifdef IUC_ASYCHNPOS_TESTMODE
	iuc_asynchpos_setTerminalAPAK(APAK, biox_StrLen(APAK));
	iuc_asynchpos_setTerminalID(TID, biox_StrLen(TID));
	#endif

	ENQrecieved = 0x00;
	timeInitalized = GWglobTime.SecOfDay;
	asynchSessionClosed = 0x00;
	iuc_asynch_PRNrecieved = 0x00;
	iuc_asynchpos_crc_old = 0;
	iucAsynchpoxDataContext = 0x00;
	iuc_asynch_printTimeout = IUC_ASYNCHPOS_PRINTTIMOUT;

	brd_switch_RS3(RS3SW2IUC);
	biox_Usart3_ClearRecBuffer();
	biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none);
	biox_delay_ms(1);

	/*
	Apak: 9D547268976ADE1BBB39DE90F3A449E5
	Terminal id: T-LT-OPT-01
	*/

	for (uitmp = 0; uitmp < IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE; ++uitmp)
		terminalAPAK[uitmp] = Conf.APAK_backup[uitmp];

	//biox_CopyBlock(Conf.APAK_backup,0,terminalAPAK,0,IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE);

	iuc_asynchpos_resetBuffers(0x00);
	iuc_asynchpos_startCommunication();
}

unsigned char iuc_asynchpos_recieve_serial(unsigned char waitforACK) {
	unsigned int rxLength = 0;
	unsigned int uitemp = 0;
	unsigned int uitemp2 = 0;
	unsigned char rxData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE];
//	unsigned char messageReturnData[100];
	unsigned char messageLength_[8];
	unsigned char messageCounter_[8];
	unsigned char chksum = 0x00;
	unsigned char uctmp = 0x00;
	unsigned char resetBuffers = 0x00;
	//unsigned int rxCounter = messageLength;
	unsigned char fullPackage = 0x00;
	unsigned char rxBuf[8];

	//if (biox_Usart2_NewTelegram()) {
		//brd_SendDiagStr("<----- IUC ASYNCHPOS",1);
		//get datastream from buffer
		//iuc_asynchpos_sub_initArray(rxData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
	rxLength = biox_Usart3BuffSize();
	
	rxData_[0] = 0xFF;
	
	if (rxLength > 0) {
		brd_SendDiagStr("<----- IUC ASYNCHPOS",1);

		if (rxLength >= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) {
			brd_SendDiagStr("->IUC ASYNCHPOS rx buffer overflow!",1);
			biox_Usart3_ClearRecBuffer();
			return 8;
		}
		
		brd_SendDiagStr("->IUC ASYNCHPOS Data recieved, ISMAS locked!",1);
		ism_lock();
		timeHoldISMAS = GWglobTime.SecOfDay;

		//iuc_asynchpos_sub_initArray(rxData_, rxLength);
		biox_Usart3_GetRecBuffer(rxData_,rxLength);

		if (GWstate.DebugLevel & 0x10)
		{
			biox_itoa(rxLength,messageLength_);
			brd_SendDiagStr("->IUC ASYNCHPOS recieved: ",0);
			brd_SendDiagBlock(messageLength_,1,8);
			brd_SendDiagStr("->IUC ASYNCHPOS rx data: ",0);
			brd_SendDiagBlock(rxData_,1,rxLength);
		
			if (rxLength <= 1)
				brd_SendDiagStr("->IUC ASYNCHPOS Single Byte recieved.",1);
		}

		for (uitemp = 0; uitemp < rxLength/* && resetBuffers == 0x00*/; ++uitemp) {
			if (rxData_[uitemp] == EOT || (!ENQrecieved && rxData_[uitemp] == ENQ))	{//Either we did not initialize everysthing yet OR the PT wants to send something.
				if (uitemp == 0 || (uitemp > 0 && (rxData_[uitemp-1] != ETX1 || rxData_[uitemp-1] != ETX2))) {
					if (rxData_[uitemp] != ENQ) {
						resetBuffers = 0x01;
					} else {
						resetBuffers = 0x02;
						
						brd_SendDiagStr("->IUC ASYNCHPOS ENQ recieved, ISMAS unlocked!",1);
						ism_unlock();
					}
				}
			}

			if (rxData_[uitemp] == ETX1 || (rxData_[uitemp] == ETX2))
				fullPackage = 0x01;
		}

		if (resetBuffers) {	//Does the terminal want to send? / Did we receive an EOT?
			/*ENQrecieved = 0x01;
			rxCounter = 0;
			messageLength = 0;
			iuc_asynchpos_sub_initArray(rxData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);*/
			/*if (ENQrecieved == 0) {
				brd_SendDiagStr("-> IUC ANSNYCHPOS initialized",1);
			} else {
				brd_SendDiagStr("->IUC ASYNCHPOS listening to terminal",1);
			}*/

			if (resetBuffers >= 0x01) {
				iuc_asynchpos_resetBuffers(0x01);
			} else {
				iuc_asynchpos_resetBuffers(0x00);
			}

			if (rxLength > 1) {
				//biox_Usart2_ClearRecBuffer();
				uctmp = NAK;
				biox_Usart3_SendBlock(&uctmp,1);
			}

			//iuc_asynchpos_sub_initArray(messageData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
			return 2; //Yes, it does. / Yes, we did.
		} else

		if (ENQrecieved && fullPackage/* && biox_Usart2_NewTelegram()*/) {
			
			brd_SendDiagStr("->IUC ASYNCHPOS Full packet recieved, ISMAS unlocked!",1);
			ism_unlock();
			
			//brd_SendDiagStr("->IUC ASYNCHPOS Data recieved.",1);
			//calculate chksum
			for (uitemp = 1; uitemp < (rxLength - 1) && (rxData_[uitemp - 1] != ACK1 || rxData_[uitemp - 1] != ACK2); ++uitemp) {
				chksum ^= rxData_[uitemp];
			}

			if (chksum != rxData_[uitemp]) {
				biox_Usart3_ClearRecBuffer();
				uctmp = NAK;
				biox_Usart3_SendBlock(&uctmp,1);
				brd_SendDiagStr("->IUC ASYNCHPOS Sending NACK (Checksum mismatch).",1);
				return 3;	//checksum mismatch
			} else {
				biox_Usart3_ClearRecBuffer();
				if (rxData_[rxLength - 2] == ETX1) {
					uctmp = ACK1;
					biox_Usart3_SendBlock(&uctmp,1);
					brd_SendDiagStr("->IUC ASYNCHPOS Sending ACK1.",1);
					//iucAsynchpoxDataContext = 0x01;
				} else if (rxData_[rxLength - 2] == ETX2) {
					uctmp = ACK2;
					biox_Usart3_SendBlock(&uctmp,1);
					brd_SendDiagStr("->IUC ASYNCHPOS Sending ACK2.",1);
					//iucAsynchpoxDataContext = 0x00;
				} else {
					uctmp = NAK;
					biox_Usart3_SendBlock(&uctmp,1);
					brd_SendDiagStr("->IUC ASYNCHPOS Sending NACK (Wrong Byte).",1);
					return 4;	//We got something wrong and it's causing an error
				}
			}

            /*if (iuc_asynchpos_crc_old == rxData_[rxLength - 2]) {   //We recieved that package already
				iuc_asynchpos_crc_old = 0;
				brd_SendDiagStr("->IUC ASYNCHPOS EXCEPTION: double package!",1);

				brd_SendDiagStr("->IUC ASYNCHPOS rx data: ",0);
				brd_SendDiagBlock(rxData_,1,rxLength);
                return 5;
			}

			iuc_asynchpos_crc_old = rxData_[rxLength - 2];*/

			//reformatting according to specs
			for (uitemp = 0; uitemp < rxLength; ++uitemp) {
				if (rxData_[uitemp] == DLE) {
					rxData_[uitemp] = rxData_[uitemp + 1] - 0x30;
					for (uitemp2 = uitemp + 2; uitemp2 < rxLength; ++uitemp2) {
						rxData_[uitemp2 - 1] = rxData_[uitemp2];
					}
					--rxLength;
				}
			}

			//Check if we received a logical ACK or NACK
			if (rxCounter == 0) {
				if (rxData_[3] == 0x0F) {
					//NACK recieved, resend message
					brd_SendDiagStr("-> IUC ANSNYCHPOS Message NOT ackknowledged",1);
					if (asynchState < 0x02) {
						iuc_asynchpos_sub_initArray(rxBuf,8);
						rxBuf[0] = 0x45;
						rxBuf[1] = 0x00;
						rxBuf[2] = 0xFF;
						vmc_SendWithBuffer(rxBuf,3,0x69,0);
					}
					return 0;
				}

				if (rxData_[3] == 0x0A) {
					//ACK recieved, do nothing
					brd_SendDiagStr("-> IUC ANSNYCHPOS Message acknowledged",1);
					if (asynchState < 0x02) {
						asynchState = 0x02;
						iuc_asynchpos_sub_initArray(rxBuf,8);
						rxBuf[0] = 0x45;
						rxBuf[1] = 0x00;
						rxBuf[2] = 0x00;
						vmc_SendWithBuffer(rxBuf,3,0x69,0);
					}
					return 0;
				}
			}

			if (rxCounter == 0) {
				messageLength = ((UINT) rxData_[1] << 8) | rxData_[2];

				if (GWstate.DebugLevel & 0x10)
				{
					biox_itoa(messageLength,messageLength_);
					brd_SendDiagStr("->IUC ASYNCHPOS message length: ",0);
					brd_SendDiagBlock(messageLength_,1,8);
				}

				if (messageLength + 1 < IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE) {
					iuc_asynchpos_sub_initArray(messageData, /*messageLength + 1*/ IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE);
				} else {
					messageLength = 0;
                    brd_SendDiagStr("->IUC ASYNCHPOS message too long!",0);
					//iuc_asynchpos_sub_initArray(messageData, IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE);
					iuc_asynchpos_sub_initArray(rxBuf,8);
                    rxBuf[0] = 0x45;
					rxBuf[1] = 0x00;
					rxBuf[2] = 0xFF;
					vmc_SendWithBuffer(rxBuf,3,0x69,0);
					iuc_asynchpos_resetBuffers(0x00);
                    return 6;
				}
			}

			if (messageLength > 0) {
				//add to rxData
				uitemp = 1;
			//while (rxData_[uitemp] != ETX1 && rxData_[uitemp] != ETX2  && rxData_[uitemp] != STX) {
				while (/*rxData_[uitemp] != 0x02 && rxData_[uitemp] != 0x03*/uitemp < (rxLength - 2)) {	//removing the STX, ETX, the checksum and additional zero at the end
					rxAsynchData[(uitemp - 1) + rxCounter] = rxData_[uitemp];
					++uitemp;
				}

				rxCounter += uitemp - 1;

				if (GWstate.DebugLevel & 0x10)
				{
					biox_itoa(rxCounter,messageCounter_);
					brd_SendDiagStr("->IUC ASYNCHPOS message counter: ",0);
					brd_SendDiagBlock(messageCounter_,1,8);

					brd_SendDiagStr("->IUC ASYNCHPOS recieve buffer: ",0);
					brd_SendDiagBlock(rxAsynchData,1,rxCounter);
				}
				
				//NEXT Telegram
				if (/*messageLength != 0 && messageLength <= (rxCounter + 5)*/ rxCounter >= (messageLength - 1)) {
					if (GWstate.DebugLevel & 0x10)
					{
						biox_itoa(messageLength,messageLength_);
						brd_SendDiagStr("->IUC ASYNCHPOS message length FINAL: ",0);
						brd_SendDiagBlock(messageLength_,1,8);

						biox_itoa(rxCounter,messageCounter_);
						brd_SendDiagStr("->IUC ASYNCHPOS message counter FINAL: ",0);
						brd_SendDiagBlock(messageCounter_,1,8);
					}

					if (rxAsynchData[2] != 0x0A) {
						//iuc_asynchpos_sub_initArray(messageReturnData, 100);; //iuc_asynchpos_sub_initArray(messageData, messageLength + 1);//iuc_asynchpos_sub_initArray(messageReturnData, IUC_ASYNCHPOS_MAX_MESSAGE_SIZE);

						//if (!iuc_asynchpos_sub_confirm_message(messageData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE))) {
						//Send ACK to terminal
						//iuc_asynchpos_resetBuffers(0x02);

						/*for (uitemp = 0; uitemp < rxAsynchData[11] + 9; ++uitemp) {
							messageReturnData[uitemp + 3] = rxAsynchData[uitemp + 3];
						}
						++uitemp;

						//messageReturnData[0] = 0x02;
						messageReturnData[0] = uitemp & (0xFF00);
						messageReturnData[1] = uitemp & (0x00FF);
						messageReturnData[2] = 0x0A;*/
						//messageReturnData[uitemp + 2] = ETX1;

						//calculate chksum
						/*for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) {
							messageReturnData[uitemp + 3] ^= messageReturnData[uitemp];
						}*/

						//biox_Usart2_SendBlock(messageReturnData,uitemp + 4);

						//brd_SendDiagStr("->IUC ASYNCHPOS message ACKNOWLEDGE: ",0);
						//brd_SendDiagBlock(messageReturnData,1,uitemp + 1);
						//iuc_asynchpos_send_serial(messageReturnData,uitemp + 1,0x01,0x01);

						for (uitemp = 0; uitemp < rxCounter - (12 + rxAsynchData[11]); ++uitemp) {
							messageData[uitemp] = rxAsynchData[uitemp + (12 + (UINT) rxAsynchData[11])];

							if (messageData[uitemp] == 0x00)
								messageData[uitemp] = 0x30;
						}

						uitemp = biox_FindStrInBufferInt("PrintReceipt",messageData) | biox_FindStrInBufferInt("PRINTRECEIPT",messageData)
							| biox_FindStrInBufferInt("AuthorizationResult",messageData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",messageData);

						if (uitemp) {
							if (biox_FindStrInBufferInt("PrintReceipt",messageData) | biox_FindStrInBufferInt("PRINTRECEIPT",messageData)) {
								biox_CopyBlock(rxAsynchData,3,terminalSignature,0,8);
							} else {
								biox_CopyBlock(rxAsynchData,3,terminalSignature,8,8);
							}
						} else {
							iuc_asynchpos_sub_sendACK(0);
						}
						
						if (GWstate.DebugLevel & 0x10)
						{		
							brd_SendDiagStr("->IUC ASYNCHPOS full message: ",0);
							brd_SendDiagBlock(messageData,1,rxCounter - (12 + ((UINT) rxAsynchData[11])));
						}

						iuc_asynchpos_handleMessage(messageData);
						brd_SendDiagStr("-> IUC ANSNYCHPOS Data handled",1);
					}

					/*brd_SendDiagStr("->IUC ASYNCHPOS full message: ",0);
					brd_SendDiagBlock(messageData,1,rxCounter - (12 + rxAsynchData[11]));

					iuc_asynchpos_handleMessage(messageData);
					brd_SendDiagStr("-> IUC ANSNYCHPOS Data handled",1);*/
					iuc_asynchpos_resetBuffers(0x00);
				}
			}

			return 1;	//Still busy
		}
	} //else {

		if (ENQrecieved == 0 && (timeInitalized + 10) < GWglobTime.SecOfDay) {
			brd_SendDiagStr("->IUC ASYNCHPOS waiting for initialization",1);
			biox_Usart3_ClearRecBuffer();
			iuc_asynchpos_init();
			return 1;
		}
		
		if (ism_islocked() && (timeHoldISMAS - GWglobTime.SecOfDay >= 1800))
		{
			brd_SendDiagStr("->IUC ASYNCHPOS ISMAS holding timeout, ISMAS unlocked!",1);
			ism_unlock();
		}
		
        if (iuc_asynch_PrintControl == 0xFF) {
			iuc_asynch_keepAlive = 0x00;
			iuc_asynchpos_sub_sendACK(1);
			biox_delay_ms(2);
			iuc_asynchpos_sub_sendACK(2);
			biox_delay_ms(2);
			iuc_asynchpos_command_print_Result(0x01);
			biox_delay_ms(2);
            if (0x04 == asynchState) {    //Was the authorization successful?
				brd_SendDiagStr("->IUC ASYNCHPOS Sending YES receipt to VMC.",1);
                vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x10); //Yes
            } else {
				brd_SendDiagStr("->IUC ASYNCHPOS Sending NO receipt to VMC.",1);
                vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x20); //No
            }
            iuc_asynch_PrintControl = 0;

			//VendRequest=0;
			return 1;
        }

		/*if (iuc_asynch_PrintControl == 0xFE) {
			iuc_asynch_keepAlive = 0x00;
			iuc_asynchpos_sub_initArray(rxBuf,8);
			rxBuf[0] = 0x45;
			rxBuf[1] = 0x00;
			rxBuf[2] = 0x00;
			vmc_SendWithBuffer(rxBuf,8,0x69,0);
			iuc_asynch_PrintControl = 0;
			return 1;
		}*/

		if (rxData_[0] != STX/* && rxLength > 0 && rxData_[0] != 0xFF*/) {
			//brd_SendDiagStr("->IUC ASYNCHPOS No STX recieved, ISMAS unlocked, sending NACK!",1);
			if (rxData_[0] != 0xFF) {
				brd_SendDiagStr("->IUC ASYNCHPOS No STX recieved, ISMAS unlocked!",1);
				ism_unlock();
			}
			biox_Usart3_ClearRecBuffer();
			//uctmp = NAK;
			//biox_Usart3_SendBlock(&uctmp,1);
		}

		//Workaround for our terminal problem, which, sometimes, fails to send a Print Result
		/*if (0xF0 == iuc_asynch_PrintControl) {
			if (0x00 == iuc_asynch_printTimeout) {
				iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
				receiptData[0] = 0x50;
				if (0x04 == asynchState) {    //Was the authorization successful?
					vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x10); //Yes
				} else {
					vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x20); //No
				}
				iuc_asynch_printTimeout = IUC_ASYNCHPOS_PRINTTIMOUT;
				iuc_asynch_PrintControl = 0;
			} else {
				--iuc_asynch_printTimeout;
				biox_delay_ms(1);
			}
		}*/
	//}

	if (waitforACK)
		return 8;
	return 0;
}

//messagees

void iuc_asynchpos_sub_synchTime() {
	UINT uitemp = 0;

	//unsigned char timeStart[] = "2017-12-19 13:40:00";
	//biox_CopyBlock(timeStart,0,asynchBill.time,0,biox_StrLen(timeStart));

	for (uitemp = 0; uitemp < 6; ++uitemp) {
		switch (uitemp) {
			case 0:	//year
			asynchBill.time[2] = (GWglobTime.year / 10) + 0x30;;
			asynchBill.time[3] = (GWglobTime.year % 10) + 0x30;
			
			/*#ifdef IUC_ASYCHNPOS_TESTMODE
			asynchBill.time[2] = 0x31;
			asynchBill.time[3] = 0x39;
			#endif*/
			break;
			case 1:	//month
			asynchBill.time[5] = (GWglobTime.month / 10) + 0x30;;
			asynchBill.time[6] = (GWglobTime.month % 10) + 0x30;
			
			/*#ifdef IUC_ASYCHNPOS_TESTMODE
			asynchBill.time[5] = 0x31;
			asynchBill.time[6] = 0x32;
			#endif*/
			break;
			case 2:	//day
			asynchBill.time[8] = (GWglobTime.dayOfMon / 10) + 0x30;;
			asynchBill.time[9] = (GWglobTime.dayOfMon % 10) + 0x30;
			
			/*#ifdef IUC_ASYCHNPOS_TESTMODE
			asynchBill.time[8] = 0x30;
			asynchBill.time[9] = 0x32;
			#endif*/
			break;
			case 3:	//hours
			asynchBill.time[11] = (GWglobTime.hour / 10) + 0x30;;
			asynchBill.time[12] = (GWglobTime.hour % 10) + 0x30;
			
			/*#ifdef IUC_ASYCHNPOS_TESTMODE
			asynchBill.time[11] = 0x31;
			asynchBill.time[12] = 0x32;
			#endif*/
			break;

			case 4:	//minutes
			asynchBill.time[14] = (GWglobTime.min / 10) + 0x30;;
			asynchBill.time[15] = (GWglobTime.min % 10) + 0x30;

			/*#ifdef IUC_ASYCHNPOS_TESTMODE			
			asynchBill.time[14] = 0x30;
			asynchBill.time[15] = 0x30;
			#endif*/
			break;
			case 5:	//seconds
			asynchBill.time[17] = (GWglobTime.sec / 10) + 0x30;;
			asynchBill.time[18] = (GWglobTime.sec % 10) + 0x30;
			break;
		}
	}
}

void iuc_asynchpos_command_ping_terminal() {
	UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE];
	UCHAR packetType = 0x00;
	UINT uitemp = 0;
	UCHAR command[] = "Ping";
	UCHAR tagName[] = "Time";
//	UCHAR tagValue[] = "2017-12-19 13:40:00";

	//Constructing the message
	iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE);

	//biox_CopyBlock(UCHAR *src, UINT srcPos, UCHAR *dest, UINT destPos, UINT len);
	uitemp = (UCHAR) biox_StrLen(command);
	message[0] = (UCHAR) uitemp + 0x80;					//constructed element, tag name length
	biox_CopyBlock(command,0,message,1,uitemp);	//tag name
	++uitemp;

	message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name
	uitemp += (1 + biox_StrLen(tagName));

	iuc_asynchpos_sub_synchTime();
	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value

	uitemp += biox_StrLen(asynchBill.time)/* + 1*/;

	iuc_asynchpos_send(packetType,message,uitemp,0x00);
}

//80 - d
void iuc_asynchpos_command_Login() {	//Kasse registrieren
	UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE];
	UCHAR packetType = 0x00;
	UINT uitemp = 0;
	UCHAR command[] = "Login";
	UCHAR tagName[] = "Time";
	//UCHAR tag2Name[] = "IdleText";
	UCHAR tag3Name[] = "Flags";
	UCHAR tag3Value[] = "AP3";

	//Constructing the message
	iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE);

	uitemp = (UCHAR) biox_StrLen(command);
	message[0] = (UCHAR) uitemp + 0x80;					//constructed element, tag name length
	biox_CopyBlock(command,0,message,1,uitemp);	//tag name
	++uitemp;

	message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name
	uitemp += (1 + biox_StrLen(tagName));

	//Time
	iuc_asynchpos_sub_synchTime();
	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value
	uitemp += biox_StrLen(asynchBill.time);

	//Flags
	message[uitemp] = (UCHAR) biox_StrLen(tag3Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name
	uitemp += (1 + biox_StrLen(tag3Name));

	message[uitemp] = (UCHAR) biox_StrLen(tag3Value);//value length
	++uitemp;
	biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value

	uitemp += biox_StrLen(tag3Value)/* + 1*/;

	iuc_asynchpos_send(packetType,message,uitemp,0x01);
}

//81 - d
void iuc_asynchpos_command_Logout () {	//Kassenschluss
	UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE];
	UCHAR packetType = 0x00;
	UINT uitemp = 0;
	UCHAR command[] = "Logout";
	UCHAR tagName[] = "Time";

	//Constructing the message
	iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE);

	uitemp = (UCHAR) biox_StrLen(command);
	message[0] = (UCHAR) uitemp + 0x80;					//constructed element, tag name length
	biox_CopyBlock(command,0,message,1,uitemp);	//tag name
	++uitemp;

	message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name
	uitemp += (1 + biox_StrLen(tagName));

	iuc_asynchpos_sub_synchTime();
	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value

	uitemp += biox_StrLen(asynchBill.time)/* + 1*/;

	iuc_asynchpos_send(packetType,message,uitemp,0x01);
	asynchState = 0x00;
}

//54 - d
void iuc_asynchpos_command_authorize(unsigned int vkPreis) {
	UCHAR message[IUC_ASYNCHPOS_MAX_ARRAY_SIZE];
	UCHAR packetType = 0x00;
	UINT uitemp = 0;
	UCHAR command[] = "Authorize";
	UCHAR tag1Name[] = "Amount";
	UCHAR tag2Name[] = "Cash";
	UCHAR tag3Name[] = "Currency";
	UCHAR tag4Name[] = "DocNr";
	UCHAR tag5Name[] = "Time";
	UCHAR tag6Name[] = "Lang";
	UCHAR tag1Value[10];
	UCHAR tag2Value[] = "0";
	UCHAR tag3Value[] = "978";
	UCHAR tag6Value[] = "lt";
	UINT vkPreis_ = vkPreis;

	iuc_asynch_PRNrecieved = 0;

	//Constructing the message
	iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
	iuc_asynchpos_sub_initArray(tag1Value,10);

	uitemp = (UCHAR) biox_StrLen(command);
	message[0] = (UCHAR) uitemp + 0x80;					//constructed element, tag name length
	biox_CopyBlock(command,0,message,1,uitemp);	//tag name
	++uitemp;

	//Amount
	message[uitemp] = (UCHAR) biox_StrLen(tag1Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag1Name,0,message,uitemp, biox_StrLen(tag1Name));// tag name
	uitemp += (1 + biox_StrLen(tag1Name));

	biox_itoa(vkPreis_,tag1Value);
	message[uitemp] = (UCHAR) biox_StrLen(tag1Value);//value length
	++uitemp;
	biox_CopyBlock(tag1Value,0,message,uitemp, biox_StrLen(tag1Value));//value
	uitemp += (/*1 + */biox_StrLen(tag1Value));

	//Cash
	message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name
	uitemp += (1 + biox_StrLen(tag2Name));

	message[uitemp] = (UCHAR) biox_StrLen(tag2Value);//value length
	++uitemp;
	biox_CopyBlock(tag2Value,0,message,uitemp, biox_StrLen(tag2Value));//value
	uitemp += (/*1 + */biox_StrLen(tag2Value));

	//Currency
	message[uitemp] = (UCHAR) biox_StrLen(tag3Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name
	uitemp += (1 + biox_StrLen(tag3Name));

	message[uitemp] = (UCHAR) biox_StrLen(tag3Value);//value length
	++uitemp;
	biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value
	uitemp += (/*1 + */biox_StrLen(tag3Value));

	//DocNr
	message[uitemp] = (UCHAR) biox_StrLen(tag4Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag4Name,0,message,uitemp, biox_StrLen(tag4Name));// tag name
	uitemp += (1 + biox_StrLen(tag4Name));

	//biox_ltoa(asynchBill.docuNr,asynchBill.docNr);
	//++asynchBill.docuNr;

	generate_UniqueTransNr(asynchBill.docNr);

	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value

	uitemp += biox_StrLen(asynchBill.docNr)/* + 1*/;

	//Time
	message[uitemp] = (UCHAR) biox_StrLen(tag5Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag5Name,0,message,uitemp, biox_StrLen(tag5Name));// tag name
	uitemp += (1 + biox_StrLen(tag5Name));

	iuc_asynchpos_sub_synchTime();
	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value

	uitemp += biox_StrLen(asynchBill.time)/* + 1*/;

	//Language
	message[uitemp] = (UCHAR) biox_StrLen(tag6Name);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tag6Name,0,message,uitemp, biox_StrLen(tag6Name));// tag name
	uitemp += (1 + biox_StrLen(tag6Name));

	message[uitemp] = (UCHAR) biox_StrLen(tag6Value);//value length
	++uitemp;
	biox_CopyBlock(tag6Value,0,message,uitemp, biox_StrLen(tag6Value));//value
	uitemp += biox_StrLen(tag6Value)/* + 1*/;

	iuc_asynchpos_send(packetType,message,uitemp,0x00);
}

//73 - d
void iuc_asynchpos_command_cancel_authorize() {
	UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE];
	UCHAR packetType = 0x00;
	UINT uitemp = 0;
	UCHAR command[] = "AuthorizationCancelled";
	UCHAR tagName[] = "ID";

	//Constructing the message
	iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE);

	uitemp = biox_StrLen(command);
	message[0] = (UCHAR) uitemp + 0x80;					//constructed element, tag name length
	biox_CopyBlock(command,0,message,1,uitemp);	//tag name

	if (asynchBill.id[0] != 0x00) {
		++uitemp;
		message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length
		++uitemp;
		biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name
		uitemp += (1 + biox_StrLen(tagName));

		message[uitemp] = (UCHAR) biox_StrLen(asynchBill.id);//value length
		++uitemp;
		biox_CopyBlock(asynchBill.id,0,message,uitemp, biox_StrLen(asynchBill.id));//value

		uitemp += biox_StrLen(asynchBill.id)/* + 1*/;
	}

	iuc_asynchpos_send(packetType,message,uitemp,0x00);
}

//77 - d
void iuc_asynchpos_command_close_Document(unsigned char isStorno) { //Finalize sale
	UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE];
	UCHAR packetType = 0x00;
	UINT uitemp = 0;
	UCHAR command[] = "DocClosed";
	UCHAR tagName[] = "DocNr";
	UCHAR tag2Name[] = "AuthID";

	//Constructing the message
	iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE);

	uitemp = biox_StrLen(command);
	message[0] = (UCHAR) uitemp + 0x80;					//constructed element, tag name length
	biox_CopyBlock(command,0,message,1,uitemp);	//tag name
	++uitemp;

	//DocNr
	message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length
	++uitemp;
	biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name
	uitemp += (1 + biox_StrLen(tagName));

	message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length
	++uitemp;
	biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value
	uitemp += biox_StrLen(asynchBill.docNr);

	//AuthID
	if (!isStorno) {
		message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length
		++uitemp;
		biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name
		uitemp += (1 + biox_StrLen(tag2Name));

		message[uitemp] = (UCHAR) biox_StrLen(asynchBill.id);//value length
		++uitemp;
		biox_CopyBlock(asynchBill.id,0,message,uitemp, biox_StrLen(asynchBill.id));//value
		uitemp += biox_StrLen(asynchBill.id)/* + 1*/;
	}

	iuc_asynchpos_send(packetType,message,uitemp,0x00);
}

void iuc_asynchpos_handleCommand(unsigned char command, unsigned char status) {
	//r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt
	UCHAR	tempBuf[3];
	UCHAR	rxBuf[8];
//	UINT	uitemp = 0;
UINT uitmp= 700;

	tempBuf[0] = 0x00;
	tempBuf[1] = 0x00;
	tempBuf[2] = 0x00;
	
	timeHoldISMAS = GWglobTime.SecOfDay;

	iuc_asynchpos_sub_initArray(rxBuf,8);
	//iuc_asynchpos_resetBuffers(0x00);

	switch (command) {
		case 0x72:	//registration
					//iuc_asynchpos_init();
					asynchState = 0x01;
					iuc_asynchpos_command_Login();
					GWstate.VendRequest=1;
					break;
		case 0x61:	//authorisation
					iuc_asynch_keepAlive = 0x01;
					iuc_asynch_PrintControl = 0;
					iuc_asynchpos_sub_clear_message(0x01);
                    //VendRequest=1;
					iuc_asynchpos_resetBuffers(0x00);
					///#ifdef IUC_ASYCHNPOS_TESTMODE 
					//iuc_asynchpos_command_authorize(uitmp);
					//#else
					iuc_asynchpos_command_authorize(Vend.Amount);
					//#endif
					break;
		case 0x63:	//cancel
		case 0x73:	//storno
					/*if (asynchState <= 0x02 != 0) {	//Authorization result recieved?
						iuc_asynchpos_command_cancel_authorize();
					} else {*/
						iuc_asynchpos_command_close_Document(0x01);
					//}
					iuc_asynch_keepAlive = 0x00;
                    //VendRequest=0;
					break;
		case 0x6B:	//kassenschnitt
					iuc_asynchpos_command_Logout();
					break;
		case 0x62:	//get last bill
					//iuc_zvt_getLastBill(tempBuf);
					break;
		case 0x01:	iuc_asynchpos_command_close_Document(0x00);
					iuc_asynch_keepAlive = 0x00;
                    //VendRequest=0;
					break;
		case 0x70:	iuc_asynchpos_command_ping_terminal();
					break;
		default:
			break;
	}
}

int iuc_asynchpos_checkTime() {
    int retVal = 0;

    if ((GWglobTime.hour == 0) && asynchSessionClosed != 0x00) {
        asynchSessionClosed = 0x00;
		retVal = 1;
    } else if ((GWglobTime.hour == 1) && asynchSessionClosed == 0x00) {
		iuc_asynchpos_command_Logout();
        retVal = 1;
		asynchSessionClosed = 0x01;
    } else if ((GWglobTime.hour == 2) && asynchSessionClosed == 0x01) {
		iuc_asynchpos_command_Login();
		retVal = 1;
		asynchSessionClosed = 0x02;
	}

    return retVal;
}

unsigned char iuc_asynchpos_getIsSaleRunning() {

    //Print, when idle
    /*if (iuc_print_counter && asynchState == 0x01) {
        iuc_asynchpos_command_print_Result(0x01);
        --iuc_print_counter;
        return 1;
    }*/

	return iuc_asynch_keepAlive;
}


#endif