edu16_sbc/libraries/Arduino_Software_I2C-master/SeeedGrayOLED.cpp
2025-09-22 20:00:44 +08:00

493 lines
17 KiB
C++

/*
SeeedGrayOLED.cpp
SSD1327 Gray OLED Driver Library
Copyright (c) 2011 seeed technology inc.
Author : Visweswara R
Create Time : Dec 2011
Change Log :
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Arduino.h"
#include <SoftwareI2C.h>
#include "SeeedGrayOLED.h"
#if defined(ESP32)
#include <pgmspace.h>
#else
#include <avr/pgmspace.h>
#endif
#if defined(__arm__) && !defined(PROGMEM)
#define PROGMEM
#define pgm_read_byte(STR) STR
#endif
// 8x8 Font ASCII 32 - 127 Implemented
// Users can modify this to support more characters(glyphs)
// BasicFont is placed in code memory.
// This font can be freely used without any restriction(It is placed in public domain)
const unsigned char BasicFont[][8] PROGMEM = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00},
{0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, 0x00},
{0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x00},
{0x00, 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 0x00},
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50, 0x00, 0x00},
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x08, 0x2A, 0x1C, 0x2A, 0x08, 0x00, 0x00},
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00},
{0x00, 0xA0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00},
{0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00},
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00},
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x00},
{0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x00, 0x00},
{0x00, 0x22, 0x41, 0x49, 0x49, 0x36, 0x00, 0x00},
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x00},
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x00},
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00, 0x00},
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03, 0x00, 0x00},
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00},
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00},
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xAC, 0x6C, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00},
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00},
{0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00},
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06, 0x00, 0x00},
{0x00, 0x32, 0x49, 0x79, 0x41, 0x3E, 0x00, 0x00},
{0x00, 0x7E, 0x09, 0x09, 0x09, 0x7E, 0x00, 0x00},
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00},
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 0x00},
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00, 0x00},
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 0x00},
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 0x00},
{0x00, 0x3E, 0x41, 0x41, 0x51, 0x72, 0x00, 0x00},
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x00},
{0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, 0x00},
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00},
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00, 0x00},
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, 0x00},
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x00},
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 0x00},
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 0x00},
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 0x00},
{0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00},
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, 0x00, 0x00},
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 0x00},
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 0x00},
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 0x00},
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x00},
{0x00, 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, 0x00},
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43, 0x00, 0x00},
{0x00, 0x7F, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00},
{0x00, 0x41, 0x41, 0x7F, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00},
{0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00},
{0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x00, 0x00},
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, 0x00, 0x00},
{0x00, 0x38, 0x44, 0x44, 0x28, 0x00, 0x00, 0x00},
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, 0x00, 0x00},
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x00},
{0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, 0x00, 0x00},
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, 0x00, 0x00},
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x00},
{0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x80, 0x84, 0x7D, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00},
{0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, 0x00, 0x00},
{0x00, 0x7C, 0x08, 0x04, 0x7C, 0x00, 0x00, 0x00},
{0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00},
{0x00, 0xFC, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00},
{0x00, 0x18, 0x24, 0x24, 0xFC, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7C, 0x08, 0x04, 0x00, 0x00, 0x00},
{0x00, 0x48, 0x54, 0x54, 0x24, 0x00, 0x00, 0x00},
{0x00, 0x04, 0x7F, 0x44, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x3C, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00},
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, 0x00},
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, 0x00},
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00},
{0x00, 0x1C, 0xA0, 0xA0, 0x7C, 0x00, 0x00, 0x00},
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x00},
{0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x41, 0x36, 0x08, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x00},
{0x00, 0x02, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00}
};
void SeeedGrayOLED::init(int IC) {
Drive_IC = IC;
if (Drive_IC == SSD1327) {
sendCommand(0xFD); // Unlock OLED driver IC MCU interface from entering command. i.e: Accept commands
sendCommand(0x12);
sendCommand(0xAE); // Set display off
sendCommand(0xA8); // set multiplex ratio
sendCommand(0x5F); // 96
sendCommand(0xA1); // set display start line
sendCommand(0x00);
sendCommand(0xA2); // set display offset
sendCommand(0x60);
sendCommand(0xA0); // set remap
sendCommand(0x46);
sendCommand(0xAB); // set vdd internal
sendCommand(0x01); //
sendCommand(0x81); // set contrasr
sendCommand(0x53); // 100 nit
sendCommand(0xB1); // Set Phase Length
sendCommand(0X51); //
sendCommand(0xB3); // Set Display Clock Divide Ratio/Oscillator Frequency
sendCommand(0x01);
sendCommand(0xB9); //
sendCommand(0xBC); // set pre_charge voltage/VCOMH
sendCommand(0x08); // (0x08);
sendCommand(0xBE); // set VCOMH
sendCommand(0X07); // (0x07);
sendCommand(0xB6); // Set second pre-charge period
sendCommand(0x01); //
sendCommand(0xD5); // enable second precharge and enternal vsl
sendCommand(0X62); // (0x62);
sendCommand(0xA4); // Set Normal Display Mode
sendCommand(0x2E); // Deactivate Scroll
sendCommand(0xAF); // Switch on display
delay(100);
// Row Address
sendCommand(0x75); // Set Row Address
sendCommand(0x00); // Start 0
sendCommand(0x5f); // End 95
// Column Address
sendCommand(0x15); // Set Column Address
sendCommand(0x08); // Start from 8th Column of driver IC. This is 0th Column for OLED
sendCommand(0x37); // End at (8 + 47)th column. Each Column has 2 pixels(segments)
// Init gray level for text. Default:Brightest White
grayH = 0xF0;
grayL = 0x0F;
} else if (Drive_IC == SH1107G) {
sendCommand(0xae); //Display OFF
sendCommand(0xd5); // Set Dclk
sendCommand(0x50); // 100Hz
sendCommand(0x20); // Set row address
sendCommand(0x81); // Set contrast control
sendCommand(0x80);
sendCommand(0xa0); // Segment remap
sendCommand(0xa4); // Set Entire Display ON
sendCommand(0xa6); // Normal display
sendCommand(0xad); // Set external VCC
sendCommand(0x80);
sendCommand(0xc0); // Set Common scan direction
sendCommand(0xd9); // Set phase leghth
sendCommand(0x1f);
sendCommand(0xdb); // Set Vcomh voltage
sendCommand(0x27);
sendCommand(0xaf); //Display ON
sendCommand(0xb0);
sendCommand(0x00);
sendCommand(0x11);
}
}
void SeeedGrayOLED::sendCommand(unsigned char command) {
Wire->beginTransmission(SeeedGrayOLED_Address); // begin I2C communication
Wire->write(SeeedGrayOLED_Command_Mode); // Set OLED Command mode
Wire->write(command);
Wire->endTransmission(); // End I2C communication
}
void SeeedGrayOLED::setContrastLevel(unsigned char ContrastLevel) {
sendCommand(SeeedGrayOLED_Set_ContrastLevel_Cmd);
sendCommand(ContrastLevel);
}
void SeeedGrayOLED::setHorizontalMode() {
if (Drive_IC == SSD1327) {
sendCommand(0xA0); // remap to
sendCommand(0x42); // horizontal mode
// Row Address
sendCommand(0x75); // Set Row Address
sendCommand(0x00); // Start 0
sendCommand(0x5f); // End 95
// Column Address
sendCommand(0x15); // Set Column Address
sendCommand(0x08); // Start from 8th Column of driver IC. This is 0th Column for OLED
sendCommand(0x37); // End at (8 + 47)th column. Each Column has 2 pixels(or segments)
} else if (Drive_IC == SH1107G) {
sendCommand(0xA0);
sendCommand(0xC8);
}
}
void SeeedGrayOLED::setVerticalMode() {
if (Drive_IC == SSD1327) {
sendCommand(0xA0); // remap to
sendCommand(0x46); // Vertical mode
} else if (Drive_IC == SH1107G) {
sendCommand(0xA0);
sendCommand(0xC0);
}
}
void SeeedGrayOLED::setTextXY(unsigned char Row, unsigned char Column) {
if (Drive_IC == SSD1327) {
//Column Address
sendCommand(0x15); /* Set Column Address */
sendCommand(0x08 + (Column * 4)); /* Start Column: Start from 8 */
sendCommand(0x37); /* End Column */
// Row Address
sendCommand(0x75); /* Set Row Address */
sendCommand(0x00 + (Row * 8)); /* Start Row*/
sendCommand(0x07 + (Row * 8)); /* End Row*/
} else if (Drive_IC == SH1107G) {
uint8_t col_l;
Column % 2 ? col_l = 0x08 : col_l = 0x00;
sendCommand(0xb0 + Row);
sendCommand(col_l);
sendCommand(0x11 + (Column / 2));
}
}
void SeeedGrayOLED::clearDisplay() {
unsigned char i, j;
if (Drive_IC == SSD1327) {
for (j = 0; j < 48; j++) {
for (i = 0; i < 96; i++) { //clear all columns
sendData(0x00);
}
}
} else if (Drive_IC == SH1107G) {
for (i = 0; i < 16; i++) {
sendCommand(0xb0 + i);
sendCommand(0x0);
sendCommand(0x10);
for (j = 0; j < 128; j++) {
sendData(0x00);
}
}
}
}
void SeeedGrayOLED::sendData(unsigned char Data) {
Wire->beginTransmission(SeeedGrayOLED_Address); // begin I2C transmission
Wire->write(SeeedGrayOLED_Data_Mode); // data mode
Wire->write(Data);
Wire->endTransmission(); // stop I2C transmission
}
void SeeedGrayOLED::setGrayLevel(unsigned char grayLevel) {
grayH = (grayLevel << 4) & 0xF0;
grayL = grayLevel & 0x0F;
}
void SeeedGrayOLED::putChar(unsigned char C) {
if (C < 32 || C > 127) { //Ignore non-printable ASCII characters. This can be modified for multilingual font.
C = ' '; //Space
}
if (Drive_IC == SSD1327) {
for (char i = 0; i < 8; i = i + 2) {
for (char j = 0; j < 8; j++) {
// Character is constructed two pixel at a time using vertical mode from the default 8x8 font
char c = 0x00;
char bit1 = (pgm_read_byte(&BasicFont[C - 32][(uint8_t) i]) >> j) & 0x01;
char bit2 = (pgm_read_byte(&BasicFont[C - 32][(uint8_t) i + 1]) >> j) & 0x01;
// Each bit is changed to a nibble
c |= (bit1) ? grayH : 0x00;
c |= (bit2) ? grayL : 0x00;
sendData(c);
}
}
} else if (Drive_IC == SH1107G) {
for (int i = 0; i < 8; i++) {
//read bytes from code memory
sendData(pgm_read_byte(&BasicFont[C - 32][i])); //font array starts at 0, ASCII starts at 32. Hence the translation
}
}
}
void SeeedGrayOLED::putString(const char* String) {
unsigned char i = 0;
while (String[i]) {
putChar(String[i]);
i++;
}
}
unsigned char SeeedGrayOLED::putNumber(long long_num) {
unsigned char char_buffer[10] = "";
unsigned char i = 0;
unsigned char f = 0;
if (long_num < 0) {
f = 1;
putChar('-');
long_num = -long_num;
} else if (long_num == 0) {
f = 1;
putChar('0');
return f;
}
while (long_num > 0) {
char_buffer[i++] = long_num % 10;
long_num /= 10;
}
f = f + i;
for (; i > 0; i--) {
putChar('0' + char_buffer[i - 1]);
}
return f;
}
void SeeedGrayOLED::drawBitmap(const unsigned char* bitmaparray, int bytes) {
if (Drive_IC == SSD1327) {
char localAddressMode = addressingMode;
if (addressingMode != HORIZONTAL_MODE) {
//Bitmap is drawn in horizontal mode
setHorizontalMode();
}
for (int i = 0; i < bytes; i++) {
for (int j = 0; j < 8; j = j + 2) {
char c = 0x00;
char bit1 = pgm_read_byte(&bitmaparray[i]) << j & 0x80;
char bit2 = pgm_read_byte(&bitmaparray[i]) << (j + 1) & 0x80;
// Each bit is changed to a nibble
c |= (bit1) ? grayH : 0x00;
// Each bit is changed to a nibble
c |= (bit2) ? grayL : 0x00;
sendData(c);
}
}
if (localAddressMode == VERTICAL_MODE) {
//If Vertical Mode was used earlier, restore it.
setVerticalMode();
}
} else if (Drive_IC == SH1107G) {
int Row = 0, column_l = 0x00, column_h = 0x11;
setHorizontalMode();
for (int i = 0; i < bytes; i++) {
sendCommand(0xb0 + Row);
sendCommand(column_l);
sendCommand(column_h);
byte bits = (byte)pgm_read_byte(&bitmaparray[i]);
byte tmp = 0x00;
for (int b = 0; b < 8; b++) {
tmp |= ((bits >> (7 - b)) & 0x01) << b;
}
sendData(tmp);
Row++;
if (Row >= 12) {
Row = 0;
column_l++;
if (column_l >= 16) {
column_l = 0x00;
column_h += 0x01;
}
}
}
}
}
void SeeedGrayOLED::setHorizontalScrollProperties(bool direction, unsigned char startRow, unsigned char endRow,
unsigned char startColumn, unsigned char endColumn, unsigned char scrollSpeed) {
/*
Use the following defines for 'direction' :
Scroll_Left
Scroll_Right
Use the following defines for 'scrollSpeed' :
Scroll_2Frames
Scroll_3Frames
Scroll_4Frames
Scroll_5Frames
Scroll_25Frames
Scroll_64Frames
Scroll_128Frames
Scroll_256Frames
*/
if (Scroll_Right == direction) {
//Scroll Right
sendCommand(0x27);
} else {
//Scroll Left
sendCommand(0x26);
}
sendCommand(0x00); //Dummmy byte
sendCommand(startRow);
sendCommand(scrollSpeed);
sendCommand(endRow);
sendCommand(startColumn + 8);
sendCommand(endColumn + 8);
sendCommand(0x00); //Dummmy byte
}
void SeeedGrayOLED::activateScroll() {
sendCommand(SeeedGrayOLED_Activate_Scroll_Cmd);
}
void SeeedGrayOLED::deactivateScroll() {
sendCommand(SeeedGrayOLED_Dectivate_Scroll_Cmd);
}
void SeeedGrayOLED::setNormalDisplay() {
sendCommand(SeeedGrayOLED_Normal_Display_Cmd);
}
void SeeedGrayOLED::setInverseDisplay() {
sendCommand(SeeedGrayOLED_Inverse_Display_Cmd);
}
void SeeedGrayOLED::initSoftwareI2C(SoftwareI2C* w, int __sda, int __scl) {
Wire = w;
Wire->begin(__sda, __scl);
}
SeeedGrayOLED SeeedGrayOled; // Preinstantiate Objects