#include "h/common.h"
#include "h/lcd16x2.h"
#include "h/spi.h"
#include "h/oled.h"

void sendShiftRegister(BYTE data)
{
    int j;
    for(j=0; j<LCDDELAY; j++)asm("nop");
    WriteSPIWithoutSS(data);
    for(j=0; j<LCDDELAY; j++)asm("nop");
    LCDRS=0;
    for(j=0; j<LCDDELAY; j++)asm("nop");
    LCDRS=1;
    for(j=0; j<LCDDELAY; j++)asm("nop");    
}

void writeLCD(BYTE data, BYTE command)
{
		int i;
		BYTE dataTemp;

	if(jaycarLCD)
	{
	dataTemp=0;
	if(data & 0x80)dataTemp|=0x01;
	if(data & 0x40)dataTemp|=0x02;
	if(data & 0x20)dataTemp|=0x04;
	if(data & 0x10)dataTemp|=0x08;
	if(data & 0x08)dataTemp|=0x10;
	if(data & 0x04)dataTemp|=0x20;
	if(data & 0x02)dataTemp|=0x40;
	if(data & 0x01)dataTemp|=0x80;
	} else dataTemp=data;
    LCDE=0;		
	sendShiftRegister(dataTemp);
	if(command==LCDCOMMAND)LCDRS=0; else LCDRS=1;
	LCDE=1;
	for(i=0; i<LCDDELAY; i++)asm("nop");
	LCDE=0;
	for(i=0; i<2000; i++)asm("nop");	
}

void disaLCD(BYTE cursor, BYTE value)
{
	writeLCD((0x80 | cursor), LCDCOMMAND);
	writeLCD(disFix(value>>4), LCDDATA);
	writeLCD(disFix(value), LCDDATA);
}

int writeStringLCDInternal(char *instr)
{
	int i;
	i=0;
	while((*instr)!='\0')
	{
		writeLCD(*instr, LCDDATA);
		instr++;
		i++;
	}
	return i;
}

void disdecfreeLCD(int num, int digits)
{
	int i;
	char mystring[20];
	i=iitoa(num,mystring,10,0);
	i=i-digits-1;
	(void)writeStringLCDInternal(&mystring[i]);
}

void writeStringLCD(BYTE cursor, char* instr, int padding)
{
	int i;

	writeLCD((0x80 | cursor), LCDCOMMAND);
	i=writeStringLCDInternal(instr);
	while(i<padding)
	{
		writeLCD(' ', LCDDATA);
		i++;
	}
}

/*
void writeScreen(BYTE* inptr)
{
	BYTE i;
	writeLCD(0x80, LCDCOMMAND);
	for(i=0; i<(LCD_SIZE/2); i++)
	{
	writeLCD(*inptr, LCDDATA);
	inptr++;
	}
	writeLCD(0xC0, LCDCOMMAND);
	for(i=0; i<(LCD_SIZE/2); i++)
	{
	writeLCD(*inptr, LCDDATA);
	inptr++;
	}
}

void updateScreen(BYTE *inptr)
{
	if((!standBy)||(BUTTON==0)||((samplingCount & STANDBY_PERIOD)!=0))
	{
		writeScreen(inptr);
	}
}

void updateLCD(void)
{
	// function =  0 then update straight to the LCD screen...
	// function = -1 then update to buffer, then next update will shift left...
	// function = +1 then update to buffer, then next update will shift right... 
	
	int i;
	
	if(lcdTransitionType==0)
	{
		if(lastCall==0)
		{
		updateScreen((BYTE*)&lcdScreen[0]);
		} else
		{
		  for(i=0;i<(LCD_SIZE/2); i++)
		  {	
			updateScreen((BYTE*)&oldlcdScreen[0]);
			if(lastCall==1)
			{
			shiftGeneral(0, 15, lastCall, 2, (BYTE*)&oldlcdScreen[0]);
			oldlcdScreen[15]=lcdScreen[0];
			oldlcdScreen[31]=lcdScreen[16];
			shiftGeneral(0, 15, lastCall, 2, (BYTE*)&lcdScreen[0]);
			} else
			{
			shiftGeneral(0, 15, lastCall, 2, (BYTE*)&oldlcdScreen[0]);
			oldlcdScreen[0]=lcdScreen[15];
			oldlcdScreen[16]=lcdScreen[31];
			shiftGeneral(0, 15, lastCall, 2, (BYTE*)&lcdScreen[0]);
			}
		 	delayMs(SCROLL_DELAY/4);
 		  }
			updateScreen((BYTE*)&oldlcdScreen[0]);
			for(i=0; i<LCD_SIZE; i++)lcdScreen[i]=oldlcdScreen[i];
		}
		lcdTransitionType=0;
		lastCall=0;
	} else
	{
		for(i=0; i<LCD_SIZE; i++)oldlcdScreen[i]=lcdScreen[i];
		lastCall=lcdTransitionType;
		lcdTransitionType=0;
	} 
}

void clearLCD(void)
{
	int i;
	for(i=0; i<LCD_SIZE; i++)
	{
	lcdScreen[i]=' ';
	}
	updateLCD();
}
*/

void initLCD(void)
{
        InitSPI(0x1E);
		LCDE=0;
		LCDRS=1;
		delayMs(160);
        writeLCD(0x38, LCDCOMMAND);
        writeLCD(0x0C, LCDCOMMAND);
		writeLCD(0x06, LCDCOMMAND);
		writeLCD(0x01, LCDCOMMAND); // clear screen
		delayMs(10);
}


int printITOA(unsigned char* buffer, unsigned long xx, int blanking, int decimal, int mode)
{
		// unsigned integers from 0 to 65535
		// blanking=0 implies zero blanking
		// decimal=   number of digits before the decimal to be printed if 0 then do not print a decimal point (blanking stops after the decimal)
		int i, j;
		unsigned long ux;
		char c;
		
		ux=(unsigned long)xx;
		j=NUM_DIGITS+1;
		for(i=NUM_DIGITS; i>=0; i--)
		{
		
		c=(char)(0x30+(0x0F&(ux%10)));
		ux=ux/10;
		if(j==decimal){ *(buffer+j)='.'; j--; }
		*(buffer+j)=c;
		j--;
		}
		*(buffer+NUM_DIGITS+2)='\0';
		j=j+1;
		if(blanking==0)while(((*(buffer+j))==0x30)&&(j<NUM_DIGITS))j++;
		if(mode==0)if((j>0)&&((*(buffer+j))=='.'))j--;
		return j;
}

__attribute__((space(psv)))
double MultiplierF[11]={ 	1.0, 
							10.0, 
							100.0, 
							1000.0, 
							10000.0, 
							100000.0, 
							1000000.0, 
							10000000.0, 
							100000000.0, 
							1000000000.0, 
							10000000000.0 
};

int printFDecimal(unsigned char* buffer, double f, int numdec, int mode)
{
		if(f<0.0)f=-f;
		if(numdec<0)numdec=0; else if(numdec>10)numdec=10;
		f*=MultiplierF[numdec];
		f+=0.5;
		return printITOA(buffer, f, 0, (NUM_DIGITS+1)-numdec, mode);
}

int printFSignedDecimal(unsigned char* buffer, double f, int numdec, int mode)
{
		BYTE k;
		char c;

		if(numdec<0)numdec=0; else if(numdec>6)numdec=6;
		if(f<0){ f=-f; c='-'; } else c='+';
		f*=MultiplierF[numdec];
		f+=0.5;
		k=printITOA(buffer, f, 0, (NUM_DIGITS+1)-numdec, mode);
		k--;
		*(buffer+k)=c;
		return k;
}

void disFUnsignedLCD(BYTE cursor, double f, int numdec, int mode, int padding)
{
	int i;
	unsigned char buffer[NUM_DIGITS+3];

	writeLCD(cursor + 0x80, LCDCOMMAND);
	if(f<0.0)f=-f;
	i=printFDecimal(buffer, f, numdec, mode);
	while(buffer[i]!='\0')
	{
	writeLCD(buffer[i], LCDDATA);
	i++;
	}
}

