Reverted to standard Adafruit SH1106 library (for ESP32)
This commit is contained in:
parent
e576ec4849
commit
eb64b1a775
12 changed files with 14 additions and 995 deletions
|
@ -1,803 +0,0 @@
|
||||||
/*********************************************************************
|
|
||||||
This is a library for our Monochrome OLEDs based on SH1106 drivers
|
|
||||||
|
|
||||||
Pick one up today in the adafruit shop!
|
|
||||||
------> http://www.adafruit.com/category/63_98
|
|
||||||
|
|
||||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
|
||||||
interface
|
|
||||||
|
|
||||||
Adafruit invests time and resources providing this open source code,
|
|
||||||
please support Adafruit and open-source hardware by purchasing
|
|
||||||
products from Adafruit!
|
|
||||||
|
|
||||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
|
||||||
BSD license, check BSDlicense.txt for more information
|
|
||||||
All text above, and the splash screen below must be included in any redistribution
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
//********************************************************************************
|
|
||||||
// Modified by Ray Jones <ray@mrjones.id.au>, Oct 2018
|
|
||||||
//
|
|
||||||
// BUG FIX: Constructor for hardware SPI was not clearing "sid" which is a decision
|
|
||||||
// variable within begin() when choosing which pins to configure
|
|
||||||
//
|
|
||||||
//********************************************************************************
|
|
||||||
|
|
||||||
#ifdef __AVR__
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#elif defined(ESP8266) || defined(ESP32)
|
|
||||||
#include <pgmspace.h>
|
|
||||||
#else
|
|
||||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__ARM_ARCH) && !defined(ENERGIA) && !defined(ESP8266) && !defined(ESP32) && !defined(__arc__)
|
|
||||||
#include <util/delay.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
#include "Adafruit_GFX.h"
|
|
||||||
#include "Adafruit_SH1106.h"
|
|
||||||
|
|
||||||
// the memory buffer for the LCD
|
|
||||||
|
|
||||||
static uint8_t buffer[SH1106_LCDHEIGHT * SH1106_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,
|
|
||||||
#if (SH1106_LCDHEIGHT * SH1106_LCDWIDTH > 96*16)
|
|
||||||
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 (SH1106_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
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#define swap(a, b) { int16_t t = a; a = b; b = t; }
|
|
||||||
|
|
||||||
// the most basic function, set a single pixel
|
|
||||||
void Adafruit_SH1106::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
|
||||||
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// check rotation, move pixel around if necessary
|
|
||||||
switch (getRotation()) {
|
|
||||||
case 1:
|
|
||||||
swap(x, y);
|
|
||||||
x = WIDTH - x - 1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
x = WIDTH - x - 1;
|
|
||||||
y = HEIGHT - y - 1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
swap(x, y);
|
|
||||||
y = HEIGHT - y - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// x is which column
|
|
||||||
switch (color)
|
|
||||||
{
|
|
||||||
case WHITE: buffer[x+ (y/8)*SH1106_LCDWIDTH] |= (1 << (y&7)); break;
|
|
||||||
case BLACK: buffer[x+ (y/8)*SH1106_LCDWIDTH] &= ~(1 << (y&7)); break;
|
|
||||||
case INVERSE: buffer[x+ (y/8)*SH1106_LCDWIDTH] ^= (1 << (y&7)); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Adafruit_SH1106::Adafruit_SH1106(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SH1106_LCDWIDTH, SH1106_LCDHEIGHT) {
|
|
||||||
cs = CS;
|
|
||||||
rst = RST;
|
|
||||||
dc = DC;
|
|
||||||
sclk = SCLK;
|
|
||||||
sid = SID;
|
|
||||||
hwSPI = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset
|
|
||||||
Adafruit_SH1106::Adafruit_SH1106(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SH1106_LCDWIDTH, SH1106_LCDHEIGHT) {
|
|
||||||
dc = DC;
|
|
||||||
rst = RST;
|
|
||||||
cs = CS;
|
|
||||||
sid = 0; // BUG FIX - WAS MISSING!
|
|
||||||
hwSPI = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initializer for I2C - we only indicate the reset pin!
|
|
||||||
Adafruit_SH1106::Adafruit_SH1106(uint8_t reset) :
|
|
||||||
Adafruit_GFX(SH1106_LCDWIDTH, SH1106_LCDHEIGHT) {
|
|
||||||
sclk = dc = cs = sid = -1;
|
|
||||||
rst = reset;
|
|
||||||
}
|
|
||||||
|
|
||||||
Adafruit_SH1106::Adafruit_SH1106(int8_t SDA, int8_t SCL) :
|
|
||||||
Adafruit_GFX(SH1106_LCDWIDTH, SH1106_LCDHEIGHT) {
|
|
||||||
sclk = dc = cs = sid = -1;
|
|
||||||
sda = SDA;
|
|
||||||
scl = SCL;
|
|
||||||
hwSPI = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) {
|
|
||||||
_vccstate = vccstate;
|
|
||||||
_i2caddr = i2caddr;
|
|
||||||
|
|
||||||
// set pin directions
|
|
||||||
if (sid != -1){
|
|
||||||
pinMode(dc, OUTPUT);
|
|
||||||
pinMode(cs, OUTPUT);
|
|
||||||
csport = portOutputRegister(digitalPinToPort(cs));
|
|
||||||
cspinmask = digitalPinToBitMask(cs);
|
|
||||||
dcport = portOutputRegister(digitalPinToPort(dc));
|
|
||||||
dcpinmask = digitalPinToBitMask(dc);
|
|
||||||
if (!hwSPI){
|
|
||||||
// set pins for software-SPI
|
|
||||||
pinMode(sid, OUTPUT);
|
|
||||||
pinMode(sclk, OUTPUT);
|
|
||||||
clkport = portOutputRegister(digitalPinToPort(sclk));
|
|
||||||
clkpinmask = digitalPinToBitMask(sclk);
|
|
||||||
mosiport = portOutputRegister(digitalPinToPort(sid));
|
|
||||||
mosipinmask = digitalPinToBitMask(sid);
|
|
||||||
}
|
|
||||||
if (hwSPI){
|
|
||||||
SPI.begin ();
|
|
||||||
#ifdef __SAM3X8E__
|
|
||||||
SPI.setClockDivider (9); // 9.3 MHz
|
|
||||||
#else
|
|
||||||
SPI.setClockDivider (SPI_CLOCK_DIV2); // 8 MHz
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// I2C Init
|
|
||||||
if(sda == -1 || scl == -1){
|
|
||||||
Wire.begin();
|
|
||||||
#ifdef __SAM3X8E__
|
|
||||||
// Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL)
|
|
||||||
TWI1->TWI_CWGR = 0;
|
|
||||||
TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
Wire.begin(sda, scl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reset) {
|
|
||||||
// Setup reset pin direction (used by both SPI and I2C)
|
|
||||||
pinMode(rst, OUTPUT);
|
|
||||||
digitalWrite(rst, HIGH);
|
|
||||||
// VDD (3.3V) goes high at start, lets just chill for a ms
|
|
||||||
delay(1);
|
|
||||||
// bring reset low
|
|
||||||
digitalWrite(rst, LOW);
|
|
||||||
// wait 10ms
|
|
||||||
delay(10);
|
|
||||||
// bring out of reset
|
|
||||||
digitalWrite(rst, HIGH);
|
|
||||||
// turn on VCC (9V?)
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined SH1106_128_32
|
|
||||||
// Init sequence for 128x32 OLED module
|
|
||||||
sh1106_command(SH1106_DISPLAYOFF); // 0xAE
|
|
||||||
sh1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
|
|
||||||
sh1106_command(0x80); // the suggested ratio 0x80
|
|
||||||
sh1106_command(SH1106_SETMULTIPLEX); // 0xA8
|
|
||||||
sh1106_command(0x1F);
|
|
||||||
sh1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
|
|
||||||
sh1106_command(0x0); // no offset
|
|
||||||
sh1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
|
|
||||||
sh1106_command(SH1106_CHARGEPUMP); // 0x8D
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x10); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0x14); }
|
|
||||||
sh1106_command(SH1106_MEMORYMODE); // 0x20
|
|
||||||
sh1106_command(0x00); // 0x0 act like ks0108
|
|
||||||
sh1106_command(SH1106_SEGREMAP | 0x1);
|
|
||||||
sh1106_command(SH1106_COMSCANDEC);
|
|
||||||
sh1106_command(SH1106_SETCOMPINS); // 0xDA
|
|
||||||
sh1106_command(0x02);
|
|
||||||
sh1106_command(SH1106_SETCONTRAST); // 0x81
|
|
||||||
sh1106_command(0x8F);
|
|
||||||
sh1106_command(SH1106_SETPRECHARGE); // 0xd9
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x22); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0xF1); }
|
|
||||||
sh1106_command(SH1106_SETVCOMDETECT); // 0xDB
|
|
||||||
sh1106_command(0x40);
|
|
||||||
sh1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
|
|
||||||
sh1106_command(SH1106_NORMALDISPLAY); // 0xA6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SH1106_128_64
|
|
||||||
// Init sequence for 128x64 OLED module
|
|
||||||
sh1106_command(SH1106_DISPLAYOFF); // 0xAE
|
|
||||||
sh1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
|
|
||||||
sh1106_command(0x80); // the suggested ratio 0x80
|
|
||||||
sh1106_command(SH1106_SETMULTIPLEX); // 0xA8
|
|
||||||
sh1106_command(0x3F);
|
|
||||||
sh1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
|
|
||||||
sh1106_command(0x0); // no offset
|
|
||||||
sh1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
|
|
||||||
sh1106_command(SH1106_CHARGEPUMP); // 0x8D
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x10); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0x14); }
|
|
||||||
sh1106_command(SH1106_MEMORYMODE); // 0x20
|
|
||||||
sh1106_command(0x00); // 0x0 act like ks0108
|
|
||||||
sh1106_command(SH1106_SEGREMAP | 0x1);
|
|
||||||
sh1106_command(SH1106_COMSCANDEC);
|
|
||||||
sh1106_command(SH1106_SETCOMPINS); // 0xDA
|
|
||||||
sh1106_command(0x12);
|
|
||||||
sh1106_command(SH1106_SETCONTRAST); // 0x81
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x9F); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0xCF); }
|
|
||||||
sh1106_command(SH1106_SETPRECHARGE); // 0xd9
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x22); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0xF1); }
|
|
||||||
sh1106_command(SH1106_SETVCOMDETECT); // 0xDB
|
|
||||||
sh1106_command(0x40);
|
|
||||||
sh1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
|
|
||||||
sh1106_command(SH1106_NORMALDISPLAY); // 0xA6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SH1106_96_16
|
|
||||||
// Init sequence for 96x16 OLED module
|
|
||||||
sh1106_command(SH1106_DISPLAYOFF); // 0xAE
|
|
||||||
sh1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
|
|
||||||
sh1106_command(0x80); // the suggested ratio 0x80
|
|
||||||
sh1106_command(SH1106_SETMULTIPLEX); // 0xA8
|
|
||||||
sh1106_command(0x0F);
|
|
||||||
sh1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
|
|
||||||
sh1106_command(0x00); // no offset
|
|
||||||
sh1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
|
|
||||||
sh1106_command(SH1106_CHARGEPUMP); // 0x8D
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x10); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0x14); }
|
|
||||||
sh1106_command(SH1106_MEMORYMODE); // 0x20
|
|
||||||
sh1106_command(0x00); // 0x0 act like ks0108
|
|
||||||
sh1106_command(SH1106_SEGREMAP | 0x1);
|
|
||||||
sh1106_command(SH1106_COMSCANDEC);
|
|
||||||
sh1106_command(SH1106_SETCOMPINS); // 0xDA
|
|
||||||
sh1106_command(0x2); //ada x12
|
|
||||||
sh1106_command(SH1106_SETCONTRAST); // 0x81
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x10); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0xAF); }
|
|
||||||
sh1106_command(SH1106_SETPRECHARGE); // 0xd9
|
|
||||||
if (vccstate == SH1106_EXTERNALVCC)
|
|
||||||
{ sh1106_command(0x22); }
|
|
||||||
else
|
|
||||||
{ sh1106_command(0xF1); }
|
|
||||||
sh1106_command(SH1106_SETVCOMDETECT); // 0xDB
|
|
||||||
sh1106_command(0x40);
|
|
||||||
sh1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
|
|
||||||
sh1106_command(SH1106_NORMALDISPLAY); // 0xA6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sh1106_command(SH1106_DISPLAYON);//--turn on oled panel
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Adafruit_SH1106::invertDisplay(uint8_t i) {
|
|
||||||
if (i) {
|
|
||||||
sh1106_command(SH1106_INVERTDISPLAY);
|
|
||||||
} else {
|
|
||||||
sh1106_command(SH1106_NORMALDISPLAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::sh1106_command(uint8_t c) {
|
|
||||||
if (sid != -1)
|
|
||||||
{
|
|
||||||
// SPI
|
|
||||||
//digitalWrite(cs, HIGH);
|
|
||||||
*csport |= cspinmask;
|
|
||||||
//digitalWrite(dc, LOW);
|
|
||||||
*dcport &= ~dcpinmask;
|
|
||||||
//digitalWrite(cs, LOW);
|
|
||||||
*csport &= ~cspinmask;
|
|
||||||
fastSPIwrite(c);
|
|
||||||
//digitalWrite(cs, HIGH);
|
|
||||||
*csport |= cspinmask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// I2C
|
|
||||||
uint8_t control = 0x00; // Co = 0, D/C = 0
|
|
||||||
Wire.beginTransmission(_i2caddr);
|
|
||||||
WIRE_WRITE(control);
|
|
||||||
WIRE_WRITE(c);
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// startscrollright
|
|
||||||
// Activate a right handed scroll for rows start through stop
|
|
||||||
// Hint, the display is 16 rows tall. To scroll the whole display, run:
|
|
||||||
// display.scrollright(0x00, 0x0F)
|
|
||||||
void Adafruit_SH1106::startscrollright(uint8_t start, uint8_t stop){
|
|
||||||
sh1106_command(SH1106_RIGHT_HORIZONTAL_SCROLL);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(start);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(stop);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(0XFF);
|
|
||||||
sh1106_command(SH1106_ACTIVATE_SCROLL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// startscrollleft
|
|
||||||
// Activate a right handed scroll for rows start through stop
|
|
||||||
// Hint, the display is 16 rows tall. To scroll the whole display, run:
|
|
||||||
// display.scrollright(0x00, 0x0F)
|
|
||||||
void Adafruit_SH1106::startscrollleft(uint8_t start, uint8_t stop){
|
|
||||||
sh1106_command(SH1106_LEFT_HORIZONTAL_SCROLL);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(start);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(stop);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(0XFF);
|
|
||||||
sh1106_command(SH1106_ACTIVATE_SCROLL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// startscrolldiagright
|
|
||||||
// Activate a diagonal scroll for rows start through stop
|
|
||||||
// Hint, the display is 16 rows tall. To scroll the whole display, run:
|
|
||||||
// display.scrollright(0x00, 0x0F)
|
|
||||||
void Adafruit_SH1106::startscrolldiagright(uint8_t start, uint8_t stop){
|
|
||||||
sh1106_command(SH1106_SET_VERTICAL_SCROLL_AREA);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(SH1106_LCDHEIGHT);
|
|
||||||
sh1106_command(SH1106_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(start);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(stop);
|
|
||||||
sh1106_command(0X01);
|
|
||||||
sh1106_command(SH1106_ACTIVATE_SCROLL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// startscrolldiagleft
|
|
||||||
// Activate a diagonal scroll for rows start through stop
|
|
||||||
// Hint, the display is 16 rows tall. To scroll the whole display, run:
|
|
||||||
// display.scrollright(0x00, 0x0F)
|
|
||||||
void Adafruit_SH1106::startscrolldiagleft(uint8_t start, uint8_t stop){
|
|
||||||
sh1106_command(SH1106_SET_VERTICAL_SCROLL_AREA);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(SH1106_LCDHEIGHT);
|
|
||||||
sh1106_command(SH1106_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(start);
|
|
||||||
sh1106_command(0X00);
|
|
||||||
sh1106_command(stop);
|
|
||||||
sh1106_command(0X01);
|
|
||||||
sh1106_command(SH1106_ACTIVATE_SCROLL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::stopscroll(void){
|
|
||||||
sh1106_command(SH1106_DEACTIVATE_SCROLL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dim the display
|
|
||||||
// dim = true: display is dimmed
|
|
||||||
// dim = false: display is normal
|
|
||||||
void Adafruit_SH1106::dim(boolean dim) {
|
|
||||||
uint8_t contrast;
|
|
||||||
|
|
||||||
if (dim) {
|
|
||||||
contrast = 0; // Dimmed display
|
|
||||||
} else {
|
|
||||||
if (_vccstate == SH1106_EXTERNALVCC) {
|
|
||||||
contrast = 0x9F;
|
|
||||||
} else {
|
|
||||||
contrast = 0xCF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// the range of contrast to too small to be really useful
|
|
||||||
// it is useful to dim the display
|
|
||||||
sh1106_command(SH1106_SETCONTRAST);
|
|
||||||
sh1106_command(contrast);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::sh1106_data(uint8_t c) {
|
|
||||||
if (sid != -1)
|
|
||||||
{
|
|
||||||
// SPI
|
|
||||||
//digitalWrite(cs, HIGH);
|
|
||||||
*csport |= cspinmask;
|
|
||||||
//digitalWrite(dc, HIGH);
|
|
||||||
*dcport |= dcpinmask;
|
|
||||||
//digitalWrite(cs, LOW);
|
|
||||||
*csport &= ~cspinmask;
|
|
||||||
fastSPIwrite(c);
|
|
||||||
//digitalWrite(cs, HIGH);
|
|
||||||
*csport |= cspinmask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// I2C
|
|
||||||
uint8_t control = 0x40; // Co = 0, D/C = 1
|
|
||||||
Wire.beginTransmission(_i2caddr);
|
|
||||||
WIRE_WRITE(control);
|
|
||||||
WIRE_WRITE(c);
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::display(void) {
|
|
||||||
if (sid != -1)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int8_t i = (SH1106_LCDHEIGHT/8)-1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
sh1106_command(0xB0 + i); // Set row
|
|
||||||
sh1106_command(SH1106_SETLOWCOLUMN); // Set lower column address
|
|
||||||
sh1106_command(SH1106_SETHIGHCOLUMN); // Set higher column address
|
|
||||||
|
|
||||||
// SPI
|
|
||||||
*csport |= cspinmask;
|
|
||||||
*dcport |= dcpinmask;
|
|
||||||
*csport &= ~cspinmask;
|
|
||||||
|
|
||||||
for (uint16_t j = SH1106_LCDWIDTH; j > 0; j--)
|
|
||||||
{
|
|
||||||
fastSPIwrite(buffer[i*SH1106_LCDWIDTH+SH1106_LCDWIDTH-j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
*csport |= cspinmask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// save I2C bitrate
|
|
||||||
#ifndef ESP32
|
|
||||||
#ifndef __SAM3X8E__
|
|
||||||
uint8_t twbrbackup = TWBR;
|
|
||||||
TWBR = 12; // upgrade to 400KHz!
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
//Serial.println(TWBR, DEC);
|
|
||||||
//Serial.println(TWSR & 0x3, DEC);
|
|
||||||
|
|
||||||
// I2C
|
|
||||||
for (int8_t i = (SH1106_LCDHEIGHT/8)-1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
sh1106_command(0xB0 + i); // Set row
|
|
||||||
sh1106_command(SH1106_SETLOWCOLUMN); // Set lower column address
|
|
||||||
sh1106_command(SH1106_SETHIGHCOLUMN); // Set higher column address
|
|
||||||
|
|
||||||
for (uint16_t j = SH1106_LCDWIDTH; j > 0; j--)
|
|
||||||
{
|
|
||||||
// send a bunch of data in one xmission
|
|
||||||
Wire.beginTransmission(_i2caddr);
|
|
||||||
WIRE_WRITE(0x40);
|
|
||||||
for (uint8_t x=0; x<16; x++) {
|
|
||||||
WIRE_WRITE(buffer[i*SH1106_LCDWIDTH+SH1106_LCDWIDTH-j]);
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef ESP32
|
|
||||||
#ifndef __SAM3X8E__
|
|
||||||
TWBR = twbrbackup;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear everything
|
|
||||||
void Adafruit_SH1106::clearDisplay(void) {
|
|
||||||
memset(buffer, 0, (SH1106_LCDWIDTH*SH1106_LCDHEIGHT/8));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void Adafruit_SH1106::fastSPIwrite(uint8_t d) {
|
|
||||||
|
|
||||||
if(hwSPI) {
|
|
||||||
(void)SPI.transfer(d);
|
|
||||||
} else {
|
|
||||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
|
||||||
*clkport &= ~clkpinmask;
|
|
||||||
if(d & bit) *mosiport |= mosipinmask;
|
|
||||||
else *mosiport &= ~mosipinmask;
|
|
||||||
*clkport |= clkpinmask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//*csport |= cspinmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
|
||||||
boolean bSwap = false;
|
|
||||||
switch(rotation) {
|
|
||||||
case 0:
|
|
||||||
// 0 degree rotation, do nothing
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// 90 degree rotation, swap x & y for rotation, then invert x
|
|
||||||
bSwap = true;
|
|
||||||
swap(x, y);
|
|
||||||
x = WIDTH - x - 1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// 180 degree rotation, invert x and y - then shift y around for height.
|
|
||||||
x = WIDTH - x - 1;
|
|
||||||
y = HEIGHT - y - 1;
|
|
||||||
x -= (w-1);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// 270 degree rotation, swap x & y for rotation, then invert y and adjust y for w (not to become h)
|
|
||||||
bSwap = true;
|
|
||||||
swap(x, y);
|
|
||||||
y = HEIGHT - y - 1;
|
|
||||||
y -= (w-1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bSwap) {
|
|
||||||
drawFastVLineInternal(x, y, w, color);
|
|
||||||
} else {
|
|
||||||
drawFastHLineInternal(x, y, w, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
|
||||||
// Do bounds/limit checks
|
|
||||||
if(y < 0 || y >= HEIGHT) { return; }
|
|
||||||
|
|
||||||
// make sure we don't try to draw below 0
|
|
||||||
if(x < 0) {
|
|
||||||
w += x;
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we don't go off the edge of the display
|
|
||||||
if( (x + w) > WIDTH) {
|
|
||||||
w = (WIDTH - x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if our width is now negative, punt
|
|
||||||
if(w <= 0) { return; }
|
|
||||||
|
|
||||||
// set up the pointer for movement through the buffer
|
|
||||||
register uint8_t *pBuf = buffer;
|
|
||||||
// adjust the buffer pointer for the current row
|
|
||||||
pBuf += ((y/8) * SH1106_LCDWIDTH);
|
|
||||||
// and offset x columns in
|
|
||||||
pBuf += x;
|
|
||||||
|
|
||||||
register uint8_t mask = 1 << (y&7);
|
|
||||||
|
|
||||||
switch (color)
|
|
||||||
{
|
|
||||||
case WHITE: while(w--) { *pBuf++ |= mask; }; break;
|
|
||||||
case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
|
|
||||||
case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adafruit_SH1106::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
|
||||||
bool bSwap = false;
|
|
||||||
switch(rotation) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// 90 degree rotation, swap x & y for rotation, then invert x and adjust x for h (now to become w)
|
|
||||||
bSwap = true;
|
|
||||||
swap(x, y);
|
|
||||||
x = WIDTH - x - 1;
|
|
||||||
x -= (h-1);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// 180 degree rotation, invert x and y - then shift y around for height.
|
|
||||||
x = WIDTH - x - 1;
|
|
||||||
y = HEIGHT - y - 1;
|
|
||||||
y -= (h-1);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// 270 degree rotation, swap x & y for rotation, then invert y
|
|
||||||
bSwap = true;
|
|
||||||
swap(x, y);
|
|
||||||
y = HEIGHT - y - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bSwap) {
|
|
||||||
drawFastHLineInternal(x, y, h, color);
|
|
||||||
} else {
|
|
||||||
drawFastVLineInternal(x, y, h, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Adafruit_SH1106::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color) {
|
|
||||||
|
|
||||||
// do nothing if we're off the left or right side of the screen
|
|
||||||
if(x < 0 || x >= WIDTH) { return; }
|
|
||||||
|
|
||||||
// make sure we don't try to draw below 0
|
|
||||||
if(__y < 0) {
|
|
||||||
// __y is negative, this will subtract enough from __h to account for __y being 0
|
|
||||||
__h += __y;
|
|
||||||
__y = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we don't go past the height of the display
|
|
||||||
if( (__y + __h) > HEIGHT) {
|
|
||||||
__h = (HEIGHT - __y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if our height is now negative, punt
|
|
||||||
if(__h <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this display doesn't need ints for coordinates, use local byte registers for faster juggling
|
|
||||||
register uint8_t y = __y;
|
|
||||||
register uint8_t h = __h;
|
|
||||||
|
|
||||||
|
|
||||||
// set up the pointer for fast movement through the buffer
|
|
||||||
register uint8_t *pBuf = buffer;
|
|
||||||
// adjust the buffer pointer for the current row
|
|
||||||
pBuf += ((y/8) * SH1106_LCDWIDTH);
|
|
||||||
// and offset x columns in
|
|
||||||
pBuf += x;
|
|
||||||
|
|
||||||
// do the first partial byte, if necessary - this requires some masking
|
|
||||||
register uint8_t mod = (y&7);
|
|
||||||
if(mod) {
|
|
||||||
// mask off the high n bits we want to set
|
|
||||||
mod = 8-mod;
|
|
||||||
|
|
||||||
// note - lookup table results in a nearly 10% performance improvement in fill* functions
|
|
||||||
// register uint8_t mask = ~(0xFF >> (mod));
|
|
||||||
static uint8_t premask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
|
|
||||||
register uint8_t mask = premask[mod];
|
|
||||||
|
|
||||||
// adjust the mask if we're not going to reach the end of this byte
|
|
||||||
if( h < mod) {
|
|
||||||
mask &= (0XFF >> (mod-h));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (color)
|
|
||||||
{
|
|
||||||
case WHITE: *pBuf |= mask; break;
|
|
||||||
case BLACK: *pBuf &= ~mask; break;
|
|
||||||
case INVERSE: *pBuf ^= mask; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fast exit if we're done here!
|
|
||||||
if(h<mod) { return; }
|
|
||||||
|
|
||||||
h -= mod;
|
|
||||||
|
|
||||||
pBuf += SH1106_LCDWIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// write solid bytes while we can - effectively doing 8 rows at a time
|
|
||||||
if(h >= 8) {
|
|
||||||
if (color == INVERSE) { // separate copy of the code so we don't impact performance of the black/white write version with an extra comparison per loop
|
|
||||||
do {
|
|
||||||
*pBuf=~(*pBuf);
|
|
||||||
|
|
||||||
// adjust the buffer forward 8 rows worth of data
|
|
||||||
pBuf += SH1106_LCDWIDTH;
|
|
||||||
|
|
||||||
// adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
|
|
||||||
h -= 8;
|
|
||||||
} while(h >= 8);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// store a local value to work with
|
|
||||||
register uint8_t val = (color == WHITE) ? 255 : 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
// write our value in
|
|
||||||
*pBuf = val;
|
|
||||||
|
|
||||||
// adjust the buffer forward 8 rows worth of data
|
|
||||||
pBuf += SH1106_LCDWIDTH;
|
|
||||||
|
|
||||||
// adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
|
|
||||||
h -= 8;
|
|
||||||
} while(h >= 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now do the final partial byte, if necessary
|
|
||||||
if(h) {
|
|
||||||
mod = h & 7;
|
|
||||||
// this time we want to mask the low bits of the byte, vs the high bits we did above
|
|
||||||
// register uint8_t mask = (1 << mod) - 1;
|
|
||||||
// note - lookup table results in a nearly 10% performance improvement in fill* functions
|
|
||||||
static uint8_t postmask[8] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
|
|
||||||
register uint8_t mask = postmask[mod];
|
|
||||||
switch (color)
|
|
||||||
{
|
|
||||||
case WHITE: *pBuf |= mask; break;
|
|
||||||
case BLACK: *pBuf &= ~mask; break;
|
|
||||||
case INVERSE: *pBuf ^= mask; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,178 +0,0 @@
|
||||||
/*********************************************************************
|
|
||||||
This is a library for our Monochrome OLEDs based on SH1106 drivers
|
|
||||||
|
|
||||||
Pick one up today in the adafruit shop!
|
|
||||||
------> http://www.adafruit.com/category/63_98
|
|
||||||
|
|
||||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
|
||||||
interface
|
|
||||||
|
|
||||||
Adafruit invests time and resources providing this open source code,
|
|
||||||
please support Adafruit and open-source hardware by purchasing
|
|
||||||
products from Adafruit!
|
|
||||||
|
|
||||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
|
||||||
BSD license, check license.txt for more information
|
|
||||||
All text above, and the splash screen must be included in any redistribution
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
#if ARDUINO >= 100
|
|
||||||
#include "Arduino.h"
|
|
||||||
#define WIRE_WRITE Wire.write
|
|
||||||
#else
|
|
||||||
#include "WProgram.h"
|
|
||||||
#define WIRE_WRITE Wire.send
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __SAM3X8E__
|
|
||||||
typedef volatile RwReg PortReg;
|
|
||||||
typedef uint32_t PortMask;
|
|
||||||
#else
|
|
||||||
typedef volatile uint8_t PortReg;
|
|
||||||
typedef uint8_t PortMask;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <Adafruit_GFX.h>
|
|
||||||
|
|
||||||
#define BLACK 0
|
|
||||||
#define WHITE 1
|
|
||||||
#define INVERSE 2
|
|
||||||
|
|
||||||
#define SH1106_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D
|
|
||||||
// Address for 128x32 is 0x3C
|
|
||||||
// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded)
|
|
||||||
|
|
||||||
/*=========================================================================
|
|
||||||
SH1106 Displays
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
The driver is used in multiple displays (128x64, 128x32, etc.).
|
|
||||||
Select the appropriate display below to create an appropriately
|
|
||||||
sized framebuffer, etc.
|
|
||||||
|
|
||||||
SH1106_128_64 128x64 pixel display
|
|
||||||
|
|
||||||
SH1106_128_32 128x32 pixel display
|
|
||||||
|
|
||||||
SH1106_96_16
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------*/
|
|
||||||
#define SH1106_128_64
|
|
||||||
// #define SH1106_128_32
|
|
||||||
// #define SH1106_96_16
|
|
||||||
/*=========================================================================*/
|
|
||||||
|
|
||||||
#if defined SH1106_128_64 && defined SH1106_128_32
|
|
||||||
#error "Only one SH1106 display can be specified at once in SH1106.h"
|
|
||||||
#endif
|
|
||||||
#if !defined SH1106_128_64 && !defined SH1106_128_32 && !defined SH1106_96_16
|
|
||||||
#error "At least one SH1106 display must be specified in SH1106.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SH1106_128_64
|
|
||||||
#define SH1106_LCDWIDTH 128
|
|
||||||
#define SH1106_LCDHEIGHT 64
|
|
||||||
#endif
|
|
||||||
#if defined SH1106_128_32
|
|
||||||
#define SH1106_LCDWIDTH 128
|
|
||||||
#define SH1106_LCDHEIGHT 32
|
|
||||||
#endif
|
|
||||||
#if defined SH1106_96_16
|
|
||||||
#define SH1106_LCDWIDTH 96
|
|
||||||
#define SH1106_LCDHEIGHT 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SH1106_SETCONTRAST 0x81
|
|
||||||
#define SH1106_DISPLAYALLON_RESUME 0xA4
|
|
||||||
#define SH1106_DISPLAYALLON 0xA5
|
|
||||||
#define SH1106_NORMALDISPLAY 0xA6
|
|
||||||
#define SH1106_INVERTDISPLAY 0xA7
|
|
||||||
#define SH1106_DISPLAYOFF 0xAE
|
|
||||||
#define SH1106_DISPLAYON 0xAF
|
|
||||||
|
|
||||||
#define SH1106_SETDISPLAYOFFSET 0xD3
|
|
||||||
#define SH1106_SETCOMPINS 0xDA
|
|
||||||
|
|
||||||
#define SH1106_SETVCOMDETECT 0xDB
|
|
||||||
|
|
||||||
#define SH1106_SETDISPLAYCLOCKDIV 0xD5
|
|
||||||
#define SH1106_SETPRECHARGE 0xD9
|
|
||||||
|
|
||||||
#define SH1106_SETMULTIPLEX 0xA8
|
|
||||||
|
|
||||||
#define SH1106_SETLOWCOLUMN 0x02 //to use with SSD1306, set to 0x00
|
|
||||||
#define SH1106_SETHIGHCOLUMN 0x10
|
|
||||||
|
|
||||||
#define SH1106_SETSTARTLINE 0x40
|
|
||||||
|
|
||||||
#define SH1106_MEMORYMODE 0x20
|
|
||||||
#define SH1106_COLUMNADDR 0x21
|
|
||||||
#define SH1106_PAGEADDR 0x22
|
|
||||||
|
|
||||||
#define SH1106_COMSCANINC 0xC0
|
|
||||||
#define SH1106_COMSCANDEC 0xC8
|
|
||||||
|
|
||||||
#define SH1106_SEGREMAP 0xA0
|
|
||||||
|
|
||||||
#define SH1106_CHARGEPUMP 0x8D
|
|
||||||
|
|
||||||
#define SH1106_EXTERNALVCC 0x1
|
|
||||||
#define SH1106_SWITCHCAPVCC 0x2
|
|
||||||
|
|
||||||
// Scrolling #defines
|
|
||||||
#define SH1106_ACTIVATE_SCROLL 0x2F
|
|
||||||
#define SH1106_DEACTIVATE_SCROLL 0x2E
|
|
||||||
#define SH1106_SET_VERTICAL_SCROLL_AREA 0xA3
|
|
||||||
#define SH1106_RIGHT_HORIZONTAL_SCROLL 0x26
|
|
||||||
#define SH1106_LEFT_HORIZONTAL_SCROLL 0x27
|
|
||||||
#define SH1106_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
|
|
||||||
#define SH1106_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
|
|
||||||
|
|
||||||
class Adafruit_SH1106 : public Adafruit_GFX {
|
|
||||||
public:
|
|
||||||
Adafruit_SH1106(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);
|
|
||||||
Adafruit_SH1106(int8_t DC, int8_t RST, int8_t CS);
|
|
||||||
|
|
||||||
Adafruit_SH1106(uint8_t RST);
|
|
||||||
Adafruit_SH1106(int8_t SDA=-1, int8_t SCL=-1);
|
|
||||||
|
|
||||||
void begin(uint8_t switchvcc = SH1106_SWITCHCAPVCC, uint8_t i2caddr = SH1106_I2C_ADDRESS, bool reset=true);
|
|
||||||
void sh1106_command(uint8_t c);
|
|
||||||
void sh1106_data(uint8_t c);
|
|
||||||
|
|
||||||
void clearDisplay(void);
|
|
||||||
void invertDisplay(uint8_t i);
|
|
||||||
void display();
|
|
||||||
|
|
||||||
void startscrollright(uint8_t start, uint8_t stop);
|
|
||||||
void startscrollleft(uint8_t start, uint8_t stop);
|
|
||||||
|
|
||||||
void startscrolldiagright(uint8_t start, uint8_t stop);
|
|
||||||
void startscrolldiagleft(uint8_t start, uint8_t stop);
|
|
||||||
void stopscroll(void);
|
|
||||||
|
|
||||||
void dim(boolean dim);
|
|
||||||
|
|
||||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
|
||||||
|
|
||||||
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
|
||||||
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int8_t _i2caddr, _vccstate, sid, sclk, dc, cs, sda, scl;
|
|
||||||
uint8_t rst;
|
|
||||||
void fastSPIwrite(uint8_t c);
|
|
||||||
|
|
||||||
boolean hwSPI;
|
|
||||||
#ifndef ESP32
|
|
||||||
PortReg *mosiport, *clkport, *csport, *dcport;
|
|
||||||
PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
|
||||||
#else
|
|
||||||
volatile uint32_t *mosiport, *clkport, *csport, *dcport;
|
|
||||||
volatile uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
|
|
||||||
inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline));
|
|
||||||
|
|
||||||
};
|
|
|
@ -238,7 +238,7 @@ void setup() {
|
||||||
NVstore.init();
|
NVstore.init();
|
||||||
NVstore.load();
|
NVstore.load();
|
||||||
|
|
||||||
KeyPad.init(keyLeft_pin, keyRight_pin, keyCentre_pin, keyUp_pin, keyDown_pin);
|
KeyPad.begin(keyLeft_pin, keyRight_pin, keyCentre_pin, keyUp_pin, keyDown_pin);
|
||||||
KeyPad.setCallback(parentKeyHandler);
|
KeyPad.setCallback(parentKeyHandler);
|
||||||
|
|
||||||
// Initialize the rtc object
|
// Initialize the rtc object
|
||||||
|
@ -251,7 +251,7 @@ void setup() {
|
||||||
lastTemperatureTime = millis();
|
lastTemperatureTime = millis();
|
||||||
lastAnimationTime = millis();
|
lastAnimationTime = millis();
|
||||||
|
|
||||||
ScreenManager.init();
|
ScreenManager.begin();
|
||||||
|
|
||||||
#if USE_WIFI == 1
|
#if USE_WIFI == 1
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ void setup() {
|
||||||
DefaultBTCParams.setFan_Min(1680);
|
DefaultBTCParams.setFan_Min(1680);
|
||||||
DefaultBTCParams.setFan_Max(4500);
|
DefaultBTCParams.setFan_Max(4500);
|
||||||
|
|
||||||
Bluetooth.init();
|
Bluetooth.begin();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ protected:
|
||||||
sRxLine _rxLine;
|
sRxLine _rxLine;
|
||||||
CContextTimeStamp _timeStamp;
|
CContextTimeStamp _timeStamp;
|
||||||
public:
|
public:
|
||||||
virtual void init() {};
|
virtual void begin() {};
|
||||||
virtual void setRefTime() {
|
virtual void setRefTime() {
|
||||||
_timeStamp.setRefTime();
|
_timeStamp.setRefTime();
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,7 +67,7 @@ CBluetoothESP32HC05::openSerial(int baudrate)
|
||||||
// V
|
// V
|
||||||
|
|
||||||
void
|
void
|
||||||
CBluetoothESP32Classic::init()
|
CBluetoothESP32Classic::begin()
|
||||||
{
|
{
|
||||||
_rxLine.clear();
|
_rxLine.clear();
|
||||||
DebugPort.println("Initialising ESP32 Classic Bluetooth");
|
DebugPort.println("Initialising ESP32 Classic Bluetooth");
|
||||||
|
@ -210,7 +210,7 @@ CBluetoothESP32BLE::~CBluetoothESP32BLE()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CBluetoothESP32BLE::init()
|
CBluetoothESP32BLE::begin()
|
||||||
{
|
{
|
||||||
DebugPort.println("Initialising ESP32 BLE");
|
DebugPort.println("Initialising ESP32 BLE");
|
||||||
// create the BLE device
|
// create the BLE device
|
||||||
|
|
|
@ -34,7 +34,7 @@ protected:
|
||||||
class CBluetoothESP32Classic : public CBluetoothAbstract {
|
class CBluetoothESP32Classic : public CBluetoothAbstract {
|
||||||
BluetoothSerial SerialBT;
|
BluetoothSerial SerialBT;
|
||||||
public:
|
public:
|
||||||
virtual void init();
|
virtual void begin();
|
||||||
virtual void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
|
virtual void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
|
||||||
virtual void check();
|
virtual void check();
|
||||||
virtual bool isConnected();
|
virtual bool isConnected();
|
||||||
|
@ -57,7 +57,7 @@ class CBluetoothESP32BLE : public CBluetoothAbstract {
|
||||||
public:
|
public:
|
||||||
CBluetoothESP32BLE();
|
CBluetoothESP32BLE();
|
||||||
virtual ~CBluetoothESP32BLE();
|
virtual ~CBluetoothESP32BLE();
|
||||||
virtual void init();
|
virtual void begin();
|
||||||
virtual void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
|
virtual void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
|
||||||
virtual void check();
|
virtual void check();
|
||||||
virtual bool isConnected();
|
virtual bool isConnected();
|
||||||
|
|
|
@ -43,7 +43,7 @@ CBluetoothHC05::CBluetoothHC05(int keyPin, int sensePin)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CBluetoothHC05::init()
|
CBluetoothHC05::begin()
|
||||||
{
|
{
|
||||||
const int BTRates[] = {
|
const int BTRates[] = {
|
||||||
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
|
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
|
||||||
|
|
|
@ -40,7 +40,7 @@ class CBluetoothHC05 : public CBluetoothAbstract {
|
||||||
int _sensePin, _keyPin;
|
int _sensePin, _keyPin;
|
||||||
public:
|
public:
|
||||||
CBluetoothHC05(int keyPin, int sensePin);
|
CBluetoothHC05(int keyPin, int sensePin);
|
||||||
void init();
|
void begin();
|
||||||
void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
|
void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
|
||||||
void check();
|
void check();
|
||||||
virtual bool isConnected();
|
virtual bool isConnected();
|
||||||
|
|
|
@ -112,7 +112,7 @@ CScreenManager::~CScreenManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CScreenManager::init()
|
CScreenManager::begin()
|
||||||
{
|
{
|
||||||
|
|
||||||
// 128 x 64 OLED support (I2C)
|
// 128 x 64 OLED support (I2C)
|
||||||
|
|
|
@ -38,7 +38,7 @@ class CScreenManager {
|
||||||
public:
|
public:
|
||||||
CScreenManager();
|
CScreenManager();
|
||||||
~CScreenManager();
|
~CScreenManager();
|
||||||
void init();
|
void begin();
|
||||||
bool checkUpdate();
|
bool checkUpdate();
|
||||||
bool animate();
|
bool animate();
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|
|
@ -38,7 +38,7 @@ CKeyPad::CKeyPad()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CKeyPad::init(int Lkey, int Rkey, int Ckey, int Ukey, int Dkey)
|
CKeyPad::begin(int Lkey, int Rkey, int Ckey, int Ukey, int Dkey)
|
||||||
{
|
{
|
||||||
_pins[0] = Lkey;
|
_pins[0] = Lkey;
|
||||||
_pins[1] = Rkey;
|
_pins[1] = Rkey;
|
||||||
|
|
|
@ -52,7 +52,7 @@ private:
|
||||||
unsigned long _debounceDelay;
|
unsigned long _debounceDelay;
|
||||||
public:
|
public:
|
||||||
CKeyPad();
|
CKeyPad();
|
||||||
void init(int Lkey, int Rkey, int Ckey, int Ukey, int Dkey);
|
void begin(int Lkey, int Rkey, int Ckey, int Ukey, int Dkey);
|
||||||
uint8_t update();
|
uint8_t update();
|
||||||
void setCallback(void (*Callback)(uint8_t event));
|
void setCallback(void (*Callback)(uint8_t event));
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue