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

Revision:
0:76a5ae915f62
diff -r 000000000000 -r 76a5ae915f62 OLEDaccel.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OLEDaccel.cpp	Fri Aug 17 15:30:29 2012 +0000
@@ -0,0 +1,400 @@
+//
+//  OLEDaccel: 96x64 OLED driver
+//  (version 0.2, August 17, 2012)
+//  xkozima@myu.ac.jp
+
+#include "OLEDaccel.h"  
+#include "font6x8.h"                                                          
+
+OLED::OLED (PinName rstPin, PinName csPin, PinName dcPin, PinName mosiPin, PinName sckPin) :
+    rst(rstPin), cs(csPin), dc(dcPin), spi(mosiPin, NC, sckPin)
+{
+    //  setup spi (8bit master @48MHz)                                          
+    spi.format(8,3);
+    spi.frequency(48000000);
+    wait_ms(20);
+
+    //  reset OLED                                                              
+    rst = 0;
+    wait_ms(20);
+    rst = 1;
+    wait_ms(20);
+
+    //  init command
+    unsigned char cmd1[] = {0xa0, 0x70};
+    cmdOut(cmd1, 2);
+    unsigned char cmd2[] = {0xaf};
+    cmdOut(cmd2, 1);
+    unsigned char cmd3[] = {0x26, 0x01};
+    cmdOut(cmd3, 2);
+    
+    //  clear flags
+    reversal = false;
+    filling = true;
+
+    //  clear and display on
+    rect(0, 0, 96, 64, 0, 1);
+    wait(0.1);
+    cmdOutOne(0xaf);    //  display on
+}
+
+void  OLED::cmdOutOne(unsigned char cmdOne)
+{
+     dc = 0;
+     cs = 0;
+     spi.write(cmdOne);
+     cs = 1;
+}
+
+void  OLED::cmdOut(unsigned char *cmd, int length)
+{
+     dc = 0;
+     cs = 0;
+     for (int i = 0; i < length; i++) {
+        spi.write(*cmd++);
+     }
+     cs = 1;
+}
+
+void  OLED::dataOut(unsigned short *data, int length)
+{
+     dc = 1;
+     cs = 0;
+     for (int i = 0; i < length; i++) {
+        unsigned short d16 = *data++;
+        spi.write((unsigned char) ((d16 & 0xff00) >> 8));
+        spi.write((unsigned char) (d16 & 0x00ff));
+     }
+     cs = 1;
+}
+
+unsigned short OLED::color (int r, int g, int b)
+{
+    return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3);
+}
+
+void OLED::clear (unsigned short color)
+{
+    rect(0, 0, 96, 64, color, 1);
+}
+
+void OLED::point(int x, int y, unsigned short color)
+{
+    //  draw a point (a small rectangle/filled)
+    unsigned char c1 = (color & 0xf800) >> 10, 
+                  c2 = (color & 0x07e0) >> 5, 
+                  c3 = (color & 0x001f) << 1;
+    unsigned char cmd[] = {0x22, x, y, x, y,  
+                           c1, c2, c3,  c1, c2, c3 };
+    cmdOut(cmd, 11);
+}
+
+void OLED::rect (int x, int y, int w, int h,
+                 unsigned short color, int fill )
+{
+    unsigned char c1 = (color & 0xf800) >> 10, 
+                  c2 = (color & 0x07e0) >> 5, 
+                  c3 = (color & 0x001f) << 1;
+    //  
+    //  fill or no fill
+    if (fill) {
+        if (! filling) {
+            unsigned char cmdF[] = {0x26, 1};
+            cmdOut(cmdF, 2); 
+            filling = true;     
+        }
+    }
+    else {
+        if (filling) {
+            unsigned char cmdN[] = {0x26, 0};
+            cmdOut(cmdN, 2);
+            filling = false;
+        }
+    }
+    //  un-reverse
+    if (reversal) {
+        unsigned char cmdN[] = {0xa0, 0x70};
+        cmdOut(cmdN, 2);
+        reversal = false;
+    }
+    //  draw/fill the rectangle
+    unsigned char cmd[] = {0x22, x, y, x + w - 1, y + h - 1, 
+                           c1, c2, c3,  c1, c2, c3 };
+    cmdOut(cmd, 11);
+    //  wait
+    wait_us(w * h / 10);
+}
+
+void OLED::line(int x1, int y1, int x2, int y2, unsigned short color)
+{
+    unsigned char c1 = (color & 0xf800) >> 10, 
+                  c2 = (color & 0x07e0) >> 5, 
+                  c3 = (color & 0x001f) << 1;
+    if (x1 < x2) {
+        if (y1 < y2) {
+            //  normal
+            unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
+            if (reversal) {
+                unsigned char cmdN[] = {0xa0, 0x70};
+                cmdOut(cmdN, 2);
+                reversal = false;
+            }
+            cmdOut(cmd, 8);
+        }
+        else if (y1 > y2) {
+            //  reversal
+            if (! reversal) {
+                unsigned char cmdR[] = {0xa0, 0x72};
+                cmdOut(cmdR, 2);
+                reversal = true;
+            }
+            unsigned char cmd[]  = {0x21, 95 - x2, y2, 95 - x1, y1, c1, c2, c3};
+            cmdOut(cmd, 8);
+        }
+        else {  //  y1 == y2
+            //  normal
+            unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
+            if (reversal) {
+                unsigned char cmdN[] = {0xa0, 0x70};
+                cmdOut(cmdN, 2);
+                reversal = false;
+            }
+            cmdOut(cmd, 8);
+        }
+    }
+    else if (x1 > x2) {
+        if (y1 < y2) {
+            //  reversal
+            if (! reversal) {
+                unsigned char cmdR[] = {0xa0, 0x72};
+                cmdOut(cmdR, 2);
+                reversal = true;
+            }
+            unsigned char cmd[]  = {0x21, 95 - x2, y2, 95 - x1, y1, c1, c2, c3};
+            cmdOut(cmd, 8);
+        }
+        else if (y1 > y2) {
+            //  normal
+            unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
+            if (reversal) {
+                unsigned char cmdN[] = {0xa0, 0x70};
+                cmdOut(cmdN, 2);
+                reversal = false;
+            }
+            cmdOut(cmd, 8);
+        }
+        else {  //  y1 == y2
+            //  reversal
+            unsigned char cmd[] = {0xa0, 0x72, 
+                                   0x21, 95 - x2, y2, 95 - x1, y1, c1, c2, c3,
+                                   0xa0, 0x70 };
+            cmdOut(cmd, 12);
+        }
+    }
+    else {  //  x1 == x2
+        if (y1 < y2) {
+            //  normal
+            unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
+            if (reversal) {
+                unsigned char cmdN[] = {0xa0, 0x70};
+                cmdOut(cmdN, 2);
+                reversal = false;
+            }
+            cmdOut(cmd, 8);
+        }
+        else if (y1 > y2) {
+            //  normal (force downward)
+            unsigned char cmd[]  = {0x21, x2, y2, x1, y1, c1, c2, c3};
+            cmdOut(cmd, 8);
+        }
+        else {  //  y1 == y2
+            //  normal (point)
+            unsigned char cmd[] = {0x21, x1, y1, x2, y2, c1, c2, c3};
+            if (reversal) {
+                unsigned char cmdN[] = {0xa0, 0x70};
+                cmdOut(cmdN, 2);
+                reversal = false;
+            }
+            cmdOut(cmd, 8);
+        }
+    }
+    //  wait
+    wait_us(1);
+}
+
+void OLED::circle(int x, int y, int r, unsigned short color, int fill)
+{
+    //  exception
+    if (r < 1) {
+        line(x, y, x, y, color);
+        return;
+    } else if (r == 1) {
+        rect(x - 1, y - 1, 3, 3, color, fill);
+        return;
+    }
+    //  ok, go
+    int xx = 0, 
+        yy = r, 
+        err = 2 - 2 * r;
+    //  iteration
+    do {
+        //  draw it! 
+        if (fill) {
+            line(x + xx, y + yy, x + xx, y, color);
+            line(x - xx, y + yy, x, y + yy, color);
+            line(x - xx, y - yy, x - xx, y, color);
+            line(x + xx, y - yy, x, y - yy, color);
+        }
+        else {
+            point(x + xx, y + yy, color);
+            point(x - xx, y + yy, color);
+            point(x - xx, y - yy, color);
+            point(x + xx, y - yy, color);
+        }
+        //  walk
+        if (err > -yy) {
+            yy--;
+            err += 1 - 2 * yy;
+        }
+        if (err <= xx) {
+            xx++;
+            err += 1 + 2 * xx;
+        }
+    } while (yy >= 0);
+}
+
+void OLED::ellipse(int x, int y, int rx, int ry, unsigned short color, int fill)
+{
+    //  exception
+    if (rx < 1) {
+        line(x, y - ry, x, y + ry, color);
+        return;
+    }
+    else if (ry < 1) {
+        line(x - rx, y, x + rx, y, color);
+        return;
+    }
+    //  ok, go
+    int xx = -rx, yy = 0;
+    int e2 = ry, 
+        dx = (2 * xx + 1) * e2 * e2, 
+        dy = xx * xx, 
+        err = dx + dy;
+    do {
+        if (fill) {
+            line(x + xx, y + yy, x + xx, y, color);
+            line(x - xx, y + yy, x, y + yy, color);
+            line(x - xx, y - yy, x - xx, y, color);
+            line(x + xx, y - yy, x, y - yy, color);
+        }
+        else {
+            point(x + xx, y + yy, color);
+            point(x - xx, y + yy, color);
+            point(x - xx, y - yy, color);
+            point(x + xx, y - yy, color);
+        }
+        e2 = 2 * err;
+        if (e2 >= dx) {
+            xx++;
+            dx += 2 * ry * ry;
+            err += dx;
+        }
+        if (e2 <= dy) {
+            yy++;
+            dy += 2 * rx * rx;
+            err += dy;
+        }
+    } while (xx <= 0);
+    if (fill) {
+        while (yy++ < ry) {
+            line(x, y + yy, x, y, color);
+            line(x, y - yy, x, y, color);
+        }
+    }
+    else {
+        while (yy++ < ry) {
+            point(x, y + yy, color);
+            point(x, y - yy, color);
+        }
+    }
+}
+
+void OLED::image(int x, int y, int w, int h, unsigned short *image16)
+{
+    //  un-reverse
+    if (reversal) {
+        unsigned char cmdN[] = {0xa0, 0x70};
+        cmdOut(cmdN, 2);
+        reversal = false;
+    }
+    //  setup the region to fill
+    unsigned char cmd[]={0x15, x, x+w-1, 0x75, y, y+h-1};
+    cmdOut(cmd, 6);
+    //  fill up the region with the image data
+    dataOut(image16, w * h);
+    //  wait
+    wait_us(100);
+}
+
+void OLED::image(int x, int y, int w, int h, const unsigned short *image16)
+{
+    image(x, y, w, h, (unsigned short *) image16);
+}
+
+void OLED::image(int x, int y, int w, int h, unsigned char *image8x3)
+{
+    //  un-reverse
+    if (reversal) {
+        unsigned char cmdN[] = {0xa0, 0x70};
+        cmdOut(cmdN, 2);
+        reversal = false;
+    }
+    //  setup the region to fill
+    unsigned char cmd[]={0x15, x, x+w-1, 0x75, y, y+h-1};
+    cmdOut(cmd, 6);
+    //  fill up the region with the image data
+    int size = w * h;
+    for (int k = 0; k < size; k++) {
+        unsigned char r, g, b;
+        b = *image8x3++;
+        g = *image8x3++;
+        r = *image8x3++;
+        unsigned short data16 = color(r, g, b);
+        dataOut(&data16, 1);
+    }
+    //  wait
+    wait_us(100);
+}
+
+void OLED::image(int x, int y, int w, int h, const unsigned char *image8x3)
+{
+    image(x, y, w, h, (unsigned char *) image8x3);
+}
+
+void OLED::text(int x, int y, char *string, unsigned short color)
+{
+    int len = strlen(string);
+    for (int i = 0; i < len; i++) {
+        int xx = x + i * 6;
+        unsigned char code = string[i];
+        if (code < 0x20 || code >= 0x80) continue;
+        unsigned char *font = font6x8 + ((code - 0x20) * 6);
+        for (int fx = 0; fx < 6; fx++) {
+            if (xx + fx > 95) break;
+            unsigned char line = *(font + fx);
+            for (int fy = 0, bit = 0x01; fy < 8; fy++, bit <<= 1) {
+                if (line & bit) point(xx + fx, y + fy, color);
+            }
+        }
+    }
+}
+
+void OLED::text(int x, int y, char *string, unsigned short colorF, unsigned short colorB)
+{
+    //  clear the background
+    int w = strlen(string) * 6;
+    if (x + w > 95) w = 95 - x;
+    rect(x, y, w, 8, colorB, 1);
+    //  overwrite the text
+    text(x, y, string, colorF);
+}
\ No newline at end of file