Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ssd1306.cpp
- Committer:
- Byrn
- Date:
- 2013-02-05
- Revision:
- 2:e479b0296757
- Parent:
- 1:1d58d378221c
- Child:
- 3:1d9df877c90a
File content as of revision 2:e479b0296757:
#include "mbed.h"
#include "ssd1306.h"
SSD1306::SSD1306(PinName cs, PinName rs, PinName dc, PinName clk, PinName data)
: _spi(data, NC, clk),
_cs(cs),
_reset(rs),
_dc(dc)
{
}
void SSD1306::off()
{
_send_command(0xAE);
}
void SSD1306::on()
{
_send_command(0xAF);
}
void SSD1306::sleep()
{
_send_command(0xAE);
}
void SSD1306::wake()
{
_send_command(0xAF);
}
void SSD1306::set_inverse(unsigned char value)
{
_send_command(value ? 0xA7 : 0xA6);
}
void SSD1306::set_display_offset(unsigned char value)
{
_send_command(0xD3);
_send_command(value & 0x3F);
}
void SSD1306::set_contrast(unsigned char value)
{
_send_command(0x81);
_send_command(value);
}
void SSD1306::set_display_start_line(unsigned char value)
{
_send_command(0x40 | 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);
_send_command(value & 0x3F);
}
void SSD1306::set_com_output_scan_direction(unsigned char value)
{
_send_command(value ? 0xC8 : 0xC0);
}
void SSD1306::set_com_pins_hardware_configuration(unsigned char sequential, unsigned char lr_remap)
{
_send_command(0xDA);
_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()
{
// Init
_reset = 1;
wait(0.01);
_reset = 0;
wait(0.10);
_reset = 1;
off();
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);
set_vcomh_deselect_level(1);
wake();
set_inverse(0);
hv_set_column_address(0, 127);
hv_set_page_address(0, 7);
pam_set_start_address(0);
pam_set_page_start(0);
// set_precharge_period(2, 2);
}
void SSD1306::update()
{
hv_set_column_address(0, 127);
hv_set_page_address(0, 7);
for (int i = 0; i < 1024; i++)
_send_data(_screen[i]);
}
void SSD1306::set_pixel(int x, int y)
{
if (x >= SSD1306_LCDWIDTH || y >= SSD1306_LCDHEIGHT) return;
_screen[x + (y / 8) * 128] |= 1 << (y % 8);
}
void SSD1306::clear_pixel(int x, int y)
{
if (x >= SSD1306_LCDWIDTH || y >= SSD1306_LCDHEIGHT) return;
_screen[x + (y / 8) * 128] &= ~(1 << (y % 8));
}
void SSD1306::line(int x0, int y0, int x1, int y1) {
int steep = abs(y1 - y0) > abs(x1 - x0);
int t;
if (steep) {
t = x0; x0 = y0; y0 = t;
t = x1; x1 = y1; y1 = t;
}
if (x0 > x1) {
t = x0; x0 = x1; x1 = t;
t = y0; y0 = y1; y1 = t;
}
int dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int err = dx / 2;
int ystep;
if (y0 < y1) {
ystep = 1;
} else {
ystep = -1;}
for (; x0<x1; x0++) {
if (steep) {
set_pixel(y0, x0);
} else {
set_pixel(x0, y0);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
void SSD1306::draw_string(char *font, int x, int y, const char *string)
{
_cursor_x = x;
_cursor_y = y;
for (int i = 0; i < strlen(string); i++)
draw_char(font, _cursor_x, _cursor_y, string[i]);
}
void SSD1306::draw_char(char *font, int x, int y, char c)
{
int height = font[FONT_HEIGHT_OFFSET];
int max_width = font[FONT_SIZE_OFFSET];
int char_size_bytes = max_width * height + 1;
int char_width = font[(c - FONT_START) * char_size_bytes + FONT_DATA_OFFSET];
for (int i = 0; i < char_width; i++)
_screen[(x + i) + (y * SSD1306_LCDWIDTH)] = font[(c - FONT_START) * (char_size_bytes) + i + FONT_DATA_OFFSET + 1];
_cursor_x = x + char_width;
_cursor_y = y;
}
void SSD1306::clear()
{
for (int i = 0; i < 1024; i++)
_screen[i] = 0;
}
void SSD1306::_send_command(unsigned char code)
{
_cs = 1;
_dc = 0;
_cs = 0;
_spi.write(code);
_cs = 1;
}
void SSD1306::_send_data(unsigned char value)
{
_cs = 1;
_dc = 1;
_cs = 0;
_spi.write(value);
_cs = 1;
}