#include "SSD1306_minimal.h"
#include <avr/pgmspace.h>
SSD1306_Mini oled;
// Pins
//int const clk = 0;
//int const data = 1;
//int const dc = 2;
//int const cs = 3;
// OLED 64x48 monochrome display **********************************************
// Screen buffer
const int Buffersize = 64*6;
unsigned char Buffer[Buffersize];
// Initialisation sequence for OLED module
int const InitLen = 24;
const unsigned char Init[InitLen] PROGMEM = {
0xAE, // Display off
0xD5, // Set display clock
0x80, // Recommended value
0xA8, // Set multiplex
0x3F,
0xD3, // Set display offset
0x00,
0x40, // Zero start line
0x8D, // Charge pump
0x14,
0x20, // Memory mode
0x00, // Horizontal addressing
0xA1, // 0xA0/0xA1 flip horizontally
0xC8, // 0xC0/0xC8 flip vertically
0xDA, // Set comp ins
0x12,
0x81, // Set contrast
0x7F, // 0x00 to 0xFF
0xD9, // Set pre charge
0xF1,
0xDB, // Set vcom detect
0x40,
0xA6, // Normal (0xA7=Inverse)
0xAF // Display on
};
// Write a data byte to the display
void Data(uint8_t d) {
uint8_t changes = d ^ (d>>1);
PORTB = PORTB & ~(1<<data);
for (uint8_t bit = 0x80; bit; bit >>= 1) {
PINB = 1<<clk; // clk low
if (changes & bit) PINB = 1<<data;
PINB = 1<<clk; // clk high
}
}
// Write a command byte to the display
void Command(uint8_t c) {
PINB = 1<<dc; // dc low
Data(c);
PINB = 1<<dc; // dc high
}
void InitDisplay () {
PINB = 1<<cs; // cs low
for (uint8_t c=0; c<InitLen; c++) Command(pgm_read_byte(&Init[c]));
PINB = 1<<cs; // cs high
}
void ClearBuffer () {
for (int i = 0 ; i < Buffersize; i++) Buffer[i] = 0;
}
void DisplayBuffer() {
PINB = 1<<cs; // cs low
// Set column address range
Command(0x21); Command(32); Command(95);
// Set page address range
Command(0x22); Command(2); Command(7);
for (int i = 0 ; i < Buffersize; i++) Data(Buffer[i]);
PINB = 1<<cs; // cs high
}
// Graphics **********************************************
// Character set for text - stored in program memory
const uint32_t CharMap[96][6] PROGMEM = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00 },
{ 0x00, 0x07, 0x00, 0x07, 0x00, 0x00 },
{ 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00 },
{ 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00 },
{ 0x23, 0x13, 0x08, 0x64, 0x62, 0x00 },
{ 0x36, 0x49, 0x56, 0x20, 0x50, 0x00 },
{ 0x00, 0x08, 0x07, 0x03, 0x00, 0x00 },
{ 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00 },
{ 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00 },
{ 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00 },
{ 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00 },
{ 0x00, 0x80, 0x70, 0x30, 0x00, 0x00 },
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x00 },
{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },
{ 0x20, 0x10, 0x08, 0x04, 0x02, 0x00 },
{ 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00 },
{ 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00 },
{ 0x72, 0x49, 0x49, 0x49, 0x46, 0x00 },
{ 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00 },
{ 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00 },
{ 0x27, 0x45, 0x45, 0x45, 0x39, 0x00 },
{ 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00 },
{ 0x41, 0x21, 0x11, 0x09, 0x07, 0x00 },
{ 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 },
{ 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00 },
{ 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 },
{ 0x00, 0x40, 0x34, 0x00, 0x00, 0x00 },
{ 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x00 },
{ 0x00, 0x41, 0x22, 0x14, 0x08, 0x00 },
{ 0x02, 0x01, 0x59, 0x09, 0x06, 0x00 },
{ 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00 },
{ 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00 },
{ 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00 },
{ 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00 },
{ 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00 },
{ 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00 },
{ 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00 },
{ 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00 },
{ 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00 },
{ 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00 },
{ 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00 },
{ 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00 },
{ 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00 },
{ 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00 },
{ 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00 },
{ 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00 },
{ 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00 },
{ 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00 },
{ 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00 },
{ 0x26, 0x49, 0x49, 0x49, 0x32, 0x00 },
{ 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00 },
{ 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00 },
{ 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00 },
{ 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00 },
{ 0x63, 0x14, 0x08, 0x14, 0x63, 0x00 },
{ 0x03, 0x04, 0x78, 0x04, 0x03, 0x00 },
{ 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00 },
{ 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00 },
{ 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 },
{ 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00 },
{ 0x04, 0x02, 0x01, 0x02, 0x04, 0x00 },
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00 },
{ 0x00, 0x03, 0x07, 0x08, 0x00, 0x00 },
{ 0x20, 0x54, 0x54, 0x78, 0x40, 0x00 },
{ 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00 },
{ 0x38, 0x44, 0x44, 0x44, 0x28, 0x00 },
{ 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00 },
{ 0x38, 0x54, 0x54, 0x54, 0x18, 0x00 },
{ 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00 },
{ 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00 },
{ 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00 },
{ 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00 },
{ 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00 },
{ 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00 },
{ 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00 },
{ 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00 },
{ 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00 },
{ 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 },
{ 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00 },
{ 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00 },
{ 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00 },
{ 0x48, 0x54, 0x54, 0x54, 0x24, 0x00 },
{ 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00 },
{ 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00 },
{ 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00 },
{ 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00 },
{ 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 },
{ 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00 },
{ 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00 },
{ 0x00, 0x08, 0x36, 0x41, 0x00, 0x00 },
{ 0x00, 0x00, 0x77, 0x00, 0x00, 0x00 },
{ 0x00, 0x41, 0x36, 0x08, 0x00, 0x00 },
{ 0x02, 0x01, 0x02, 0x04, 0x02, 0x00 },
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }
};
// Origin
signed char xOrigin = 0;
signed char yOrigin = 0;
// Current plot position
signed char x0;
signed char y0;
// Plot point x,y into buffer if in current slice
void PlotPoint(int x, int y) {
int row = 47 - y - yOrigin;
int col = x + xOrigin;
int page = row>>3;
int bit = row & 0x07;
// Set correct bit in slice buffer
Buffer[page*64 + col] |= 1<<bit;
}
// Move current plot position to x1,y1
void MoveTo(int x1, int y1) {
x0 = x1;
y0 = y1;
}
// Draw a line to x1,y1
void DrawTo(int x1, int y1) {
int sx, sy, e2, err;
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
if (x0 < x1) sx = 1; else sx = -1;
if (y0 < y1) sy = 1; else sy = -1;
err = dx - dy;
for (;;) {
PlotPoint(x0, y0);
if (x0==x1 && y0==y1) return;
e2 = err<<1;
if (e2 > -dy) {
err = err - dy;
x0 = x0 + sx;
}
if (e2 < dx) {
err = err + dx;
y0 = y0 + sy;
}
}
}
// Plot text from program memory into buffer at x,y
void PlotText(int x, int y, const __FlashStringHelper *s) {
int p = (int)s;
int page = (47 - y - yOrigin)>>3;
while (1) {
char c = pgm_read_byte(p++);
if (c == 0) return;
for (uint8_t col = 0 ; col < 6; col++) {
Buffer[page*64 + x + xOrigin] = pgm_read_byte(&CharMap[c-32][col]);
x++;
}
}
}
// Setup **********************************************
void setup() {
// Define pins
pinMode(dc, OUTPUT); digitalWrite(dc,HIGH);
pinMode(clk, OUTPUT); digitalWrite(clk,HIGH);
pinMode(data, OUTPUT);
pinMode(cs, OUTPUT); digitalWrite(cs,HIGH);
InitDisplay();
}
// Applications **********************************************
void AnalogueMeter () {
xOrigin = 32; yOrigin = 0;
const int Delta2 = 16;
int x = -(23<<9), y = 0;
ClearBuffer();
PlotText(-20, 40, F("Voltage"));
for (int i = 0; i<=100; i++) {
if (i%20 == 0) {
MoveTo(x>>9, (y>>9));
DrawTo((x>>9) - (x>>12), (y>>9) - (y>>12));
}
if (i == (analogRead(A2)*25 + 25)>>8) {
MoveTo(x>>9, y>>9);
DrawTo(0, 0);
}
MoveTo(x>>9, y>>9);
x = x + ((y>>9) * Delta2);
y = y - ((x>>9) * Delta2);
if (i != 100) DrawTo(x>>9, y>>9);
}
PlotText(-31, 0, F("0")); PlotText(27, 0, F("5"));
PlotText(-27, 16, F("1")); PlotText(23, 16, F("4"));
PlotText(-12, 24, F("2 3"));
DisplayBuffer();
}
void loop () {
AnalogueMeter();
}