/////////////////////////////////////////////////////////////////////////
////                         LC7981.C                                ////
////                                                                 ////
//// This file contains drivers for using a Crystalfontz CFAG16080A with ///
//// an LED backlight. The CFAG16080A is 160 pixles across and 80     ////
//// pixels down. The driver treats the upper left pixel as (0,0).   ////
////                                                                 ////
//// LCD Pin connections:                                            ////
//// (These can be changed as needed in the following defines).      ////
////  * 1: VSS is connected to GND                                   ////
////  * 2: VDD is connected to +5V                                   ////
////  * 3: V0 - LCD operating voltage is connected ..................////
////  * 4: R/S - Data or Instruction is connected to C5              ////
////  * 5: R/W - Read or Write is connected to C6                    ////
////  * 6: Enable is connected to C7                                 ////
////  *7-14: Data Bus 0 to 7 is connected to port d                  ////
////  *15: Chip Select is connected to E0                            ////
////  *16: Reset is connected to E2                            ////
////  *17:  Negative voltage is also connected                                 ////
////  *18:  No Connected
////  *19: Positive voltage for LED backlight is connected to +5V    ////
////  *20: Negavtive voltage for LED backlight is connected .........////
////                                                                 ////
////  glcd_init(mode)                                                ////
////     * Must be called before any other function.                 ////
////       - mode can be ON or OFF to turn the LCD on or off         ////
////                                                                 ////
////  glcd_pixel(x,y,color)                                          ////
////     * Sets the pixel to the given color.                        ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_line(x1,y1,x2,y2,color)                                   ////
////     * Draws a line from the first point to the second point     ////
////       with the given color.                                     ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_rect(x1,y1,x2,y2,fill,color)                              ////
////     * Draws a rectangle with upper left point (x1,y1) and lower ////
////       right point (x2,y2).                                      ////
////       - fill can be YES or NO                                   ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_bar(x1,y1,x2,y2,width,color)                              ////
////     * Draws a bar (wide line) from the first point to the       ////
////       second point.                                             ////
////       - width is the number of pixels wide                      ////
////       - color is ON or OFF                                      ////
////                                                                 ////
////  glcd_circle(x,y,radius,fill,color)                             ////
////     * Draws a circle with center at (x,y)                       ////
////       - fill can be YES or NO                                   ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_text57(x,y,textptr,size,color)                            ////
////     * Write the null terminated text pointed to by textptr with ////
////       the upper left coordinate of the first character at (x,y).////
////       Characters are 5 pixels wide and 7 pixels tall.           ////
////       - size is an integer that scales the size of the text     ////
////       - color is ON or OFF                                      ////
////     * Note - The given text is character wrapped. If this       ////
////       function is used on a different size display, then change ////
////       the GLCD_WIDTH define appropriately.                      ////
////                                                                 ////
////  glcd_fillScreen(color)                                         ////
////     * Fills the entire LCD with the given color.                ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2003 Custom Computer Services         ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////

#ifndef LCD_SETUP
#define LCD_WIDTH 240    //192
#define LCD_HEIGHT 128
#define bus_tris(x)   set_tris_a (x)   //8-bit data bus LCD,  
#define data_bus_out(x)      output_a(x)
#define data_bus_in      input_a()               // LCD data port
//Control pin setting  LCD
#define GLCD_CS            PIN_C2      
#define GLCD_RW            PIN_C0      
#define GLCD_E            PIN_C1     
#define GLCD_RS            PIN_C7      
#define LCD_RST             PIN_C3      // LCD RST_ line
#define GLCD_ON  0   //power on/off lcd
#endif




#define  OFF     0
#define  ON     1
#define PIXEL_OFF  0
#define PIXEL_ON  1
#define  NO     0
#define  YES     1



const int8 TEXT[51][5] ={0x00, 0x00, 0x00, 0x00, 0x00, // SPACE
                         0x00, 0x00, 0x5F, 0x00, 0x00, // !
                         0x00, 0x03, 0x00, 0x03, 0x00, // "
                         0x14, 0x3E, 0x14, 0x3E, 0x14, // #
                         0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
                         0x43, 0x33, 0x08, 0x66, 0x61, // %
                         0x36, 0x49, 0x55, 0x22, 0x50, // &
                         0x00, 0x05, 0x03, 0x00, 0x00, // '
                         0x00, 0x1C, 0x22, 0x41, 0x00, // (
                         0x00, 0x41, 0x22, 0x1C, 0x00, // )
                         0x14, 0x08, 0x3E, 0x08, 0x14, // *
                         0x08, 0x08, 0x3E, 0x08, 0x08, // +
                         0x00, 0x50, 0x30, 0x00, 0x00, // ,
                         0x08, 0x08, 0x08, 0x08, 0x08, // -
                         0x00, 0x60, 0x60, 0x00, 0x00, // .
                         0x20, 0x10, 0x08, 0x04, 0x02, // /
                         0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
                         0x04, 0x02, 0x7F, 0x00, 0x00, // 1
                         0x42, 0x61, 0x51, 0x49, 0x46, // 2
                         0x22, 0x41, 0x49, 0x49, 0x36, // 3
                         0x18, 0x14, 0x12, 0x7F, 0x10, // 4
                         0x27, 0x45, 0x45, 0x45, 0x39, // 5
                         0x3E, 0x49, 0x49, 0x49, 0x32, // 6
                         0x01, 0x01, 0x71, 0x09, 0x07, // 7
                         0x36, 0x49, 0x49, 0x49, 0x36, // 8
                         0x26, 0x49, 0x49, 0x49, 0x3E, // 9
                         0x00, 0x36, 0x36, 0x00, 0x00, // :
                         0x00, 0x56, 0x36, 0x00, 0x00, // ;
                         0x08, 0x14, 0x22, 0x41, 0x00, // <
                         0x14, 0x14, 0x14, 0x14, 0x14, // =
                         0x00, 0x41, 0x22, 0x14, 0x08, // >
                         0x02, 0x01, 0x51, 0x09, 0x06, // ?
                         0x3E, 0x41, 0x59, 0x55, 0x5E, // @
                         0x7E, 0x09, 0x09, 0x09, 0x7E, // A
                         0x7F, 0x49, 0x49, 0x49, 0x36, // B
                         0x3E, 0x41, 0x41, 0x41, 0x22, // C
                         0x7F, 0x41, 0x41, 0x41, 0x3E, // D
                         0x7F, 0x49, 0x49, 0x49, 0x41, // E
                         0x7F, 0x09, 0x09, 0x09, 0x01, // F
                         0x3E, 0x41, 0x41, 0x49, 0x3A, // G
                         0x7F, 0x08, 0x08, 0x08, 0x7F, // H
                         0x00, 0x41, 0x7F, 0x41, 0x00, // I
                         0x30, 0x40, 0x40, 0x40, 0x3F, // J
                         0x7F, 0x08, 0x14, 0x22, 0x41, // K
                         0x7F, 0x40, 0x40, 0x40, 0x40, // L
                         0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
                         0x7F, 0x02, 0x04, 0x08, 0x7F, // N
                         0x3E, 0x41, 0x41, 0x41, 0x3E, // O
                         0x7F, 0x09, 0x09, 0x09, 0x06, // P
                         0x1E, 0x21, 0x21, 0x21, 0x5E, // Q
                         0x7F, 0x09, 0x09, 0x09, 0x76};// R

const int8 TEXT2[44][5]={0x26, 0x49, 0x49, 0x49, 0x32, // S
                         0x01, 0x01, 0x7F, 0x01, 0x01, // T
                         0x3F, 0x40, 0x40, 0x40, 0x3F, // U
                         0x1F, 0x20, 0x40, 0x20, 0x1F, // V
                         0x7F, 0x20, 0x10, 0x20, 0x7F, // W
                         0x41, 0x22, 0x1C, 0x22, 0x41, // X
                         0x07, 0x08, 0x70, 0x08, 0x07, // Y
                         0x61, 0x51, 0x49, 0x45, 0x43, // Z
                         0x00, 0x7F, 0x41, 0x00, 0x00, // [
                         0x02, 0x04, 0x08, 0x10, 0x20, // \
                         0x00, 0x00, 0x41, 0x7F, 0x00, // ]
                         0x04, 0x02, 0x01, 0x02, 0x04, // ^
                         0x40, 0x40, 0x40, 0x40, 0x40, // _
                         0x00, 0x01, 0x02, 0x04, 0x00, // `
                         0x20, 0x54, 0x54, 0x54, 0x78, // a
                         0x7F, 0x44, 0x44, 0x44, 0x38, // b
                         0x38, 0x44, 0x44, 0x44, 0x44, // c
                         0x38, 0x44, 0x44, 0x44, 0x7F, // d
                         0x38, 0x54, 0x54, 0x54, 0x18, // e
                         0x04, 0x04, 0x7E, 0x05, 0x05, // f
                         0x08, 0x54, 0x54, 0x54, 0x3C, // g
                         0x7F, 0x08, 0x04, 0x04, 0x78, // h
                         0x00, 0x44, 0x7D, 0x40, 0x00, // i
                         0x20, 0x40, 0x44, 0x3D, 0x00, // j
                         0x7F, 0x10, 0x28, 0x44, 0x00, // k
                         0x00, 0x41, 0x7F, 0x40, 0x00, // l
                         0x7C, 0x04, 0x78, 0x04, 0x78, // m
                         0x7C, 0x08, 0x04, 0x04, 0x78, // n
                         0x38, 0x44, 0x44, 0x44, 0x38, // o
                         0x7C, 0x14, 0x14, 0x14, 0x08, // p
                         0x08, 0x14, 0x14, 0x14, 0x7C, // q
                         0x00, 0x7C, 0x08, 0x04, 0x04, // r
                         0x48, 0x54, 0x54, 0x54, 0x20, // s
                         0x04, 0x04, 0x3F, 0x44, 0x44, // t
                         0x3C, 0x40, 0x40, 0x20, 0x7C, // u
                         0x1C, 0x20, 0x40, 0x20, 0x1C, // v
                         0x3C, 0x40, 0x30, 0x40, 0x3C, // w
                         0x44, 0x28, 0x10, 0x28, 0x44, // x
                         0x0C, 0x50, 0x50, 0x50, 0x3C, // y
                         0x44, 0x64, 0x54, 0x4C, 0x44, // z
                         0x00, 0x08, 0x36, 0x41, 0x41, // {
                         0x00, 0x00, 0x7F, 0x00, 0x00, // |
                         0x41, 0x41, 0x36, 0x08, 0x00, // }
                         0x02, 0x01, 0x02, 0x04, 0x02};// ~

/**
 * Strobes the Enable control line to trigger the lcd to process the
 * transmitted instruction.
 */
void lcd_strobe_enable(void) {
   output_high(GLCD_E);
   delay_us (3);
   output_low(GLCD_E);
   delay_us (3);   
}

/**
 * Waits for the busy flag to clear, which should take
 * around the maximum time for an instruction to complete.
 * Note, LCD operation is kind of sensitive to this configuration. If the delay
 * is too fast, the LCD will miss some pixels when it is really put through
 * a stress test. This delay time seems to work great.
 */
 
void lcd_wait_busy(void) {
/*int8 busy_fl;
 output_high(GLCD_RW);
   output_high(GLCD_RS);
  bus_tris(0xff) ;
  while (busy_fl>= 128) busy_fl=data_bus_in; //0b10000000
*/
   delay_us(3);
}

/**
 * Writes a command and data raw instruction to the LCD.
 * @param command The 4-bit instruction code.
 * @param data The 8-bit paramater/data to the specified instruction.
 */
void lcd_write_command(int8 command, int8 data) {
   /* Wait for the busy flag to clear */
   lcd_wait_busy();
   
   /* Set RW low, RS high, CS low to write the instruction command */
   output_low(GLCD_RW);
   output_high(GLCD_RS);
   output_low(GLCD_CS); 
    bus_tris(0x00);
   data_bus_out(command);
    delay_us (3);
   lcd_strobe_enable();
   //  delay_us (3);  

   /* Set RW low, RS low to write the instruction data */
   output_low(GLCD_RW);
   output_low(GLCD_RS);
   data_bus_out(data);
    // delay_us (3);
   lcd_strobe_enable();
  //  delay_us (3);
}

/**
 * Moves the LCD cursor to the specified coordinates.
 * @param x The new x coordinante of the cursor.
 * @param y The new y coordinante of the cursor.
 */
void lcd_graphics_move(int8 x, int8 y) {
   int16 pos;
   int8 LA, UA;

   /* Calculate the raw address in terms of bytes on the screen */
   pos = (_mul(y, LCD_WIDTH)+x)/8;
   LA = make8(pos, 0);
   UA = make8(pos, 1);
   
   /* Move the cursor to the new address */
   lcd_write_command(0x0A, LA);
   lcd_write_command(0x0B, UA);
}

// Purpose:       Turn a pixel on a graphic LCD on or off
// Inputs:        x - the x coordinate of the pixel
//                y - the y coordinate of the pixel
//                color - ON or OFF
// Output:        1 if coordinate out of range, 0 if in range
void glcd_pixel(int8 x, int8 y, short color)
{
   int16 pos;
   
   lcd_graphics_move(x, y);
   /* Since lcd_graphics_move() moves the cursor to a particular
    * byte, not bit, we need the relative distance to the specified
    * bit we are going to set/clear. */
   pos = x%8;

   if (color == ON)
      lcd_write_command(0x0F, pos);
   else
      lcd_write_command(0x0E, pos);
}

// Purpose:       Draw a line on a graphic LCD using Bresenham's
//                line drawing algorithm
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                color - ON or OFF
// Dependencies:  glcd_pixel()
void glcd_line(int8 x1, int8 y1, int8 x2, int8 y2, short color)
{
   signed int8  x, y, addx, addy, dx, dy;
   signed long P;
   int8 i;
   dx = abs((signed int8)(x2 - x1));
   dy = abs((signed int8)(y2 - y1));
   x = x1;
   y = y1;

   if(x1 > x2)
      addx = -1;
   else
      addx = 1;
   if(y1 > y2)
      addy = -1;
   else
      addy = 1;

   if(dx >= dy)
   {
      P = 2*dy - dx;

      for(i=0; i<=dx; ++i)
      {
         glcd_pixel(x, y, color);

         if(P < 0)
         {
            P += 2*dy;
            x += addx;
         }
         else
         {
            P += 2*dy - 2*dx;
            x += addx;
            y += addy;
         }
      }
   }
   else
   {
      P = 2*dx - dy;

      for(i=0; i<=dy; ++i)
      {
         glcd_pixel(x, y, color);

         if(P < 0)
         {
            P += 2*dx;
            y += addy;
         }
         else
         {
            P += 2*dx - 2*dy;
            x += addx;
            y += addy;
         }
      }
   }
}

// Purpose:       Draw a rectangle on a graphic LCD
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                fill  - YES or NO
//                color - ON or OFF
// Dependencies:  glcd_pixel(), glcd_line()
void glcd_rect(int8 x1, int8 y1, int8 x2, int8 y2, short fill, short color)
{
   if(fill)
   {
      int8 y, ymax;                          // Find the y min and max
      if(y1 < y2)
      {
         y = y1;
         ymax = y2;
      }
      else
      {
         y = y2;
         ymax = y1;
      }

      for(; y<=ymax; ++y)                    // Draw lines to fill the rectangle
         glcd_line(x1, y, x2, y, color);
   }
   else
   {
      glcd_line(x1, y1, x2, y1, color);      // Draw the 4 sides
      glcd_line(x1, y2, x2, y2, color);
      glcd_line(x1, y1, x1, y2, color);
      glcd_line(x2, y1, x2, y2, color);
   }
}


// Purpose:       Draw a bar (wide line) on a graphic LCD
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                width  - The number of pixels wide
//                color - ON or OFF
void glcd_bar(int8 x1, int8 y1, int8 x2, int8 y2, int8 width, short color)
{
   signed int8  x, y, addx, addy, j;
   signed long P, dx, dy, c1, c2;
   int8 i;
   dx = abs((signed int8)(x2 - x1));
   dy = abs((signed int8)(y2 - y1));
   x = x1;
   y = y1;
   c1 = -dx*x1 - dy*y1;
   c2 = -dx*x2 - dy*y2;

   if(x1 > x2)
   {
      addx = -1;
      c1 = -dx*x2 - dy*y2;
      c2 = -dx*x1 - dy*y1;
   }
   else
      addx = 1;
   if(y1 > y2)
   {
      addy = -1;
      c1 = -dx*x2 - dy*y2;
      c2 = -dx*x1 - dy*y1;
   }
   else
      addy = 1;

   if(dx >= dy)
   {
      P = 2*dy - dx;

      for(i=0; i<=dx; ++i)
      {
         for(j=-(width/2); j<width/2+width%2; ++j)
         {
            if(dx*x+dy*(y+j)+c1 >= 0 && dx*x+dy*(y+j)+c2 <=0)
               glcd_pixel(x, y+j, color);
         }
         if(P < 0)
         {
            P += 2*dy;
            x += addx;
         }
         else
         {
            P += 2*dy - 2*dx;
            x += addx;
            y += addy;
         }
      }
   }
   else
   {
      P = 2*dx - dy;

      for(i=0; i<=dy; ++i)
      {
         if(P < 0)
         {
            P += 2*dx;
            y += addy;
         }
         else
         {
            P += 2*dx - 2*dy;
            x += addx;
            y += addy;
         }
         for(j=-(width/2); j<width/2+width%2; ++j)
         {
            if(dx*x+dy*(y+j)+c1 >= 0 && dx*x+dy*(y+j)+c2 <=0)
               glcd_pixel(x+j, y, color);
         }
      }
   }
}

// Purpose:       Draw a circle on a graphic LCD
// Inputs:        (x,y) - the center of the circle
//                radius - the radius of the circle
//                fill - YES or NO
//                color - ON or OFF
void glcd_circle(int8 x, int8 y, int8 radius, short fill, short color)
{
   signed int8 a, b, P;
   a = 0;
   b = radius;
   P = 1 - radius;

   do
   {
      if(fill)
      {
         glcd_line(x-a, y+b, x+a, y+b, color);
         glcd_line(x-a, y-b, x+a, y-b, color);
         glcd_line(x-b, y+a, x+b, y+a, color);
         glcd_line(x-b, y-a, x+b, y-a, color);
      }
      else
      {
         glcd_pixel(a+x, b+y, color);
         glcd_pixel(b+x, a+y, color);
         glcd_pixel(x-a, b+y, color);
         glcd_pixel(x-b, a+y, color);
         glcd_pixel(b+x, y-a, color);
         glcd_pixel(a+x, y-b, color);
         glcd_pixel(x-a, y-b, color);
         glcd_pixel(x-b, y-a, color);
      }

      if(P < 0)
         P+= 3 + 2*a++;
      else
         P+= 5 + 2*(a++ - b--);
    } while(a <= b);
}

// Purpose:       Write text on a graphic LCD
// Inputs:        (x,y) - The upper left coordinate of the first letter
//                textptr - A pointer to an array of text to display
//                size - The size of the text: 1 = 5x7, 2 = 10x14, ...
//                color - ON or OFF
void glcd_text57(int8 x, int8 y, char* textptr, int8 size, short color)
{
   int8 i, j, k, l, m;                     // Loop counters
   int8 pixelData[5];                     // Stores character data
   for(i=0; textptr[i] != '\0'; ++i, ++x) // Loop through the passed string
   {
      if(textptr[i] < 'S') // Checks if the letter is in the first text array
         memcpy(pixelData, TEXT[textptr[i]-' '], 5); 
      else if(textptr[i] <= '~') // Check if the letter is in the second array
         memcpy(pixelData, TEXT2[textptr[i]-'S'], 5);
      else
         memset(pixelData, ' ', 5);   // Default to space

      if(x+5*size >= LCD_WIDTH)          // Performs character wrapping
      {
         x = 0;                           // Set x at far left position
         y += 8*size + 1;                 // Set y at next position down
      }
      for(j=0; j<5; ++j, x+=size)         // Loop through character byte data
      {
         for(k=0; k<8*size; ++k)          // Loop through the vertical pixels
         {
            if(bit_test(pixelData[j], k)) // Check if the pixel should be set
            {
               for(l=0; l<size; ++l)      // The next two loops change the
               {                          // character's size
                  for(m=0; m<size; ++m)
                  {
                     glcd_pixel(x+m, y+k*size+l, color); // Draws the pixel
                  }
               }
            }
            else
            {
               for(l=0; l<size; ++l)      // The next two loops change the
               {                          // character's size
                  for(m=0; m<size; ++m)
                  {
                     glcd_pixel(x+m, y+k*size+l, 0); // Clears the pixel
                  }
               }
            }
         }
      }
   }
}

/**
 * Draws a byte to the LCD at the current LCD's cursor location.
 * @param data The byte to draw. The pixels are drawn MSB to LSB.
 */
void lcd_graphics_draw_byte(int8 data) {
   lcd_write_command(0x0C, data);
}

/**
 * Plots a byte at the specified coordinates.
 * @param x The x coordinante of the byte to be drawn.
 * @param y The y coordinante of the byte to be drawn.
 * @param data The byte to draw. The pixels are drawn MSB to LSB.
 */
void lcd_graphics_plot_byte(int8 x, int8 y, int8 data) {
   lcd_graphics_move(x, y);
   lcd_graphics_draw_byte(data);
}

// Purpose:       Fill the LCD screen with the passed in color.
//                Works much faster than drawing a rectangle to fill the screen.
// Inputs:        ON - turn all the pixels on
//                OFF - turn all the pixels off
// Dependencies:  glcd_writeByte()
void glcd_fillScreen(short mode)
{
   long i;
   /* Move cursor to home (top left corner) */
   lcd_graphics_move(0, 0);
   /* Draw empty bytes to ocucpy the entire screen */
   for (i = 0; i < ((LCD_WIDTH*LCD_HEIGHT)/8); i++)
      if (mode == OFF)
         lcd_graphics_draw_byte(PIXEL_OFF);
      else
         lcd_graphics_draw_byte(PIXEL_ON);
}

// Purpose:       Reads a byte of data from the specified chip
// Ouputs:        A byte of data read from the chip
int8 glcd_readByte(int8 chip)
{
   int8 data;                 // Stores the data read from the LCD
   lcd_write_command(0x0D, 0x00);
   output_low(GLCD_CS);
   output_high(GLCD_RW);      // Set for reading
   bus_tris(0xff);                 // Set port  to input
   output_high(GLCD_E);       // Pulse the enable pin
   delay_us(2);
   output_low(GLCD_E);
    delay_us(2);
   output_high(GLCD_E);       // Pulse the enable pin
    delay_us(2);
   output_low(GLCD_E);
    delay_us(2);
   data = data_bus_in;          // Get the data from the display's output register

   output_low(GLCD_CS);      // Reset the chip select lines
   return data;               // Return the read data
}

// Purpose:       Initialize a graphic LCD. This must be called before any
//                other glcd function is used.
// Inputs:        The initialization mode
//                OFF - Turns character mode ON
//                ON  - Turns graphic mode ON
// Date:          5/28/2003
void glcd_init(short mode)
{
   // Initialze some pins
   output_low(GLCD_RST);
   output_low(GLCD_E);
   output_low(GLCD_RS);
   output_high(GLCD_CS);
   bus_tris(0x00);
   data_bus_out(0x00);
   delay_ms(1);
   output_high(GLCD_RST);
   delay_ms(1);

   if(mode == ON)
   {
   lcd_write_command(0x00, 0x32);  //graf mod
   lcd_write_command(0x01, 0b01110111); //Hp=8 dot per byte
   }
   else
   {
   lcd_write_command(0x00, 0x3C); //text mod blik cursor on, build cgram
   lcd_write_command(0x01, 0b10000111);  // char 11x8  
   }
   lcd_write_command(0x02, 28); // Hn= 28 je 29zn/radek a zapsat pouze24znaků,bytu/řadek;nové radky jsou násobky 30;
   lcd_write_command(0x03, 127);//duty Nx=128 lines      
   lcd_write_command(0x04, 0x07);//cursor position 7
   lcd_write_command(0x08, 0x00);//start adress lower byte
   lcd_write_command(0x09, 0x00);//start adress upper byte
   lcd_write_command(0x0A, 0x00);
   lcd_write_command(0x0B, 0x00);

   glcd_fillScreen(OFF);               // Clear the display
}

//
void glcd_power(short mode) {
  if(mode == ON) {
      output_high(GLCD_ON);           // Turn the display on
   }
   else
   {
      output_low(GLCD_ON);           // Turn the display off
   }
}



// glcd_pixel8(x,y,px8) sets or clears 8 pixels in line at x,y
void glcd_pixel8(int8 x, int8 y, int8 pixel8) {
   lcd_graphics_move(x+1,y);
   lcd_write_command(0x0c, pixel8);
}

//glcd_image8 (*Pic, x, y, size_x, size_y)
void glcd_image8(int8 *pic_px, int8 x, int8 y,
                 int8 size_x, int8 size_y) {
   int8 px_y;
   int8 px_x;
   int8 px=0;

   for(px_y=y; px_y<(y+size_y); px_y++) {
      for(px_x=x; px_x<(x+size_x); px_x+=8) {
         glcd_pixel8(px_x, px_y, *(pic_px+px));
         px+=1;
      }
   }
}
 
//

/*
void glcd_text8x8(char *Pix, int8 line) {
int8 i;                     // Loop counters
char pixelData[8];

   for(i=0; i<20; ++i) // Loop through the passed string
   {
//      if(textptr[i] < 'S') // Checks if the letter is in the first text array
//         memcpy(pixelData, TEXT[textptr[i]-' '], 5);
//      else if(textptr[i] <= '~') // Check if the letter is in the second array
//         memcpy(pixelData, TEXT2[textptr[i]-'S'], 5);
//      else
//         memset(pixelData, ' ', 5);   // Default to space

      if(Pix[i] < '4') // Checks if the letter is in the first text array
         memcpy(pixelData, TEXTA[Pix[i]-' '], 8);
      else if(Pix[i] < 'H') // Check if the letter is in the second array
         memcpy(pixelData, TEXTB[Pix[i]-'4'], 8);
      else if(Pix[i] < ('\\')) // Check if the letter is in the second array
         memcpy(pixelData, TEXTC[Pix[i]-'H'], 8);
      else if(Pix[i] < 'p') // Check if the letter is in the second array
         memcpy(pixelData, TEXTD[Pix[i]-'\\'], 8);
      else if(Pix[i] <= 0x7F) // Check if the letter is in the second array
         memcpy(pixelData, TEXTE[Pix[i]-'p'], 8);
      else {
         memcpy(pixelData, TEXTA[0], 8);   // Default to space
      }
      glcd_image8(pixelData, i*8, line*10, 8, 8);
   }
}
*/
//
void move_char(int8 x, int8 y) {
   int16 pos;
   int8 LA, UA;

   /* Calculate the raw address in terms of characters on the screen */
   // pos = (_mul(y, 20)+x); //original!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   pos = (_mul(y, 24)+x);
   LA = make8(pos, 0);
   UA = make8(pos, 1);
   
   /* Move the cursor to the new address */
   lcd_write_command(0x0A, LA);
   lcd_write_command(0x0B, UA);
}

//
void glcd_char(int8 x, int8 y, char* textptr) {
int8 i;

   move_char(x, y);
   for(i=0; i<20; i++) {
      lcd_write_command(0x0c, textptr[i]);
   }
}

//
void char_fillScreen(short mode) {
   long i;
   /* Move cursor to home (top left corner) */
   move_char(0, 0);
   /* Draw blank or filled chars to ocucpy the entire screen */
   for (i = 0; i < 160; i++)
      if (mode == OFF)
         lcd_write_command(0x0c, 0x20);
      else
         lcd_write_command(0x0c, 0xFF);
} 
