Version finale
Dependencies: mbed
Fork of Main_V3_Old by
ssd1306.cpp
- Committer:
- ramialjed
- Date:
- 2018-01-15
- Revision:
- 7:2748b1a2742c
- Parent:
- 6:f552ca0f5165
File content as of revision 7:2748b1a2742c:
#include "mbed.h" #include "ssd1306.h" #include <stdarg.h> #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) SSD1306::SSD1306(PinName cs, PinName rs, PinName dc, PinName clk, PinName data) : _spi(data, NC, clk), _cs(cs), _reset(rs), _dc(dc), _cursor_x(0), _cursor_y(0) { } 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; across then down 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::drawBitmap(int x, int y, const unsigned char *bitmap, int w, int h, int color) { int16_t i, j, byteWidth = (w + 7) / 8; for(j=0; j<h; j++) { for(i=0; i<w; i++ ) { if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) { color? set_pixel(x+i, y+j): clear_pixel(x+i, y+j); } } } } 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::set_font(unsigned char *font, unsigned int width) { _console_font_data = font; _console_font_width = width; } void SSD1306::set_double_height_text(unsigned int double_height) { _double_height_text = double_height; } void SSD1306::putc(unsigned char c) { while (_cursor_x >= (128 / _console_font_width)) { _cursor_x -= (128 / _console_font_width); _cursor_y++; } while (_cursor_y > 7) { scroll_up(); } switch (c) { case '\n': _cursor_y++; break; case '\r': _cursor_x = 0; break; case '\t': _cursor_x = (_cursor_x + 4) % 4; break; default: for (int b = 0; b < _console_font_width; b++) { _screen[_cursor_x * _console_font_width + _cursor_y * 128 + b] = _console_font_data[(c - FONT_START) * _console_font_width + b]; } _cursor_x++; } } void SSD1306::scroll_up() { for (int y = 1; y <= 7; y++) { for (int x = 0; x < 128; x++) { _screen[x + 128 * (y - 1)] = _screen[x + 128 * y]; } } for (int x = 0; x < 128; x++) { _screen[x + 128 * 7] = 0; } _cursor_y--; } void SSD1306::printf(const char *format, ...) { static char buffer[128]; va_list args; va_start(args, format); vsprintf(buffer, format, args); va_end(args); char *c = (char *)&buffer; while (*c != 0) { putc(*c++); } } void SSD1306::clear() { for (int i = 0; i < 1024; i++) _screen[i] = 0; _cursor_x = 0; _cursor_y = 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; }