Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OLED I2C display example #135

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 202 additions & 0 deletions avr/libraries/TinyWire/examples/i2c_oled/i2c_oled.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/***********************************************************************|
| TinyWSoftware i2c master library for ATtiny13 |
| |
| i2c_oled.ino (by Dhiru Kholia - VU3CER) |
| |
| Based on https://github.com/wagiminator/ATtiny13-TinyOLEDdemo (by |
| Stefan Wagner - wagiminator) |
| |
| In this example we drive a 0.96" OLED Display Module over I2C. |
| |
| SERIAL REMINDER |
| The baud rate is ignored on the ATtiny13 due to using a simplified |
| serial. The baud rate used is dependent on the processor speed. |
| Note that you can specify a custom baud rate if the following ones |
| does not fit your application. |
| |
| THESE CLOCKS USES 115200 BAUD: THIS CLOCK USES 57600 BAUD: |
| 20 MHz, 16 MHz, 9.6 MHz, 8 MHz 4.8 MHz |
| THESE CLOCKS USES 19200 BAUD: THIS CLOCK USES 9600 BAUD: |
| 1.2 MHz, 1 MHz 600 KHz |
| |
| If you get garbage output: |
| 1. Check baud rate as above |
| 2. Check if you have anything else connected to TX/RX like an LED |
| 3. Check OSCCAL (see MicroCore OSCCAL tuner example) |
|***********************************************************************/

#include <TinyWire.h>

// We have to define which pins to use for SDA and SCL
const uint8_t TinyWire::SCL = 3;
const uint8_t TinyWire::SDA = 4;

// Sets the i2c clock speed in [Hz]
// Use MAX_SPEED for the highest possible clock speed
const uint32_t TinyWire::FREQ = 100000;

// OLED definitions
#define OLED_ADDR 0x3C // OLED write address - for '0.96" OLED Display Module'
#define OLED_CMD_MODE 0x00 // set command mode
#define OLED_DAT_MODE 0x40 // set data mode
#define OLED_INIT_LEN 14 // 12: no screen flip, 14: screen flip

// OLED init settings
const uint8_t OLED_INIT_CMD[] PROGMEM = {
0xA8, 0x1F, // set multiplex (HEIGHT-1): 0x1F for 128x32, 0x3F for 128x64
0x22, 0x00, 0x03, // set min and max page
0x20, 0x00, // set horizontal memory addressing mode
0xDA, 0x02, // set COM pins hardware configuration to sequential
0x8D, 0x14, // enable charge pump
0xAF, // switch on OLED
0xA1, 0xC8 // flip the screen
};

// standard ASCII 5x8 font (adapted from Neven Boyanov and Stephen Denne)
const uint8_t OLED_FONT[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, // 0
0x00, 0x00, 0x2f, 0x00, 0x00, // ! 1
0x00, 0x07, 0x00, 0x07, 0x00, // " 2
0x14, 0x7f, 0x14, 0x7f, 0x14, // # 3
0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ 4
0x62, 0x64, 0x08, 0x13, 0x23, // % 5
0x36, 0x49, 0x55, 0x22, 0x50, // & 6
0x00, 0x05, 0x03, 0x00, 0x00, // ' 7
0x00, 0x1c, 0x22, 0x41, 0x00, // ( 8
0x00, 0x41, 0x22, 0x1c, 0x00, // ) 9
0x14, 0x08, 0x3E, 0x08, 0x14, // * 10
0x08, 0x08, 0x3E, 0x08, 0x08, // + 11
0x00, 0x00, 0xA0, 0x60, 0x00, // , 12
0x08, 0x08, 0x08, 0x08, 0x08, // - 13
0x00, 0x60, 0x60, 0x00, 0x00, // . 14
0x20, 0x10, 0x08, 0x04, 0x02, // / 15
0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 16
0x00, 0x42, 0x7F, 0x40, 0x00, // 1 17
0x42, 0x61, 0x51, 0x49, 0x46, // 2 18
0x21, 0x41, 0x45, 0x4B, 0x31, // 3 19
0x18, 0x14, 0x12, 0x7F, 0x10, // 4 20
0x27, 0x45, 0x45, 0x45, 0x39, // 5 21
0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 22
0x01, 0x71, 0x09, 0x05, 0x03, // 7 23
0x36, 0x49, 0x49, 0x49, 0x36, // 8 24
0x06, 0x49, 0x49, 0x29, 0x1E, // 9 25
0x00, 0x36, 0x36, 0x00, 0x00, // : 26
0x00, 0x56, 0x36, 0x00, 0x00, // ; 27
0x08, 0x14, 0x22, 0x41, 0x00, // < 28
0x14, 0x14, 0x14, 0x14, 0x14, // = 29
0x00, 0x41, 0x22, 0x14, 0x08, // > 30
0x02, 0x01, 0x51, 0x09, 0x06, // ? 31
0x32, 0x49, 0x59, 0x51, 0x3E, // @ 32
0x7C, 0x12, 0x11, 0x12, 0x7C, // A 33
0x7F, 0x49, 0x49, 0x49, 0x36, // B 34
0x3E, 0x41, 0x41, 0x41, 0x22, // C 35
0x7F, 0x41, 0x41, 0x22, 0x1C, // D 36
0x7F, 0x49, 0x49, 0x49, 0x41, // E 37
0x7F, 0x09, 0x09, 0x09, 0x01, // F 38
0x3E, 0x41, 0x49, 0x49, 0x7A, // G 39
0x7F, 0x08, 0x08, 0x08, 0x7F, // H 40
0x00, 0x41, 0x7F, 0x41, 0x00, // I 41
0x20, 0x40, 0x41, 0x3F, 0x01, // J 42
0x7F, 0x08, 0x14, 0x22, 0x41, // K 43
0x7F, 0x40, 0x40, 0x40, 0x40, // L 44
0x7F, 0x02, 0x0C, 0x02, 0x7F, // M 45
0x7F, 0x04, 0x08, 0x10, 0x7F, // N 46
0x3E, 0x41, 0x41, 0x41, 0x3E, // O 47
0x7F, 0x09, 0x09, 0x09, 0x06, // P 48
0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 49
0x7F, 0x09, 0x19, 0x29, 0x46, // R 50
0x46, 0x49, 0x49, 0x49, 0x31, // S 51
0x01, 0x01, 0x7F, 0x01, 0x01, // T 52
0x3F, 0x40, 0x40, 0x40, 0x3F, // U 53
0x1F, 0x20, 0x40, 0x20, 0x1F, // V 54
0x3F, 0x40, 0x38, 0x40, 0x3F, // W 55
0x63, 0x14, 0x08, 0x14, 0x63, // X 56
0x07, 0x08, 0x70, 0x08, 0x07, // Y 57
0x61, 0x51, 0x49, 0x45, 0x43, // Z 58
0x00, 0x7F, 0x41, 0x41, 0x00, // [ 59
0x02, 0x04, 0x08, 0x10, 0x20, // \ 60
0x00, 0x41, 0x41, 0x7F, 0x00, // ] 61
0x04, 0x02, 0x01, 0x02, 0x04, // ^ 62
0x40, 0x40, 0x40, 0x40, 0x40 // _ 63
};

// messages to print on OLED
const char Message1[] PROGMEM = "HELLO WORLD! :)";

// OLED init function
void OLED_init(void) {
Wire.beginTransmission(OLED_ADDR);
Wire.write(OLED_CMD_MODE); // set command mode
for (uint8_t i = 0; i < OLED_INIT_LEN; i++)
Wire.write(pgm_read_byte(&OLED_INIT_CMD[i])); // send the command bytes
Wire.endTransmission(); // initialize I2C first
}

// OLED set vertical shift
void OLED_shift(uint8_t ypos) {
Wire.beginTransmission(OLED_ADDR); // start transmission to OLED
Wire.write(OLED_CMD_MODE); // set command mode
Wire.write(0xD3); // vertical shift command
Wire.write(ypos); // set vertical shift value
Wire.endTransmission(); // stop transmission
}

// OLED print a character
void OLED_printC(char ch) {
uint16_t offset = ch - 32; // calculate position of character in font array
offset += offset << 2; // -> offset = (ch - 32) * 5
Wire.write(0x00); // print spacing between characters
for (uint8_t i = 5; i; i--)
Wire.write(pgm_read_byte(&OLED_FONT[offset++])); // print character
}

// OLED print a string from program memory
void OLED_printP(const char* p) {
Wire.beginTransmission(OLED_ADDR); // start transmission to OLED
Wire.write(OLED_DAT_MODE); // set data mode
char ch = pgm_read_byte(p); // read first character from program memory
while (ch != 0) { // repeat until string terminator
OLED_printC(ch); // print character on OLED
ch = pgm_read_byte(++p); // read next character
}
Wire.endTransmission(); // stop transmission
}

// OLED set the cursor
void OLED_cursor(uint8_t xpos, uint8_t ypos) {
Wire.beginTransmission(OLED_ADDR); // start transmission to OLED
Wire.write(OLED_CMD_MODE); // set command mode
Wire.write(xpos & 0x0F); // set low nibble of start column
Wire.write(0x10 | (xpos >> 4)); // set high nibble of start column
Wire.write(0xB0 | (ypos & 0x07)); // set start page
Wire.endTransmission(); // stop transmission
}

// OLED clear screen
void OLED_clear(void) {
OLED_cursor(0, 0); // set cursor at upper left corner
Wire.beginTransmission(OLED_ADDR); // start transmission to OLED
Wire.write(OLED_DAT_MODE); // set data mode
for (uint16_t i = 512; i; i--)
Wire.write(0x00); // clear the screen
Wire.endTransmission(); // stop transmission
OLED_shift(0); // reset vertical shift
}

void setup()
{
// No baudrate to select. See header for details
Serial.begin();
Serial.println(F("Check your OLED screen ;)"));
OLED_init();
}

void loop()
{
while (1) {
OLED_clear(); // clear screen
OLED_cursor(0, 0); // set cursor position
OLED_printP(Message1); // print message 1
delay(5000);
}
}