SG12864A

Dependents:   SG12864A_TestProgram

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SG12864A.cpp Source File

SG12864A.cpp

00001 /**
00002  * SG12864A Graphics LCD module driver class (Version 0.0.1)
00003  *
00004  * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
00005  * http://shinta.main.jp/
00006  *
00007  * See also ...
00008  * http://mbed.org/users/shintamainjp/notebook/sg12864asunlike-display-graphics-lcd-driver/
00009  */
00010 
00011 #include "SG12864A.h"
00012 
00013 #define setPixel(x,y) buffer[((COLUMNS * 2)* ((y) / 8)) + (x)] |= (1 << ((y) % 8))
00014 #define unsetPixel(x,y) buffer[((COLUMNS * 2)* ((y) / 8)) + (x)] &= ~(1 << ((y) % 8))
00015 #define swap(a,b) {int c=a;a=b;b=c;}
00016 
00017 const uint8_t SG12864A::font5x7_data[] = {
00018     0x00, 0x00, 0x00, 0x00, 0x00, // (white space)
00019     0x00, 0x00, 0x5F, 0x00, 0x00, // !
00020     0x00, 0x07, 0x00, 0x07, 0x00, // "
00021     0x14, 0x7F, 0x14, 0x7F, 0x14, // #
00022     0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
00023     0x23, 0x13, 0x08, 0x64, 0x62, // %
00024     0x36, 0x49, 0x55, 0x22, 0x50, // &
00025     0x00, 0x05, 0x03, 0x00, 0x00, // '
00026     0x00, 0x1C, 0x22, 0x41, 0x00, // (
00027     0x00, 0x41, 0x22, 0x1C, 0x00, // )
00028     0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
00029     0x08, 0x08, 0x3E, 0x08, 0x08, // +
00030     0x00, 0x50, 0x30, 0x00, 0x00, // ,
00031     0x08, 0x08, 0x08, 0x08, 0x08, // -
00032     0x00, 0x60, 0x60, 0x00, 0x00, // .
00033     0x20, 0x10, 0x08, 0x04, 0x02, // /
00034     0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
00035     0x00, 0x42, 0x7F, 0x40, 0x00, // 1
00036     0x42, 0x61, 0x51, 0x49, 0x46, // 2
00037     0x21, 0x41, 0x45, 0x4B, 0x31, // 3
00038     0x18, 0x14, 0x12, 0x7F, 0x10, // 4
00039     0x27, 0x45, 0x45, 0x45, 0x39, // 5
00040     0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
00041     0x01, 0x71, 0x09, 0x05, 0x03, // 7
00042     0x36, 0x49, 0x49, 0x49, 0x36, // 8
00043     0x06, 0x49, 0x49, 0x29, 0x1E, // 9
00044     0x00, 0x36, 0x36, 0x00, 0x00, // :
00045     0x00, 0x56, 0x36, 0x00, 0x00, // ;
00046     0x00, 0x08, 0x14, 0x22, 0x41, // <
00047     0x14, 0x14, 0x14, 0x14, 0x14, // =
00048     0x41, 0x22, 0x14, 0x08, 0x00, // >
00049     0x02, 0x01, 0x51, 0x09, 0x06, // ?
00050     0x32, 0x49, 0x79, 0x41, 0x3E, // @
00051     0x7E, 0x11, 0x11, 0x11, 0x7E, // A
00052     0x7F, 0x49, 0x49, 0x49, 0x36, // B
00053     0x3E, 0x41, 0x41, 0x41, 0x22, // C
00054     0x7F, 0x41, 0x41, 0x22, 0x1C, // D
00055     0x7F, 0x49, 0x49, 0x49, 0x41, // E
00056     0x7F, 0x09, 0x09, 0x01, 0x01, // F
00057     0x3E, 0x41, 0x41, 0x51, 0x32, // G
00058     0x7F, 0x08, 0x08, 0x08, 0x7F, // H
00059     0x00, 0x41, 0x7F, 0x41, 0x00, // I
00060     0x20, 0x40, 0x41, 0x3F, 0x01, // J
00061     0x7F, 0x08, 0x14, 0x22, 0x41, // K
00062     0x7F, 0x40, 0x40, 0x40, 0x40, // L
00063     0x7F, 0x02, 0x04, 0x02, 0x7F, // M
00064     0x7F, 0x04, 0x08, 0x10, 0x7F, // N
00065     0x3E, 0x41, 0x41, 0x41, 0x3E, // O
00066     0x7F, 0x09, 0x09, 0x09, 0x06, // P
00067     0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
00068     0x7F, 0x09, 0x19, 0x29, 0x46, // R
00069     0x46, 0x49, 0x49, 0x49, 0x31, // S
00070     0x01, 0x01, 0x7F, 0x01, 0x01, // T
00071     0x3F, 0x40, 0x40, 0x40, 0x3F, // U
00072     0x1F, 0x20, 0x40, 0x20, 0x1F, // V
00073     0x7F, 0x20, 0x18, 0x20, 0x7F, // W
00074     0x63, 0x14, 0x08, 0x14, 0x63, // X
00075     0x03, 0x04, 0x78, 0x04, 0x03, // Y
00076     0x61, 0x51, 0x49, 0x45, 0x43, // Z
00077     0x00, 0x00, 0x7F, 0x41, 0x41, // [
00078     0x02, 0x04, 0x08, 0x10, 0x20, // /
00079     0x41, 0x41, 0x7F, 0x00, 0x00, // ]
00080     0x04, 0x02, 0x01, 0x02, 0x04, // ^
00081     0x40, 0x40, 0x40, 0x40, 0x40, // _
00082     0x00, 0x01, 0x02, 0x04, 0x00, // `
00083     0x20, 0x54, 0x54, 0x54, 0x78, // a
00084     0x7F, 0x48, 0x44, 0x44, 0x38, // b
00085     0x38, 0x44, 0x44, 0x44, 0x20, // c
00086     0x38, 0x44, 0x44, 0x48, 0x7F, // d
00087     0x38, 0x54, 0x54, 0x54, 0x18, // e
00088     0x08, 0x7E, 0x09, 0x01, 0x02, // f
00089     0x08, 0x14, 0x54, 0x54, 0x3C, // g
00090     0x7F, 0x08, 0x04, 0x04, 0x78, // h
00091     0x00, 0x44, 0x7D, 0x40, 0x00, // i
00092     0x20, 0x40, 0x44, 0x3D, 0x00, // j
00093     0x00, 0x7F, 0x10, 0x28, 0x44, // k
00094     0x00, 0x41, 0x7F, 0x40, 0x00, // l
00095     0x7C, 0x04, 0x18, 0x04, 0x78, // m
00096     0x7C, 0x08, 0x04, 0x04, 0x78, // n
00097     0x38, 0x44, 0x44, 0x44, 0x38, // o
00098     0x7C, 0x14, 0x14, 0x14, 0x08, // p
00099     0x08, 0x14, 0x14, 0x18, 0x7C, // q
00100     0x7C, 0x08, 0x04, 0x04, 0x08, // r
00101     0x48, 0x54, 0x54, 0x54, 0x20, // s
00102     0x04, 0x3F, 0x44, 0x40, 0x20, // t
00103     0x3C, 0x40, 0x40, 0x20, 0x7C, // u
00104     0x1C, 0x20, 0x40, 0x20, 0x1C, // v
00105     0x3C, 0x40, 0x30, 0x40, 0x3C, // w
00106     0x44, 0x28, 0x10, 0x28, 0x44, // x
00107     0x0C, 0x50, 0x50, 0x50, 0x3C, // y
00108     0x44, 0x64, 0x54, 0x4C, 0x44, // z
00109     0x00, 0x08, 0x36, 0x41, 0x00, // {
00110     0x00, 0x00, 0x7F, 0x00, 0x00, // |
00111     0x00, 0x41, 0x36, 0x08, 0x00, // }
00112     0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
00113     0x08, 0x1C, 0x2A, 0x08, 0x08  // <-
00114 };
00115 
00116 SG12864A::SG12864A(PinName di,
00117                    PinName rw,
00118                    PinName en,
00119                    PinName db0,
00120                    PinName db1,
00121                    PinName db2,
00122                    PinName db3,
00123                    PinName db4,
00124                    PinName db5,
00125                    PinName db6,
00126                    PinName db7,
00127                    PinName cs1,
00128                    PinName cs2,
00129                    PinName res)
00130         :
00131         ioDI(di),
00132         ioRW(rw),
00133         ioEN(en),
00134         ioDB(db0, db1, db2, db3, db4, db5, db6, db7),
00135         ioCS1(cs1),
00136         ioCS2(cs2),
00137         ioRES(res) {
00138     bufferClear();
00139     setDirectionToWrite();
00140 }
00141 
00142 SG12864A::~SG12864A() {
00143 }
00144 
00145 void SG12864A::bufferPush(void) {
00146     for (uint8_t i = 0; i < PAGES; i++) {
00147         // CS1
00148         setPageAddress(SG12864A::CS1, i);
00149         setColumnAddress(SG12864A::CS1, 0);
00150         for (uint8_t j = 0; j < COLUMNS; j++) {
00151             writeData(CS1, buffer[0 + ((COLUMNS * 2) * i) + j]);
00152         }
00153         // CS2
00154         setPageAddress(SG12864A::CS2, i);
00155         setColumnAddress(SG12864A::CS2, 0);
00156         for (uint8_t j = 0; j < COLUMNS; j++) {
00157             writeData(CS2, buffer[COLUMNS + ((COLUMNS * 2) * i) + j]);
00158         }
00159     }
00160 }
00161 
00162 void SG12864A::bufferPull(void) {
00163 }
00164 
00165 void SG12864A::bufferClear(bool reverse) {
00166     for (int i = 0; i < sizeof(buffer); i++) {
00167         if (reverse) {
00168             buffer[i] = 0xFF;
00169         } else {
00170             buffer[i] = 0x00;
00171         }
00172     }
00173 }
00174 
00175 void SG12864A::bufferDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
00176     /*
00177      * Bresenham's line algorithm
00178      */
00179     bool steep = abs(y2 - y1) > abs(x2 - x1);
00180     if (steep) {
00181         swap(x1, y1);
00182         swap(x2, y2);
00183     }
00184     if (x1 > x2) {
00185         swap(x1, x2);
00186         swap(y1, y2);
00187     }
00188     int deltax = x2 - x1;
00189     int deltay = abs(y2 - y1);
00190     int error = deltax / 2;
00191     int ystep;
00192     int y = y1;
00193     if (y1 < y2) {
00194         ystep = 1;
00195     } else {
00196         ystep = -1;
00197     }
00198     for (int x = x1; x <= x2; x++) {
00199         if (steep) {
00200             if (reverse) {
00201                 unsetPixel(y, x);
00202             } else {
00203                 setPixel(y, x);
00204             }
00205         } else {
00206             if (reverse) {
00207                 unsetPixel(x, y);
00208             } else {
00209                 setPixel(x, y);
00210             }
00211         }
00212         error = error - deltay;
00213         if (error < 0) {
00214             y = y + ystep;
00215             error = error + deltax;
00216         }
00217     }
00218 }
00219 
00220 void SG12864A::bufferDrawBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
00221     for (int x = x1; x <= x2; x++) {
00222         if (reverse) {
00223             unsetPixel(x, y1);
00224             unsetPixel(x, y2);
00225         } else {
00226             setPixel(x, y1);
00227             setPixel(x, y2);
00228         }
00229     }
00230     for (int y = y1; y <= y2; y++) {
00231         if (reverse) {
00232             unsetPixel(x1, y);
00233             unsetPixel(x2, y);
00234         } else {
00235             setPixel(x1, y);
00236             setPixel(x2, y);
00237         }
00238     }
00239 }
00240 
00241 void SG12864A::bufferFillBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
00242     for (int x = x1; x <= x2; x++) {
00243         for (int y = y1; y <= y2; y++) {
00244             if (reverse) {
00245                 unsetPixel(x, y);
00246             } else {
00247                 setPixel(x, y);
00248             }
00249         }
00250     }
00251 }
00252 
00253 void SG12864A::bufferDrawString(uint8_t x, uint8_t y, char * str, bool reverse) {
00254     char *p = str;
00255     int cnt = 0;
00256     while (*p) {
00257         bufferDrawChar(x + (FONT_X * cnt), y, *p, reverse);
00258         p++;
00259         cnt++;
00260     }
00261 }
00262 
00263 void SG12864A::bufferDrawChar(uint8_t x, uint8_t y, char c, bool reverse) {
00264     if ((FONT_MIN_CODE <= c) &&(c <= FONT_MAX_CODE)) {
00265         int aofs = (c - FONT_MIN_CODE) * FONT_X;
00266         for (int i = 0; i < FONT_X; i++) {
00267             uint8_t pat = font5x7_data[aofs + i];
00268             for (int j = 0; j < FONT_Y; j++) {
00269                 if (pat & (1 << j)) {
00270                     if (reverse) {
00271                         unsetPixel(x + i, y + j);
00272                     } else {
00273                         setPixel(x + i, y + j);
00274                     }
00275                 } else {
00276                     if (reverse) {
00277                         setPixel(x + i, y + j);
00278                     } else {
00279                         unsetPixel(x + i, y + j);
00280                     }
00281                 }
00282             }
00283         }
00284     } else {
00285         for (int i = 0; i < FONT_X; i++) {
00286             uint8_t pat = (i % 2) ? 0x55 : 0xAA;
00287             for (int j = 0; j < FONT_Y; j++) {
00288                 if (pat & (1 << j)) {
00289                     if (reverse) {
00290                         unsetPixel(x + i, y + j);
00291                     } else {
00292                         setPixel(x + i, y + j);
00293                     }
00294                 } else {
00295                     if (reverse) {
00296                         setPixel(x + i, y + j);
00297                     } else {
00298                         unsetPixel(x + i, y + j);
00299                     }
00300                 }
00301             }
00302         }
00303     }
00304 }
00305 
00306 void SG12864A::bufferDrawCheckbox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool state, bool reverse) {
00307     bufferDrawBox(x1, y1, x2, y2, reverse);
00308     if (state) {
00309         bufferDrawLine(x1, y1, x2, y2, reverse);
00310         bufferDrawLine(x1, y2, x2, y1, reverse);
00311     }
00312 }
00313 
00314 void SG12864A::bufferDrawProgressbar(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, int min, int max, int value, bool reverse) {
00315     bufferDrawBox(x1, y1, x2, y2, reverse);
00316     if ((value < min) || (max < value)) {
00317         return;
00318     }
00319     int tmp_max = max - min;
00320     int tmp_val = value - min;
00321     int pix = ((x2 - x1) * tmp_val) / tmp_max;
00322     bufferFillBox(x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, reverse);
00323 }
00324 
00325 /**
00326  * High Level Interface.
00327  *
00328  * Reset display module.
00329  */
00330 void SG12864A::reset(void) {
00331     reset(true);
00332     wait_ms(200);
00333     reset(false);
00334     wait_ms(200);
00335 
00336     setDisplayOnOff(SG12864A::CS1, true);
00337     setDisplayOnOff(SG12864A::CS2, true);
00338     setDisplayStartLine(SG12864A::CS1, 0);
00339     setDisplayStartLine(SG12864A::CS2, 0);
00340     setPageAddress(SG12864A::CS1, 0);
00341     setPageAddress(SG12864A::CS2, 0);
00342     setColumnAddress(SG12864A::CS1, 0);
00343     setColumnAddress(SG12864A::CS2, 0);
00344 }
00345 
00346 /**
00347  * High Level Interface.
00348  *
00349  * Clear display module.
00350  */
00351 void SG12864A::clear(void) {
00352     for (uint8_t page = 0; page < PAGES; page++) {
00353         for (uint8_t column = 0; column < COLUMNS; column++) {
00354             // CS1
00355             setPageAddress(SG12864A::CS1, page);
00356             setColumnAddress(SG12864A::CS1, column);
00357             writeData(CS1, 0x00);
00358             // CS2
00359             setPageAddress(SG12864A::CS2, page);
00360             setColumnAddress(SG12864A::CS2, column);
00361             writeData(CS2, 0x00);
00362         }
00363     }
00364     // CS1
00365     setPageAddress(SG12864A::CS1, 0);
00366     setColumnAddress(SG12864A::CS1, 0);
00367     writeData(CS1, 0x00);
00368     // CS2
00369     setPageAddress(SG12864A::CS2, 0);
00370     setColumnAddress(SG12864A::CS2, 0);
00371     writeData(CS2, 0x00);
00372 }
00373 
00374 /**
00375  * Middle Level Interface.
00376  *
00377  * Set display on/off.
00378  *
00379  * @param t Target (CS1, CS2).
00380  * @param on ON/OFF (true, false).
00381  */
00382 void SG12864A::setDisplayOnOff(Target t, bool on) {
00383     setDirectionToWrite();
00384     uint8_t c = 0x3e | (on ? 0x01 : 0x00);
00385     write(t, SG12864A::Instruction, c);
00386     wait_us(1);
00387 }
00388 
00389 /**
00390  * Middle Level Interface.
00391  *
00392  * Set display start line.
00393  *
00394  * @param t Target (CS1, CS2).
00395  * @param addr Display start line (0-63).
00396  */
00397 void SG12864A::setDisplayStartLine(Target t, uint8_t addr) {
00398     setDirectionToWrite();
00399     uint8_t c = 0xc0 | (addr & 0x3f);
00400     write(t, SG12864A::Instruction, c);
00401     wait_us(1);
00402 }
00403 
00404 /**
00405  * Middle Level Interface.
00406  *
00407  * Set page address.
00408  *
00409  * @param t Target (CS1, CS2).
00410  * @param addr Page address(0-7).
00411  */
00412 void SG12864A::setPageAddress(Target t, uint8_t addr) {
00413     setDirectionToWrite();
00414     uint8_t c = 0xb8 | (addr & 0x07);
00415     write(t, SG12864A::Instruction, c);
00416     wait_us(1);
00417 }
00418 
00419 /**
00420  * Middle Level Interface.
00421  *
00422  * Set column address.
00423  *
00424  * @param t Target. (CS1, CS2)
00425  * @param addr Column address (0-63).
00426  */
00427 void SG12864A::setColumnAddress(Target t, uint8_t addr) {
00428     setDirectionToWrite();
00429     uint8_t c = 0x40 | (addr & 0x3f);
00430     write(t, SG12864A::Instruction, c);
00431     wait_us(1);
00432 }
00433 
00434 /**
00435  * Middle Level Interface.
00436  */
00437 void SG12864A::readStatus(Target t, uint8_t *c) {
00438     setDirectionToRead();
00439     read(t, SG12864A::Instruction, c);
00440     wait_us(1);
00441 }
00442 
00443 /**
00444  * Middle Level Interface.
00445  */
00446 void SG12864A::writeData(Target t, uint8_t c) {
00447     setDirectionToWrite();
00448     write(t, SG12864A::Data, c);
00449     wait_us(1);
00450 }
00451 
00452 /**
00453  * Middle Level Interface.
00454  */
00455 void SG12864A::readData(Target t, uint8_t *c) {
00456     setDirectionToRead();
00457     read(t, SG12864A::Data, c);
00458     wait_us(1);
00459 }
00460 
00461 /**
00462  * Low Level Interface.
00463  */
00464 void SG12864A::setDirectionToRead() {
00465     ioDB.input();
00466     ioRW = 1;
00467 }
00468 
00469 /**
00470  * Low Level Interface.
00471  */
00472 void SG12864A::setDirectionToWrite() {
00473     ioDB.output();
00474     ioRW = 0;
00475 }
00476 
00477 /**
00478  * Low Level Interface.
00479  */
00480 void SG12864A::write(Target t, Mode m, uint8_t c) {
00481     switch (t) {
00482         case CS1:
00483             ioCS1 = 1;
00484             ioCS2 = 0;
00485             break;
00486         case CS2:
00487             ioCS1 = 0;
00488             ioCS2 = 1;
00489             break;
00490     }
00491     switch (m) {
00492         case Data:
00493             ioDI = 1;
00494             break;
00495         case Instruction:
00496             ioDI = 0;
00497             break;
00498     }
00499     ioDB = c;
00500     wait_us(1);
00501     ioEN = 1;
00502     wait_us(1);
00503     ioEN = 0;
00504     wait_us(5);
00505 }
00506 
00507 /**
00508  * Low Level Interface.
00509  */
00510 void SG12864A::read(Target t, Mode m, uint8_t *c) {
00511     // TODO
00512 }
00513 
00514 /**
00515  * Low Level Interface.
00516  */
00517 void SG12864A::reset(bool b) {
00518     if (b) {
00519         ioRES = 0;
00520     } else {
00521         ioRES = 1;
00522     }
00523 }