#include "lcd.h"
#include "boardcfg.h"
#include "hw_config.h"

#define LCD_WR_Takt LCD_WR_L(); delay_us(0); LCD_WR_H(); delay_us(0);
#define LCD_Delay_short delay_us(1);
#define LCD_Delay_long delay_us(10);
#define LCD_Leatch_grab LCD_LE_H(); delay_us(1); LCD_LE_L(); delay_us(1);
u16 LCD_DeviceCode;
//Fortschrittsbalken #################################################################
//LCD_SetProgBar(0,90,50,10,60,255,LCD_Red,0,128); //nr,X,Y,H,W,Max,Color,Typ,Value
struct ProgressBar {
	u16 X;
	u16 Y;
	u16 H;
	u16 W;
	u16 Max;
	u16 Color;
	u16 Value;
	u16 LastValue;
	u8 Typ;
}Bar[LCD_Max_ProgBars];

void LCD_SetProgBar(u8 i, u16 Xpos, u16 Ypos, u16 Height, u16 Width, u16 Max, u16 Color, u8 Typ, u16 Value) {
	Bar[i].X = Xpos;
	Bar[i].Y = Ypos;
	Bar[i].H = Height;
	Bar[i].W = Width;
	Bar[i].Max = Max;
	Bar[i].Color = Color;
	Bar[i].Value = Value;
	Bar[i].Typ = Typ;
	Bar[i].LastValue = 0xFFFF;
}
void LCD_SetBarVal(u8 i, u16 Value) {
	Bar[i].Value = Value;
}
void LCD_DrawBars() {
	u8 i; //u16 Len,Len2;
	for(i = 0; i < LCD_Max_ProgBars; i++) {
		if(Bar[i].H!=0){ //hoehe 0 pixel -> nicht aktiv
			u16 Val = Bar[i].Value;
			u16 LVal = Bar[i].LastValue;
            if (Val<0) { Val = 0; }
            if (Val>Bar[i].Max-2) { Val = Bar[i].Max-2; }
			if (LVal==0xFFFF) { //initialisieren
				u16 X = Bar[i].X;
				u16 Y = Bar[i].Y;
				u16 H = Bar[i].H;
				u16 W = Bar[i].W;

				#ifndef Objekte_in_2D
				LCD_DrawLine(X, Y, W, HORI,OCol_High); LCD_DrawLine(X+1, Y+1, W-2, HORI,OCol_High);//nord
				LCD_DrawLine(X+2, Y+2, W-4, HORI,OCol_Low);//nord
				LCD_DrawLine(X, Y+1, H-1, VERT,OCol_High); LCD_DrawLine(X+1, Y+2, H-3, VERT,OCol_High);//west
				LCD_DrawLine(X+2, Y+2, H-4, VERT,OCol_Low);//west
				LCD_DrawLine((X+W-1), Y, H, VERT,OCol_Low); LCD_DrawLine((X+W-2), Y+1, H-2, VERT,OCol_Low);//ost
				LCD_DrawLine((X+W-3), Y+3, H-4, VERT,OCol_High);//ost
				LCD_DrawLine(X, (Y+H-1), W, HORI,OCol_Low); LCD_DrawLine(X+1, (Y+H-2), W-1, HORI,OCol_Low);//sued
				LCD_DrawLine(X+3, (Y+H-3), W-6, HORI,OCol_High);//sued
				#else
				LCD_DrawRect(X, Y, H, W, OCol_Center);
				LCD_DrawRect(X+1, Y+1, H-2, W-2, Bar[i].Color);
				LCD_DrawRect(X+2, Y+2, H-4, W-4, OCol_Center);
				#endif

				if (Bar[i].Typ==HORI) {
					u16 Len=((float)Val/(float)Bar[i].Max)*((float)W-6);
					LCD_DrawFilledRect(Bar[i].X+3, Bar[i].Y+3, Bar[i].H-6, Len, Bar[i].Color);
					LCD_DrawFilledRect(Bar[i].X+3+Len, Bar[i].Y+3, Bar[i].H-6, W-6-Len, OCol_Center);
				} else {//Vertikal
					u16 Len=((float)(Bar[i].Max-Val)/(float)Bar[i].Max)*((float)H-6);
					LCD_DrawFilledRect(Bar[i].X+3, Bar[i].Y+3+Len, Bar[i].H-6-Len, W-6, Bar[i].Color);
					LCD_DrawFilledRect(Bar[i].X+3, Bar[i].Y+3, Len, W-6, OCol_Center);
				}

				Bar[i].LastValue=Val;
			} else {
				if (Val!=LVal) {
					if (Bar[i].Typ==HORI) {
						u16 Len=((float)Val/(float)Bar[i].Max)*((float)Bar[i].W-6);
						u16 Len2=((float)LVal/(float)Bar[i].Max)*((float)Bar[i].W-6);
						if (Len-Len2!=0) {//aenderung zu klein zur darstellung
							if (Len>Len2) {//Balken breiter
								LCD_DrawFilledRect(Bar[i].X+3+Len2, Bar[i].Y+3, Bar[i].H-6, Len-Len2, Bar[i].Color);
							} else { //Balken schmaler
								LCD_DrawFilledRect(Bar[i].X+3+Len, Bar[i].Y+3, Bar[i].H-6, Len2-Len, OCol_Center);
							}
						}
					} else {//Vertikal
						u16 Len=((float)(Bar[i].Max-LVal)/(float)Bar[i].Max)*((float)Bar[i].H-6);
						u16 Len2=((float)(Bar[i].Max-Val)/(float)Bar[i].Max)*((float)Bar[i].H-6);
						if (Len-Len2!=0) {//aenderung zu klein zur darstellung
							if (Len>Len2) {//Balken hoeher
								LCD_DrawFilledRect(Bar[i].X+3, Bar[i].Y+3+Len2, Len-Len2, Bar[i].W-6, Bar[i].Color);
							} else { //Balken niedriger
								LCD_DrawFilledRect(Bar[i].X+3, Bar[i].Y+3+Len, Len2-Len, Bar[i].W-6, OCol_Center);
							}
						}
					}

					Bar[i].LastValue=Val;
				}
			} //if (LVal==0xFFFF)
		} //if(Bar[i].H!=0){
	} //for(i = 0; i < LCD_Max_ProgBars; i++)
}
void LCD_ClearBars(bool doDraw) {
	u8 i;
	for(i = 0; i < LCD_Max_ProgBars; i++) {
		Bar[i].H=0;
	}
	if (doDraw==true) {
		LCD_DrawBars();
	} //if
}
//Schaltflaechen #################################################################
//LCD_SetButtons(4,180,200,35,60," Clear",BtnNormal,font_8x16);//nr,X,Y,H,W,txt,State,Font
struct Button {
	u16 X;
	u16 Y;
	u16 H;
	u16 W;
	char *Name[12];
	u8 State;
	u8 Font;
	u16 ForeCol;
	u16 BackCol;
}Btn[LCD_Max_Buttons];

void LCD_SetButtons(u8 i, u16 Xpos, u16 Ypos, u16 Height, u16 Width, char *txt, u8 state, u8 font, u16 foreC, u16 backC) {
	Btn[i].X = Xpos;
	Btn[i].Y = Ypos;
	Btn[i].H = Height;
	Btn[i].W = Width;
	Btn[i].Name[0] = txt;
	Btn[i].State = state;
	Btn[i].Font = font;
	Btn[i].ForeCol = foreC;
	Btn[i].BackCol = backC;
}
void LCD_SetButtonstate(u8 i, u8 state){
	Btn[i].State = state;
	//Aktive States bei down
	//0 -> 1 btn down
	//3 -> 6 switch geht on
	//4 -> 5 switch geht off
	//aktive States bei up
	//1 -> 0 btn up
	//5 -> 3 switch ist on
	//6 -> 4 switch ist off
	//passive States bei up
	//3 = BtnIsOn
	//4 = BtnIsOff
	//5 = BtnSetOn
	//6 = BtnSetOff
}
u8 LCD_GetButtonstate(u8 i) {
	return Btn[i].State;
}
void LCD_DrawButtons(u16 Xpos, u16 Ypos) {
	u8 i;
	//positionsberechnung des textes
	#define TXT_X   X+TX
	#define TXT_Y   Y+((H-TY)/2)
	for(i = 0; i < LCD_Max_Buttons; i++) {
		if(Btn[i].H>0){ //hoehe 0 pixel -> nicht aktiv
			u16 X = Btn[i].X;
			u16 Y = Btn[i].Y;
			u16 H = Btn[i].H;
			u16 W = Btn[i].W;
			u8 TX=0,TY=0; //textoffset

            switch (Btn[i].Font) {
                case font_4x6: TX=3; TY=6; break;
                case font_5x8: TX=3; TY=8; break;
                case font_5x12: TX=3; TY=12; break;
                case font_6x10: TX=4; TY=10; break;
                case font_8x12: TX=5; TY=12; break;
                case font_8x16: TX=5; TY=16; break;
                case font_12x16: TX=6; TY=16; break;
                case font_22x36: TX=8; TY=36; break;
            }

			if(Xpos>X && Xpos<X+W && Ypos>Y && Ypos<Y+H){
				//btn aktiv  ###############
				if (Btn[i].State==0||
                    Btn[i].State==3||
                    Btn[i].State==4||(Xpos==0&&Ypos==0)){
					#ifndef Objekte_in_2D
					if (Btn[i].State==0) {
                        LCD_DrawFilledRect(X+2,Y+2,H-4,W-4,Btn[i].ForeCol); //Flaeche
					} else {
					    LCD_DrawFilledRect(X+2,Y+2,H-4,W-16,Btn[i].ForeCol); //Flaeche
					}
					LCD_DrawLine(X, Y, W, 0,LCD_GrayLow); LCD_DrawLine(X+1, Y+1, W-3, 0,OCol_Low);//nord
					LCD_DrawLine(X, Y, H, 1,LCD_GrayLow); LCD_DrawLine(X+1, Y+1, H-3, 1,OCol_Low);//west
					LCD_DrawLine((X+W-1), Y, H, 1,LCD_White); LCD_DrawLine((X+W-2), Y+1, H-2, 1,OCol_High);//ost
					LCD_DrawLine(X, (Y+H-1), W, 0,LCD_White); LCD_DrawLine(X+1, (Y+H-2), W-3, 0,OCol_High);//sued
					#else
					LCD_DrawRect(X,Y,H,W,Btn[i].ForeCol);
					#endif

					LCD_BTN_down(i); //main.c
				}
				#ifndef Objekte_in_2D
				switch (Btn[i].State) {//state = ist zustand  ### active
					case 0: //btn normal inaktiv
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].BackCol, Btn[i].ForeCol, Btn[i].Font);
						Btn[i].State=1;
						break;
					case 3: //btn on/off inaktiv ein
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].ForeCol); //Flaeche on/off
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].BackCol, Btn[i].ForeCol, Btn[i].Font);
						Btn[i].State=6;//on/off status bearbeitet
						break;
					case 4: //btn on/off inaktiv aus
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].BackCol); //Flaeche on/off
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].BackCol, Btn[i].ForeCol, Btn[i].Font);
						Btn[i].State=5;//on/off status bearbeitet
						break;
				}
				#else //2D aktiv
				switch (Btn[i].State) {//state = zustand vor active
					case 0: //btn normal inaktiv
						LCD_DrawFilledRect(X+1,Y+1,H-2,W-2,Btn[i].ForeCol); //Flaeche
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].BackCol, Btn[i].ForeCol, Btn[i].Font);
						Btn[i].State=1;
						break;
					case 3: //btn on/off ein
					    LCD_DrawFilledRect(X+1,Y+1,H-2,W-15,Btn[i].ForeCol); //Flaeche
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].BackCol, Btn[i].ForeCol, Btn[i].Font);
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].ForeCol); //Flaeche on/off
						Btn[i].State=6;//auf aktiv umstellen
						break;
					case 4: //btn on/off aus
					    LCD_DrawFilledRect(X+1,Y+1,H-2,W-15,Btn[i].ForeCol); //Flaeche
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].BackCol, Btn[i].ForeCol, Btn[i].Font);
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].BackCol); //Flaeche on/off
						Btn[i].State=5;//auf aktiv umstellen
						break;
				}
				#endif
			} else {
				//btn normal ###############
				if (Btn[i].State!=0&&
                    Btn[i].State!=3&&
                    Btn[i].State!=4) {
					#ifndef Objekte_in_2D
					if (Btn[i].State==1) {
                        LCD_DrawFilledRect(X+2,Y+2,H-4,W-4,Btn[i].BackCol); //Flaeche
					} else {
					    LCD_DrawFilledRect(X+2,Y+2,H-4,W-16,Btn[i].BackCol); //Flaeche
					}
					LCD_DrawLine(X, Y, W, 0,LCD_White); LCD_DrawLine(X+1, Y+1, W-3, 0,OCol_High);//nord
					LCD_DrawLine(X, Y, H, 1,LCD_White); LCD_DrawLine(X+1, Y+1, H-3, 1,OCol_High);//west
					LCD_DrawLine((X+W-1), Y, H, 1,LCD_GrayLow); LCD_DrawLine((X+W-2), Y+1, H-2, 1,OCol_Low);//ost
					LCD_DrawLine(X, (Y+H-1), W, 0,LCD_GrayLow); LCD_DrawLine(X+1, (Y+H-2), W-3, 0,OCol_Low);//sued
					#else
					LCD_DrawRect(X,Y,H,W,Btn[i].ForeCol);
					#endif
					LCD_BTN_up(i); //main.c
				}
				#ifndef Objekte_in_2D
				switch (Btn[i].State) {//state = ist zustand  ### normal
					case 1: //btn normal aktiv
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
						Btn[i].State=0;
						break;
					case 5: //btn on/off ein
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].ForeCol); //Flaeche on/off
						Btn[i].State=3;//on/off status bearbeitet
						break;
					case 6: //btn on/off aus
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].BackCol); //Flaeche on/off
						Btn[i].State=4;//on/off status bearbeitet
						break;
				}
				#else //2D Normal
				switch (Btn[i].State) {//state = zustand vor normal
					case 1: //btn normal aktiv
						LCD_DrawFilledRect(X+1,Y+1,H-2,W-2,Btn[i].BackCol); //Flaeche
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
						Btn[i].State=0;
						break;
					case 5: //btn on/off aktiv aus
					    LCD_DrawFilledRect(X+1,Y+1,H-2,W-15,Btn[i].BackCol); //Flaeche
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].ForeCol); //Flaeche on/off
						Btn[i].State=3;
						break;
					case 6: //btn on/off aktiv ein
					    LCD_DrawFilledRect(X+1,Y+1,H-2,W-15,Btn[i].BackCol); //Flaeche
						LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
						LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].BackCol); //Flaeche on/off
						Btn[i].State=4;
						break;
				}
				#endif
            } //if(Xpos>X && Xpos<X+W && Ypos>Y && Ypos<Y+H){
			switch (Btn[i].State) {//state = zustand VORHER
                case 254: //new draw on/off
					#ifndef Objekte_in_2D
					LCD_DrawFilledRect(X+2,Y+2,H-4,W-4,Btn[i].BackCol); //Flaeche
					LCD_DrawFilledRect(X+W-12,Y+2,H-4,10,Btn[i].BackCol); //Flaeche on/off
					LCD_DrawLine((X+W-14), Y+1, H-2, 1,OCol_Low);//ost
					LCD_DrawLine((X+W-13), Y+1, H-2, 1,OCol_High);//ost
					LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
					#else
					LCD_DrawFilledRect(X+1,Y+1,H-2,W-2,Btn[i].BackCol); //Flaeche
					LCD_DrawLine((X+W-14), Y+1, H-2, 1,Btn[i].ForeCol);//ost
					LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
					#endif

                    Btn[i].State=6;
                    break;
                case 255: //new draw nomal
					#ifndef Objekte_in_2D
					LCD_DrawFilledRect(X+2,Y+2,H-4,W-4,Btn[i].BackCol); //Flaeche
					LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
					#else
					LCD_DrawFilledRect(X+1,Y+1,H-2,W-2,Btn[i].BackCol); //Flaeche
					LCD_DrawText(TXT_X,TXT_Y, Btn[i].Name[0], Btn[i].ForeCol, Btn[i].BackCol, Btn[i].Font);
					#endif
                    Btn[i].State=0;
                    break;
            }
		} //if(Btn[i].H!=0){
	} //for(i = 0; i < LCD_Max_Buttons; i++)
}
void LCD_ReDrawButtons() {
	u8 i;
	for(i = 0; i < LCD_Max_Buttons; i++) {
		Btn[i].State=255;//neu zeichnen
	}
	LCD_DrawButtons(0,0);
}
void LCD_ClearButtons(bool doDraw) {
	u8 i;
	for(i = 0; i < LCD_Max_Buttons; i++) {
		Btn[i].H=0;
	}
	if (doDraw==true) {
		LCD_DrawButtons(0,0);
	} //if
}
//Geometrische darstellungen ####################################################
void LCD_DrawLine(u16 Xpos, u16 Ypos, u16 Length, u8 Direction, u16 Color) {
	u16 i = 0;

	LCD_SetCursor(Xpos, Ypos);
	if (Direction == VERT) {
		LCD_WriteRegister(0x0003,0x1030);		//Entry Mode vertical
		LCD_WriteRAM_Prepare(); LCD_WriteData(Color);
		for (i = 0; i < Length; i++) {
			LCD_WR_Takt;
		}
	} else {
		LCD_WriteRegister(0x0003,0x1018);		//Entry Mode horizontal
		LCD_WriteRAM_Prepare(); LCD_WriteData(Color);
		for (i = 0; i < Length; i++) {
			LCD_WR_Takt;
		}
	}
	LCD_CS_H();
}
void LCD_DrawLine2(u16 x0, u16 y0, u16 x1, u16 y1, u16 col) {
    s16 dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
    s16 dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
    s16 err = (dx>dy ? dx : -dy)/2, e2;
    for(;;){
        LCD_DrawPoint(x0,y0,col);
        if (x0==x1 && y0==y1) break;
        e2 = err;
        if (e2 >-dx) { err -= dy; x0 += sx; }
        if (e2 < dy) { err += dx; y0 += sy; }
    }
}
void LCD_DrawRect(u16 Xpos, u16 Ypos, u16 Height, u16 Width, u16 Color) {
	LCD_DrawLine(Xpos, Ypos, Width, HORI,Color);
	LCD_DrawLine(Xpos, Ypos, Height, VERT,Color);
	LCD_DrawLine((Xpos + Width - 1), Ypos, Height, VERT,Color);
	LCD_DrawLine(Xpos, (Ypos + Height - 1), Width, HORI,Color);
}
void LCD_DrawFilledRect(u16 Xpos, u16 Ypos, u16 Height, u16 Width, u16 Color) {
	u32 CurY=0; //u16 i = 0;
	LCD_WriteRegister(0x0003,0x1018);		//Entry Mode horizontal
	LCD_SetWindows(Ypos,320-(Xpos+Width),Ypos+Height-1,319-(Xpos));
	LCD_SetCursor(Xpos,Ypos);
	LCD_WriteRAM_Prepare(); LCD_Delay_short;
	LCD_WriteData(Color);
	CurY=Height*Width;
	while(CurY--) {
		LCD_WR_Takt;
	}
	LCD_SetWindows(0,0,239,319);
}
void LCD_DrawEllipse(u16 x, u16 y, u16 h, u16 w, u16 col) {
   s16 dx = 0, dy = h; /* im I. Quadranten von links oben nach rechts unten */
   long w2 = w*w, h2 = h*h;
   long err = h2-(2*h-1)*w2, e2; /* Fehler im 1. Schritt */

   do {
       LCD_DrawPoint(x+dx, y+dy, col); /* I. Quadrant */
       LCD_DrawPoint(x-dx, y+dy, col); /* II. Quadrant */
       LCD_DrawPoint(x-dx, y-dy, col); /* III. Quadrant */
       LCD_DrawPoint(x+dx, y-dy, col); /* IV. Quadrant */

       e2 = 2*err;
       if (e2 <  (2*dx+1)*h2) { dx++; err += (2*dx+1)*h2; }
       if (e2 > -(2*dy-1)*w2) { dy--; err -= (2*dy-1)*w2; }
   } while (dy >= 0);

   while (dx++ < w) { /* fehlerhafter Abbruch bei flachen Ellipsen (b=1) */
       LCD_DrawPoint(x+dx, y, col); /* -> Spitze der Ellipse vollenden */
       LCD_DrawPoint(x-dx, y, col);
   }
}
void LCD_DrawPoint(u16 x,u16 y,u16 point) {
	if ( (x>320)||(y>240) ) return;
	LCD_SetCursor(x,y);
	LCD_CS_L();
	LCD_WriteIndex(0x0022);
	LCD_RS_H(); LCD_Delay_short;
	LCD_WriteData(point);
	LCD_WR_Takt;
//	LCD_CS_H();
}
//Text ###########################################################################
void LCD_DrawTextBlock(u16 x, u16 y, char *text, u16 charColor, u16 bkColor, u8 Fill_cnt, char *Fill_char, u8 font) {
	u8 i=0;
	LCD_WriteRegister(0x0003,0x1018);		//Entry Mode horizontal
	while(*text) {
		switch (font) {
            case font_4x6: LCD_PutChar((x+4*i), y, *text++, charColor, bkColor, font); break;
            case font_5x8: LCD_PutChar((x+5*i), y, *text++, charColor, bkColor, font); break;
            case font_5x12: LCD_PutChar((x+5*i), y, *text++, charColor, bkColor, font); break;
            case font_6x10: LCD_PutChar((x+6*i), y, *text++, charColor, bkColor, font); break;
            case font_8x12: LCD_PutChar((x+8*i), y, *text++, charColor, bkColor, font); break;
            case font_8x16: LCD_PutChar((x+8*i), y, *text++, charColor, bkColor, font); break;
            //case font_10x16: LCD_PutChar((x+10*i), y, *text++, charColor, bkColor, font); break;
            case font_12x16: LCD_PutChar((x+12*i), y, *text++, charColor, bkColor, font); break;
            default : LCD_PutChar((x+8*i), y, *text++, charColor, bkColor, font); break;
        }
		i++;
		if (Fill_cnt==i) { return; }
	}
	if (Fill_cnt>i) {
		Fill_cnt-=i;
		while (Fill_cnt>0) {
	        switch (font) {
                case font_4x6: LCD_PutChar((x+4*i), y, *Fill_char, charColor, bkColor, font); break;
                case font_5x8: LCD_PutChar((x+5*i), y, *Fill_char, charColor, bkColor, font); break;
                case font_5x12: LCD_PutChar((x+5*i), y, *Fill_char, charColor, bkColor, font); break;
                case font_6x10: LCD_PutChar((x+6*i), y, *Fill_char, charColor, bkColor, font); break;
                case font_8x12: LCD_PutChar((x+8*i), y, *Fill_char, charColor, bkColor, font); break;
                case font_8x16: LCD_PutChar((x+8*i), y, *Fill_char, charColor, bkColor, font); break;
                //case font_10x16: LCD_PutChar((x+10*i), y, *Fill_char, charColor, bkColor, font); break;
                case font_12x16: LCD_PutChar((x+12*i), y, *Fill_char, charColor, bkColor, font); break;
                default : LCD_PutChar((x+8*i), y, *Fill_char, charColor, bkColor, font); break;
            }
		    Fill_cnt--; i++;
		}
	}
}
void LCD_DrawText(u16 x, u16 y, char *text, u16 charColor, u16 bkColor, u8 font) {
	u8 i=0;
	LCD_WriteRegister(0x0003,0x1018);		//Entry Mode horizontal
	while(*text) {
        switch (font) {
            case font_4x6: LCD_PutChar((x+4*i), y, *text++, charColor, bkColor, font); break;
            case font_5x8: LCD_PutChar((x+5*i), y, *text++, charColor, bkColor, font); break;
            case font_5x12: LCD_PutChar((x+5*i), y, *text++, charColor, bkColor, font); break;
            case font_6x10: LCD_PutChar((x+6*i), y, *text++, charColor, bkColor, font); break;
            case font_8x12: LCD_PutChar((x+8*i), y, *text++, charColor, bkColor, font); break;
            case font_8x16: LCD_PutChar((x+8*i), y, *text++, charColor, bkColor, font); break;
            case font_12x16: LCD_PutChar((x+12*i), y, *text++, charColor, bkColor, font); break;
            case font_22x36: LCD_PutChar((x+22*i), y, *text++, charColor, bkColor, font); break;
            default : LCD_PutChar((x+8*i), y, *text++, charColor, bkColor, font); break;
        }
		i++;
	}
}
void LCD_PutChar(u16 x,u16 y,u8 c,u16 charColor,u16 bkColor, u8 font) {
	u16 i;
	u8 tmp_char=0,a,b,d=7,l=0;
	switch (font) {
        case font_4x6: a=4; b=6; d=3; break;
        case font_5x8: a=5; b=8; d=4; break;
        case font_5x12: a=5; b=12; d=4; break;
        case font_6x10: a=6; b=10; d=5; break;
        case font_8x12: a=8; b=12; break;
        case font_8x16: a=8; b=16; break;
        case font_12x16: a=12; b=32; break;
        case font_22x36: a=22; b=108; break;
        default: a=8; b=16; break; //font_8x16
	}

    for (i=0;i<b;i++) {
        switch (font) {
            case font_4x6: tmp_char=ascii_4x6[c][i]; break;
            case font_5x8: tmp_char=ascii_5x8[c][i]; break;
            case font_5x12: tmp_char=ascii_5x12[c][i]; break;
            case font_6x10: tmp_char=ascii_6x10[c][i]; break;
            case font_8x12: tmp_char=ascii_8x12[c][i]; break;
            case font_8x16: tmp_char=ascii_8x16[c][i]; break;
            case font_12x16: tmp_char=ascii_12x16[c][i+1]; break;
            case font_22x36: tmp_char=ascii_22x36[c][i+2]; break;
        }

        LCD_WriteRegister(0x0020,y+l);
        LCD_WriteRegister(0x0021,319-(x));
        LCD_CS_L(); LCD_Delay_short;
        LCD_WriteIndex(0x0022);
        LCD_RS_H(); LCD_Delay_short;
        switch (font) {
            case font_12x16:
                sub_WR_Dataline(tmp_char,4,d,4,charColor,bkColor);
                tmp_char=ascii_12x16[c][i];
                sub_WR_Dataline(tmp_char,8,d,0,charColor,bkColor);
                i++; break;
            case font_22x36:
                sub_WR_Dataline(tmp_char,8,d,0,charColor,bkColor);
                tmp_char=ascii_22x36[c][i+1];
                sub_WR_Dataline(tmp_char,8,d,0,charColor,bkColor);
                tmp_char=ascii_22x36[c][i];
                sub_WR_Dataline(tmp_char,8,d,0,charColor,bkColor);
                i+=2; break;
            default : sub_WR_Dataline(tmp_char,a,d,0,charColor,bkColor); break;
        }
        l++;
    }

}
void sub_WR_Dataline(u8 data, u8 a,u8 d,u8 e,u16 colC,u16 colB) {
    u8 i;
    for (i=0;i<a;i++) {
        if (data >> (d-e-i)&1) {
            LCD_WriteData(colC);// character color
        } else {
            LCD_WriteData(colB);// background color
        }
        LCD_WR_Takt;
    }
}
//Bilder (ungetestet)###########################################################################
void LCD_DrawPicture(u16 StartX,u16 StartY,u16 EndX,u16 EndY,u16 *pic) {
  u16  i;
  LCD_SetWindows(StartX,StartY,EndX,EndY);
  LCD_SetCursor(StartX,StartY);

  LCD_CS_L();

  LCD_WriteIndex(0x0022);
  LCD_RS_H();LCD_Delay_short;
  for (i=0;i<(EndX*EndY);i++) {
      LCD_WriteData(*pic++);
	  LCD_WR_Takt;
  }

  LCD_CS_H();
}
void LCD_DrawMonoPict(unsigned char  *Pict) {
  u32 index = 0, i = 0;

  LCD_SetWindows(0, 0, 239, 319);
  LCD_SetCursor(0, 0);

  LCD_WriteRegister(0x03,0x1018);		// freeRTOS demo  ( LCD_Message.h format )

  LCD_CS_L();
  LCD_WriteIndex(0x0022);
  LCD_RS_H();

  for(index = 0; index < 9600; index++)
  {
    for(i = 0; i < 8; i++)
    {
		if((Pict[index] & (1 << i)) == 0x00){
			LCD_WriteData(LCD_Blue);	// Font Color
		}
		else{	LCD_WriteData(LCD_Yellow);	// Background Color

		}
		LCD_WR_Takt;
    }
  }
 //LCD_WriteRegister(0x03,0x1030);	// original scan direction
  LCD_CS_H();
}
//########################################################################################
//								LCD Objekte
//########################################################################################
//########################################################################################
//								LCD Treiber
//########################################################################################
void LCD_Enable(u8 status) {
  if ( status > 0 ) {
    LCD_LED_H();
	LCD_Initializtion();
  } else {
    LCD_LED_L();
	LCD_WriteRegister(0x0010,0x0004); //Turn off
  }
}
void LCD_Initializtion() {
 	//u16 i;
  	LCD_WriteData(0xffff);
  	LCD_Delay_short;
	LCD_WR_H();
	LCD_CS_L();
	LCD_RS_H();
	LCD_RD_H();
	LCD_Delay_short;

	//reset
//	LCD_Rst_L();
//	LCD_Delay_long;
//	LCD_WR_Takt;
//	LCD_Delay_long;
//	LCD_Rst_H();

	LCD_Delay_long; LCD_Delay_long;
	LCD_WriteRegister(0x0000,0x0001); //LCD_Delay(100000);
	LCD_Delay_long; LCD_Delay_long;
	LCD_DeviceCode = 0x9325;//LCD_ReadRegister(0x0000);//0x9320;//
	if(LCD_DeviceCode==0x9325||LCD_DeviceCode==0x9328) {

		//Power On sequence //
		LCD_WriteRegister(0x0010,0x1590);		//Power Control 1
		LCD_WriteRegister(0x0011,0x0227);		//Power Control 2
		LCD_WriteRegister(0x0012,0x009c);		//Power Control 3
		LCD_WriteRegister(0x0013,0x1000);		//Power Control 4
		LCD_Delay_long;

		//LCD_WriteRegister(0x0000,0x0001);		//start internal osc (read=>DeviceCode 0x9325)
		LCD_WriteRegister(0x0001,0x0100); 		//Driver Output Control
		LCD_WriteRegister(0x0002,0x0300);		//LCD Driving Wave Control
		LCD_WriteRegister(0x0003,0x1030);		//Entry Mode horizontal S.56
		LCD_WriteRegister(0x0004,0x0000);		//Resizing Control Register
		LCD_WriteRegister(0x0007,0x0133);		//Display Control 1
		LCD_WriteRegister(0x0008,0x0207);		//Display Control 2
		LCD_WriteRegister(0x0009,0x0000);		//Display Control 3
		LCD_WriteRegister(0x000a,0x0000);		//Display Control 4
		LCD_WriteRegister(0x000c,0x0001);		//RGB Display Interface Control 1
		LCD_WriteRegister(0x000d,0x0000);		//Frame Marker Position
		LCD_WriteRegister(0x000f,0x0000);		//RGB Display Interface Control 2

		LCD_WriteRegister(0x0029,0x001E);
		LCD_WriteRegister(0x002b,0x000D);

		LCD_WriteRegister(0x0020,0x0000);		//GRAM Horizontal/Vertical Address Set
		LCD_WriteRegister(0x0021,0x0000);		//GRAM Horizontal/Vertical Address Set
		//LCD_WriteRegister(0x0022,0x0000);		//Write Data to GRAM S.68

		LCD_WriteRegister(0x0050,0);//GRAM horizontal start position
		LCD_WriteRegister(0x0051,239);//GRAM horizontal end position
		LCD_WriteRegister(0x0052,0);//Vertical GRAM Start position
		LCD_WriteRegister(0x0053,319);//Vertical GRAM end position

		LCD_WriteRegister(0x0060,0xa700);
		LCD_WriteRegister(0x0061,0x0001);
		LCD_WriteRegister(0x006a,0x0000);

		LCD_LED_H();
	} else if(LCD_DeviceCode==0x9919) {
		//
	} else if(LCD_DeviceCode==0x4531) {
		//
	} else if(LCD_DeviceCode==0x7783) {
		//
	}
  LCD_Delay_long;

  LCD_Clear(LCD_Black);LCD_Clear(LCD_Black);
  #ifdef LCD_DrawTest
  LCD_Test();
  #endif
}
void LCD_Clear(u16 bkColor) {
	u32  i;

	LCD_SetWindows(0, 0, 239, 319);
	LCD_CS_L(); LCD_Delay_short;
	LCD_WriteIndex(0x0022);
	LCD_RS_H(); LCD_Delay_short;
	LCD_WriteData(bkColor);
	LCD_Delay_short;
	for(i=0;i<76800;i++) {
		LCD_WR_Takt;
	}
//	LCD_CS_H();
}
void LCD_SetOrientation(u8 m) {
	u16 em;

	switch (m) {
	case 1: em = 0x1030; break;
	case 2: em = 0x1010; break;
	case 3: em = 0x1018; break;
	case 4: em = 0x1008; break;
	default: em = 0x0130; break;
	}
	LCD_WriteRegister(0x0003, em);  /* Entry Mode */
	LCD_SetCursor(0x00, 0x00);
}
__inline void LCD_WriteRAM_Prepare(void) {
	LCD_CS_L(); LCD_RD_H();
	LCD_RS_L(); LCD_Delay_short;
	LCD_WriteData(0x0022); /* Select GRAM Reg */
	LCD_WR_Takt;
	LCD_RS_H(); LCD_Delay_short;
}
__inline void LCD_SetCursor(u16 x,u16 y) {
	LCD_WriteRegister(0x0020,y);
	LCD_WriteRegister(0x0021,319-x);
}
__inline void LCD_SetWindows(u16 StartX,u16 StartY,u16 EndX,u16 EndY) {
	LCD_WriteRegister(0x0050, StartX); LCD_WriteRegister(0x0051, EndX);
	LCD_WriteRegister(0x0052, StartY); LCD_WriteRegister(0x0053, EndY);
}

__inline void LCD_WriteIndex(u16 idx) {
    LCD_CS_L();
	LCD_RD_H();
	LCD_RS_L(); LCD_Delay_short;
	LCD_WriteData(idx);
	LCD_WR_Takt;
	LCD_RS_H(); LCD_Delay_short;
}
void LCD_WriteData(u16 data) {

	#ifdef Use_LCD_8Bit_Latch
	LCD_DataPort_8to15->ODR=(LCD_DataPort_8to15->ODR&0x00ff)|((data<<8)&0xff00);
	LCD_Leatch_grab;
	LCD_DataPort_8to15->ODR=(LCD_DataPort_8to15->ODR&0x00ff)|((data)&0xff00);
	#endif
	#ifdef Use_LCD_8Bit_Direct
	LCD_DataPort_8to15->ODR=(LCD_DataPort_8to15->ODR&0x00ff)|((data)&0xff00);
	LCD_Leatch_grab;
	LCD_DataPort_8to15->ODR=(LCD_DataPort_8to15->ODR&0x00ff)|((data<<8)&0xff00);
	#endif
	#ifdef Use_LCD_16Bit
	LCD_DataPort_0to7->ODR=(LCD_DataPort_0to7->ODR&0xff00)|((data)&0x00ff);
	LCD_DataPort_8to15->ODR=(LCD_DataPort_8to15->ODR&0x00ff)|((data)&0xff00);
	#endif
}
void LCD_WriteRegister(u16 index,u16 dat) {
 /************************************************************************
  ** nCS       ----\__________________________________________/-------  **
  ** RS        ------\____________/-----------------------------------  **
  ** nRD       -------------------------------------------------------  **
  ** nWR       --------\_______/--------\_____/-----------------------  **
  ** DB[0:15]  ---------[index]----------[data]-----------------------  **
  ************************************************************************/
    LCD_CS_L();
	LCD_RS_L(); LCD_Delay_short;
	LCD_RD_H(); LCD_Delay_short;
	LCD_WriteData(index);
	LCD_WR_Takt;
	LCD_RS_H(); LCD_Delay_short;
	LCD_WriteData(dat);
	LCD_WR_Takt;
	LCD_CS_H();
}

void LCD_WriteRAM(u16 RGB_Code) {
	LCD_WriteData(RGB_Code);
	LCD_WR_Takt;
}
//void LCD_Delay(vu32 nCount) {
//  for(; nCount != 0; nCount--);
//}
void LCD_Test() {
  u8  R_data,G_data,B_data,i,j;

	LCD_SetCursor(0x00, 0x0000);
	LCD_WriteRegister(0x0050,0);//GRAM horizontal start position
	LCD_WriteRegister(0x0051,239);//GRAM horizontal end position
	LCD_WriteRegister(0x0052,0);//Vertical GRAM Start position
	LCD_WriteRegister(0x0053,319);//Vertical GRAM end position
	LCD_CS_L();
	LCD_WriteIndex(0x0022);
	LCD_RS_H();LCD_RS_H();
    R_data=0;G_data=0;B_data=0;
    for(j=0;j<50;j++)//red crescendo Article
    {
        for(i=0;i<240;i++)
            {R_data=i/8;LCD_WriteData(R_data<<11|G_data<<5|B_data);
			LCD_WR_L();LCD_WR_H();}
    }
    R_data=0x1f;G_data=0x3f;B_data=0x1f;
    for(j=0;j<50;j++)
    {
        for(i=0;i<240;i++)
            {
            G_data=0x3f-(i/4);
            B_data=0x1f-(i/8);
            LCD_WriteData(R_data<<11|G_data<<5|B_data);
			LCD_WR_L();
			LCD_WR_H();
			}
    }
//----------------------------------
    R_data=0;G_data=0;B_data=0;
    for(j=0;j<50;j++)//green crescendo Article
    {
        for(i=0;i<240;i++)
            {G_data=i/4;
			LCD_WriteData(R_data<<11|G_data<<5|B_data);
			LCD_WR_L();
			LCD_WR_H();}
    }

    R_data=0x1f;G_data=0x3f;B_data=0x1f;
    for(j=0;j<50;j++)
    {
        for(i=0;i<240;i++)
            {
            R_data=0x1f-(i/8);
            B_data=0x1f-(i/8);
            LCD_WriteData(R_data<<11|G_data<<5|B_data);
			LCD_WR_L();
			LCD_WR_H();
		}
    }
//----------------------------------

    R_data=0;G_data=0;B_data=0;
    for(j=0;j<60;j++)//blue crescendo Article
    {
        for(i=0;i<240;i++)
            {B_data=i/8;LCD_WriteData(R_data<<11|G_data<<5|B_data);
			LCD_WR_L();
			LCD_WR_H();}
    }

    B_data=0;
    R_data=0x1f;G_data=0x3f;B_data=0x1f;

    for(j=0;j<60;j++)
    {
        for(i=0;i<240;i++)
            {
            G_data=0x3f-(i/4);
            R_data=0x1f-(i/8);
            LCD_WriteData(R_data<<11|G_data<<5|B_data);
			LCD_WR_L();
			LCD_WR_H();
		}
    }
	LCD_CS_H();
}
u16 LCD_BGR2RGB(u16 c) {
	u16  r, g, b, rgb;
	b = (c>>0)  & 0x1f;
	g = (c>>5)  & 0x3f;
	r = (c>>11) & 0x1f;
	rgb =  (b<<11) + (g<<5) + (r<<0);
	return( rgb );
}
u16 LCD_RGB2Pixel565(u8 r, u8 g, u8 b) {
	/* RGB2PIXEL565 from a Macro in Greg Haerr's Nano-X, MPL license */
	return ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3));
}
void BattVolt(float Value, char* Buffer) {
	int vorkomma=0;
	int nachkomma=0;
	u8 index=0;
	vorkomma = Value;
	nachkomma = (Value*10)-(vorkomma*10);

    Buffer[index++]=' ';
	itoa(vorkomma, &Buffer[index++], 10);
	Buffer[index++]='.';
	itoa(nachkomma, &Buffer[index++], 10);
	Buffer[index++]=' ';
	Buffer[index++]='V';
	Buffer[index++]=' ';
	Buffer[index++]='\0';
}

