A buffered display driver for the SSD1306 OLED controller. Please note that this is a work-in-progress; only very rudimentary drawing support is provided.

Dependents:   Projetv0 greenhouse_proj ProjetLong_Serre_V3 ProjetLong_Serre_V3_1 ... more

Example of use:

#include "mbed.h"

#include "ssd1306.h"
#include "standard_font.h"
#include "bold_font.h"

SSD1306 oled(p8 /* cs */, p9 /* reset */, p14 /* dc */,
             p13 /* clock */, p11 /* data */);

int main()
{
    oled.initialise();
    oled.clear();
    oled.set_contrast(255); // max contrast

    oled.set_font(bold_font, 8);
    oled.printf("Heading\r\n");

    oled.set_font(standard_font, 6);
    oled.printf("Hello World!\r\n");
    oled.printf("Some more text here...");

    oled.update();

    while (1)
    {
        wait(2);
        oled.scroll_up();
        oled.update();
    }
}
Revision:
2:e479b0296757
Parent:
1:1d58d378221c
Child:
3:1d9df877c90a
--- a/ssd1306.cpp	Tue Feb 05 17:18:23 2013 +0000
+++ b/ssd1306.cpp	Tue Feb 05 21:21:22 2013 +0000
@@ -10,29 +10,14 @@
 {
 }
 
-void SSD1306::set_low_column(int v)
-{
-    _send_command(SSD1306_SETLOWCOLUMN | v);
-}
-
-void SSD1306::set_high_column(int v)
-{
-    _send_command(SSD1306_SETHIGHCOLUMN | v);
-}
-
-void SSD1306::set_start_line(int v)
-{
-    _send_command(SSD1306_SETSTARTLINE | v);
-}
-
 void SSD1306::off()
 {
-    _send_command(SSD1306_DISPLAYOFF);
+    _send_command(0xAE);
 }
 
 void SSD1306::on()
 {
-    _send_command(SSD1306_DISPLAYON);
+    _send_command(0xAF);
 }
 
 void SSD1306::sleep()
@@ -53,7 +38,7 @@
 void SSD1306::set_display_offset(unsigned char value)
 {
     _send_command(0xD3);
-    _send_command(value); 
+    _send_command(value & 0x3F); 
 }
 
 void SSD1306::set_contrast(unsigned char value) 
@@ -67,14 +52,15 @@
     _send_command(0x40 | value);
 }
 
-void SSD1306::set_horizontal_flip(unsigned char value)
+void SSD1306::set_segment_remap(unsigned char value)
 {
     _send_command(value ? 0xA1 : 0xA0);
 }
 
 void SSD1306::set_multiplex_ratio(unsigned char value)
 {
-    _send_command(0xA8 | value);
+    _send_command(0xA8);
+    _send_command(value & 0x3F);
 }
 
 void SSD1306::set_com_output_scan_direction(unsigned char value)
@@ -85,7 +71,127 @@
 void SSD1306::set_com_pins_hardware_configuration(unsigned char sequential, unsigned char lr_remap)
 {
     _send_command(0xDA);
-    _send_command(0x02 | ((sequential & 1) << 5) | ((lr_remap & 1) << 6));
+    _send_command(0x02 | ((sequential & 1) << 4) | ((lr_remap & 1) << 5));
+}
+
+void SSD1306::start_horizontal_scroll(unsigned char direction, unsigned char start, unsigned char end, unsigned char interval) 
+{
+    _send_command(direction ? 0x27 : 0x26);
+    _send_command(0x00);
+    _send_command(start & 0x07);
+    switch (interval) {
+        case   2: _send_command(0x07); break; // 111b
+        case   3: _send_command(0x04); break; // 100b
+        case   4: _send_command(0x05); break; // 101b
+        case   5: _send_command(0x00); break; // 000b
+        case  25: _send_command(0x06); break; // 110b
+        case  64: _send_command(0x01); break; // 001b
+        case 128: _send_command(0x02); break; // 010b
+        case 256: _send_command(0x03); break; // 011b
+        default:
+            // default to 2 frame interval
+            _send_command(0x07); break;
+    }
+    _send_command(end & 0x07);
+    _send_command(0x00);
+    _send_command(0xFF);
+    
+    // activate scroll
+    _send_command(0x2F);
+}
+
+void SSD1306::start_vertical_and_horizontal_scroll(unsigned char direction, unsigned char start, unsigned char end, unsigned char interval, unsigned char vertical_offset)
+{
+    _send_command(direction ? 0x2A : 0x29);
+    _send_command(0x00);
+    _send_command(start & 0x07);
+    switch (interval) {
+        case   2: _send_command(0x07); break; // 111b
+        case   3: _send_command(0x04); break; // 100b
+        case   4: _send_command(0x05); break; // 101b
+        case   5: _send_command(0x00); break; // 000b
+        case  25: _send_command(0x06); break; // 110b
+        case  64: _send_command(0x01); break; // 001b
+        case 128: _send_command(0x02); break; // 010b
+        case 256: _send_command(0x03); break; // 011b
+        default:
+            // default to 2 frame interval
+            _send_command(0x07); break;
+    }
+    _send_command(end & 0x07);
+    _send_command(vertical_offset);    
+    
+    // activate scroll
+    _send_command(0x2F);
+}
+
+void SSD1306::stop_scroll()
+{
+    // all scroll configurations are removed from the display when executing this command.
+    _send_command(0x2E);
+}
+
+void SSD1306::pam_set_start_address(unsigned char address)
+{
+    // "Set Lower Column Start Address for Page Addressing Mode"
+    _send_command(address & 0x0F);
+    
+    // "Set Higher Column Start Address for Page Addressing Mode"
+    _send_command((address << 4) & 0x0F);
+}
+
+void SSD1306::set_memory_addressing_mode(unsigned char mode)
+{
+    _send_command(0x20);
+    _send_command(mode & 0x3);
+}
+
+void SSD1306::hv_set_column_address(unsigned char start, unsigned char end)
+{
+    _send_command(0x21);
+    _send_command(start & 0x7F);
+    _send_command(end & 0x7F);
+}
+
+void SSD1306::hv_set_page_address(unsigned char start, unsigned char end)
+{
+    _send_command(0x22);
+    _send_command(start & 0x07);
+    _send_command(end & 0x07);
+}
+
+void SSD1306::pam_set_page_start(unsigned char address)
+{
+    _send_command(0xB0 | (address & 0x07));
+}
+
+void SSD1306::set_display_clock_ratio_and_frequency(unsigned char ratio, unsigned char frequency)
+{
+    _send_command(0xD5);
+    _send_command((ratio & 0x0F) | ((frequency & 0x0F) << 4));
+}
+
+void SSD1306::set_precharge_period(unsigned char phase1, unsigned char phase2)
+{
+    _send_command(0xD9);
+    _send_command((phase1 & 0x0F) | ((phase2 & 0x0F ) << 4));
+}
+
+void SSD1306::set_vcomh_deselect_level(unsigned char level)
+{
+    _send_command(0xDB);
+    _send_command((level & 0x03) << 4);
+}
+
+void SSD1306::nop()
+{
+    _send_command(0xE3);
+}
+
+void SSD1306::set_charge_pump_enable(unsigned char enable)
+{
+    _send_command(0x8D);
+    _send_command(enable ? 0x14 : 0x10);
 }
 
 void SSD1306::initialise()
@@ -98,78 +204,36 @@
     _reset = 1;
     
     off();
-    
-    set_low_column(0);
-    set_high_column(0);
-    set_start_line(0);
-    
-    _send_command(0xAE);  // turn off
-    _send_command(0x00);  // set low column address
-    _send_command(0x10);  // set high column address
-    _send_command(0x40);  // set start line address
-    
+
+    set_display_clock_ratio_and_frequency(0, 8);
+    set_multiplex_ratio(0x3F); // 1/64 duty
+    set_precharge_period(0xF, 0x01);
+    set_display_offset(0);    
+    set_display_start_line(0);  
+    set_charge_pump_enable(1);    
+    set_memory_addressing_mode(0); // horizontal addressing mode
+    set_segment_remap(1);
+    set_com_output_scan_direction(1);
+    set_com_pins_hardware_configuration(1, 0);
     set_contrast(0xFF);
-    
-    _send_command(0xA1);  // set segment re-map 95 to 0
-    _send_command(0xA6);  // set normal display
-    _send_command(0xA8);  // set multiplex ratio (1-64);
-    _send_command(0x3F);  // 1/64 duty
-    _send_command(0xD3);  // set display offset
-    _send_command(0x00);  // -- no offset
-    _send_command(0xD5);  // set display clock divide ratio/oscillator frequency
-    _send_command(0x80);  // -- set divide ratio
-    _send_command(0xD9);  // set precharge period;
-    _send_command(0xF1);
-    _send_command(0xDA);  // set com pins hardware config
-    _send_command(0x12);
-    _send_command(0xDB);  // set vcomh
-    _send_command(0x40); 
-    _send_command(0x8D);  // set charge pump enable/disable
-    _send_command(0x14);  // enable  (0x10 disable)
-    _send_command(0xAF);  // switch panel on
-    
-    set_inverse(1);
+    set_vcomh_deselect_level(1);
     
-    /*
-    _send_command(SSD1306_SETCONTRAST);
-    _send_command(0xCF); // chargepump, could be 0x9F for external 9V
-    
-    _send_command(0xA1); // setment remap 95 to 0 (??)
-    
-    invert(0);
-    
-    _send_command(SSD1306_DISPLAYALLON_RESUME);
-    _send_command(SSD1306_SETMULTIPLEX);    
-    _send_command(0x3F); // 1/64 duty
-    
-    set_display_offset(0);
+    wake();
+    set_inverse(0);
     
-    _send_command(SSD1306_SETDISPLAYCLOCKDIV);
-    _send_command(0x80); // suggested value = 0x80
-    _send_command(SSD1306_SETPRECHARGE);
-    _send_command(0xF1); // dc/dc, could be 0x22 for external 9V
-    _send_command(SSD1306_SETCOMPINS);
-    _send_command(0x12); // disable COM left/right remap
-    _send_command(SSD1306_SETVCOMDETECT);
-    _send_command(0x40); // apparently, 0x20 is default...
-    _send_command(SSD1306_MEMORYMODE);
-    _send_command(0x0); // act like KS0108
+    hv_set_column_address(0, 127);
+    hv_set_page_address(0, 7);
     
-    // left-to-right scan
-    _send_command(SSD1306_SEGREMAP | 0x1);
-    _send_command(SSD1306_COMSCANDEC);
-    _send_command(SSD1306_CHARGEPUMP);
-    _send_command(0x14); // disable, for external 9v 0x10 disable
-    */
-    // turn it on
-    // on();
+    pam_set_start_address(0);
+    pam_set_page_start(0);
+    
+    // set_precharge_period(2, 2);
 }
 
 void SSD1306::update()
 {
-    set_low_column(0);
-    set_high_column(0);
-    set_start_line(0);
+    hv_set_column_address(0, 127);
+    hv_set_page_address(0, 7);
     
     for (int i = 0; i < 1024; i++)
         _send_data(_screen[i]);
@@ -275,4 +339,3 @@
     _spi.write(value);
     _cs = 1;
 }
-