OULOUTECH / SSD1306

Dependents:   Affich_Lum_Moist

Fork of SSD1306 by Jonathan Gaul

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ssd1306.cpp Source File

ssd1306.cpp

00001 #include "mbed.h"
00002 #include "ssd1306.h"
00003 
00004 #include <stdarg.h>
00005 
00006 SSD1306::SSD1306(PinName cs, PinName rs, PinName dc, PinName clk, PinName data)
00007     : _spi(data, NC, clk), 
00008       _cs(cs), 
00009       _reset(rs), 
00010       _dc(dc),
00011       _cursor_x(0),
00012       _cursor_y(0)
00013 {
00014 }
00015 
00016 void SSD1306::off()
00017 {
00018     _send_command(0xAE);
00019 }
00020 
00021 void SSD1306::on()
00022 {
00023     _send_command(0xAF);
00024 }
00025 
00026 void SSD1306::sleep()
00027 {
00028     _send_command(0xAE);
00029 }
00030 
00031 void SSD1306::wake()
00032 {
00033     _send_command(0xAF);
00034 }
00035 
00036 void SSD1306::set_inverse(unsigned char value)
00037 {
00038     _send_command(value ? 0xA7 : 0xA6);
00039 }
00040 
00041 void SSD1306::set_display_offset(unsigned char value)
00042 {
00043     _send_command(0xD3);
00044     _send_command(value & 0x3F); 
00045 }
00046 
00047 void SSD1306::set_contrast(unsigned char value) 
00048 {
00049     _send_command(0x81);
00050     _send_command(value);
00051 }
00052 
00053 void SSD1306::set_display_start_line(unsigned char value)
00054 {
00055     _send_command(0x40 | value);
00056 }
00057 
00058 void SSD1306::set_segment_remap(unsigned char value)
00059 {
00060     _send_command(value ? 0xA1 : 0xA0);
00061 }
00062 
00063 void SSD1306::set_multiplex_ratio(unsigned char value)
00064 {
00065     _send_command(0xA8);
00066     _send_command(value & 0x3F);
00067 }
00068 
00069 void SSD1306::set_com_output_scan_direction(unsigned char value)
00070 {
00071     _send_command(value ? 0xC8 : 0xC0);
00072 }
00073 
00074 void SSD1306::set_com_pins_hardware_configuration(unsigned char sequential, unsigned char lr_remap)
00075 {
00076     _send_command(0xDA);
00077     _send_command(0x02 | ((sequential & 1) << 4) | ((lr_remap & 1) << 5));
00078 }
00079 
00080 void SSD1306::start_horizontal_scroll(unsigned char direction, unsigned char start, unsigned char end, unsigned char interval) 
00081 {
00082     _send_command(direction ? 0x27 : 0x26);
00083     _send_command(0x00);
00084     _send_command(start & 0x07);
00085     switch (interval) {
00086         case   2: _send_command(0x07); break; // 111b
00087         case   3: _send_command(0x04); break; // 100b
00088         case   4: _send_command(0x05); break; // 101b
00089         case   5: _send_command(0x00); break; // 000b
00090         case  25: _send_command(0x06); break; // 110b
00091         case  64: _send_command(0x01); break; // 001b
00092         case 128: _send_command(0x02); break; // 010b
00093         case 256: _send_command(0x03); break; // 011b
00094         default:
00095             // default to 2 frame interval
00096             _send_command(0x07); break;
00097     }
00098     _send_command(end & 0x07);
00099     _send_command(0x00);
00100     _send_command(0xFF);
00101     
00102     // activate scroll
00103     _send_command(0x2F);
00104 }
00105 
00106 void SSD1306::start_vertical_and_horizontal_scroll(unsigned char direction, unsigned char start, unsigned char end, unsigned char interval, unsigned char vertical_offset)
00107 {
00108     _send_command(direction ? 0x2A : 0x29);
00109     _send_command(0x00);
00110     _send_command(start & 0x07);
00111     switch (interval) {
00112         case   2: _send_command(0x07); break; // 111b
00113         case   3: _send_command(0x04); break; // 100b
00114         case   4: _send_command(0x05); break; // 101b
00115         case   5: _send_command(0x00); break; // 000b
00116         case  25: _send_command(0x06); break; // 110b
00117         case  64: _send_command(0x01); break; // 001b
00118         case 128: _send_command(0x02); break; // 010b
00119         case 256: _send_command(0x03); break; // 011b
00120         default:
00121             // default to 2 frame interval
00122             _send_command(0x07); break;
00123     }
00124     _send_command(end & 0x07);
00125     _send_command(vertical_offset);    
00126     
00127     // activate scroll
00128     _send_command(0x2F);
00129 }
00130 
00131 void SSD1306::stop_scroll()
00132 {
00133     // all scroll configurations are removed from the display when executing this command.
00134     _send_command(0x2E);
00135 }
00136 
00137 void SSD1306::pam_set_start_address(unsigned char address)
00138 {
00139     // "Set Lower Column Start Address for Page Addressing Mode"
00140     _send_command(address & 0x0F);
00141     
00142     // "Set Higher Column Start Address for Page Addressing Mode"
00143     _send_command((address << 4) & 0x0F);
00144 }
00145 
00146 void SSD1306::set_memory_addressing_mode(unsigned char mode)
00147 {
00148     _send_command(0x20);
00149     _send_command(mode & 0x3);
00150 }
00151 
00152 void SSD1306::hv_set_column_address(unsigned char start, unsigned char end)
00153 {
00154     _send_command(0x21);
00155     _send_command(start & 0x7F);
00156     _send_command(end & 0x7F);
00157 }
00158 
00159 void SSD1306::hv_set_page_address(unsigned char start, unsigned char end)
00160 {
00161     _send_command(0x22);
00162     _send_command(start & 0x07);
00163     _send_command(end & 0x07);
00164 }
00165 
00166 void SSD1306::pam_set_page_start(unsigned char address)
00167 {
00168     _send_command(0xB0 | (address & 0x07));
00169 }
00170 
00171 void SSD1306::set_display_clock_ratio_and_frequency(unsigned char ratio, unsigned char frequency)
00172 {
00173     _send_command(0xD5);
00174     _send_command((ratio & 0x0F) | ((frequency & 0x0F) << 4));
00175 }
00176 
00177 void SSD1306::set_precharge_period(unsigned char phase1, unsigned char phase2)
00178 {
00179     _send_command(0xD9);
00180     _send_command((phase1 & 0x0F) | ((phase2 & 0x0F ) << 4));
00181 }
00182 
00183 void SSD1306::set_vcomh_deselect_level(unsigned char level)
00184 {
00185     _send_command(0xDB);
00186     _send_command((level & 0x03) << 4);
00187 }
00188 
00189 void SSD1306::nop()
00190 {
00191     _send_command(0xE3);
00192 }
00193 
00194 void SSD1306::set_charge_pump_enable(unsigned char enable)
00195 {
00196     _send_command(0x8D);
00197     _send_command(enable ? 0x14 : 0x10);
00198 }
00199 
00200 void SSD1306::initialise()
00201 {
00202     // Init
00203     _reset = 1;
00204     wait(0.01);
00205     _reset = 0;
00206     wait(0.10);
00207     _reset = 1;
00208     
00209     off();
00210 
00211     set_display_clock_ratio_and_frequency(0, 8);
00212     set_multiplex_ratio(0x3F); // 1/64 duty
00213     set_precharge_period(0xF, 0x01);
00214     set_display_offset(0);    
00215     set_display_start_line(0);  
00216     set_charge_pump_enable(1);    
00217     set_memory_addressing_mode(0); // horizontal addressing mode; across then down
00218     set_segment_remap(1);
00219     set_com_output_scan_direction(1);
00220     set_com_pins_hardware_configuration(1, 0);
00221     set_contrast(0xFF);
00222     set_vcomh_deselect_level(1);
00223     
00224     wake();
00225     set_inverse(0);
00226     
00227     hv_set_column_address(0, 127);
00228     hv_set_page_address(0, 7);
00229     
00230     pam_set_start_address(0);
00231     pam_set_page_start(0);
00232     
00233     // set_precharge_period(2, 2);
00234 }
00235 
00236 void SSD1306::update()
00237 {
00238     hv_set_column_address(0, 127);
00239     hv_set_page_address(0, 7);
00240     
00241     for (int i = 0; i < 1024; i++)
00242         _send_data(_screen[i]);
00243 }
00244 
00245 void SSD1306::set_pixel(int x, int y)
00246 {
00247     if (x >= SSD1306_LCDWIDTH || y >= SSD1306_LCDHEIGHT) return;
00248     
00249     _screen[x + (y / 8) * 128] |= 1 << (y % 8);
00250 }
00251 
00252 void SSD1306::clear_pixel(int x, int y)
00253 {
00254     if (x >= SSD1306_LCDWIDTH || y >= SSD1306_LCDHEIGHT) return;
00255     
00256     _screen[x + (y / 8) * 128] &= ~(1 << (y % 8));
00257 }
00258 
00259 void SSD1306::line(int x0, int y0, int x1, int y1) {
00260   int steep = abs(y1 - y0) > abs(x1 - x0);
00261   int t;
00262   
00263   if (steep) {
00264     t = x0; x0 = y0; y0 = t;
00265     t = x1; x1 = y1; y1 = t;
00266   }
00267 
00268   if (x0 > x1) {
00269     t = x0; x0 = x1; x1 = t;
00270     t = y0; y0 = y1; y1 = t;
00271   }
00272 
00273   int dx, dy;
00274   
00275   dx = x1 - x0;
00276   dy = abs(y1 - y0);
00277 
00278   int err = dx / 2;
00279   int ystep;
00280 
00281   if (y0 < y1) {
00282     ystep = 1;
00283   } else {
00284     ystep = -1;}
00285 
00286   for (; x0<x1; x0++) {
00287     if (steep) {
00288       set_pixel(y0, x0);
00289     } else {
00290       set_pixel(x0, y0);
00291     }
00292     err -= dy;
00293     if (err < 0) {
00294       y0 += ystep;
00295       err += dx;
00296     }
00297   }
00298 }
00299 
00300 void SSD1306::set_font(unsigned char *font, unsigned int width)
00301 {
00302     _console_font_data = font;
00303     _console_font_width = width;
00304 }
00305 
00306 void SSD1306::set_double_height_text(unsigned int double_height)
00307 {
00308     _double_height_text = double_height;
00309 }
00310 
00311 void SSD1306::putc(unsigned char c)
00312 {
00313     while (_cursor_x >= (128 / _console_font_width))
00314     {
00315         _cursor_x -= (128 / _console_font_width);
00316         _cursor_y++;            
00317     }
00318 
00319     while (_cursor_y > 7)
00320     {
00321         scroll_up();            
00322     }
00323 
00324     switch (c)
00325     {
00326     case '\n':
00327         _cursor_y++;
00328         break;
00329         
00330     case '\r':
00331         _cursor_x = 0;
00332         break;
00333         
00334     case '\t':
00335         _cursor_x = (_cursor_x + 4) % 4;
00336         break;
00337         
00338     default:
00339         for (int b = 0; b < _console_font_width; b++)
00340         {
00341             _screen[_cursor_x * _console_font_width + _cursor_y * 128 + b] = _console_font_data[(c - FONT_START) * _console_font_width + b];
00342         }
00343         
00344         _cursor_x++;
00345     }            
00346 }
00347 
00348 void SSD1306::scroll_up()
00349 {
00350     for (int y = 1; y <= 7; y++)
00351     {
00352         for (int x = 0; x < 128; x++)
00353         {
00354             _screen[x + 128 * (y - 1)] = _screen[x + 128 * y];
00355         }
00356     }
00357     
00358     for (int x = 0; x < 128; x++)
00359     {
00360         _screen[x + 128 * 7] = 0;
00361     }    
00362 
00363     _cursor_y--;
00364 }
00365 
00366 void SSD1306::printf(const char *format, ...)
00367 {
00368     static char buffer[128];
00369     
00370     va_list args;
00371     va_start(args, format);
00372     vsprintf(buffer, format, args);
00373     va_end(args);
00374     
00375     char *c = (char *)&buffer;
00376     while (*c != 0)
00377     {
00378         putc(*c++);
00379     }
00380 }
00381 
00382 void SSD1306::clear()
00383 {
00384     for (int i = 0; i < 1024; i++)
00385         _screen[i] = 0;
00386         
00387     _cursor_x = 0;
00388     _cursor_y = 0;
00389 }
00390 
00391 void SSD1306::_send_command(unsigned char code)
00392 {
00393     _cs = 1;
00394     _dc = 0;
00395     _cs = 0;
00396     _spi.write(code);
00397     _cs = 1;
00398 }
00399 
00400 void SSD1306::_send_data(unsigned char value)
00401 {
00402     _cs = 1;
00403     _dc = 1;
00404     _cs = 0;
00405     _spi.write(value);
00406     _cs = 1;
00407 }