/****************************************************************************
 *
 * Projekt			:	Glacier Batterieboxdeckel Prüfgerät
 * Dateiname		:	ObjLCD.c
 * Autor			:	orginal MHoffmann, abgeändert für dieses Projekt Irene Saxer
 * Erstellungsdatum	:	17.04.2019
 * Beschreibung		:	"Modul zur 8-bit-Ansteuerung eines Charakterdisplays"
 *
 *
 * Versionsgeschichte
 * 	Revision 1.0	17.04.2019 SAI erste Version
 *
 ****************************************************************************/

/****************************************************************************/
/* COMPILER Direktiven */

/****************************************************************************/
/* INCLUDE Dateien */
#include "objLCD.h"

/****************************************************************************/
/* KONSTANTEN */

/****************************************************************************/
/* Globale Variablen */
TObjLcdPara gudt_ObjLcdPara;

/****************************************************************************/
/* Funktionen */
static int16_t Imp_WaitForReady(void);
static uint8_t ObjLcd_Conv(uint8_t u8_InData);
static uint8_t	ObjLcd_DataIn(void);
static void	ObjLcd_DataOut(uint8_t u8_Data);

static uint8_t	ObjLcd_DataIn(void)
{
	uint8_t	u8_Ergebnis = 0;

	u8_Ergebnis = LCD_DATAIN;

	return u8_Ergebnis;
}

static void	ObjLcd_DataOut(uint8_t u8_Data)
{
	LCD_DATAOUT = u8_Data;
}

static int16_t Imp_WaitForReady()
/*============================================================================
 *
 *  Funktion:		Imp_WaitForReady
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	liest solange das Statusbyte aus, bis es den READY-Zustand
 *  				signalisiert
 *
 *==========================================================================*/
{
	uint8_t		u8_Status = 0;
	uint16_t	u16_TO = 0;
	uint8_t		u8_TO = 0;

	//Steuerleitungen setzen
	LCD_INSTSEL;
	LCD_READ;

	//Timeout initialisieren
	u16_TO = DrvTim_StartTimer();

	//warten, bis READY
	do
	{
		LCD_ENABLE;
		DrvTim_DelayClk5();
		u8_Status = ObjLcd_DataIn();
		LCD_DISABLE;
		u8_Status &= 0x80;

		//auf Timeout pruefen
		if (DrvTim_ReadTimer(u16_TO) > OBJLCD_READY_TO)
		{
			//TO abgelaufen
			u8_TO = 1;
		}
	}
	while ((u8_Status > 0) && (u8_TO == 0));

	if (u8_TO == 1)
	{
		return(int16_t)(ERROR_OBJLCD_READY_TIMEOUT);
	}
	else
	{
		return (int16_t)(ERROR_NOERROR);
	}
}

int16_t ObjLcd_Init()
/*============================================================================
 *
 *  Funktion:		ObjLcd_Init
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Initialisierung des LCD-Objektes
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;

	//Puffer fuer Displaydaten leeren
	int_Ergebnis = ObjLcd_ClearDispBuf();

	//LCD initialisieren
	int_Ergebnis |= ObjLcd_Reset();

	//LCD loeschen
	int_Ergebnis |= ObjLcd_ClearDisplay();

	//die Cursorattribute setzen
	int_Ergebnis |= ObjLcd_DisplayControl(1, 1, 1);

	return int_Ergebnis;
}

int16_t ObjLcd_Handler(void)
{
	int16_t i16_Ergebnis = ERROR_NOERROR;

	//Bildinhalt uebertragen, wenn er veraendert wurde und das EEPROM nocht aktiv ist...
	if ( (gudt_ObjLcdPara.u8_DirtyFlag != 0) && ((SPCR & (1<<SPE)) == 0))
	{
		i16_Ergebnis |= ObjLcd_TransmitBuffer();

		//DirtyFlag zuruecksetzen
		gudt_ObjLcdPara.u8_DirtyFlag = 0;

		//auf "READ" stellen, damit micht versehentlich geschrieben werden kann (parallele Nutzung von PortPins)
		LCD_READ;
		LCD_INSTSEL;
	}
	return i16_Ergebnis;
}

//Anzeige eines vordefinierten Textes auf dem LCD
int16_t ObjLcd_ShowAction(uint8_t	u8_TextId)
{
	int16_t 	i16_Ergebnis = ERROR_NOERROR;
	uint16_t	TS;
	
	switch(u8_TextId)
	{
		case 0:
		{
			//Text ausgeben
			ObjLcd_ClearDispBuf();
			ObjLcd_SetBufPos(0,6);
			ObjLcd_Puts("Prüfgerät");
			ObjLcd_SetBufPos(1,1);
			ObjLcd_Puts("zuerst kalibrieren");
			
			TS = DrvTim_StartTimer();
			
			while(DrvTim_ReadTimer(TS) < 2000)
			ObjLcd_Handler();
			break;
		}
		case 1:
		{
			//Text ausgeben
			ObjLcd_ClearDispBuf();
			ObjLcd_SetBufPos(0,6);
			ObjLcd_Puts("Prüfgerät");
			ObjLcd_SetBufPos(1,3);
			ObjLcd_Puts("ist messbereit");
			break;
		}
		case 2:
		{
			//Text bei Fehlender BatterieBox ausgeben
			ObjLcd_ClearDispBuf();
			ObjLcd_SetBufPos(0,1);
			ObjLcd_Puts("BatterieBoxDeckel");
			ObjLcd_SetBufPos(1,5);
			ObjLcd_Puts("einlegen");
			
			TS = DrvTim_StartTimer();
			
			while(DrvTim_ReadTimer(TS) < 1000)
			ObjLcd_Handler();
			break;
		}
		default:
		{
			i16_Ergebnis = -1;
		}

	}

	return i16_Ergebnis;
}

int16_t ObjLcd_Reset()
/*============================================================================
 *
 *  Funktion:		ObjLcd_Reset
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	zuruecksetzen des LCD-Controllers (auch nach Neustart)
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;

	//LCD einschalten
	LCD_ON;

	LCD_WRITE;
	LCD_INSTSEL;

	DrvTim_Delay_ms((uint8_t)40);		

	LCD_WRITE;
	LCD_INSTSEL;

	//Function set
	LCD_ENABLE;
	ObjLcd_DataOut(0x30);
	DrvTim_DelayClk5();
	LCD_DISABLE;
	DrvTim_DelayClk5();


	//min. 4,1 ms warten
	DrvTim_Delay_ms(6);

	LCD_WRITE;
	LCD_INSTSEL;
	//Function set
	LCD_ENABLE;
	ObjLcd_DataOut(0x30);
	DrvTim_DelayClk5();
	LCD_DISABLE;
	DrvTim_DelayClk5();

	//min. 0,1ms warten
	DrvTim_Delay_us(200);

	LCD_WRITE;
	LCD_INSTSEL;

	//Function set
	LCD_ENABLE;
	ObjLcd_DataOut(0x30);
	DrvTim_DelayClk5();
	LCD_DISABLE;
	DrvTim_DelayClk5();

	//min 37µs warten
	DrvTim_Delay_us(40);


	LCD_WRITE;
	LCD_INSTSEL;

	//Function set
	LCD_ENABLE;
	ObjLcd_DataOut(0x38);
	DrvTim_DelayClk5();
	LCD_DISABLE;
	DrvTim_DelayClk5();

	//min. 37µs warten
	DrvTim_Delay_us(50);

	LCD_WRITE;
	LCD_INSTSEL;

	//Display off
	LCD_ENABLE;
	ObjLcd_DataOut(0x08);
	DrvTim_DelayClk5();
	LCD_DISABLE;
	DrvTim_DelayClk5();

	//min. 37µs warten
	DrvTim_Delay_us(50);

	LCD_WRITE;
	LCD_INSTSEL;

	//Clear Display all
	LCD_ENABLE;
	ObjLcd_DataOut(0x01);
	DrvTim_DelayClk5();
	LCD_DISABLE;
	DrvTim_DelayClk5();

	//min. 37µs warten
	DrvTim_Delay_us(50);

	LCD_WRITE;
	LCD_INSTSEL;

	//Entry mode set
	LCD_ENABLE;
	ObjLcd_DataOut(0x06);
	DrvTim_DelayClk5();
	LCD_DISABLE;
	DrvTim_DelayClk5();

	return int_Ergebnis;
}
int16_t ObjLcd_ClearDispBufZeile1()
/*============================================================================
 *
 *  Funktion:		ObjLcd_ClearDispBuf
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Loescht den Puffer mit den an das Display zu uebertragenden
 *  				Daten indem er mit Leerzeichen gefuellt wird
 *
 *==========================================================================*/
{
	uint8_t	u8_Index = 0;

	//beide Zeilen des Displayspuffers mit Leerzeichen fuellen
	for (u8_Index = 0; u8_Index < OBJLCD_CHARS_PER_LINE; u8_Index++)
	{
		gudt_ObjLcdPara.char_Zeile1[u8_Index] = OBJLCD_BLANK;
	}

	//Zeilen- und Spaltenindex zuruecksetzen
	gudt_ObjLcdPara.u8_iZeile = 0;
	gudt_ObjLcdPara.u8_iSpalte = 0;

	//DirtyFlag setzen
	gudt_ObjLcdPara.u8_DirtyFlag = 1;

	return (int16_t)ERROR_NOERROR;
}
int16_t ObjLcd_ClearDispBufZeile2()
/*============================================================================
 *
 *  Funktion:		ObjLcd_ClearDispBuf
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Loescht den Puffer mit den an das Display zu uebertragenden
 *  				Daten indem er mit Leerzeichen gefuellt wird
 *
 *==========================================================================*/
{
	uint8_t	u8_Index = 0;

	//beide Zeilen des Displayspuffers mit Leerzeichen fuellen
	for (u8_Index = 0; u8_Index < OBJLCD_CHARS_PER_LINE; u8_Index++)
	{
		gudt_ObjLcdPara.char_Zeile2[u8_Index] = OBJLCD_BLANK;
	}

	//Zeilen- und Spaltenindex zuruecksetzen
	gudt_ObjLcdPara.u8_iZeile = 0;
	gudt_ObjLcdPara.u8_iSpalte = 0;

	//DirtyFlag setzen
	gudt_ObjLcdPara.u8_DirtyFlag = 1;

	return (int16_t)ERROR_NOERROR;
}

int16_t ObjLcd_ClearDispBuf()
/*============================================================================
 *
 *  Funktion:		ObjLcd_ClearDispBuf
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Loescht den Puffer mit den an das Display zu uebertragenden
 *  				Daten indem er mit Leerzeichen gefuellt wird
 *
 *==========================================================================*/
{
	uint8_t	u8_Index = 0;

	//beide Zeilen des Displayspuffers mit Leerzeichen fuellen
	for (u8_Index = 0; u8_Index < OBJLCD_CHARS_PER_LINE; u8_Index++)
	{
		gudt_ObjLcdPara.char_Zeile1[u8_Index] = OBJLCD_BLANK;
		gudt_ObjLcdPara.char_Zeile2[u8_Index] = OBJLCD_BLANK;
	}

	//Zeilen- und Spaltenindex zuruecksetzen
	gudt_ObjLcdPara.u8_iZeile = 0;
	gudt_ObjLcdPara.u8_iSpalte = 0;

	//DirtyFlag setzen
	gudt_ObjLcdPara.u8_DirtyFlag = 1;

	return (int16_t)ERROR_NOERROR;
}

int16_t ObjLcd_SetBufPos(uint8_t u8_Zeile, uint8_t u8_Spalte)
/*============================================================================
 *
 *  Funktion:		ObjLcd_SetBufPos
 *  Ü-Parameter:	u8_Zeile: Zeilenindex (0-indiziert)
 *  				u8_Spalte: Spaltenindex (0-indiziert)
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Setzt die aktuelle Schreibposition im uC-internen Display-
 *  				buffer
 *
 *==========================================================================*/
{
	int16_t i16_Ergebnis = ERROR_NOERROR;

	if ((u8_Zeile < OBJLCD_NR_OF_LINES) && (u8_Spalte < OBJLCD_CHARS_PER_LINE))
	{
		gudt_ObjLcdPara.u8_iSpalte =  u8_Spalte;
		gudt_ObjLcdPara.u8_iZeile = u8_Zeile;
	}
	else
	{
		i16_Ergebnis = ERROR_OBJLCD_SETPOS_INVALID_ADDR;
	}

	return i16_Ergebnis;
}


int16_t	ObjLcd_PutUByte(uint8_t u8_X)
{
	uint8_t u8_Tmp = u8_X;

	if (u8_Tmp >= 100)
	{
		ObjLcd_PutBuf('0'+(u8_Tmp/100));
		u8_Tmp %= 100;
	}

	if (u8_Tmp >= 10)
	{
		ObjLcd_PutBuf('0'+(u8_Tmp/10));
		u8_Tmp %= 10;
	}

	ObjLcd_PutBuf('0'+u8_Tmp);

	return 0;
}

int16_t ObjLcd_PutBuf(uint8_t u8_Char)
/*============================================================================
 *
 *  Funktion:		ObjLcd_PutBuf
 *  Ü-Parameter:	Charcode des Displays
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Schreibt ein Zeichen in den Displaypuffer
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;

	//wenn u8_Char ist kein Zeilenumbruch, und Zeilenende noch nicht erreicht
	if ((u8_Char != (uint8_t)CR) && (gudt_ObjLcdPara.u8_iSpalte < OBJLCD_CHARS_PER_LINE))
	{	// Zeichen in den Puffer schreiben
		switch (gudt_ObjLcdPara.u8_iZeile)
		{
			case 0:	//Zeile1 beschreiben
			{
				gudt_ObjLcdPara.char_Zeile1[gudt_ObjLcdPara.u8_iSpalte++] = u8_Char;
				break;
			}
			case 1:	//Zeile2 beschreiben
			{
				gudt_ObjLcdPara.char_Zeile2[gudt_ObjLcdPara.u8_iSpalte++] = u8_Char;
				break;
			}
			default:	//unbekannte Zeile
			{
				//Fehlercode senden
				int_Ergebnis = ERROR_OBJLCD_PUTBUF_LINEINDEX_OVF;
			}
		}
	}
	else
	{	//wenn Zeichen Zeilenumbruch, und Zeilenindex == 1.Zeile (0),
		if ((u8_Char == (uint8_t)CR) && (gudt_ObjLcdPara.u8_iZeile == 0))
		{
			//dann Zeile weiterschalten
			gudt_ObjLcdPara.u8_iZeile++;

			//Spaltenindex zuruecksetzen
			gudt_ObjLcdPara.u8_iSpalte = 0;
		}
		else
		{
			//Fehler melden: Zeichen ausserhalb des Displaybereichs
			int_Ergebnis = ERROR_OBJLCD_PUTBUF_LINEINDEX_OVF;
		}
	}

	//DirtyFlag setzen
	gudt_ObjLcdPara.u8_DirtyFlag = 1;

	return int_Ergebnis;
}

// String in den Displaybuffer schreiben
int16_t ObjLcd_Puts(char* pchr_char)
{
	int16_t	i16_Ergebnis = ERROR_NOERROR;
	uint8_t	u8_Tmp;

	while( (u8_Tmp = *pchr_char++) ) //&& (i16_Ergebnis == ERROR_NOERROR) )
	{
		i16_Ergebnis |= ObjLcd_PutBuf(ObjLcd_Conv(u8_Tmp));
	}

	return i16_Ergebnis;
}

int16_t ObjLcd_TransmitBuffer()
/*============================================================================
 *
 *  Funktion:		ObjLcd_TransmitBuffer
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Uebertraegt den Inhalt des Displaypuffers zu dem Display
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;
	uint8_t	iSpalte = 0;

		//Display auf autoincrement stellen
		int_Ergebnis |= ObjLcd_EntryModeSet(1, 0);

		//Datenzeiger auf erstes Zeichen der ersten Zeile richten
		int_Ergebnis |= ObjLcd_SetDDaddr(0x00);

		//die Daten der ersten Zeile uebertragen
		for (iSpalte = 0; iSpalte < OBJLCD_CHARS_PER_LINE; iSpalte++)
		{
			int_Ergebnis |= ObjLcd_PutChar(gudt_ObjLcdPara.char_Zeile1[iSpalte]);
		}

		//Datenzeiger auf erstes Zeichen der ersten Zeile richten
		int_Ergebnis |= ObjLcd_SetDDaddr(0x40);

		//die Daten der ersten Zeile uebertragen
		for (iSpalte = 0; iSpalte < OBJLCD_CHARS_PER_LINE; iSpalte++)
		{
			int_Ergebnis |= ObjLcd_PutChar(gudt_ObjLcdPara.char_Zeile2[iSpalte]);
		}

	return int_Ergebnis;
}

int16_t ObjLcd_ClearDisplay()
/*============================================================================
 *
 *  Funktion:		ObjLcd_ClearDisplay
 *  Ü-Parameter:	-
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	sendet eine Clear-display instruction
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;

	//warten, bis das LCD READY ist
	Imp_WaitForReady();

	//Steuerleitungen setzen
	LCD_INSTSEL;
	LCD_WRITE;

	//Datenleitungen setzen
	ObjLcd_DataOut(0x01);	// Opcode clear display

	//Enableleitung toggeln
	LCD_ENABLE;
	DrvTim_DelayClk5();
	LCD_DISABLE;

	return int_Ergebnis;
}

int16_t ObjLcd_DisplayControl(uint8_t u8_D, uint8_t u8_C, uint8_t u8_B)
/*============================================================================
 *
 *  Funktion:		ObjLcd_DisplayControl
 *  Ü-Parameter:	Display on/off, Cursor on/off, Blinking Pos-Char on/off
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Setzen der Display und Cursorflags im Displaycontroller
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;
	uint8_t	u8_Tmp = 0;

	u8_Tmp = 0x08;	//OP-Code DisplayControl

	if (u8_D == 1)
	{
		u8_Tmp |= 0x04;	//Display on/off-Bit
	}

	if (u8_C == 1)
	{
		u8_Tmp |= 0x02;	//Cursor on/off-Bit
	}

	if (u8_B == 1)
	{
		u8_Tmp |= 0x01;	//blinkende Positionsanzeige on/off
	}

	//warten, bis das LCD READY ist
	Imp_WaitForReady();

	//Steuerleitungen setzen
	LCD_INSTSEL;
	LCD_WRITE;

	//Datenleitungen setzen
	ObjLcd_DataOut(u8_Tmp);

	//Enableleitung toggeln
	LCD_ENABLE;
	DrvTim_DelayClk5();
	LCD_DISABLE;

	return int_Ergebnis;
}

int16_t ObjLcd_EntryModeSet(uint8_t	u8_InD, uint8_t u8_shift)
/*============================================================================
 *
 *  Funktion:		ObjLcd_EntryModeSet
 *  Ü-Parameter:	u8_InD: 1 <=> Increment AC, 0 <=> Decrement AC
 *					u8_shift: 1 <=> shiftet den gesamten Displayinhalt
 *							  0 <=> Displayinhalt bleibt fest stehen
 *  R-Parameter:	-
 *  Beschreibung:	legt fest, ob bei Datenschreibzugriffen der RAMpointer
 *  				erhoeht oder gesenkt wird
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;
	uint8_t	u8_Tmp = 0;

	u8_Tmp = 0x04;	//OP-Code Cursor or Display shift

	if (u8_InD == 1)
	{
		u8_Tmp |= 0x02;	//Increment/decrement
	}

	if (u8_shift == 1)
	{
		u8_Tmp |= 0x01;	//gesamten Disp-Inhalt shiften (oder nicht)
	}


	//warten, bis das LCD READY ist
	Imp_WaitForReady();

	//Steuerleitungen setzen
	LCD_INSTSEL;
	LCD_WRITE;

	//Datenleitungen setzen
	ObjLcd_DataOut(u8_Tmp);

	//Enableleitung toggeln
	LCD_ENABLE;
	DrvTim_DelayClk5();
	LCD_DISABLE;

	return int_Ergebnis;
}

int16_t ObjLcd_SetDDaddr(uint8_t u8_DDaddr)
/*============================================================================
 *
 *  Funktion:		ObjLcd_SetDDaddr
 *  Ü-Parameter:	Adresse im DDRAM (7 Bit)
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Setzten des DDRAM-Adresszeigers
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;
	uint8_t	u8_Tmp = 0;

	u8_Tmp = 0x80;	//OP-Code set DDRAM address

	if (u8_DDaddr < 0x80)
	{
		//gueltiger Adresswert...
		u8_Tmp |= u8_DDaddr;

		//warten, bis das LCD READY ist
		Imp_WaitForReady();

		//Steuerleitungen setzen
		LCD_INSTSEL;
		LCD_WRITE;

		//Datenleitungen setzen
		ObjLcd_DataOut(u8_Tmp);

		//Enableleitung toggeln
		LCD_ENABLE;
		DrvTim_DelayClk5();
		LCD_DISABLE;
	}
	else
	{
		//ungueltige CGRAM-Adresse
		int_Ergebnis = ERROR_OBJLCD_SETDDADDRESS_INVALID_ADDR;
	}

	return int_Ergebnis;
}

int16_t ObjLcd_PutChar(uint8_t u8_Char)
/*============================================================================
 *
 *  Funktion:		ObjLcd_PutChar
 *  Ü-Parameter:	Zeichencode
 *  R-Parameter:	Fehlercode
 *  Beschreibung:	Schreibt ein Zeichen in den DDRAM
 *
 *==========================================================================*/
{
	int16_t	int_Ergebnis = ERROR_NOERROR;

	//warten, bis das LCD READY ist
	Imp_WaitForReady();

	//Steuerleitungen setzen
	LCD_DATASEL;
	LCD_WRITE;

	//Datenleitungen setzen
	ObjLcd_DataOut(u8_Char);

	//Schreibzyklus initiieren
	LCD_ENABLE;
	DrvTim_DelayClk5();
	LCD_DISABLE;


	return(int_Ergebnis);
}

static uint8_t ObjLcd_Conv(uint8_t u8_InData)
/*============================================================================
 *
 *  Funktion:		ObjLcd_Conv
 *  Ü-Parameter:	ASCIIcode eines Zeichens
 *  R-Parameter:	kundenspezifischer LCD-Code, 8-Bit
 *  Beschreibung:	konvertiert einen ASCIIcode in den Zeichencode des kunden-
 *  				spezifischen Zeichensatzes
 *
 *==========================================================================*/
{
	uint8_t	u8_Ergebnis = 0xDB;	//leeres Rechteck

	//Bereich, der 1:1 umgesetzt werden kann
	if ((u8_InData >=0x20) && (u8_InData <= 0x7F))
	{
		u8_Ergebnis = u8_InData;
	}
	else
	{	//Bereich, welcher selektiv zugeordnet wird
		switch (u8_InData)
		{
			case (uint8_t)('ä'): {u8_Ergebnis = (uint8_t)0xe1; break;}
			case (uint8_t)('ö'): {u8_Ergebnis = (uint8_t)0xef; break;}
			case (uint8_t)('ü'): {u8_Ergebnis = (uint8_t)0xf5; break;}
			case (uint8_t)('ß'): {u8_Ergebnis = (uint8_t)0xe2; break;}
			case 0xff: {u8_Ergebnis = (uint8_t)0xff; break;}
			//Falls grosse Umlaute gebraucht werden, muessen sie mit GenerateChar() erzeugt und hier zugeordnet werden
		}
	}

	return u8_Ergebnis;
}
