//-------------------------------------------------------------------------------------------------
// Universal KS0108 driver library
// (c) Radosław Kwiecień, radek@dxp.pl
//-------------------------------------------------------------------------------------------------

#include "font5x8.h"
#include "font7x12.h"
#include "font10x16.h"
#include "font11x16.h"
#include "KS0108.h"
#include "KS0108-PIC16.h"
//-------------------------------------------------------------------------------------------------
extern void GLCD_InitalizePorts(void);
//-------------------------------------------------------------------------------------------------
unsigned char screen_x = 0, screen_y = 0;
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_Initalize(void)
{
unsigned char i;
GLCD_InitializePorts();
for(i = 0; i < 2; i++)
  GLCD_WriteCommand((DISPLAY_ON_CMD | DISPLAY_ON), i);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_GoTo(unsigned char x, unsigned char y)
{
unsigned char i;
screen_x = x;
screen_y = y;

for(i = 0; i < KS0108_SCREEN_WIDTH/64; i++)
  {
  GLCD_WriteCommand(DISPLAY_SET_Y | 0,i);
  GLCD_WriteCommand(DISPLAY_SET_X | y,i);
  GLCD_WriteCommand(DISPLAY_START_LINE | 0,i);
  }
GLCD_WriteCommand(DISPLAY_SET_Y | (x % 64), (x / 64));
GLCD_WriteCommand(DISPLAY_SET_X | y, (x / 64));
}



//-------------------------------------------------------------------------------------------------
// Expects X2 >= x1 and y2 >= y1
//-------------------------------------------------------------------------------------------------
void GLCD_ClearRegion_buff(unsigned char * buf, unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2)
{
unsigned char i, j, k, background;

/* trap erroneous input*/
if ((x2 >= x1) && (y2 >= y1))
    {
    /* How many rows of bytes?*/
    k = y2 - y1;
    /* start with first row of bytes on display in Y dimension */
    j = y1/8;

    /* we have either zero or up to 7 pixels to update on the first row*/
    if ((k%8) > 0)
        {
        for(i = x1; i < x2; i++)
            {
                background = *(char *)( (int)buf + j * KS0108_SCREEN_WIDTH + i);
                * (char *)( (int)buf + j * KS0108_SCREEN_WIDTH + i)= background & (0xFF-((0x01 >> k) -1));
            }
        j++;
        k = k - k%8;
        }

    while (k>=8)
        {
        for(i = x1; i < x2; i++)
            * (char *)( (int)buf + j * KS0108_SCREEN_WIDTH + i)=(0x00);
        j++; /* increment y rows */
        k -= 8; /* decrement k  - if I wasnt lazy these would use one variable*/
        }
    
    /* we have either zero or up to 7 pixels to update now*/
    if (k >0)
        {
        for(i = x1; i < x2; i++)
            {
                background = *(char *)( (int)buf + j * KS0108_SCREEN_WIDTH + i);
                * (char *)( (int)buf + j * KS0108_SCREEN_WIDTH + i)= background & ((0x01 >> k) -1);
            }
        }
    }
}



//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_ClearScreen_buff(unsigned char * buf)
{
unsigned char i, j;
for(j = 0; j < KS0108_SCREEN_HEIGHT/8; j++)
  {
  for(i = 0; i < KS0108_SCREEN_WIDTH; i++)
    * (char *)( (int)buf + j * KS0108_SCREEN_WIDTH + i)=(0x00);
  }
}

//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_ClearScreen(void)
{
unsigned char i, j;
for(j = 0; j < KS0108_SCREEN_HEIGHT/8; j++)
  {
  GLCD_GoTo(0,j);
  for(i = 0; i < KS0108_SCREEN_WIDTH; i++)
    GLCD_WriteData(0x00);
  }
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar(char charToWrite)
{
int i;
charToWrite -= 32; 
for(i = 0; i < 5; i++) 
  GLCD_WriteData(GLCD_ReadByteFromROMMemory((char *)((int)font5x8 + (5 * charToWrite) + i))); 
GLCD_WriteData(0x00);
}



//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar_12x7(unsigned char charToWrite, unsigned char x, unsigned char y)
{
int i, j, tc;
charToWrite -= 32;

// go to start location
GLCD_GoTo(x, (y/8));
for(i = 0; i < 7; i++)
{
    if((x + 1) < KS0108_SCREEN_WIDTH)
      GLCD_WriteData(GLCD_ReadByteFromROMMemory((char *)((int)font7x12 + (14 * (int)charToWrite) + i)));
}
if((x + 8) < KS0108_SCREEN_WIDTH)
    GLCD_WriteData(0x00);

// Now for the next line
GLCD_GoTo(x, ((y/8)+1));
for(i = 0; i < 7; i++)
    {
        tc = GLCD_ReadByteFromROMMemory((char *)((int)font7x12 + (14 * (int)charToWrite) + 7 + i));
        for (j = 0; j < 4; j++)
        {
            if (tc & (1<<j))
            {
                if((x + i) < KS0108_SCREEN_WIDTH)
                    GLCD_SetPixel(x + i, y + 8 + j, 1);
            }
            else
                if((x + i) < KS0108_SCREEN_WIDTH)
                {
                    GLCD_ClearPixel(x + i, y + 8 + j, 1);
                }
        }
    }
    if((x + 8) < KS0108_SCREEN_WIDTH)
        for (j = 0; j < 4; j++)
            GLCD_ClearPixel(x + 8, y + 8 + j, 1);
}



//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar_8x5_buf(unsigned char * buf, unsigned char charToWrite, unsigned char x, unsigned char y)
{
int i, j, tc, y_rem,loop, y_mask, y_temp, work_c;
// fix offset of ASCII characters to the internal character set
charToWrite -= 32;
loop = 0;

// Work out how many unused bits are at the top of the character
y_rem = y%8; 
y_mask = 0xff>>(8-y_rem);

if((y + 8) <= KS0108_SCREEN_HEIGHT)
    {
    //for a 5 pixel wide char...
    for(i = 0; i < 5; i++)
    {
        if((x + 5) < KS0108_SCREEN_WIDTH)
        { 
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i);
            tc = tc & y_mask;
            work_c = *(char *)((int)font5x8 + (5 * (int)charToWrite) + (int)i);
            work_c = work_c <<y_rem;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i) = work_c;
        }
    }
    if((x + 5) < KS0108_SCREEN_WIDTH)
    {
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)5);
            tc = tc & (y_mask);
            work_c = 0x00;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)5) = work_c;
    }


    // Work out how many unused bits are at the top of the character
    y_temp = 8  - (8-y_rem);

    do
    {
        if (y_temp >= 8)
            y_mask = 0;
        else
            y_mask = 0xff<<(y_temp);

        //for a 5 pixel wide char...
        for(i = 0; i < 5; i++)
        {
            if((x + 5) < KS0108_SCREEN_WIDTH)
            { 
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i);
                tc = tc & y_mask;
                work_c = (*(char *)((int)font5x8 + (5 * (int)charToWrite) + 5*loop + (int)i));
                work_c = work_c >> (8-y_rem);
                work_c = work_c & (0xff >> (8-y_rem));
                work_c += tc;
    //            if (loop == 0)
    //                work_c += (*(char *)((int)font5x8 + (5 * (int)charToWrite) + 5 + (int)i)) << y_rem;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i) = work_c;
            }
        }
        if((x + 5) < KS0108_SCREEN_WIDTH)
        {
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)5);
                tc = tc & (y_mask);
                work_c = 0;
                work_c = work_c + tc;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)5) = work_c;
        }
        y_temp -= 8;
        //increment the row
        loop++;
    }while (y_temp >=0);
}
}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar_12x7_buf(unsigned char * buf, unsigned char charToWrite, unsigned char x, unsigned char y)
{
int i, j, tc, y_rem,loop, y_mask, y_temp, work_c;
// fix offset of ASCII characters to the internal character set
charToWrite -= 32;
loop = 0;

// Work out how many unused bits are at the top of the character
y_rem = y%8; 
y_mask = 0xff>>(8-y_rem);


if((y + 12) <= KS0108_SCREEN_HEIGHT)
    {

    //for a 7 pixel wide char...
    for(i = 0; i < 7; i++)
    {
        if((x + 6) < KS0108_SCREEN_WIDTH)
        { 
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i);
            tc = tc & y_mask;
            work_c = *(char *)((int)font7x12 + (14 * (int)charToWrite) + (int)i);
            work_c = work_c <<y_rem;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i) = work_c;
        }
    }
    if((x + 7) < KS0108_SCREEN_WIDTH)
    {
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)7);
            tc = tc & (y_mask);
            work_c = 0x00;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)7) = work_c;
    }

    // Work out how many unused bits are at the top of the character
    y_temp = 12  - (8-y_rem);

    do
    {
        if (y_temp >= 8)
            y_mask = 0;
        else
            y_mask = 0xff<<(y_temp);

        //for a 7 pixel wide char...
        for(i = 0; i < 7; i++)
        {
            if((x + 6) < KS0108_SCREEN_WIDTH)
            { 
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i);
                tc = tc & y_mask;
                work_c = (*(char *)((int)font7x12 + (14 * (int)charToWrite) + 7*loop + (int)i));
                work_c = work_c >> (8-y_rem);
                work_c = work_c & (0xff >> (8-y_rem));
                work_c += tc;
                if (loop == 0)
                    work_c += (*(char *)((int)font7x12 + (14 * (int)charToWrite) + 7 + (int)i)) << y_rem;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i) = work_c;
            }
        }
        if((x + 7) < KS0108_SCREEN_WIDTH)
        {
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)7);
                tc = tc & (y_mask);
                work_c = 0;
                work_c = work_c + tc;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)7) = work_c;
        }


        y_temp -= 8;
        //increment the row
        loop++;
    }while (y_temp >=0);
}
}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar_16x11_buf(unsigned char * buf, unsigned char charToWrite, unsigned char x, unsigned char y)
{
int i, j, tc, y_rem,loop, y_mask, y_temp, work_c;
// fix offset of ASCII characters to the internal character set
charToWrite -= 32;
loop = 0;

// Work out how many unused bits are at the top of the character
y_rem = y%8; 
y_mask = 0xff>>(8-y_rem);

if((y + 16) <= KS0108_SCREEN_HEIGHT)
    {

    //for a 7 pixel wide char...
    for(i = 0; i < 11; i++)
    {
        if((x + 11) < KS0108_SCREEN_WIDTH)
        { 
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i);
            tc = tc & y_mask;
            work_c = *(char *)((int)font11x16 + (22 * (int)charToWrite) + (int)i);
            work_c = work_c <<y_rem;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i) = work_c;
        }
    }
    if((x + 11) < KS0108_SCREEN_WIDTH)
    {
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)11);
            tc = tc & (y_mask);
            work_c = 0x00;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)11) = work_c;
    }

    // Work out how many unused bits are at the top of the character
    y_temp = 16  - (8-y_rem);

    do
    {
        if (y_temp >= 8)
            y_mask = 0;
        else
            y_mask = 0xff<<(y_temp);

        //for a 11 pixel wide char...
        for(i = 0; i < 11; i++)
        {
            if((x + 11) < KS0108_SCREEN_WIDTH)
            { 
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i);
                tc = tc & y_mask;
                work_c = (*(char *)((int)font11x16 + (22 * (int)charToWrite) + 11*loop + (int)i));
                work_c = work_c >> (8-y_rem);
                work_c = work_c & (0xff >> (8-y_rem));
                work_c += tc;
                if (loop == 0)
                    work_c += (*(char *)((int)font11x16 + (22 * (int)charToWrite) + 11 + (int)i)) << y_rem;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i) = work_c;
            }
        }
        if((x + 11) < KS0108_SCREEN_WIDTH)
        {
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)11);
                tc = tc & (y_mask);
                work_c = 0;
                work_c = work_c + tc;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)11) = work_c;
        }
        y_temp -= 8;
        //increment the row
        loop++;
    }while (y_temp >=0);
    }
}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar_16x10_buf(unsigned char * buf, unsigned char charToWrite, unsigned char x, unsigned char y)
{
int i, j, tc, y_rem,loop, y_mask, y_temp, work_c;
// fix offset of ASCII characters to the internal character set
charToWrite -= 32;
loop = 0;

// Work out how many unused bits are at the top of the character
y_rem = y%8; 
y_mask = 0xff>>(8-y_rem);

if((y + 10) <= KS0108_SCREEN_HEIGHT)
    {
    //for a 7 pixel wide char...
    for(i = 0; i < 10; i++)
    {
        if((x + 10) < KS0108_SCREEN_WIDTH)
        { 
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i);
            tc = tc & y_mask;
            work_c = *(char *)((int)font10x16 + (20 * (int)charToWrite) + (int)i);
            work_c = work_c <<y_rem;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)i) = work_c;
        }
    }
    if((x + 11) < KS0108_SCREEN_WIDTH)
    {
            // get a copy of what is in there
            tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)10);
            tc = tc & (y_mask);
            work_c = 0x00;
            work_c += tc;
            *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)(y/8)) + (int)x + (int)10) = work_c;
    }

    // Work out how many unused bits are at the top of the character
    y_temp = 16  - (8-y_rem);

    do
    {
        if (y_temp >= 8)
            y_mask = 0;
        else
            y_mask = 0xff<<(y_temp);

        //for a 11 pixel wide char...
        for(i = 0; i < 10; i++)
        {
            if((x + 10) < KS0108_SCREEN_WIDTH)
            { 
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i);
                tc = tc & y_mask;
                work_c = (*(char *)((int)font10x16 + (22 * (int)charToWrite) + 10*loop + (int)i));
                work_c = work_c >> (8-y_rem);
                work_c = work_c & (0xff >> (8-y_rem));
                work_c += tc;
                if (loop == 0)
                    work_c += (*(char *)((int)font10x16 + (20 * (int)charToWrite) + 10 + (int)i)) << y_rem;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)i) = work_c;
            }
        }
        if((x + 10) < KS0108_SCREEN_WIDTH)
        {
                // get a copy of what is in there
                tc = *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)10);
                tc = tc & (y_mask);
                work_c = 0;
                work_c = work_c + tc;
                *(char *)((int)buf + ((int)KS0108_SCREEN_WIDTH * (int)((y/8) + 1 + loop)) + (int)x + (int)10) = work_c;
        }
        y_temp -= 8;
        //increment the row
        loop++;
    }while (y_temp >=0);
}
}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar_16x10(unsigned char charToWrite, unsigned char x, unsigned char y)
{
int i, j, tc;
charToWrite -= 32;

// go to start location
GLCD_GoTo(x, (y/8));
for(i = 0; i < 10; i++)
{
    if((x + 1) < KS0108_SCREEN_WIDTH)
      GLCD_WriteData(GLCD_ReadByteFromROMMemory((char *)((int)font10x16 + (14 * (int)charToWrite) + i)));
}
if((x + 10) < KS0108_SCREEN_WIDTH)
    GLCD_WriteData(0x00);

// Now for the next line
GLCD_GoTo(x, ((y/8)+1));
for(i = 0; i < 10; i++)
{
    if((x + 1) < KS0108_SCREEN_WIDTH)
      GLCD_WriteData(GLCD_ReadByteFromROMMemory((char *)((int)font10x16 + (14 * (int)charToWrite) + i)));
}
if((x + 10) < KS0108_SCREEN_WIDTH)
    GLCD_WriteData(0x00);
}

//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar_16x11(unsigned char charToWrite, unsigned char x, unsigned char y)
{
int i, j, tc;
charToWrite -= 32;

// go to start location
GLCD_GoTo(x, (y/8));
for(i = 0; i < 11; i++)
{
    if((x + 1) < KS0108_SCREEN_WIDTH)
      GLCD_WriteData(GLCD_ReadByteFromROMMemory((char *)((int)font11x16 + (14 * (int)charToWrite) + i)));
}
if((x + 11) < KS0108_SCREEN_WIDTH)
    GLCD_WriteData(0x00);

// Now for the next line
GLCD_GoTo(x, ((y/8)+1));
for(i = 0; i < 11; i++)
{
    if((x + 1) < KS0108_SCREEN_WIDTH)
      GLCD_WriteData(GLCD_ReadByteFromROMMemory((char *)((int)font11x16 + (14 * (int)charToWrite) + i)));
}
if((x + 11) < KS0108_SCREEN_WIDTH)
    GLCD_WriteData(0x00);

}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteString_16x11_buf(unsigned char * buf, char * stringToWrite, unsigned char x, unsigned char y)
{
char tmp;

tmp = 0;
while(*stringToWrite)
    {
        GLCD_WriteChar_16x11_buf(buf, *stringToWrite++,x + tmp,y);
        tmp += 12;
    }
}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteString_16x10_buf(unsigned char * buf, char * stringToWrite, unsigned char x, unsigned char y)
{
char tmp;

tmp = 0;
while(*stringToWrite)
    {
        GLCD_WriteChar_16x11_buf(buf, *stringToWrite++,x + tmp,y);
        tmp += 12;
    }
}



//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteString_12x7_buf(unsigned char * buf, char * stringToWrite, unsigned char x, unsigned char y)
{
char tmp;

tmp = 0;
while(*stringToWrite)
    {
        GLCD_WriteChar_12x7_buf(buf, *stringToWrite++,x + tmp,y);
        tmp += 8;
    }
}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteString_8x5_buf(unsigned char * buf, char * stringToWrite, unsigned char x, unsigned char y)
{
char tmp;

tmp = 0;
while(*stringToWrite)
    {
        GLCD_WriteChar_8x5_buf(buf, *stringToWrite++,x + tmp,y);
        tmp += 6;
    }
}

//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteString(char * stringToWrite)
{
while(*stringToWrite)
  GLCD_WriteChar(*stringToWrite++);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_SetPixel(unsigned char x, unsigned char y, unsigned char color)
{
unsigned char tmp;
GLCD_GoTo(x, (y / 8));
tmp = GLCD_ReadData();
GLCD_GoTo(x, (y / 8));
tmp = GLCD_ReadData();
GLCD_GoTo(x, (y / 8));
tmp |= (1 << (y % 8));
GLCD_WriteData(tmp);
}

//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_SetPixelBuf(unsigned char * buf, unsigned char x, unsigned char y, unsigned char color)
{
unsigned char temp_buf, ydiv;

    temp_buf = *(buf + (x + ((y/8) * KS0108_SCREEN_WIDTH)));
    ydiv = y%8;
    temp_buf = temp_buf | 1<<ydiv;
    *(buf + (x + ((y/8) * KS0108_SCREEN_WIDTH))) = temp_buf;
}


//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_DrawLineBuf(unsigned char * buf, unsigned char Start_x, unsigned char Start_y, unsigned char End_x, unsigned char End_y, unsigned char color)
{
unsigned char temp_buf, ydiv, tempx, tempy;
int dx, dy;
float Delta_Err, Current_Err;

        /* Sort out start and end point such that End_X > StartX*/
    if (End_x < Start_x)
    {
        tempx = End_x;
        tempy = End_y;
        End_x = Start_x;         
        End_y = Start_y;
        Start_x = tempx;
        Start_y = tempy;
    }

    /* Work out line parameters */
    dx = End_x - Start_x;
    dy = End_y - Start_y;
    /* provided the line is not vertical*/
    if(dx)
        Delta_Err = (float)dy/ (float)dx;
    /* ser error counter to xero for first pixel and tempx and y to start pixel*/
    Current_Err = 0;
    tempy = Start_y;
    tempx = Start_x;

    if(dx && (abs(Delta_Err) <= 0.5))
    {
        for(tempx = Start_x; tempx <= End_x; tempx++)
        {
            /* Set the pixel */
            GLCD_SetPixelBuf(buf, tempx, tempy, 0);
            /* increment the y error per pixel, and if necessary step y */
            Current_Err += Delta_Err;
            if (Current_Err > 0.5)
            {
                tempy += 1;
                Current_Err -= 1;
            }
            else if (Current_Err < -0.5)
            {
                tempy -= 1;
                Current_Err += 1;
            }
        }
    }
    else if(dx && (abs(Delta_Err) > 0.5))
    {
        /* If the end is after the start, then flip delta error to other axes*/
        if (End_y < Start_y)
        {
            tempx = End_x;
            tempy = End_y;
            End_x = Start_x;         
            End_y = Start_y;
            Start_x = tempx;
            Start_y = tempy;
        }
        dx = End_x - Start_x;
        dy = End_y - Start_y;

        /* then flip delta error to other axes*/
        Delta_Err = (float)dx/ (float)dy;
        for(tempy = Start_y; tempy < End_y; tempy++)
        {
            /* Set the pixel */
            GLCD_SetPixelBuf(buf, tempx, tempy, 0);
            /* increment the y error per pixel, and if necessary step y */
            Current_Err += Delta_Err;
            if (Current_Err > 0.5)
            {
                tempx += 1;
                Current_Err -= 1;
            }
            else if (Current_Err < -0.5)
            {
                tempx -= 1;
                Current_Err += 1;
            }
        }
    }
    /* deal with vertical line */
    else if (!dx)
    {
        /* swap pooints so y goes upwards from start to finish*/
        if (End_y < Start_y)
        {
            tempx = End_x;
            tempy = End_y;
            End_x = Start_x;         
            End_y = Start_y;
            Start_x = tempx;
            Start_y = tempy;
        }
        
        for(tempy = Start_y; tempy < End_y; tempy++)
        {
            /* Set the pixel */
            GLCD_SetPixelBuf(buf, tempx, tempy, 0);
        }
    }
}



//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_ClearPixel(unsigned char x, unsigned char y, unsigned char color)
{
unsigned char tmp;
GLCD_GoTo(x, (y / 8));
tmp = GLCD_ReadData();
GLCD_GoTo(x, (y / 8));
tmp = GLCD_ReadData();
GLCD_GoTo(x, (y / 8));
tmp &= 0xff-(1 << (y % 8));
GLCD_WriteData(tmp);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_Bitmap(char * bmp, unsigned char x, unsigned char y, unsigned char dx, unsigned char dy)
{
unsigned char i, j;
for(j = 0; j < dy / 8; j++)
  {
  GLCD_GoTo(x,y + j);
  for(i = 0; i < dx; i++) 
    GLCD_WriteData(GLCD_ReadByteFromROMMemory(bmp++));
  }
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteBuf(char * bmp, unsigned char x, unsigned char y, unsigned char dx, unsigned char dy)
{
unsigned char i, j;
for(j = 0; j < dy / 8; j++)
  {
  GLCD_GoTo(x,y + j);
  for(i = 0; i < dx; i++) 
    GLCD_WriteData(GLCD_ReadByteFromROMMemory(bmp++));
  }
}

//-------------------------------------------------------------------------------------------------
//
// WriteBMP (*buf, *bmp, x, y, dx, dy)
// *buf is the buffer - target address
// *bmp is the bitmap to be copied
// x - start x address
// y - start x address
// dx - x range
// dy - y range
//-------------------------------------------------------------------------------------------------
void WriteBMP(char * buf, char * bmp,unsigned char x, unsigned char y, unsigned char dx, unsigned char dy)
{
unsigned char i, j;

for(j = 0; j < dy / 8; j++)
  {
     for(i = 0; i < dx; i++) 
         *(buf + (i + j*KS0108_SCREEN_WIDTH)) = (GLCD_ReadByteFromROMMemory(bmp++));
  }
}

//-------------------------------------------------------------------------------------------------
//
// WriteBMP (*buf, *bmp, x, y, dx, dy)
// *buf is the buffer - target address
// *bmp is the bitmap to be copied
// x - start x address
// y - start y address - Must be on an 8 pixel boundary
// dx - x range
// dy - y range - must be a multiple of 8 bits in size
//-------------------------------------------------------------------------------------------------
void WriteBMP_Buf(char * buf, char * bmp,unsigned char x, unsigned char y, unsigned char dx, unsigned char dy)
{
unsigned char i, j, Temp_Byte, Temp_Byte1;

for(j = 0; j < (dy/8); j++)
  {
     for(i = 0; i < (dx); i++) 
        {
        Temp_Byte = *(bmp + (i + (j * dx)));
        *(buf + (x + i + (j + y/8)*KS0108_SCREEN_WIDTH)) = Temp_Byte;
        }
  }
    
}


