mirror of
https://github.com/adafruit/Adafruit_SSD1306.git
synced 2026-07-27 20:05:50 +00:00
425 lines
15 KiB
C++
425 lines
15 KiB
C++
// some of this code was written by <cstone@pobox.com> originally;
|
|
// it is in the public domain.
|
|
|
|
//#include <Wire.h>
|
|
#include <avr/pgmspace.h>
|
|
#include <util/delay.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "SSD1306.h"
|
|
#include "glcdfont.c"
|
|
|
|
static uint8_t is_reversed = 0;
|
|
|
|
// a 5x7 font table
|
|
extern uint8_t PROGMEM font[];
|
|
|
|
// the memory buffer for the LCD
|
|
|
|
static uint8_t buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 8] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
|
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFF,
|
|
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
|
|
0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84, 0x00, 0x00, 0x80, 0xF8,
|
|
0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80,
|
|
0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0x01, 0x01,
|
|
0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01, 0x01, 0x01, 0x83, 0xFF,
|
|
0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7, 0xFF, 0xFF, 0x00, 0x00,
|
|
0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x7F, 0xFF,
|
|
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF,
|
|
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x8F,
|
|
0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC,
|
|
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x01, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01,
|
|
0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
|
|
0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03,
|
|
0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
#if (SSD1306_LCDHEIGHT == 64)
|
|
0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F,
|
|
0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7D, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00, 0x30, 0x30, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F,
|
|
0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0,
|
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
|
|
0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xF8, 0x1C, 0x0E,
|
|
0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFC,
|
|
0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0x06,
|
|
0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xC0, 0xF8,
|
|
0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76, 0xE6, 0xCE, 0xCC, 0x80,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
|
|
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x0C,
|
|
0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E, 0x0C, 0x18, 0x0C, 0x0F,
|
|
0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
|
|
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x07,
|
|
0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
#endif
|
|
};
|
|
|
|
|
|
void SSD1306::drawbitmap(uint8_t x, uint8_t y,
|
|
const uint8_t *bitmap, uint8_t w, uint8_t h,
|
|
uint8_t color) {
|
|
for (uint8_t j=0; j<h; j++) {
|
|
for (uint8_t i=0; i<w; i++ ) {
|
|
if (pgm_read_byte(bitmap + i + (j/8)*w) & _BV(j%8)) {
|
|
setpixel(x+i, y+j, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SSD1306::drawstring(uint8_t x, uint8_t line, char *c) {
|
|
while (c[0] != 0) {
|
|
drawchar(x, line, c[0]);
|
|
c++;
|
|
x += 6; // 6 pixels wide
|
|
if (x + 6 >= SSD1306_LCDWIDTH) {
|
|
x = 0; // ran out of this line
|
|
line++;
|
|
}
|
|
if (line >= (SSD1306_LCDHEIGHT/8))
|
|
return; // ran out of space :(
|
|
}
|
|
|
|
}
|
|
|
|
void SSD1306::drawchar(uint8_t x, uint8_t line, uint8_t c) {
|
|
if ((line >= SSD1306_LCDHEIGHT/8) || (x >= (SSD1306_LCDWIDTH - 6)))
|
|
return;
|
|
for (uint8_t i =0; i<5; i++ ) {
|
|
buffer[x + (line*128) ] = pgm_read_byte(font+(c*5)+i);
|
|
x++;
|
|
}
|
|
}
|
|
|
|
|
|
// bresenham's algorithm - thx wikpedia
|
|
void SSD1306::drawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
|
uint8_t color) {
|
|
uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
|
|
if (steep) {
|
|
swap(x0, y0);
|
|
swap(x1, y1);
|
|
}
|
|
|
|
if (x0 > x1) {
|
|
swap(x0, x1);
|
|
swap(y0, y1);
|
|
}
|
|
|
|
uint8_t dx, dy;
|
|
dx = x1 - x0;
|
|
dy = abs(y1 - y0);
|
|
|
|
int8_t err = dx / 2;
|
|
int8_t ystep;
|
|
|
|
if (y0 < y1) {
|
|
ystep = 1;
|
|
} else {
|
|
ystep = -1;}
|
|
|
|
for (; x0<x1; x0++) {
|
|
if (steep) {
|
|
setpixel(y0, x0, color);
|
|
} else {
|
|
setpixel(x0, y0, color);
|
|
}
|
|
err -= dy;
|
|
if (err < 0) {
|
|
y0 += ystep;
|
|
err += dx;
|
|
}
|
|
}
|
|
}
|
|
|
|
// filled rectangle
|
|
void SSD1306::fillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,
|
|
uint8_t color) {
|
|
|
|
// stupidest version - just pixels - but fast with internal buffer!
|
|
for (uint8_t i=x; i<x+w; i++) {
|
|
for (uint8_t j=y; j<y+h; j++) {
|
|
setpixel(i, j, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
// draw a rectangle
|
|
void SSD1306::drawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,
|
|
uint8_t color) {
|
|
// stupidest version - just pixels - but fast with internal buffer!
|
|
for (uint8_t i=x; i<x+w; i++) {
|
|
setpixel(i, y, color);
|
|
setpixel(i, y+h-1, color);
|
|
}
|
|
for (uint8_t i=y; i<y+h; i++) {
|
|
setpixel(x, i, color);
|
|
setpixel(x+w-1, i, color);
|
|
}
|
|
}
|
|
|
|
// draw a circle outline
|
|
void SSD1306::drawcircle(uint8_t x0, uint8_t y0, uint8_t r,
|
|
uint8_t color) {
|
|
int8_t f = 1 - r;
|
|
int8_t ddF_x = 1;
|
|
int8_t ddF_y = -2 * r;
|
|
int8_t x = 0;
|
|
int8_t y = r;
|
|
|
|
setpixel(x0, y0+r, color);
|
|
setpixel(x0, y0-r, color);
|
|
setpixel(x0+r, y0, color);
|
|
setpixel(x0-r, y0, color);
|
|
|
|
while (x<y) {
|
|
if (f >= 0) {
|
|
y--;
|
|
ddF_y += 2;
|
|
f += ddF_y;
|
|
}
|
|
x++;
|
|
ddF_x += 2;
|
|
f += ddF_x;
|
|
|
|
setpixel(x0 + x, y0 + y, color);
|
|
setpixel(x0 - x, y0 + y, color);
|
|
setpixel(x0 + x, y0 - y, color);
|
|
setpixel(x0 - x, y0 - y, color);
|
|
|
|
setpixel(x0 + y, y0 + x, color);
|
|
setpixel(x0 - y, y0 + x, color);
|
|
setpixel(x0 + y, y0 - x, color);
|
|
setpixel(x0 - y, y0 - x, color);
|
|
|
|
}
|
|
}
|
|
|
|
void SSD1306::fillcircle(uint8_t x0, uint8_t y0, uint8_t r,
|
|
uint8_t color) {
|
|
int8_t f = 1 - r;
|
|
int8_t ddF_x = 1;
|
|
int8_t ddF_y = -2 * r;
|
|
int8_t x = 0;
|
|
int8_t y = r;
|
|
|
|
for (uint8_t i=y0-r; i<=y0+r; i++) {
|
|
setpixel(x0, i, color);
|
|
}
|
|
|
|
while (x<y) {
|
|
if (f >= 0) {
|
|
y--;
|
|
ddF_y += 2;
|
|
f += ddF_y;
|
|
}
|
|
x++;
|
|
ddF_x += 2;
|
|
f += ddF_x;
|
|
|
|
for (uint8_t i=y0-y; i<=y0+y; i++) {
|
|
setpixel(x0+x, i, color);
|
|
setpixel(x0-x, i, color);
|
|
}
|
|
for (uint8_t i=y0-x; i<=y0+x; i++) {
|
|
setpixel(x0+y, i, color);
|
|
setpixel(x0-y, i, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
// the most basic function, set a single pixel
|
|
void SSD1306::setpixel(uint8_t x, uint8_t y, uint8_t color) {
|
|
if ((x >= SSD1306_LCDWIDTH) || (y >= SSD1306_LCDHEIGHT))
|
|
return;
|
|
|
|
// x is which column
|
|
if (color == WHITE)
|
|
buffer[x+ (y/8)*SSD1306_LCDWIDTH] |= _BV((y%8));
|
|
else
|
|
buffer[x+ (y/8)*SSD1306_LCDWIDTH] &= ~_BV((y%8));
|
|
}
|
|
|
|
void SSD1306::ssd1306_init(uint8_t vccstate) {
|
|
// set pin directions
|
|
pinMode(sid, OUTPUT);
|
|
pinMode(sclk, OUTPUT);
|
|
pinMode(dc, OUTPUT);
|
|
pinMode(rst, OUTPUT);
|
|
pinMode(cs, OUTPUT);
|
|
|
|
digitalWrite(rst, HIGH);
|
|
// VDD (3.3V) goes high at start, lets just chill for a ms
|
|
delay(1);
|
|
// bring0xset low
|
|
digitalWrite(rst, LOW);
|
|
// wait 10ms
|
|
delay(10);
|
|
// bring out of reset
|
|
digitalWrite(rst, HIGH);
|
|
// turn on VCC (9V?)
|
|
|
|
#if defined SSD1306_128_32
|
|
// Init sequence for 128x32 OLED module
|
|
ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
|
|
ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
|
|
ssd1306_command(0x80); // the suggested ratio 0x80
|
|
ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
|
|
ssd1306_command(0x1F);
|
|
ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
|
|
ssd1306_command(0x0); // no offset
|
|
ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
|
|
ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
|
|
if (vccstate == SSD1306_EXTERNALVCC)
|
|
{ ssd1306_command(0x10); }
|
|
else
|
|
{ ssd1306_command(0x14); }
|
|
ssd1306_command(SSD1306_MEMORYMODE); // 0x20
|
|
ssd1306_command(0x00); // 0x0 act like ks0108
|
|
ssd1306_command(SSD1306_SEGREMAP | 0x1);
|
|
ssd1306_command(SSD1306_COMSCANDEC);
|
|
ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
|
|
ssd1306_command(0x02);
|
|
ssd1306_command(SSD1306_SETCONTRAST); // 0x81
|
|
ssd1306_command(0x8F);
|
|
ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
|
|
if (vccstate == SSD1306_EXTERNALVCC)
|
|
{ ssd1306_command(0x22); }
|
|
else
|
|
{ ssd1306_command(0xF1); }
|
|
ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
|
|
ssd1306_command(0x40);
|
|
ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
|
|
ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
|
|
#endif
|
|
|
|
#if defined SSD1306_128_64
|
|
// Init sequence for 128x64 OLED module
|
|
ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
|
|
ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
|
|
ssd1306_command(0x80); // the suggested ratio 0x80
|
|
ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
|
|
ssd1306_command(0x3F);
|
|
ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
|
|
ssd1306_command(0x0); // no offset
|
|
ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
|
|
ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
|
|
if (vccstate == SSD1306_EXTERNALVCC)
|
|
{ ssd1306_command(0x10); }
|
|
else
|
|
{ ssd1306_command(0x14); }
|
|
ssd1306_command(SSD1306_MEMORYMODE); // 0x20
|
|
ssd1306_command(0x00); // 0x0 act like ks0108
|
|
ssd1306_command(SSD1306_SEGREMAP | 0x1);
|
|
ssd1306_command(SSD1306_COMSCANDEC);
|
|
ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
|
|
ssd1306_command(0x12);
|
|
ssd1306_command(SSD1306_SETCONTRAST); // 0x81
|
|
if (vccstate == SSD1306_EXTERNALVCC)
|
|
{ ssd1306_command(0x9F); }
|
|
else
|
|
{ ssd1306_command(0xCF); }
|
|
ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
|
|
if (vccstate == SSD1306_EXTERNALVCC)
|
|
{ ssd1306_command(0x22); }
|
|
else
|
|
{ ssd1306_command(0xF1); }
|
|
ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
|
|
ssd1306_command(0x40);
|
|
ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
|
|
ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
|
|
#endif
|
|
|
|
ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel
|
|
}
|
|
|
|
|
|
void SSD1306::invert(uint8_t i) {
|
|
if (i) {
|
|
ssd1306_command(SSD1306_INVERTDISPLAY);
|
|
} else {
|
|
ssd1306_command(SSD1306_NORMALDISPLAY);
|
|
}
|
|
}
|
|
|
|
inline void SSD1306::spiwrite(uint8_t c) {
|
|
shiftOut(sid, sclk, MSBFIRST, c);
|
|
|
|
}
|
|
void SSD1306::ssd1306_command(uint8_t c) {
|
|
digitalWrite(cs, HIGH);
|
|
digitalWrite(dc, LOW);
|
|
digitalWrite(cs, LOW);
|
|
spiwrite(c);
|
|
digitalWrite(cs, HIGH);
|
|
}
|
|
|
|
void SSD1306::ssd1306_data(uint8_t c) {
|
|
digitalWrite(cs, HIGH);
|
|
digitalWrite(dc, HIGH);
|
|
digitalWrite(cs, LOW);
|
|
spiwrite(c);
|
|
digitalWrite(cs, HIGH);
|
|
}
|
|
|
|
void SSD1306::ssd1306_set_brightness(uint8_t val) {
|
|
|
|
}
|
|
|
|
|
|
void SSD1306::display(void) {
|
|
ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0
|
|
ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0
|
|
ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
|
|
|
|
for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) {
|
|
ssd1306_data(buffer[i]);
|
|
}
|
|
// i wonder why we have to do this (check datasheet)
|
|
if (SSD1306_LCDHEIGHT == 32) {
|
|
for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) {
|
|
ssd1306_data(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// clear everything
|
|
void SSD1306::clear(void) {
|
|
memset(buffer, 0, (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8));
|
|
}
|
|
|
|
void SSD1306::clear_display(void) {
|
|
|
|
}
|