This library provides an OLED (SSD1332, 96x64xRGB) interface that best utilizes SSD1332's graphic accelerator (especially for drawing lines and rectangles). Though it still has some limitations --- it does not support 'clipping', odd numbers for circle/ellipse diameter, and so on, it runs quite fast. Enjoy the speed.

Dependents:   OLEDexample

Fork of OLEDaccel by Hideki Kozima

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OLEDaccel.cpp Source File

OLEDaccel.cpp

00001 //
00002 //  OLEDaccel: 96x64 OLED driver
00003 //  (version 0.2, August 17, 2012)
00004 //  xkozima@myu.ac.jp
00005 
00006 #include "OLEDaccel.h"  
00007 #include "font6x8.h"                                                          
00008 
00009 OLED::OLED (PinName rstPin, PinName csPin, PinName dcPin, PinName mosiPin, PinName sckPin) :
00010     rst(rstPin), cs(csPin), dc(dcPin), spi(mosiPin, NC, sckPin)
00011 {
00012     //  setup spi (8bit master @48MHz)                                          
00013     spi.format(8,3);
00014     spi.frequency(48000000);
00015     wait_ms(20);
00016 
00017     //  reset OLED                                                              
00018     rst = 0;
00019     wait_ms(20);
00020     rst = 1;
00021     wait_ms(20);
00022 
00023     //  init command
00024     unsigned char cmd1[] = {0xa0, 0x70};
00025     cmdOut(cmd1, 2);
00026     unsigned char cmd2[] = {0xaf};
00027     cmdOut(cmd2, 1);
00028     unsigned char cmd3[] = {0x26, 0x01};
00029     cmdOut(cmd3, 2);
00030     
00031     //  clear flags
00032     reversal = false;
00033     filling = true;
00034 
00035     //  clear and display on
00036     rect(0, 0, 96, 64, 0, 1);
00037     wait(0.1);
00038     cmdOutOne(0xaf);    //  display on
00039 }
00040 
00041 void  OLED::cmdOutOne(unsigned char cmdOne)
00042 {
00043      dc = 0;
00044      cs = 0;
00045      spi.write(cmdOne);
00046      cs = 1;
00047 }
00048 
00049 void  OLED::cmdOut(unsigned char *cmd, int length)
00050 {
00051      dc = 0;
00052      cs = 0;
00053      for (int i = 0; i < length; i++) {
00054         spi.write(*cmd++);
00055      }
00056      cs = 1;
00057 }
00058 
00059 void  OLED::dataOut(unsigned short *data, int length)
00060 {
00061      dc = 1;
00062      cs = 0;
00063      for (int i = 0; i < length; i++) {
00064         unsigned short d16 = *data++;
00065         spi.write((unsigned char) ((d16 & 0xff00) >> 8));
00066         spi.write((unsigned char) (d16 & 0x00ff));
00067      }
00068      cs = 1;
00069 }
00070 
00071 unsigned short OLED::color (int r, int g, int b)
00072 {
00073     return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3);
00074 }
00075 
00076 void OLED::clear (unsigned short color)
00077 {
00078     rect(0, 0, 96, 64, color, 1);
00079 }
00080 
00081 void OLED::point(int x, int y, unsigned short color)
00082 {
00083     //  draw a point (a small rectangle/filled)
00084     unsigned char c1 = (color & 0xf800) >> 10, 
00085                   c2 = (color & 0x07e0) >> 5, 
00086                   c3 = (color & 0x001f) << 1;
00087     unsigned char cmd[] = {0x22, x, y, x, y,  
00088                            c1, c2, c3,  c1, c2, c3 };
00089     cmdOut(cmd, 11);
00090 }
00091 
00092 void OLED::rect (int x, int y, int w, int h,
00093                  unsigned short color, int fill )
00094 {
00095     unsigned char c1 = (color & 0xf800) >> 10, 
00096                   c2 = (color & 0x07e0) >> 5, 
00097                   c3 = (color & 0x001f) << 1;
00098     //  
00099     //  fill or no fill
00100     if (fill) {
00101         if (! filling) {
00102             unsigned char cmdF[] = {0x26, 1};
00103             cmdOut(cmdF, 2); 
00104             filling = true;     
00105         }
00106     }
00107     else {
00108         if (filling) {
00109             unsigned char cmdN[] = {0x26, 0};
00110             cmdOut(cmdN, 2);
00111             filling = false;
00112         }
00113     }
00114     //  un-reverse
00115     if (reversal) {
00116         unsigned char cmdN[] = {0xa0, 0x70};
00117         cmdOut(cmdN, 2);
00118         reversal = false;
00119     }
00120     //  draw/fill the rectangle
00121     unsigned char cmd[] = {0x22, x, y, x + w - 1, y + h - 1, 
00122                            c1, c2, c3,  c1, c2, c3 };
00123     cmdOut(cmd, 11);
00124     //  wait
00125     wait_us(w * h / 10);
00126 }
00127 
00128 void OLED::line(int x1, int y1, int x2, int y2, unsigned short color)
00129 {
00130     unsigned char c1 = (color & 0xf800) >> 10, 
00131                   c2 = (color & 0x07e0) >> 5, 
00132                   c3 = (color & 0x001f) << 1;
00133     if (x1 < x2) {
00134         if (y1 < y2) {
00135             //  normal
00136             unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
00137             if (reversal) {
00138                 unsigned char cmdN[] = {0xa0, 0x70};
00139                 cmdOut(cmdN, 2);
00140                 reversal = false;
00141             }
00142             cmdOut(cmd, 8);
00143         }
00144         else if (y1 > y2) {
00145             //  reversal
00146             if (! reversal) {
00147                 unsigned char cmdR[] = {0xa0, 0x72};
00148                 cmdOut(cmdR, 2);
00149                 reversal = true;
00150             }
00151             unsigned char cmd[]  = {0x21, 95 - x2, y2, 95 - x1, y1, c1, c2, c3};
00152             cmdOut(cmd, 8);
00153         }
00154         else {  //  y1 == y2
00155             //  normal
00156             unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
00157             if (reversal) {
00158                 unsigned char cmdN[] = {0xa0, 0x70};
00159                 cmdOut(cmdN, 2);
00160                 reversal = false;
00161             }
00162             cmdOut(cmd, 8);
00163         }
00164     }
00165     else if (x1 > x2) {
00166         if (y1 < y2) {
00167             //  reversal
00168             if (! reversal) {
00169                 unsigned char cmdR[] = {0xa0, 0x72};
00170                 cmdOut(cmdR, 2);
00171                 reversal = true;
00172             }
00173             unsigned char cmd[]  = {0x21, 95 - x2, y2, 95 - x1, y1, c1, c2, c3};
00174             cmdOut(cmd, 8);
00175         }
00176         else if (y1 > y2) {
00177             //  normal
00178             unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
00179             if (reversal) {
00180                 unsigned char cmdN[] = {0xa0, 0x70};
00181                 cmdOut(cmdN, 2);
00182                 reversal = false;
00183             }
00184             cmdOut(cmd, 8);
00185         }
00186         else {  //  y1 == y2
00187             //  reversal
00188             unsigned char cmd[] = {0xa0, 0x72, 
00189                                    0x21, 95 - x2, y2, 95 - x1, y1, c1, c2, c3,
00190                                    0xa0, 0x70 };
00191             cmdOut(cmd, 12);
00192         }
00193     }
00194     else {  //  x1 == x2
00195         if (y1 < y2) {
00196             //  normal
00197             unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
00198             if (reversal) {
00199                 unsigned char cmdN[] = {0xa0, 0x70};
00200                 cmdOut(cmdN, 2);
00201                 reversal = false;
00202             }
00203             cmdOut(cmd, 8);
00204         }
00205         else if (y1 > y2) {
00206             //  normal (force downward)
00207             unsigned char cmd[]  = {0x21, x2, y2, x1, y1, c1, c2, c3};
00208             cmdOut(cmd, 8);
00209         }
00210         else {  //  y1 == y2
00211             //  normal (point)
00212             unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
00213             if (reversal) {
00214                 unsigned char cmdN[] = {0xa0, 0x70};
00215                 cmdOut(cmdN, 2);
00216                 reversal = false;
00217             }
00218             cmdOut(cmd, 8);
00219         }
00220     }
00221     //  wait
00222     wait_us(1);
00223 }
00224 
00225 void OLED::circle(int x, int y, int r, unsigned short color, int fill)
00226 {
00227     //  exception
00228     if (r < 1) {
00229         line(x, y, x, y, color);
00230         return;
00231     } else if (r == 1) {
00232         rect(x - 1, y - 1, 3, 3, color, fill);
00233         return;
00234     }
00235     //  ok, go
00236     int xx = 0, 
00237         yy = r, 
00238         err = 2 - 2 * r;
00239     //  iteration
00240     do {
00241         //  draw it! 
00242         if (fill) {
00243             line(x + xx, y + yy, x + xx, y, color);
00244             line(x - xx, y + yy, x, y + yy, color);
00245             line(x - xx, y - yy, x - xx, y, color);
00246             line(x + xx, y - yy, x, y - yy, color);
00247         }
00248         else {
00249             point(x + xx, y + yy, color);
00250             point(x - xx, y + yy, color);
00251             point(x - xx, y - yy, color);
00252             point(x + xx, y - yy, color);
00253         }
00254         //  walk
00255         if (err > -yy) {
00256             yy--;
00257             err += 1 - 2 * yy;
00258         }
00259         if (err <= xx) {
00260             xx++;
00261             err += 1 + 2 * xx;
00262         }
00263     } while (yy >= 0);
00264 }
00265 
00266 void OLED::ellipse(int x, int y, int rx, int ry, unsigned short color, int fill)
00267 {
00268     //  exception
00269     if (rx < 1) {
00270         line(x, y - ry, x, y + ry, color);
00271         return;
00272     }
00273     else if (ry < 1) {
00274         line(x - rx, y, x + rx, y, color);
00275         return;
00276     }
00277     //  ok, go
00278     int xx = -rx, yy = 0;
00279     int e2 = ry, 
00280         dx = (2 * xx + 1) * e2 * e2, 
00281         dy = xx * xx, 
00282         err = dx + dy;
00283     do {
00284         if (fill) {
00285             line(x + xx, y + yy, x + xx, y, color);
00286             line(x - xx, y + yy, x, y + yy, color);
00287             line(x - xx, y - yy, x - xx, y, color);
00288             line(x + xx, y - yy, x, y - yy, color);
00289         }
00290         else {
00291             point(x + xx, y + yy, color);
00292             point(x - xx, y + yy, color);
00293             point(x - xx, y - yy, color);
00294             point(x + xx, y - yy, color);
00295         }
00296         e2 = 2 * err;
00297         if (e2 >= dx) {
00298             xx++;
00299             dx += 2 * ry * ry;
00300             err += dx;
00301         }
00302         if (e2 <= dy) {
00303             yy++;
00304             dy += 2 * rx * rx;
00305             err += dy;
00306         }
00307     } while (xx <= 0);
00308     if (fill) {
00309         while (yy++ < ry) {
00310             line(x, y + yy, x, y, color);
00311             line(x, y - yy, x, y, color);
00312         }
00313     }
00314     else {
00315         while (yy++ < ry) {
00316             point(x, y + yy, color);
00317             point(x, y - yy, color);
00318         }
00319     }
00320 }
00321 
00322 void OLED::image(int x, int y, int w, int h, unsigned short *image16)
00323 {
00324     //  un-reverse
00325     if (reversal) {
00326         unsigned char cmdN[] = {0xa0, 0x70};
00327         cmdOut(cmdN, 2);
00328         reversal = false;
00329     }
00330     //  setup the region to fill
00331     unsigned char cmd[]={0x15, x, x+w-1, 0x75, y, y+h-1};
00332     cmdOut(cmd, 6);
00333     //  fill up the region with the image data
00334     dataOut(image16, w * h);
00335     //  wait
00336     wait_us(100);
00337 }
00338 
00339 void OLED::image(int x, int y, int w, int h, const unsigned short *image16)
00340 {
00341     image(x, y, w, h, (unsigned short *) image16);
00342 }
00343 
00344 void OLED::image(int x, int y, int w, int h, unsigned char *image8x3)
00345 {
00346     //  un-reverse
00347     if (reversal) {
00348         unsigned char cmdN[] = {0xa0, 0x70};
00349         cmdOut(cmdN, 2);
00350         reversal = false;
00351     }
00352     //  setup the region to fill
00353     unsigned char cmd[]={0x15, x, x+w-1, 0x75, y, y+h-1};
00354     cmdOut(cmd, 6);
00355     //  fill up the region with the image data
00356     int size = w * h;
00357     for (int k = 0; k < size; k++) {
00358         unsigned char r, g, b;
00359         b = *image8x3++;
00360         g = *image8x3++;
00361         r = *image8x3++;
00362         unsigned short data16 = color(r, g, b);
00363         dataOut(&data16, 1);
00364     }
00365     //  wait
00366     wait_us(100);
00367 }
00368 
00369 void OLED::image(int x, int y, int w, int h, const unsigned char *image8x3)
00370 {
00371     image(x, y, w, h, (unsigned char *) image8x3);
00372 }
00373 
00374 void OLED::text(int x, int y, char *string, unsigned short color)
00375 {
00376     int len = strlen(string);
00377     for (int i = 0; i < len; i++) {
00378         int xx = x + i * 6;
00379         unsigned char code = string[i];
00380         if (code < 0x20 || code >= 0x80) continue;
00381         unsigned char *font = font6x8 + ((code - 0x20) * 6);
00382         for (int fx = 0; fx < 6; fx++) {
00383             if (xx + fx > 95) break;
00384             unsigned char line = *(font + fx);
00385             for (int fy = 0, bit = 0x01; fy < 8; fy++, bit <<= 1) {
00386                 if (line & bit) point(xx + fx, y + fy, color);
00387             }
00388         }
00389     }
00390 }
00391 
00392 void OLED::text(int x, int y, char *string, unsigned short colorF, unsigned short colorB)
00393 {
00394     //  clear the background
00395     int w = strlen(string) * 6;
00396     if (x + w > 95) w = 95 - x;
00397     rect(x, y, w, 8, colorB, 1);
00398     //  overwrite the text
00399     text(x, y, string, colorF);
00400 }