///////////////////////////////////////////////////////////////////////// //// 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= 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= 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