/** \file display.c:
 *  Contains MIOS DISPLAY_Tick function of c skeleton, as well as all functions
 *  that realize printing anything on the display. Those functions are only
 *  called upon during DISPLAY_Tick. Display updates are handled through global
 *  variables, that determine which parts of the display have to be updated.
 */

//#include "../../common/mios_glcd_font.xpm"
//#include "../../common/lc_big_font.xpm"
//#include "../../common/mios_glcd_font.h"


/**
 *  FUNCTION WRITEBAR
 *  writes statusbar and numerical value at display "display" corresponding to
 *  knob value "v" at line "line". line corresponds to handled encoder.
 *  depending on "bitmode", "scale" and "sign" of parameter, different display
 *  modes of the value are chosen. if value is a sswitch (textual values instead
 *  of numerical values, sswitchon=1), the textual description of the parameter
 *  value is read from bankstick at "switch_addr" and printed on display.
 *  \param display display which is being adressed
 *	\param line vertical write position, corresponds to handled encoder (0-7)
 *  \param v determines how big the bar will be, and what number (or text) is being written
 *  \param bitmode passes bitmode (7/14 bit) of written parameter
 *  \param scale passes scalefactor of written parameter
 *  \param sign passes sign of written parameter
 *	\param sswitchon determines if parameter is textual switch
 *  \param sswitch_addr passes memory adress of textual value descriptions in dynamic memory
 */
void writeBar(unsigned char number) {
	unsigned long x,i;
	unsigned char printBuff[6];

	unsigned char display;
	unsigned char line;
	int v;
	unsigned char bitmode;
	int scale;
	unsigned char sign;
	unsigned int min,max;
	unsigned char sswitchon;
	unsigned int sswitch_addr;

	display=number>7?1:0;
	line=number%8*3+4;

	//determine function parameters for writeBar out of the parameters struct
	bitmode=number>7?((parametersright[number%8].modeSelect)&0x02)>>1:((parametersleft[number].modeSelect)&0x02)>>1;
	sswitchon=number>7?(((parametersright[number%8].edit)&0x2000)>>13):(((parametersleft[number].edit)&0x2000)>>13);
	sswitch_addr=number>7?(parametersright[number%8].sswitch_addr):(parametersleft[number].sswitch_addr);
	scale=number>7?(parametersright[number%8].scale):(parametersleft[number].scale);
	sign=number>7?((parametersright[number%8].modeSelect)&0x01):((parametersleft[number].modeSelect)&0x01);

	v= potis[number];


	if(bitmode==0) {										//7Bit
		min=number>7?(parametersright[number%8].valueMin[0]):(parametersleft[number].valueMin[0]);
		setCursor(display,line%2*54,line);					//on the right for every 2nd line
		if (v==0)
			printChar(display,' ');							//no bar when value==0
		else printChar(display,(char)(v)/16);


		if (sswitchon==1) {									//Text-Switches used?
			setCursor(display,line%2*12+6,line);
			x=BASE_DYNMEM+DYNBLOCK_LENGTH*device+(unsigned long)(sswitch_addr);
			for (i=0;i<6;i++)
				//printBuff[i]=readBank(x+i+(((v&0x7F)/(scale==0?stepwidth:scale))*6));
				printBuff[i]=readBank(x+i+(scale==0? ((v&0x7F)*stepwidth/0x7F):(v&0x7F/scale)) *6);
			for (i=0;i<6;i++)
				printChar(display, printBuff[i]);
		}

		else {
			setCursor(display,line%2*30+6,line);
			if (sign==1) {									//negative minimum
				if((v-64)&0x8000) {							//negative value
					printChar(display,'-');
					//printBCD2(display, (~((v&0x7F)-65))/(scale==0?stepwidth:scale));
					printBCD2(display, scale==0?(min+(~((v&0x7F)-65)*stepwidth/0x7F)):(~((v&0x7F)-65)));
				}
				else {										//positive value
					printChar(display,' ');
					//printBCD2(display, ((v&0x7F)-64)/(scale==0?stepwidth:scale));
					printBCD2(display, scale==0?(min+(((v&0x7F)-64)*stepwidth/0x7F)):(v&0x7F)-64);
				}
			}
			else
			if (sign==0) {									//positive minimum
//				printBCD3(display, min+((v&0x7F)/scale==0?stepwidth:scale));
				printBCD3(display, scale==0?(min+((v&0x7F)*stepwidth/0x7F)):(v&0x7F));
			}
		}
	}

	else
	if(bitmode==1) {										//14Bit
		min=number>7?(parametersright[number%8].valueMin[0]<<7|parametersright[number%8].valueMin[1]):(parametersleft[number].valueMin[0]<<7|parametersleft[number].valueMin[1]);

		setCursor(display,line%2*54,line);					//on the right for every 2nd line
		if (v==0)
			printChar(display,' ');							//no bar when value==0
			else printChar(display,v/2048);

		if (sswitchon==1) {									//Text-Switches used?
			setCursor(display,line%2*12+6,line);
			x=BASE_DYNMEM+DYNBLOCK_LENGTH*device+(unsigned long)(sswitch_addr);
			for (i=0;i<6;i++)
				//printBuff[i]=readBank(x+i+((v/(scale==0?stepwidth:scale))*6));
				printBuff[i]=readBank(x+i+((scale==0?(v*stepwidth/0x3FFF):(v/scale))*6));

			for (i=0;i<6;i++)
				printChar(display, printBuff[i]);
		}

		else {
			setCursor(display,line%2*18+6,line);
			if (sign==1) {									//negative minimum
						if((v-8192)&0x8000) {				//negative value
							printChar(display,'-');
							//printBCD4(display, (~(v-8193))/(scale==0?stepwidth:scale));
							printBCD4(display, scale==0?(min+(~((v)-8193)*stepwidth/0x3FFF)):(~((v)-8193)));

						}
						else {								//positive value
							printChar(display,' ');
							//printBCD4(display, (v-8192)/(scale==0?stepwidth:scale));
							printBCD4(display, scale==0?(min+(((v)-8192)*stepwidth/0x3FFF)):(v)-8192);

						}
					}
					else
					if (sign==0) {							//positive minimum
						//printBCD5(display, min+((v)/scale==0?stepwidth:scale));
						printBCD5(display, scale==0?(min+((v)*stepwidth/0x3FFF)):(v));
			}
		}
	}
}



/**
 *  FUNCTION DISPLAYDEVICE
 *  writes some static lines plus values which are stored in bankstick
 */
void displayDevice()  {
	unsigned char buff,line;
	unsigned long disp,addr;
	disp=BASE;
	//clear both displays and print header-lines
	clearLCD(0);
	setCursor(0,12,0);
	printString(0,"MIDIbox");
	setCursor(0,2,28);
	printString(0,"University");
	setCursor(0,12,29);
	printString(0,"Ilmenau");
	//display 1
	clearLCD(1);
	setCursor(1,19,0);
	printString(1,"GLCD");
	setCursor(1,1,28);
	printString(1,"TU-Ilmenau");
	setCursor(1,21,29);
	printString(1,".de");
	//display1
	//writes values which are stored in the static memory of the bankstick from
	//the location of the "device"-structs
	for(line=0;line<8;line++) {
		setCursor(1,0, line*3+3);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+(long)line*DEVICE_MENU_ENTRY+176+disp);
			printChar(1,buff);
		}
		setCursor(1,0, line*3+4);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+(long)line*DEVICE_MENU_ENTRY+186+disp);
			printChar(1,buff);
		}
		setCursor(0,0, line*3+3);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+((long)line)*DEVICE_MENU_ENTRY+disp);
			printChar(0,buff);
		}
		setCursor(0,0, line*3+4);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+((long)line)*DEVICE_MENU_ENTRY+10+disp);
			printChar(0,buff);
		}
	}
	//display 0
	//writes values which are stored in the static memory of the bankstick from
	//the location of the "device"-structs
}

void displayModul() {
	unsigned char buff,addr,line;
	char begin,end;
	unsigned int disp;
	disp=BASE+DEVICE_MENU_LENGTH+16*MODUL_MENU_ENTRY*bank+64*MODUL_MENU_ENTRY*device;
	//clear both displays and print header-lines
	clearLCD(1);
	setCursor(1,13,0);
	printString(1,"BANK ");
	printBCD1(1,2);
	setCursor(1,12,29);
	printString(1,"BANK ");
	printBCD1(1,4);
	setCursor(1,0,28);
	begin=0;end=10;
	for(addr=0;addr<10;addr++)	{
		buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE+10);
		if(!begin && buff!=' ')
			begin=addr;
		if(begin && buff!=' ')
			end=addr+1;
	}
	if ((end-begin)%2)
		end+=1;
	for(addr=0;addr<10;addr++)	{
		if(addr<(10-end+begin)/2 || addr>9-(10-end+begin)/2)
			buff=' ';
		else
			buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE+10-((10-end+begin)/2)*(begin>(10-end)?-1:1));
		printChar(1,buff);
	}
	clearLCD(0);
	setCursor(0,13,0);
	printString(0,"BANK ");
	printBCD1(0,1);
	setCursor(0,12,29);
	printString(0,"BANK ");
	printBCD1(0,3);
	setCursor(0,0,28);
	begin=0;end=10;
	for(addr=0;addr<10;addr++)	{
		buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE);
		if(!begin && buff!=' ')
			begin=addr;
		if(begin && buff!=' ')
			end=addr+1;
	}
	if ((end-begin)%2)
		end+=1;
	for(addr=0;addr<10;addr++)	{
		if(addr<(10-end+begin)/2 || addr>9-(10-end+begin)/2)
			buff=' ';
		else
			buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE-((10-end+begin)/2)*(begin>(10-end)?-1:1));
		printChar(0,buff);
	}
	//writes values which are stored in bankstick on display1
	for(line=0;line<8;line++) {
		setCursor(1,0, line*3+3);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+line*MODUL_MENU_ENTRY+disp+176);
			printChar(1,buff);
		}
		setCursor(1,0, line*3+4);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+line*MODUL_MENU_ENTRY+disp+186);
			printChar(1,buff);
		}
		setCursor(0,0, line*3+3);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+line*MODUL_MENU_ENTRY+disp);
			printChar(0,buff);
		}
		setCursor(0,0, line*3+4);
		for(addr=0;addr<10;addr++)	{
			buff=readBank(addr+line*MODUL_MENU_ENTRY+disp+10);
			printChar(0,buff);
		}
	}
}

/**
 *  FUNCTION DISPLAYPARAMETER
 *  writes some static lines plus values which are stored in bankstick
 */
void displayParameter() {
	unsigned long i;
	unsigned long addr,line;
	unsigned char buff;
	char begin,end;
	//clear both displays and print header-lines
	clearLCD(1);
	setCursor(1,13,0);
	printString(1,"BANK ");
	printBCD1(1,2);
	setCursor(1,12,29);
	printString(1,"BANK ");
	printBCD1(1,4);
	setCursor(1,0,28);
	begin=0;end=10;
	for(addr=0;addr<10;addr++)	{
		buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE+10);
		if(!begin && buff!=' ')
			begin=addr;
		if(begin && buff!=' ')
			end=addr+1;
	}
	if ((end-begin)%2)
		end+=1;
	for(addr=0;addr<10;addr++)	{
		if(addr<(10-end+begin)/2 || addr>9-(10-end+begin)/2)
			buff=' ';
		else
			buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE+10-((10-end+begin)/2)*(begin>(10-end)?-1:1));
		printChar(1,buff);
	}
	clearLCD(0);
	setCursor(0,13,0);
	printString(0,"BANK ");
	printBCD1(0,1);
	setCursor(0,12,29);
	printString(0,"BANK ");
	printBCD1(0,3);
	setCursor(0,0,28);
	begin=0;end=10;
	for(addr=0;addr<10;addr++)	{
		buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE);
		if(!begin && buff!=' ')
			begin=addr;
		if(begin && buff!=' ')
			end=addr+1;
	}
	if ((end-begin)%2)
		end+=1;
	for(addr=0;addr<10;addr++)	{
		if(addr<(10-end+begin)/2 || addr>9-(10-end+begin)/2)
			buff=' ';
		else
			buff=readBank(addr+(DEVICE_MENU_ENTRY*device)+BASE-((10-end+begin)/2)*(begin>(10-end)?-1:1));
		printChar(0,buff);
	}
	//writes values which are stored in the static memory of the bankstick from
	//the location of the "parameter"-structs on displays 0 and 1
	for(line=0;line<8;line++) {
		setCursor(1,0, line*3+3);
		for(addr=0;addr<10;addr++) {
			buff=parametersright[line].name[addr];
			printChar(1,buff);
		}
		setCursor(0,0, line*3+3);
		for(addr=0;addr<10;addr++) {
			buff=parametersleft[line].name[addr];
			printChar(0,buff);
		}
	}
}


/**
 * This function is called by MIOS when the display content should be
 * initialized. Thats the case during startup and after a temporary message
 * has been printed on the screen
 */
void DISPLAY_Init(void) __wparam
{
}

/**
 *  \brief This function is called in the mainloop when no temporary message is shown
 *  on screen. Print the realtime messages here
 *
 *  Central element is the "update" variable. Only if this is set the display
 *  gets to be updated.
 *  Several states of this variable are possible:
 *  update 0x00: reset of variable, no more updates
 *  update 0x01: refresh of complete screen, for menu change
 *  update 0x02: refresh of values of the parameters
 *  update 0x04: print loading screen
 *  update 0x08: print error screen
 */
void DISPLAY_Tick(void) __wparam
{
	int x;
	unsigned char bitmode;
	int scale;
	unsigned char sign,sswitchon;
	char i;
	unsigned int sswitch_addr;
	//unsigned char line;
	if(update&0x01){
		switch(modus){
			case MOD_DEVICE:
				displayDevice();
				break;
			case MOD_MODUL:
				displayModul();
				break;
			case MOD_PARAMETER:
				displayParameter();
				break;
		}
	}
	if(update&0x02 && modus==MOD_PARAMETER) {
		x=potis[16];
		potis[16]=0;
		for(i=0;i<16;i++)
			if((x>>i)&1) {
				writeBar(i);
			}
	}
	if(update&0x04) {
		clearLCD(0);
		clearLCD(1);
		setCursor(0,17,10);
		printString(0,"Load");
		setCursor(0,17,11);
		printString(0,"Edit");
		setCursor(0,15,12);
		printString(0,"Buffer");
		setCursor(1,17,10);
		printString(1,"Load");
		setCursor(1,17,11);
		printString(1,"Edit");
		setCursor(1,15,12);
		printString(1,"Buffer");
	}
	if(update&0x08) {
		clearLCD(0);
		clearLCD(1);
		setCursor(0,16,10);
		printString(0,"Error");
		setCursor(1,16,10);
		printString(1,"Error");
	}
	if(update&0x10) {
		clearLCD(0);
		clearLCD(1);
		setCursor(0,10,10);
		printString(0,"Receive");
		setCursor(0,18,11);
		printString(0,"User");
		setCursor(0,18,12);
		printString(0,"Data");
		setCursor(1,10,10);
		printString(1,"Receive");
		setCursor(1,18,11);
		printString(1,"User");
		setCursor(1,18,12);
		printString(1,"Data");
	}
	if(update&0x20) {
		clearLCD(0);
		clearLCD(1);
		setCursor(0,17,10);
		printString(0,"Send");
		setCursor(0,17,11);
		printString(0,"Edit");
		setCursor(0,15,12);
		printString(0,"Buffer");
		setCursor(1,17,10);
		printString(1,"Send");
		setCursor(1,17,11);
		printString(1,"Edit");
		setCursor(1,15,12);
		printString(1,"Buffer");
	}

	update=0x00;


	//debugging: show progress of BankInit
	//if(bankinitcount<1080) {
		setCursor(0,0,0);
		//MIOS_LCD_PrintBCD5(bankinitcount);
	//}
}

