PCD8544 multiscreen

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PCD8544MS.cpp Source File

PCD8544MS.cpp

00001 /* mbed PCD8544 - Graphic Library for driving monochrome displays based on
00002  *  the PCD8544  48 x 84 pixels matrix LCD controller/driver
00003  *  used in Nokia 3310, 3315, 3330, 3350, 3410, 3210,  5110, 5120, 5130, 5160, 6110, 6150
00004  *
00005  * Copyright (c) 2011, Wim De Roeve
00006  * partial port of the code found on http://serdisplib.sourceforge.net/ser/pcd8544.html#links
00007  * and by Petras Saduikis <petras@petras.co.uk>
00008  *
00009  * Permission is hereby granted, free of charge, to any person obtaining a copy
00010  * of this software and associated documentation files (the "Software"), to deal
00011  * in the Software without restriction, including without limitation the rights
00012  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00013  * copies of the updaSoftware, and to permit persons to whom the Software is
00014  * furnished to do so, subject to the following conditions:
00015  *
00016  * The above copyright notice and this permission notice shall be included in
00017  * all copies or substantial portions of the Software.
00018  *
00019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00022  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00024  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00025  * THE SOFTWARE.
00026  */
00027 
00028 #include "PCD8544MS.h"
00029 
00030 #include "fonts/font_3x5.h"
00031 #include "fonts/font_5x7.h"
00032 #include "fonts/font_6x8.h"
00033 #include "fonts/font_8x8.h"
00034 #include "fonts/font_8x12.h"
00035 #include "fonts/font_16x20.h"
00036 #include "fonts/font_16x24.h"
00037 
00038 #include "DebugTrace.h"
00039 #include "sstream"
00040 #include "stdio.h"
00041 #include "stringman.h"
00042 
00043 #define GLCD_CS6_ON            0x01   //P0
00044 #define GLCD_RESET_ON          0x02   //P1
00045 #define GLCD_CS1_ON            0x04   //P2
00046 #define GLCD_CS5_ON            0x08   //P3
00047 #define GLCD_DC_ON             0x10   //P4
00048 #define GLCD_CS2_ON            0x20   //P5
00049 #define GLCD_CS3_ON            0x40   //P6
00050 #define GLCD_CS4_ON            0x80   //P7
00051 
00052 #define TLCD_RS_ON             0x1000 //P12
00053 #define TLCD_E1_ON             0x2000 //P13
00054 #define TLCD_E2_ON             0x4000 //P14
00055 #define TLCD_BACKLIGHT_ON      0x8000 //P15
00056 
00057 /* Display ON/OFF Control defines */
00058 #define DON                0x0F  //0b00001111  Display on 
00059 #define DOFF               0x0B  //0b00001011  Display off 
00060 #define CURSOR_ON          0x0F  //0b00001111  Cursor on 
00061 #define CURSOR_OFF         OxOD  //0b00001101  Cursor off 
00062 #define BLINK_ON           0x0F  //0b00001111  Cursor Blink 
00063 #define BLINK_OFF          0x0E  //0b00001110  Cursor No Blink 
00064 
00065 /* Cursor or Display Shift defines */
00066 #define SHIFT_CUR_LEFT     Ox13  //0b00010011  Cursor shifts to the left 
00067 #define SHIFT_CUR_RIGHT    Ox17  //0b00010111  Cursor shifts to the right 
00068 #define SHIFT_DISP_LEFT    Ox1B  //0b00011011  Display shifts to the left 
00069 #define SHIFT_DISP_RIGHT   0x1F  //0b00011111  Display shifts to the right 
00070 
00071 /* Function Set defines */
00072 #define EIGHT_BITMODE      0x03  //0b00000011  8-bit Interface D4-D7
00073 #define FOUR_BITMODE       0x02  //0b00000010  4-bit Interface D4-D7
00074 #define LINE_5X7           0x30  //0b00110000
00075 #define LINE_5X10          0x34  //0b00110100
00076 #define LINES_5X7          0x38  //0b00111000
00077 
00078 // Addtional define to support display mode
00079 
00080 #define DISP_FLIP_NONE     0x00  //0b00111100  No flip
00081 #define CLEAR_LCD          0x01  //0b00000001 
00082 
00083 /* Number of pixels on the LCD */
00084 
00085 #define HIGH  1
00086 #define LOW   0
00087 #define TRUE  1
00088 #define FALSE 0
00089 
00090 /* Display control command */
00091 #define EXTENDEDSET   0x21
00092 #define STANDARDSET   0x20
00093 #define DISPLAYOFF    0x08  // switch off display 
00094 #define ALL_SEG_ON    0x09  // switch on display and set to all pixels on
00095 #define NORMAL_MODE   0x0C  // NOREVERSE
00096 #define INVERSE_MODE  0x0D  // REVERSE
00097 
00098 #define SET_ADDRES_X  0x80
00099 #define SET_ADDRES_Y  0x40
00100 
00101 
00102 DebugTrace pc_PCD8544(ON, TO_SERIAL);
00103 
00104 /*
00105        PCD8544 from Philips Semiconductors is
00106        48 x 84 pixels monochrome matrix LCD controller/driver
00107 
00108        generic for LPH7366, LPH7677, and LPH7779; no backlight
00109 
00110        model name (of display)     type     used in cellphones
00111        LPH 7366         2     Nokia 5110, 5120, 5130, 5160, 6110, 6150
00112        LPH 7677         1     Nokia 3210
00113        LPH 7779         1     Nokia 3310, 3315, 3330, 3350, 3410
00114 
00115 
00116        +-------------------------+
00117        |     1 2 3 4 5 6 7 8     |
00118        |     # # # # # # # #     |
00119        |  ===#=#=#=#=#=#=#=#===  |  Red     1 .. VDD  - chip power supply +3.3V
00120        +--=====================--+  Green   2 .. SCLK - serial clock line of LCD
00121        |                         |  Yellow  3 .. SI   - serial data input of LCD
00122        |                         |  Gray    4 .. D/C  - command/data switch
00123        |        rear view        |  Blue    5 .. /CS  - active low chip select
00124        |  connector is visible   |  Black   6 .. GND  - for VDD
00125        |                         |          7 .. Vout - output of display-internal dc/dc converter
00126        |         LPH7779         |  White   8 .. /RES - active low reset
00127        |                         |
00128        +-------------------------+
00129 
00130 */
00131 
00132 
00133 PCD8544MS::PCD8544MS(PinName mosi, PinName miso, PinName sclk, PinName sda, PinName scl,int i2cAddress, bool TextLCD, bool backlight):
00134         _spi(mosi, miso, sclk),_i2c(sda, scl) {
00135 
00136     _i2cAddress = i2cAddress;
00137 //   _type = type;
00138 
00139     if (TextLCD) {
00140         TLCD_reset();
00141         _columns = 16;
00142         _rows = 2;
00143         _backlight=backlight;
00144     }
00145 
00146     GLCD_reset();
00147 }
00148 
00149 void PCD8544MS::writeI2CByte(int data) {
00150     char cmd[2];
00151     cmd[0] = (data & 0xFF);
00152     cmd[1] = (data >> 8);
00153     _i2c.write(_i2cAddress, cmd, 2);
00154     // pc_PCD8544.traceOut("I2C=%i ",data);
00155 
00156 }
00157 
00158 // ############# TEXTLCD FUNCTIONS ###################
00159 
00160 void PCD8544MS::TLCD_reset() {
00161     for (int i=0; i<3; i++) {
00162         TLCD_writeNibble(EIGHT_BITMODE,false);
00163         wait(0.00164);      // this command takes 1.64ms, so wait for it
00164     }
00165     TLCD_writeNibble(FOUR_BITMODE,false); // 4-bit mode
00166 
00167     TLCD_writeCommand(0x28);    // Function set 001 BW N F - -
00168     TLCD_writeCommand(0x0C);
00169     TLCD_writeCommand(0x6);  //  Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
00170 }
00171 
00172 void PCD8544MS::TLCD_writeNibble(int data, bool rs) {
00173 
00174     data = ((data & 0xF) << 8) || GLCD_RESET_ON || GLCD_CS1_ON ||  GLCD_CS2_ON || GLCD_CS3_ON || GLCD_CS4_ON || GLCD_CS5_ON || GLCD_CS6_ON ;
00175 
00176     if (_backlight)
00177         data= data  | TLCD_BACKLIGHT_ON;
00178 
00179     if (rs) {
00180         data = data | TLCD_RS_ON; // set rs bit
00181     }
00182 
00183     writeI2CByte(data | TLCD_E1_ON); // E=1
00184 
00185     wait(0.000040f);
00186     writeI2CByte(data);   // E=0
00187 
00188     wait(0.000040f);
00189     writeI2CByte(data | TLCD_E1_ON);  // E=1
00190 }
00191 
00192 
00193 void PCD8544MS::TLCD_writeByte(int data, bool rs) {
00194     TLCD_writeNibble(data >> 4 , rs);
00195     TLCD_writeNibble(data >> 0 , rs);
00196 }
00197 
00198 void PCD8544MS::TLCD_writeCommand(int command) {
00199     // RS = 0;
00200     TLCD_writeByte(command,false);
00201 }
00202 
00203 void PCD8544MS::TLCD_writeData(int data) {
00204     //RS = 1
00205     TLCD_writeByte(data,true);
00206 
00207     _column++;
00208     if (_column >= _columns) {
00209         TLCD_newline();
00210     }
00211 }
00212 
00213 int PCD8544MS::_putc(int value) {
00214     if (value == '\n') {
00215         TLCD_newline();
00216     } else {
00217         TLCD_writeData(value);
00218     }
00219     return value;
00220 }
00221 
00222 int PCD8544MS::_getc() {
00223     return 0;
00224 }
00225 
00226 void PCD8544MS::TLCD_backlight(bool status) {
00227     _backlight=status;
00228     if (_backlight)
00229         writeI2CByte(TLCD_BACKLIGHT_ON | TLCD_E1_ON | TLCD_E2_ON | GLCD_CS1_ON);
00230     else
00231         writeI2CByte(TLCD_E1_ON | TLCD_E2_ON | GLCD_CS1_ON);
00232 }
00233 
00234 
00235 void PCD8544MS::TLCD_newline() {
00236     _column = 0;
00237     _row++;
00238     if (_row >= _rows) {
00239         _row = 0;
00240     }
00241     TLCD_locate(_column, _row);
00242 }
00243 
00244 
00245 void PCD8544MS::TLCD_locate(int column, int row) {
00246     if (column < 0 || column >= _columns || row < 0 || row >= _rows) {
00247         error("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows);
00248         return;
00249     }
00250 
00251     _row = row;
00252     _column = column;
00253     int address = 0x80 + (_row * 40) + _column; // memory starts at 0x80, and is 40 chars long per row
00254     // pc_LCD.traceOut("locate %dx%d\r\n", column, row);
00255     TLCD_writeCommand(address);
00256 }
00257 
00258 
00259 void PCD8544MS::TLCD_cls() {
00260     TLCD_writeCommand(0x01); // Clear Display
00261     wait(0.00164f);     // This command takes 1.64 ms
00262     TLCD_locate(0, 0);
00263 }
00264 
00265 
00266 
00267 // ############# GRAPHICLCD FUNCTIONS ###################
00268 
00269 void PCD8544MS::GLCD_reset() {
00270 
00271     /* reset lcd
00272 
00273       After reset, the LCD driver has the following state:
00274       - Power-down mode (bit PD = 1)
00275       - Horizontal addressing (bit V = 0)
00276       - normal instruction set (bit H = 0)
00277       - Display blank (bit E = D = 0)
00278       - Address counter X6 to X0 = 0; Y2 to Y0 = 0
00279       - Temperature control mode (TC1 TC0 = 0)
00280       - Bias system (BS2 to BS0 = 0)
00281       - VLCD is equal to 0, the HV generator is switched off
00282        (VOP6 to VOP0 = 0)
00283       - After power-on, the RAM contents are undefined.
00284     */
00285 
00286 
00287     GLCD_writeI2C(HIGH,LOW,HIGH,0); // all screens
00288 
00289     _spi.format(8,0);
00290     _spi.frequency(1000000);
00291 
00292     pc_PCD8544.traceOut("\r\nreset GLCD ");
00293 
00294     //_cs=HIGH;
00295     //_reset=HIGH;
00296 
00297 
00298     // for (int i=1;i<=maxscreen;i++) {
00299 
00300     wait_ms(1);
00301     //_reset=LOW;
00302     GLCD_writeI2C(LOW,LOW,HIGH,0);
00303 
00304     wait_ms(1);
00305     //_reset = HIGH;
00306     GLCD_writeI2C(HIGH,LOW,HIGH,0);
00307 
00308     GLCD_writeCmd(EXTENDEDSET,1,0);   // folowing commands are extended ones
00309     GLCD_writeCmd(0xc8,0,0);          // Set Voltage 0x80+value: set contrast
00310     GLCD_writeCmd(0x06,0,0);          // set temp coefficient
00311     GLCD_writeCmd(0x13,0,0);          // set BIAS mode 1:48
00312     GLCD_writeCmd(STANDARDSET,0,0);   // STANDARDSET: following commands are standard ones
00313 
00314     GLCD_writeCmd(NORMAL_MODE,2,0);
00315     _LoMark = 0;
00316     _HiMark = LCD_CACHE_SIZE - 1;
00317 
00318     GLCD_cls(0,TRUE);
00319 }
00320 
00321 void PCD8544MS::GLCD_writeCmd(BYTE data, BYTE CF, int screen) {
00322     //_cs = LOW;
00323     //_dc = LOW;
00324     // _spi.write(data);
00325 
00326 //    pc_PCD8544.traceOut("\r\n %i %i %i ",(CF & 1),data,(CF & 2));
00327 
00328     if ((CF & 1)==1) {
00329         GLCD_writeI2C(HIGH,LOW,LOW,screen);
00330         wait_ms(1);
00331     }
00332 
00333     _spi.write(data);
00334 
00335     if ((CF & 2)==2) {
00336         GLCD_writeI2C(HIGH,LOW,HIGH,screen);
00337     }
00338 
00339     //_cs = HIGH;
00340 
00341 }
00342 
00343 void PCD8544MS::GLCD_writeData(BYTE data, BYTE CF, int screen) {
00344     // _cs = LOW;
00345     //_dc = HIGH;
00346     //_spi.write(data);
00347 
00348     if ((CF & 1)==1) {
00349         GLCD_writeI2C(HIGH,HIGH,LOW,screen);
00350         wait_ms(1);
00351     }
00352 
00353     _spi.write(data);
00354 
00355     if ((CF & 2)==2) {
00356         GLCD_writeI2C(HIGH,HIGH,HIGH,screen);
00357     }
00358 
00359     //  _cs = HIGH;
00360 
00361 }
00362 
00363 void PCD8544MS::GLCD_writeI2C(bool reset, bool dc, bool cs,int screen) {
00364 
00365     int cb=TLCD_E1_ON | TLCD_E2_ON;  // prevent TextLCD for
00366 
00367     if (reset==HIGH) cb = cb | GLCD_RESET_ON;
00368     if (dc==HIGH) cb = cb | GLCD_DC_ON;
00369 
00370     if (cs==HIGH) {
00371         cb = cb | GLCD_CS1_ON |  GLCD_CS2_ON | GLCD_CS3_ON | GLCD_CS4_ON | GLCD_CS5_ON | GLCD_CS6_ON ;
00372     } else {
00373         switch (screen)  {
00374             case 1: {
00375                 cb = cb | GLCD_CS2_ON | GLCD_CS3_ON | GLCD_CS4_ON | GLCD_CS5_ON | GLCD_CS6_ON;
00376                 break;
00377             }
00378             case 2: {
00379                 cb = cb | GLCD_CS1_ON | GLCD_CS3_ON | GLCD_CS4_ON | GLCD_CS5_ON | GLCD_CS6_ON;
00380                 break;
00381             }
00382             case 3: {
00383                 cb = cb | GLCD_CS1_ON |  GLCD_CS2_ON | GLCD_CS4_ON | GLCD_CS5_ON | GLCD_CS6_ON;
00384                 break;
00385             }
00386             case 4: {
00387                 cb = cb | GLCD_CS1_ON |  GLCD_CS2_ON | GLCD_CS3_ON | GLCD_CS5_ON | GLCD_CS6_ON;
00388                 break;
00389             }
00390             case 5: {
00391                 cb = cb | GLCD_CS1_ON |  GLCD_CS2_ON | GLCD_CS3_ON | GLCD_CS4_ON | GLCD_CS6_ON;
00392                 break;
00393             }
00394             case 6: {
00395                 cb = cb | GLCD_CS1_ON |  GLCD_CS2_ON | GLCD_CS3_ON | GLCD_CS4_ON | GLCD_CS5_ON;
00396                 break;
00397             }
00398             default: {
00399                 break;
00400             }
00401         }
00402     }
00403 
00404 
00405     writeI2CByte(cb);
00406 
00407 }
00408 
00409 void PCD8544MS::GLCD_close() {
00410     GLCD_writeCmd(DISPLAYOFF,3,0);
00411     GLCD_writeI2C(HIGH,HIGH,HIGH,0);
00412 //   _cs    = HIGH;
00413 //   _reset = HIGH;
00414 
00415 }
00416 
00417 //  GRAPHICAL functions
00418 
00419 void PCD8544MS::GLCD_cls(int screen,bool fupdate) {
00420 //    pc_PCD8544.traceOut("\r\ncls %i ",LCD_CACHE_SIZE);
00421 
00422     for (int i = 0; i < LCD_CACHE_SIZE ; i++) {
00423         //    pc_PCD8544.traceOut("%i",i);
00424         LcdCache[i]=0x00;
00425     }
00426     _LoMark = 0;
00427     _HiMark = LCD_CACHE_SIZE - 1;
00428 
00429 //     pc_PCD8544.traceOut("\r\nfupdate");
00430     if (fupdate)
00431         GLCD_update(screen);
00432 }
00433 
00434 void PCD8544MS::GLCD_update(int screen) {
00435 //   pc_PCD8544.traceOut("\r\nupdate");
00436     if ( _LoMark < 0 )
00437         _LoMark = 0;
00438     else if ( _LoMark >= LCD_CACHE_SIZE )
00439         _LoMark = LCD_CACHE_SIZE - 1;
00440     if ( _HiMark < 0 )
00441         _HiMark = 0;
00442     else if ( _HiMark >= LCD_CACHE_SIZE )
00443         _HiMark = LCD_CACHE_SIZE - 1;
00444 
00445     GLCD_writeCmd(SET_ADDRES_X | (_LoMark % LCD_X_RES),1,screen);
00446     GLCD_writeCmd(SET_ADDRES_Y | (_LoMark / LCD_X_RES),2,screen);
00447 
00448     GLCD_writeI2C(HIGH,HIGH,LOW,screen);
00449     wait_ms(1);
00450 
00451     for (int i = _LoMark; i <= _HiMark; i++ ) {
00452         _spi.write(LcdCache[i]);
00453         //writeData( );
00454     }
00455     GLCD_writeI2C(HIGH,HIGH,HIGH,screen);
00456     _LoMark = LCD_CACHE_SIZE - 1;
00457     _HiMark = 0;
00458 }
00459 
00460 
00461 
00462 void PCD8544MS::GLCD_locate(BYTE x0, BYTE y0) {
00463     LcdCacheIdx = x0*LCD_BANKS + y0 * LCD_X_RES;
00464 }
00465 
00466 // Bitmap
00467 
00468 void PCD8544MS::GLCD_drawBitmap(BYTE x0, BYTE y0, const unsigned char* bitmap, BYTE bmpXSize, BYTE bmpYSize,BYTE fupdate,int screen) {
00469     BYTE row;
00470     //  pc_PCD8544.traceOut("\r\ndrawbitmap");
00471 
00472     if (0 == bmpYSize % 8)
00473         row = bmpYSize/8;
00474     else
00475         row = bmpYSize/8 + 1;
00476 
00477     _LoMark= 0;
00478     _HiMark= LCD_CACHE_SIZE - 1;
00479 
00480     for (BYTE n = 0; n < row; n++) {
00481         GLCD_locate(x0, y0);
00482 
00483         for (BYTE i = 0; i < bmpXSize; i++) {
00484             LcdCache[LcdCacheIdx+ i]=bitmap[i + (n * bmpXSize)];
00485         }
00486         y0++;
00487     }
00488     if (fupdate==TRUE)
00489         GLCD_update(screen);
00490 }
00491 
00492 void PCD8544MS::GLCD_writeString(BYTE x0, BYTE y0, char* string,  eFonts font,ePixelMode pmode,eDisplayMode dmode,eSpaceMode smode, BYTE fupdate,int screen) {
00493 
00494 //   pc_PCD8544.traceOut("\r\nwriteString");
00495     GLCD_locate(x0, y0);
00496     chooseFont(font);
00497 
00498     while (*string) {
00499         GLCD_writeChar(x0,y0,*string++,font,pmode, dmode, FALSE,screen);
00500         x0+=_font_width;   // width +1;
00501         if (smode==SPACE_NORMAL)
00502             x0++;
00503     }
00504     if (fupdate==TRUE)
00505         GLCD_update(screen);
00506 }
00507 
00508 void PCD8544MS::chooseFont(eFonts font) {
00509 
00510     switch (font) {
00511 
00512         case VERYSMALLFONT: {
00513             _font_width  = FONT3x5_WIDTH;
00514             _font_height = FONT3x5_HEIGHT;
00515             _font_start  = FONT3x5_START;
00516             _font_end    = FONT3x5_END;
00517             _font_bytes  = FONT3x5_BYTES;
00518 
00519             _pFont = (unsigned char*) font_3x5;
00520 
00521             break;
00522         }
00523         case TINYFONT: {
00524             _font_width  = FONT5x7_WIDTH;
00525             _font_height = FONT5x7_HEIGHT;
00526             _font_start  = FONT5x7_START;
00527             _font_end    = FONT5x7_END;
00528             _font_bytes  = FONT5x7_BYTES;
00529 
00530             _pFont = (unsigned char*) font_5x7;
00531 
00532             break;
00533         }
00534 
00535         case SMALLFONT: {
00536             _font_width  = FONT6x8_WIDTH;
00537             _font_height = FONT6x8_HEIGHT;
00538             _font_start  = FONT6x8_START;
00539             _font_end    = FONT6x8_END;
00540             _font_bytes  = FONT6x8_BYTES;
00541 
00542             _pFont = (unsigned char*) font_6x8;
00543 
00544             break;
00545         }
00546         case NORMALFONT: {
00547             _font_width  = FONT8x8_WIDTH;
00548             _font_height = FONT8x8_HEIGHT;
00549             _font_start  = FONT8x8_START;
00550             _font_end    = FONT8x8_END;
00551             _font_bytes  = FONT8x8_BYTES;
00552 
00553             _pFont = (unsigned char*) font_8x8;
00554 
00555             break;
00556         }
00557         case BIGFONT: {
00558             _font_width  = FONT8x12_WIDTH;
00559             _font_height = FONT8x12_HEIGHT;
00560             _font_start  = FONT8x12_START;
00561             _font_end    = FONT8x12_END;
00562             _font_bytes  = FONT8x12_BYTES;
00563 
00564             _pFont = (unsigned char*) font_8x12;
00565 
00566             break;
00567         }
00568 
00569         case TIMENUMBERFONT: {
00570             _font_width  = FONT16x20_WIDTH;
00571             _font_height = FONT16x20_HEIGHT;
00572             _font_start  = FONT16x20_START;
00573             _font_end    = FONT16x20_END;
00574             _font_bytes  = FONT16x20_BYTES;
00575 
00576             _pFont = (unsigned char*) font_16x20;
00577 
00578             break;
00579         }
00580 
00581         case BIGNUMBERFONT: {
00582             _font_width  = FONT16x24_WIDTH;
00583             _font_height = FONT16x24_HEIGHT;
00584             _font_start  = FONT16x24_START;
00585             _font_end    = FONT16x24_END;
00586             _font_bytes  = FONT16x24_BYTES;
00587 
00588             _pFont = (unsigned char*) font_16x24;
00589 
00590             break;
00591         }
00592     }
00593 }
00594 
00595 void PCD8544MS::GLCD_writeChar(BYTE x0, BYTE y0, BYTE ch,  eFonts font, ePixelMode pmode,eDisplayMode mode,BYTE fupdate,int screen) {
00596     BYTE sendByte;
00597 
00598     chooseFont(font);
00599 
00600     if ((ch <= _font_start) || (ch > _font_end))
00601         ch=_font_start;
00602 
00603     ch -= _font_start;
00604 
00605 
00606     /* for (BYTE i = 0; i < 3; i++) {
00607          locate(x, y + i);
00608 
00609          for (BYTE j = 0; j < 16; j++) {
00610              sendByte =  *(pFont + ch*48 + i*16 + j);
00611              writeData((mode == NORMAL)? sendByte : (sendByte^0xff));
00612          }
00613      }*/
00614 
00615 
00616     for (int i = 0; i < _font_width; i++ ) {
00617         for (int f=0; f<_font_bytes; f++) {
00618             sendByte = *(_pFont + ch*_font_width*_font_bytes +f*_font_width+i);
00619             sendByte = ((mode == DISPLAY_NORMAL)? sendByte:(sendByte ^ 0xff));
00620 
00621             for (int j=0 ; j<_font_height; j++) {
00622                 if ((sendByte & 0x01) == 0x01) {
00623                     GLCD_drawpixel(x0,y0+j+f*8,PIXEL_ON,FALSE,screen);
00624                 } else {
00625                     GLCD_drawpixel(x0,y0+j+f*8,PIXEL_OFF,FALSE,screen);
00626                 }
00627                 sendByte=sendByte>>1;
00628             }
00629         }
00630         x0++;
00631     }
00632 
00633 
00634     if (fupdate==TRUE)
00635         GLCD_update(screen);
00636 }
00637 
00638 
00639 void PCD8544MS::GLCD_drawpixel(BYTE x0, BYTE  y0, ePixelMode mode,BYTE fupdate,int screen) {
00640     uint16_t index;
00641     BYTE offset;
00642     BYTE data;
00643 
00644     if ( x0 > LCD_X_RES-1 ) return;
00645     if ( y0 > LCD_Y_RES-1 ) return;
00646 
00647     index = ((y0 / 8) * LCD_X_RES) + x0;
00648     offset = y0 - ((y0 / 8) * 8);
00649 
00650     data = LcdCache[index];
00651 
00652     if ( mode == PIXEL_OFF ) {
00653         data &= (~(0x01 << offset));
00654     } else if ( mode == PIXEL_ON ) {
00655         data |= (0x01 << offset);
00656     } else if ( mode == PIXEL_XOR ) {
00657         data ^= (0x01 << offset);
00658     }
00659     LcdCache[index] = data;
00660 
00661     if ( index < _LoMark ) {
00662         _LoMark = index;
00663     }
00664     if ( index > _HiMark ) {
00665         _HiMark = index;
00666     }
00667     if (fupdate==TRUE)
00668         GLCD_update(screen);
00669 }
00670 
00671 void PCD8544MS::GLCD_drawline(BYTE  x0, BYTE y0, BYTE x1, BYTE y1, ePixelMode mode,BYTE fupdate,int screen) {
00672     int dx, dy, stepx, stepy, fraction;
00673 
00674     dy = y1 - y0;
00675     dx = x1 - x0;
00676     if ( dy < 0 ) {
00677         dy = -dy;
00678         stepy = -1;
00679     } else {
00680         stepy = 1;
00681     }
00682     if ( dx < 0 ) {
00683         dx = -dx;
00684         stepx = -1;
00685     } else {
00686         stepx = 1;
00687     }
00688     dx <<= 1;
00689     dy <<= 1;
00690 
00691     GLCD_drawpixel( x0, y0, mode , FALSE,screen);
00692     if ( dx > dy ) {
00693         fraction = dy - (dx >> 1);
00694         while ( x0 != x1 ) {
00695             if ( fraction >= 0 ) {
00696                 y0 += stepy;
00697                 fraction -= dx;
00698             }
00699             x0 += stepx;
00700             fraction += dy;
00701             GLCD_drawpixel( x0, y0, mode , FALSE,screen);
00702         }
00703     } else {
00704         fraction = dx - (dy >> 1);
00705         while ( y0 != y1 ) {
00706             if ( fraction >= 0 ) {
00707                 x0 += stepx;
00708                 fraction -= dy;
00709             }
00710             y0 += stepy;
00711             fraction += dx;
00712             GLCD_drawpixel( x0, y0, mode , FALSE,screen);
00713         }
00714     }
00715     if (fupdate==TRUE)
00716         GLCD_update(screen);
00717 }
00718 
00719 void PCD8544MS::GLCD_drawrectangle(BYTE  x0, BYTE y0, BYTE x1, BYTE y1, eFillMode fill, ePixelMode mode,BYTE fupdate,int screen) {
00720     if (fill==1) {
00721         BYTE i, xmin, xmax, ymin, ymax;
00722         if (x0 < x1) { // Find x min and max
00723             xmin = x0;
00724             xmax = x1;
00725         } else {
00726             xmin = x1;
00727             xmax = x0;
00728         }
00729         if (y0 < y1) { // Find the y min and max
00730             ymin = y0;
00731             ymax = y1;
00732         } else {
00733             ymin = y1;
00734             ymax = y0;
00735         }
00736         for (; xmin <= xmax; ++xmin) {
00737             for (i=ymin; i<=ymax; ++i) {
00738                 GLCD_drawpixel(xmin, i, mode, FALSE,screen);
00739             }
00740         }
00741     } else {
00742         GLCD_drawline(x0, y0, x1, y0, mode, FALSE,screen); // Draw the 4 sides
00743         GLCD_drawline(x0, y1, x1, y1, mode, FALSE,screen);
00744         GLCD_drawline(x0, y0, x0, y1, mode, FALSE,screen);
00745         GLCD_drawline(x1, y0, x1, y1, mode, FALSE,screen);
00746     }
00747     if (fupdate==TRUE)
00748         GLCD_update(screen);
00749 }
00750 
00751 
00752 void  PCD8544MS::GLCD_drawcircle(BYTE x0, BYTE y0, BYTE radius, eFillMode fill, ePixelMode mode, BYTE fupdate,int screen) {
00753     int err, x, y;
00754 
00755     err = -radius;
00756     x   = radius;
00757     y   = 0;
00758 
00759     while (x >= y) {
00760         if (fill==1) {
00761             GLCD_drawline(x0 - x, y0 + y, x0 + x, y0 + y, mode,FALSE,screen);
00762             GLCD_drawline(x0 - x, y0 - y, x0 + x, y0 - y, mode,FALSE,screen);
00763             GLCD_drawline(x0 - y, y0 + x, x0 + y, y0 + x, mode,FALSE,screen);
00764             GLCD_drawline(x0 - y, y0 - x, x0 + y, y0 - x, mode,FALSE,screen);
00765         } else {
00766             GLCD_drawpixel(x0 + x, y0 + y, mode,FALSE,screen);
00767             GLCD_drawpixel(x0 - x, y0 + y, mode,FALSE,screen);
00768             GLCD_drawpixel(x0 + x, y0 - y, mode,FALSE,screen);
00769             GLCD_drawpixel(x0 - x, y0 - y, mode,FALSE,screen);
00770             GLCD_drawpixel(x0 + y, y0 + x, mode,FALSE,screen);
00771             GLCD_drawpixel(x0 - y, y0 + x, mode,FALSE,screen);
00772             GLCD_drawpixel(x0 + y, y0 - x, mode,FALSE,screen);
00773             GLCD_drawpixel(x0 - y, y0 - x, mode,FALSE,screen);
00774         }
00775         err += y;
00776         y++;
00777         err += y;
00778         if (err >= 0) {
00779             x--;
00780             err -= x;
00781             err -= x;
00782         }
00783     }
00784 
00785     if (fupdate==TRUE)
00786         GLCD_update(screen);
00787 
00788 }
00789 
00790 void PCD8544MS::GLCD_drawprogressbar(BYTE  x0, BYTE y0, BYTE w, BYTE h, BYTE percentage,BYTE fupdate,int screen) {
00791     GLCD_drawrectangle(x0,y0,x0+w,y0+h,FILL_OFF,PIXEL_ON, FALSE,screen);
00792     GLCD_drawrectangle(x0+2,y0+2,x0+w-2,y0+h-2,FILL_ON,PIXEL_OFF, FALSE,screen);
00793     GLCD_drawrectangle(x0+2,y0+2,x0+2+(percentage*(w-4)/100),y0+h-2,FILL_ON,PIXEL_ON, FALSE,screen);
00794     if (fupdate==TRUE)
00795         GLCD_update(screen);
00796 }
00797 
00798 void PCD8544MS::GLCD_drawchart(BYTE  x0, BYTE y0, BYTE w, BYTE h, BYTE unitx, BYTE unity,
00799                                eRasterMode rMode, eChartMode cMode,eDrawMode dMode, int16_t * val, int size, int t,int screen)  {
00800     int maxy;
00801     int _scale=1;
00802     int prescale=1;
00803 
00804     signed char v1,v2;
00805     char buffer[4];
00806 
00807     if (size>w)
00808         size=w;
00809 
00810     // search maximum value to calculate scale
00811     if (dMode==DRAW_OVERWRITE) {
00812         maxy=0;
00813         for (int i=0; i<size; i++) {
00814             if (val[i]>maxy)
00815                 maxy=val[i];
00816 
00817         }
00818 
00819         if (maxy>h) {  //scale can be 1,2,5  *10i
00820             prescale= ((maxy-1)/((h/unity)*unity));
00821             _scale=1;
00822             while (prescale>10) {
00823                 _scale=_scale*10;
00824                 prescale=prescale/10;
00825             }
00826             if (prescale>1)
00827                 _scale=_scale*5;
00828             else if (prescale==1)
00829                 _scale  =_scale*2;
00830 
00831 
00832         }
00833         Scale=_scale;
00834     }
00835 
00836     if (dMode==DRAW_OVERWRITE) {
00837         GLCD_drawrectangle(x0-11,y0-h,x0+w,y0+4+7,FILL_ON,PIXEL_OFF,FALSE,screen);
00838         GLCD_drawline(x0,y0,x0,y0-h,PIXEL_ON,FALSE,screen);
00839         GLCD_drawline(x0,y0,x0+w,y0,PIXEL_ON,FALSE,screen);
00840 
00841         //drawrectangle(x0,y0-h,x0+w,y0,FILL_OFF,PIXEL_ON,FALSE);
00842 
00843         for (int i=0; i<=h; i++) {
00844             if ((i % unity) == 0) {
00845                 GLCD_drawpixel(x0-2,y0-i,PIXEL_ON,FALSE,screen);
00846                 //    drawpixel(x0+w+2,y0-i,PIXEL_ON,FALSE);
00847 
00848                 if (rMode==RASTER_ON) {
00849                     for (int r=0; r<=w; r++) {
00850                         if ((r % 2) ==0)
00851                             GLCD_drawpixel(x0+r,y0-i,PIXEL_ON,FALSE,screen);
00852                     }
00853                 }
00854                 // draw vertical axis labels
00855 
00856                 itostr(buffer,i*Scale);
00857 
00858                 //  pc_PCD8544.traceOut(" %i %s |",i*Scale,buffer);
00859                 GLCD_writeString(x0-11,y0-i+1,buffer,VERYSMALLFONT,PIXEL_OFF,DISPLAY_NORMAL,SPACE_NONE,FALSE,screen);
00860 
00861             }
00862             if ((i % 2) == 0) {
00863                 GLCD_drawpixel(x0-1,y0-i,PIXEL_ON,FALSE,screen);
00864                 //      drawpixel(x0+w+1,y0-i,PIXEL_ON,FALSE);
00865             }
00866         }
00867 
00868         for (int i=0; i<=w; i++) {
00869             if (((i+(t % unitx)) % unitx) == 0) {
00870                 GLCD_drawpixel(x0+i,y0+2,PIXEL_ON,FALSE,screen);
00871 
00872                 if (rMode==RASTER_ON) {
00873                     for (int r=0; r<=h; r++) {
00874                         if ((r % 2) ==0)
00875                             GLCD_drawpixel(x0+i,y0-r,PIXEL_ON,FALSE,screen);
00876                     }
00877                 }
00878                 if (((t-w+i)/unitx)>=0)
00879                     snprintf(buffer,3,"%i",((t-w+i)/unitx));
00880                 else
00881                     snprintf(buffer,3,"%i",24+((t-w+i)/unitx));
00882 
00883                 // pc_PCD8544.traceOut(" %i %s ",(t-w+i)/unitx,buffer);
00884                 GLCD_writeString(x0+i-3,y0+4,buffer,VERYSMALLFONT,PIXEL_OFF,DISPLAY_NORMAL,SPACE_NORMAL,FALSE,screen);
00885             }
00886             if ((i % 2) == 0) {
00887                 GLCD_drawpixel(x0+i,y0+1,PIXEL_ON,FALSE,screen);
00888             }
00889         }
00890         //     update();
00891     }
00892 
00893     for (int i=0; i<size; i++) {
00894         //   pc_PCD8544.traceOut(" %i ",val[i]);
00895         v1 = val[i] / Scale;
00896         if (v1>h)
00897             v1=h;
00898 
00899         if (i!=(size-1)) {
00900             v2 = val[i+1] / Scale;
00901             if (v2>h)
00902                 v2=h;
00903         } else
00904             v2=v1;
00905 
00906 
00907         switch (cMode) {
00908             case C_POINT: {
00909                 GLCD_drawpixel(x0+i,y0-v1,PIXEL_ON,FALSE,screen);
00910                 break;
00911             }
00912             case C_LINE: {
00913                 GLCD_drawline(x0+i,y0-v1,x0+i+1,y0-v2,PIXEL_ON,FALSE,screen);
00914                 break;
00915             }
00916             case C_VLINE: {
00917                 GLCD_drawline(x0+i,y0-v1,x0+i,y0,PIXEL_ON,FALSE,screen);
00918                 break;
00919             }
00920         }
00921     }
00922 
00923     GLCD_update(screen);
00924 }
00925