/* ICWrite
 * Schreibt eine Zeichenfolge in die Istec rein
 */
int	ICWrite(UBYTE *Buffer, int len);

/* ICRead
 * Liest eine Zeichenfolge aus der Istec raus
 * Und gibt die Anzahl gelesener Zeichen zurueck
 * len => Groesse des Buffers
 */
int	ICRead(UBYTE *Buffer, int len);

/* ICCheck
 * Testet die Istec auf Bereitschaft
 * UpdateGUI => TRUE=GUI anpassen, FALSE=GUI nicht aendern
 * Wenn alles iO ist, wird TRUE zurueckgegeben, ansonsten FALSE
 */
BOOL	ICCheck(BOOL UpdateGUI);

/* ICClearIO
 * Keine Parameter
 * Liest Zeichen, die sich noch in dem Eingangspuffer befinden
 * sollten aus und schickt diese ins Nirwana
 * (Speziell Tag-/Nachtumschaltung)
 */
void	ICClearIO(void);

/* MyDoIO
 * Startet einen SerialIO und bricht nach max. ms ab
 * SerialIO => Request der ausgeführt werden soll
 * timems   => Max. Ausfuehrungszeit fuer den Request
 * return   => Rueckgabewert von SerialIO-Request, bzw. SERIAL_TIMEOUT_ERROR bei Zeitueberschreitung
 */
ULONG	MyDoIO(struct IORequest *SerialIO, ULONG timems);

/* ICReadCharge
 * Charge     => Zeiger auf die IC_Charge-Struktur, in die die Daten geschrieben werden
 * ChargeType => Kosten je Einheit in Pfennig, 0=Einheiten anzeigen
 * return     => TRUE=Alles iO, FALSE=Fehler aufgetreten
 */
BOOL	ICReadCharge(struct IC_Charge *Charge, int ChargeType, BOOL UpdateGUI);

/* ICWriteCharge
 * Charge     => Zeiger auf die IC_Charge-Struktur, in die die Daten geschrieben werden
 * return     => TRUE=Alles iO, FALSE=Fehler aufgetreten
 */
BOOL	ICWriteCharge(struct IC_Charge *Charge, BOOL UpdateGUI);

/* ICWriteDayNight
 * Aendert den Tag-/Nachtstatus der Anlage
 * DayNight  => 0=Tag, 1= Nacht
 * UpdateGUI => TRUE=GUI anpassen
 * return    => TRUE=Kein Fehler aufgetreten
 */
BOOL	ICWriteDayNight(int DayNight, BOOL UpdateGUI);

/* ICSaveConfig
 * Dient zum Abschliessen des Schreibens der Konfiguration
 */
BOOL	ICSaveConfig(BOOL UpdateGUI);










#ifndef SERIAL_TIMEOUT_ERROR
#define	SERIAL_TIMEOUT_ERROR	429942
#endif

/* ICWrite
 * Schreibt eine Zeichenfolge in die Istec rein
 */
int	ICWrite(UBYTE *Buffer, int len)
{
int	i = 0, n;
ULONG	Packet;

#ifdef	USEGUI
	LT_LockWindow(MainWindow);
#endif
	/* Erst einmal die vollständigen Packete verschicken */
	while((len > 3) &&
			(!SerialError))
	{
		Packet = 0l;
		Packet = 0x03 << 24;									/* Es werden drei Bytes uebertragen */
		for(n = 1 ; n <= 3 ; n++, len--)
			Packet += Buffer[i++] << (24 - n*8);		/* Das sind die drei Bytes */

		SerialIO->IOSer.io_Length = 4;
		SerialIO->IOSer.io_Data = &Packet;
		SerialIO->IOSer.io_Command = CMD_WRITE;
#ifdef	BETA
	printf("ICWrite: %08lx\n", Packet);
#endif
		SerialError = MyDoIO((struct IORequest *)SerialIO, 5000);
		WaitTime(40);
	}

	/* Jetzt die restlichen Bytes verschicken */
	if(!SerialError)
	{
		Packet = ((0x80 + len) << 24);					/* Es werden "len" Bytes uebertragen, gleichzeitig wird die Endekennung uebertragen */
		for(n = 1 ; n <= len ; n++)
			Packet += Buffer[i++] << (24 - n*8);		/* Das sind die restlichen Bytes */
		for(      ; n <= 3 ; n++)
			Packet += 0xFF << (24 - n*8);					/* Rest mit 0xFF auffuellen */

		SerialIO->IOSer.io_Length = 4;
		SerialIO->IOSer.io_Data = &Packet;
		SerialIO->IOSer.io_Command = CMD_WRITE;
#ifdef BETA
	printf("ICWrite: %08lx\n", Packet);
#endif
		SerialError = MyDoIO((struct IORequest *)SerialIO, 5000);
		WaitTime(40 + 60);
	}
#ifdef	USEGUI
	LT_UnlockWindow(MainWindow);
#endif

	return (NULL);
}

/* ICRead
 * Liest eine Zeichenfolge aus der Istec raus
 * Und gibt die Anzahl gelesener Zeichen zurueck
 * len => Groesse des Buffers
 */
int	ICRead(UBYTE *Buffer, int len)
{
int	i = 0, m, n;
UBYTE	Packet[10];

#ifdef	USEGUI
	LT_LockWindow(MainWindow);
#endif
#ifdef BETA
	printf("ICRead\n");
#endif
	do
	{
		SerialIO->IOSer.io_Length = 4;
		SerialIO->IOSer.io_Data = Packet;
		SerialIO->IOSer.io_Command = CMD_READ;
		SerialError = MyDoIO((struct IORequest *)SerialIO, 5000);

		n = Packet[0] & 3;
		for(m = 1; m <= n ; m++, i++)
		{
			if(i < len)
				Buffer[i] = Packet[m];
#ifdef BETA
	printf("%02lx", Buffer[i]);
#endif
		}
	}
	while(((Packet[0] & 0x80) != 0x80) &&
			(!SerialError));
#ifdef BETA
	printf("\nICRead: Soll%ld ; Ist%ldZeichen\n", len, i);
#endif
#ifdef	USEGUI
	LT_UnlockWindow(MainWindow);
#endif

	return(i);
}


/* ICCheck
 * Testet die Istec auf Bereitschaft
 * UpdateGUI => TRUE=GUI anpassen, FALSE=GUI nicht aendern
 * Wenn alles iO ist, wird TRUE zurueckgegeben, ansonsten FALSE
 */
BOOL	ICCheck(BOOL UpdateGUI)
{
UBYTE	CMD[]	= {0x02, 0x02, 0x00};
UBYTE	Buffer[100];
int	i;

	if(!SerialError)
	{
#ifdef	USEGUI
		if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, "Prüfe Anlage auf Bereitschaft...", TAG_DONE);
#endif
		ICClearIO();
		ICWrite(CMD, 3);
		i = ICRead(Buffer, sizeof(Buffer));

		if(Buffer[0] == 0x12)
		{
#ifdef	BETA
			printf("ICCheck == iO\n");
#endif
#ifdef	USEGUI
			if(UpdateGUI)
				strcpy(gad_Status, "Anlage ist bereit"),
				LT_SetAttributes(Handle, GAD_Status, GTTX_Text, gad_Status, TAG_DONE);
#endif
			return(TRUE);
		}
#ifdef	BETA
		printf("ICCheck == niO\n");
#endif
#ifdef	USEGUI
		if(UpdateGUI)
			strcpy(gad_Status, "Anlage ist nicht bereit!"),
			LT_SetAttributes(Handle, GAD_Status, GTTX_Text, gad_Status, TAG_DONE);
#endif
		return(FALSE);
	}
	else
		return(FALSE);
}

/* ICClearIO
 * Keine Parameter
 * Liest Zeichen, die sich noch in dem Eingangspuffer befinden
 * sollten aus und schickt diese ins Nirwana
 * (Speziell Tag-/Nachtumschaltung)
 */
void	ICClearIO()
{
UBYTE	Buffer[100];
ULONG	Bytes;

	do
	{
		SerialIO->IOSer.io_Command = SDCMD_QUERY;
		SendIO((struct IORequest *)SerialIO);
		if(Bytes = SerialIO->IOSer.io_Actual)
		{
			SerialIO->IOSer.io_Length = ( Bytes > 98 ) ? 98 : Bytes;
			SerialIO->IOSer.io_Data = Buffer;
			SerialIO->IOSer.io_Command = CMD_READ;
			SendIO((struct IORequest *)SerialIO);
		}
	}
	while(Bytes);
}

/* MyDoIO
 * Startet einen SerialIO und bricht nach max. ms ab
 * SerialIO => Request der ausgeführt werden soll
 * timems   => Max. Ausfuehrungszeit fuer den Request
 * return   => Rueckgabewert von SerialIO-Request, bzw. SERIAL_TIMEOUT_ERROR bei Zeitueberschreitung
 */
ULONG	MyDoIO(struct IORequest *SerialIO, ULONG timems)
{
ULONG	ret;
ULONG	i = 0;

	/* Starte SerialIO */
	SendIO(SerialIO);

	while((!CheckIO(SerialIO)) && (i < timems))
	{
		TimerIO->tr_node.io_Command	= TR_ADDREQUEST;
		TimerIO->tr_time.tv_secs		= 0;
		TimerIO->tr_time.tv_micro		= 1 * 1000;
		DoIO((struct IORequest *)TimerIO);
		i++;
	}
	if(i < timems)
		ret = WaitIO((struct IORequest *)SerialIO);
	else
	{
		AbortIO((struct IORequest *)SerialIO);
		WaitIO ((struct IORequest *)SerialIO);
		ret = SERIAL_TIMEOUT_ERROR;
	}

	return(ret);
}


/* ICReadCharge
 * Charge     => Zeiger auf die IC_Charge-Struktur, in die die Daten geschrieben werden
 * ChargeType => Kosten je Einheit in Pfennig, 0=Einheiten anzeigen
 * UpdateGUI  => TRUE=Updaten, FALSE=GUI nicht aendern
 * return     => TRUE=Alles iO, FALSE=Fehler aufgetreten
 */
BOOL	ICReadCharge(struct IC_Charge *Charge, int ChargeType, BOOL UpdateGUI)
{
UBYTE	CMD[] = {0x06};
int	n;

#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, "Lese Gebühreninformationen ein...", TAG_DONE);
#endif
	ICWrite(CMD, sizeof(CMD));
	if(!SerialError)
	{
		ICRead((UBYTE *)Charge, sizeof(struct IC_Charge) - 2 * 8 * sizeof(UWORD));
		if(!SerialError)
		{
//			for(n = 0 ; n < 8 ; n++)
//				Charge->ChargeType[n] = ChargeType;
			for(n = 0 ; n < 8 ; n++)
				Charge->Charge[n] = (Charge->ChargeInfo[n*2 + 1] << 8) + (Charge->ChargeInfo[n*2]);
		}
	}
#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, gad_Status, TAG_DONE);
#endif
	if(SerialError)
		return(FALSE);
	return(TRUE);
}

/* ICWriteCharge
 * Charge     => Zeiger auf die IC_Charge-Struktur, in die die Daten geschrieben werden
 * return     => TRUE=Alles iO, FALSE=Fehler aufgetreten
 */
BOOL	ICWriteCharge(struct IC_Charge *Charge, BOOL UpdateGUI)
{
BOOL	ret;

#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, "Schreibe Gebühreninformationen...", TAG_DONE);
#endif
	if(ret = ICCheck(FALSE))
	{
	UBYTE	CMD = Charge->Command;
	UBYTE	Buffer[10];
	int	n;
		Charge->Command = 0x05;
		for(n = 0 ; n < 8 ; n++)
			Charge->ChargeInfo[n*2    ] = (Charge->Charge[n]      ) & 0xFF;
			Charge->ChargeInfo[n*2 + 1] = (Charge->Charge[n] >> 8 ) & 0xFF;
		ICWrite((UBYTE *)Charge, 17);
		Charge->Command = CMD;
		ICRead(Buffer, 8);
//		if(Buffer[0] != 0x11)
//			printf("Error%02lx%02lx%02lx%02lx\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
	}
#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, gad_Status, TAG_DONE);
#endif
	if(!SerialError)
		return(ret);
	return(FALSE);
}

/* ICWriteDayNight
 * Aendert den Tag-/Nachtstatus der Anlage
 * DayNight  => 0=Tag, 1= Nacht
 * UpdateGUI => TRUE=GUI anpassen
 * return    => TRUE=Kein Fehler aufgetreten
 */
BOOL	ICWriteDayNight(int DayNight, BOOL UpdateGUI)
{
UBYTE	CMD[] = {CTI_START, CTI_CONF, CTI_DAY_NIGHT, 0, CTI_STOP};

UBYTE	Buffer[10];

	CMD[3] = DayNight;
#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, "Schalte Tag-/Nachtkonfiguration um...", TAG_DONE);
#endif
	if(ICCheck(FALSE))
		ICWrite(CMD, sizeof(CMD));
	if(!SerialError)
		ICRead(Buffer, sizeof(Buffer));
	if(!SerialError)
	{
		if( !((Buffer[0] == CTI_START)		&&
				(Buffer[1] == CTI_ACK)			&&
				(Buffer[2] == CTI_DAY_NIGHT)	&&

				((Buffer[3] == CTI_RC_DAY_NIGHT_CHANGED)	||
				 (Buffer[3] == CTI_RC_DAY_NIGHT_SAME))		&&

				(Buffer[4] == CTI_STOP)))
		{
			SerialError = -1;
			IstecError = Buffer[2] << 8 + Buffer[3];
		}
#ifdef	USEGUI
		else
			IC_DayNight = DayNight;
#endif
	}
#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, gad_Status, TAG_DONE);
#endif
	return((BOOL)!SerialError);
}

/* ICSaveConfig
 * Dient zum Abschliessen des Schreibens der Konfiguration
 */
BOOL	ICSaveConfig(BOOL UpdateGUI)
{
UBYTE	CMD[] = {0x0C};
BOOL	ret;

#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, "Abschluss Konfiguration...", TAG_DONE);
#endif
	if(ret = ICCheck(FALSE))
		ICWrite(CMD, sizeof(CMD));
#ifdef	USEGUI
	if(UpdateGUI) LT_SetAttributes(Handle, GAD_Status, GTTX_Text, gad_Status, TAG_DONE);
#endif
	if(!SerialError)
		return(ret);
	return(FALSE);
}
