Skip to content

Instantly share code, notes, and snippets.

@Electronza
Created May 5, 2020 09:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Electronza/f512ce82d55e62f4828c7f3c598593ac to your computer and use it in GitHub Desktop.
Save Electronza/f512ce82d55e62f4828c7f3c598593ac to your computer and use it in GitHub Desktop.
OLED click arduino tutorial
/*
* File: oled.h
*/
#define OLED_WIDTH 96
#define OLED_HEIGHT 39
#define SSD1306_DISPLAYOFF 0xAE
#define SSD1306_SETDISPLAYCLOCKDIV 0xD5
#define SSD1306_SETMULTIPLEX 0xA8
#define SSD1306_SETDISPLAYOFFSET 0xD3
#define SSD1306_SETSTARTLINE 0x40
#define SSD1306_CHARGEPUMP 0x8D
#define SSD1306_SETSEGMENTREMAP 0xA1
#define SSD1306_SEGREMAP 0xA0
#define SSD1306_COMSCANDEC 0xC8
#define SSD1306_SETCOMPINS 0xDA
#define SSD1306_SETCONTRAST 0x81
#define SSD1306_SETPRECHARGE 0xD9
#define SSD1306_SETVCOMDETECT 0xDB
#define SSD1306_DISPLAYALLON_RESUME 0xA4
#define SSD1306_NORMALDISPLAY 0xA6
#define SSD1306_DISPLAYON 0xAF
#define SSD1306_DISPLAYALLON 0xA5
#define SSD1306_INVERTDISPLAY 0xA7
#define SSD1306_SETLOWCOLUMN 0x00
#define SSD1306_SETHIGHCOLUMN 0x10
#define SSD1306_MEMORYMODE 0x20
#define SSD1306_COLUMNADDR 0x21
#define SSD1306_PAGEADDR 0x22
#define SSD1306_COMSCANINC 0xC0
#define SSD1306_SEGREMAP 0xA0
#define SSD1306_EXTERNALVCC 0x1
#define SSD1306_SWITCHCAPVCC 0x2
#define SSD1306_ACTIVATE_SCROLL 0x2F
#define SSD1306_DEACTIVATE_SCROLL 0x2E
#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3
#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26
#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
const uint8_t font[] = { // compact 5x8 font
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0x00,0x00,0x00,0x07,0x00,0x07,0x00, // 'sp,!,"
0x14,0x7F,0x14,0x7F,0x14, // #
0x24,0x2A,0x7F,0x2A,0x12,0x23,0x13,0x08,0x64,0x62,0x36,0x49,0x56,0x20,0x50, // '$,%,&
0x00,0x08,0x07,0x03,0x00,0x00,0x1C,0x22,0x41,0x00,0x00,0x41,0x22,0x1C,0x00, // '',(,)
0x2A,0x1C,0x7F,0x1C,0x2A,0x08,0x08,0x3E,0x08,0x08,0x00,0x00,0x70,0x30,0x00, // '*,+,,
0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x60,0x60,0x00,0x20,0x10,0x08,0x04,0x02, // '-,.,/
0x3E,0x51,0x49,0x45,0x3E,0x00,0x42,0x7F,0x40,0x00,0x72,0x49,0x49,0x49,0x46, // '0,1,2
0x21,0x41,0x49,0x4D,0x33,0x18,0x14,0x12,0x7F,0x10,0x27,0x45,0x45,0x45,0x39, // '3,4,5
0x3C,0x4A,0x49,0x49,0x31,0x41,0x21,0x11,0x09,0x07,0x36,0x49,0x49,0x49,0x36, // '6,7,8
0x46,0x49,0x49,0x29,0x1E,0x00,0x00,0x14,0x00,0x00,0x00,0x40,0x34,0x00,0x00, // '9,:,;
0x00,0x08,0x14,0x22,0x41,0x14,0x14,0x14,0x14,0x14,0x00,0x41,0x22,0x14,0x08, // '<,=,>
0x02,0x01,0x59,0x09,0x06,0x3E,0x41,0x5D,0x59,0x4E, // '?,@
0x7C,0x12,0x11,0x12,0x7C, // 'A
0x7F,0x49,0x49,0x49,0x36,0x3E,0x41,0x41,0x41,0x22,0x7F,0x41,0x41,0x41,0x3E, // 'B,C,D
0x7F,0x49,0x49,0x49,0x41,0x7F,0x09,0x09,0x09,0x01,0x3E,0x41,0x41,0x51,0x73, // 'E,F,G
0x7F,0x08,0x08,0x08,0x7F,0x00,0x41,0x7F,0x41,0x00,0x20,0x40,0x41,0x3F,0x01, // 'H,I,J
0x7F,0x08,0x14,0x22,0x41,0x7F,0x40,0x40,0x40,0x40,0x7F,0x02,0x1C,0x02,0x7F, // 'K,L,M
0x7F,0x04,0x08,0x10,0x7F,0x3E,0x41,0x41,0x41,0x3E,0x7F,0x09,0x09,0x09,0x06, // 'N,O,P
0x3E,0x41,0x51,0x21,0x5E,0x7F,0x09,0x19,0x29,0x46,0x26,0x49,0x49,0x49,0x32, // 'Q,R,S
0x03,0x01,0x7F,0x01,0x03,0x3F,0x40,0x40,0x40,0x3F,0x1F,0x20,0x40,0x20,0x1F, // 'T,U,V
0x3F,0x40,0x38,0x40,0x3F,0x63,0x14,0x08,0x14,0x63,0x03,0x04,0x78,0x04,0x03, // 'W,X,Y
0x61,0x59,0x49,0x4D,0x43, // 'Z
0x00,0x7F,0x41,0x41,0x41,0x02,0x04,0x08,0x10,0x20, // '[,\
0x00,0x41,0x41,0x41,0x7F,0x04,0x02,0x01,0x02,0x04,0x40,0x40,0x40,0x40,0x40, // '],^,_
0x00,0x03,0x07,0x08,0x00,0x20,0x54,0x54,0x38,0x40,0x7F,0x28,0x44,0x44,0x38, // '`,a,b
0x38,0x44,0x44,0x44,0x28,0x38,0x44,0x44,0x28,0x7F,0x38,0x54,0x54,0x54,0x18, // 'c,d,e
0x00,0x08,0x7E,0x09,0x02,0x0C,0x52,0x52,0x4A,0x3C,0x7F,0x08,0x04,0x04,0x78, // 'f,g,h
0x00,0x44,0x7D,0x40,0x00,0x20,0x40,0x40,0x3D,0x00,0x7F,0x10,0x28,0x44,0x00, // 'i,j,k
0x00,0x41,0x7F,0x40,0x00,0x7C,0x04,0x78,0x04,0x78,0x7C,0x08,0x04,0x04,0x78, // 'l,m,n
0x38,0x44,0x44,0x44,0x38,0x7C,0x18,0x24,0x24,0x18,0x18,0x24,0x24,0x18,0x7C, // 'o,p,q
0x7C,0x08,0x04,0x04,0x08,0x48,0x54,0x54,0x54,0x24,0x04,0x04,0x3F,0x44,0x24, // 'r,s,t
0x3C,0x40,0x40,0x20,0x7C,0x1C,0x20,0x40,0x20,0x1C,0x3C,0x40,0x30,0x40,0x3C, // 'u,v,w
0x44,0x28,0x10,0x28,0x44,0x4C,0x50,0x50,0x50,0x3C,0x44,0x64,0x54,0x4C,0x44, // 'x,y,z
0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x41,0x36,0x08,0x00, // '{,|,}
0x02,0x01,0x02,0x04,0x02 // '~
};
#include <SPI.h>
#include "oled.h"
// Bitmap created with Image2GLCD
// http://www.avrportal.com/?page=image2glcd
// Set to LSB to MSB, Top to Bottom
// Custom, 96 x 40 size
// Yes, 96 x 40! It prints garbage when setting 96 x 39
const uint8_t bitmap[] = {
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, 0x10, 0xD0, 0x70, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0,
0x70, 0xD0, 0xF0, 0x30, 0x10, 0x10, 0x00, 0x10, 0x90, 0xF0, 0x70, 0x10, 0x10, 0x10, 0x10, 0x30,
0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 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, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x3F, 0xFF, 0xC0, 0xE0, 0x70, 0x1C, 0x0F, 0x03, 0x01,
0xF8, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x0C, 0x06,
0x07, 0x01, 0x01, 0xF9, 0xFF, 0x0F, 0x02, 0x01, 0x01, 0x03, 0xF0, 0xFC, 0x06, 0x03, 0x01, 0x01,
0xC3, 0xFE, 0x3C, 0x00, 0x00, 0x00, 0x01, 0xF9, 0xFF, 0x07, 0x00, 0xF0, 0xFC, 0x2E, 0x22, 0x23,
0x31, 0x11, 0x99, 0x9F, 0x0E, 0x00, 0xF0, 0xFC, 0x0E, 0x02, 0x01, 0x01, 0x01, 0x8F, 0x8E, 0x00,
0x01, 0xF9, 0xFF, 0x07, 0x01, 0x81, 0x80, 0x80, 0x0E, 0x1E, 0x19, 0x19, 0x31, 0x31, 0xE3, 0xE6,
0x02, 0x02, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
0x03, 0x02, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x02, 0x02, 0x03,
0x01, 0x20, 0x60, 0x40, 0x40, 0x60, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x02, 0x02,
0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00,
0x01, 0x03, 0x03, 0x02, 0x01, 0x00, 0x01, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x01, 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
};
// Oled W click mapping
// chipKIT UNO32, socket #1
#define OLED_CS 10
#define OLED_DC 6
#define OLED_RST A3
// Flip & Click, socket #1
//#define OLED_CS 77
//#define OLED_DC 6
//#define OLED_RST 33
void setup() {
// put your setup code here, to run once:
SPI.begin();
// Set OLED pins
pinMode(OLED_CS, OUTPUT);
pinMode(OLED_DC, OUTPUT);
pinMode(OLED_RST, OUTPUT);
OLED_Initialize();
delay(100);
OLED_PutPicture(bitmap);
delay(8000);
OLED_Clear();
OLED_SetScale(1, 2);
OLED_Putchar('T');
OLED_Putchar('H');
OLED_Putchar('I');
OLED_Putchar('S');
OLED_Putchar(' ');
OLED_Putchar('I');
OLED_Putchar('S');
OLED_Putchar(' ');
OLED_Putchar('A');
OLED_Putchar(' ');
OLED_Putchar('T');
OLED_Putchar('E');
OLED_Putchar('X');
OLED_Putchar('T');
}
void loop() {
// put your main code here, to run repeatedly:
}
// OLED W functions
void OLED_Command(uint8_t temp){
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
digitalWrite(OLED_CS,LOW);
digitalWrite(OLED_DC,LOW);
SPI.transfer(temp);
digitalWrite(OLED_CS,HIGH);
SPI.endTransaction();
}
void OLED_Data(uint8_t temp){
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
digitalWrite(OLED_CS,LOW);
digitalWrite(OLED_DC,HIGH);
SPI.transfer(temp);
digitalWrite(OLED_CS,HIGH);
SPI.endTransaction();
}
void OLED_Initialize(void)
{
digitalWrite(OLED_RST,LOW);
delay(1000);
digitalWrite(OLED_RST,HIGH);
delay(1000);
OLED_Command(SSD1306_DISPLAYOFF); //0xAE Set OLED Display Off
OLED_Command(SSD1306_SETDISPLAYCLOCKDIV); //0xD5 Set Display Clock Divide Ratio/Oscillator Frequency
OLED_Command(0x80);
OLED_Command(SSD1306_SETMULTIPLEX); //0xA8 Set Multiplex Ratio
OLED_Command(39);
OLED_Command(SSD1306_SETSEGMENTREMAP); //0xA1 Set Segment Remap Inv
OLED_Command(SSD1306_COMSCANDEC); //0xC8 Set COM Output Scan Inv
OLED_Command(SSD1306_SETDISPLAYOFFSET); //0xD3 Set Display Offset
OLED_Command(0x00);
OLED_Command(SSD1306_CHARGEPUMP); //0x8D Set Charge Pump
OLED_Command(0x14); //0x14 Enable Charge Pump
OLED_Command(SSD1306_SETSTARTLINE); //0x40 Set Display Start Line
OLED_Command(SSD1306_SETCOMPINS); //0xDA Set COM Pins Hardware Configuration
OLED_Command(0x12);
OLED_Command(SSD1306_SETCONTRAST); //0x81 Set Contrast Control
OLED_Command(0xAF);
OLED_Command(SSD1306_SETPRECHARGE); //0xD9 Set Pre-Charge Period
OLED_Command(0x25);
OLED_Command(SSD1306_SETVCOMDETECT); //0xDB Set VCOMH Deselect Level
OLED_Command(0x20);
OLED_Command(SSD1306_DISPLAYALLON_RESUME); //0xA4 Set Entire Display On/Off
OLED_Command(SSD1306_NORMALDISPLAY); //0xA6 Set Normal/Inverse Display
OLED_Command(SSD1306_DISPLAYON); //0xAF Set OLED Display On
} // OLED_Initialize
void OLED_SetRow(uint8_t add)
{
add = 0xB0 | add;
OLED_Command(add);
}
void OLED_SetColumn(uint8_t add)
{
add += 32;
OLED_Command((SSD1306_SETHIGHCOLUMN | (add >> 4))); // SET_HIGH_COLUMN
OLED_Command((0x0f & add)); // SET LOW_COLUMN
}
void OLED_PutPicture(const uint8_t *pic)
{
unsigned char i,j;
for(i=0; i<5; i++) // 5*8=40 pixel rows (actually 39)
{
OLED_SetRow(i);
OLED_SetColumn(0);
for(j=0; j<96; j++) // 96 pixel columns
{
OLED_Data(*pic++);
}
}
}
void OLED_SetContrast(uint8_t temp)
{
OLED_Command(SSD1306_SETCONTRAST);
OLED_Command(temp); // contrast step 1 to 256
}
uint8_t _x, _y;
uint8_t _sx=1, _sy=1; // scaling factors
void OLED_SetScale(uint8_t sx, uint8_t sy){
_sx = sx; _sy = sy;
}
void OLED_Clear(void)
{
unsigned char i,j;
for(i=0; i<5; i++) // 5*8=40 pixel rows (actually 39)
{
OLED_SetRow(i);
OLED_SetColumn(0);
for(j=0; j<96; j++) OLED_Data(0);
}
_x = 0; _y = 0;
OLED_SetRow(0);
OLED_SetColumn(0);
}
/** scalable horizontally and vertically
*/
void OLED_Putchar(char ch)
{
uint8_t i, j, k, byte;
const uint8_t *f = &font[(ch-' ')*5];
const uint8_t mask[]={1, 3, 7, 0xf };
for(i=0; i<6; i++) {
uint32_t word;
byte = *f++ << 1;
if (i==5) byte = 0;
for(j=0; j<8; j++) { // expand byte to word
word <<= _sy;
if (byte & 0x80) word |= mask[_sy-1];
byte <<= 1;
}
for(j=0; j<_sy; j++){ // exp vert
OLED_SetRow(_y+j) ;
OLED_SetColumn(_x+i*_sx);
for(k=0; k<_sx; k++){ // exp horiz
OLED_Data(word);
}
word >>= 8;
}
}
_x+= 6 * _sx;
if (_x >= OLED_WIDTH) { // wrap x
_x = 0; OLED_SetColumn(0);
_y += _sy;
if (_y >= 5-_sy) { // wrap y
_y = 0;
}
OLED_SetRow(_y);
}
}
void OLED_Puts(char x, char y, char *s)
{
_y = y; _x = x;
OLED_SetRow(_y);
OLED_SetColumn(_x);
while(*s) {
OLED_Putchar(*s++);
_x++;
}
}
@stevantosic
Copy link

stevantosic commented Nov 1, 2020

Hello
Some remarks about OLED lib:

  1. oled.h:

Line 70 : char \ cause ASCII shifting

  1. Sometimes PROGMEM may be useful :

a) oled.h:
const uint8_t font[] PROGMEM

b) oled.ino:
void OLED_Putchar(char ch)
{
///
//byte = *f++ << 1;
byte = pgm_read_byte_near(font + (ch-' ')*5 + i);
byte << 1;
///
}

Stevan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment