Autodetect SSD1306 vs SH1106 OLED type

pull/8/head
Max-Plastix 2022-01-29 23:46:48 -08:00
rodzic b90680746b
commit 2749d67de6
5 zmienionych plików z 89 dodań i 19 usunięć

Wyświetl plik

@ -169,11 +169,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#define RED_LED 4 // GPIO4 on T-Beam v1.1
// -----------------------------------------------------------------------------
// OLED
// -----------------------------------------------------------------------------
#define SSD1306_ADDRESS 0x3C
// -----------------------------------------------------------------------------
// GPS

Wyświetl plik

@ -99,8 +99,9 @@ float min_dist_moved = MIN_DIST;
AXP20X_Class axp;
bool pmu_irq = false; // true when PMU IRQ pending
bool ssd1306_found = false;
bool oled_found = false;
bool axp192_found = false;
uint8_t oled_addr = 0; // i2c address of OLED controller
bool packetQueued;
bool isJoined = false;
@ -498,7 +499,7 @@ void lora_msg_callback(uint8_t message) {
void scanI2Cdevice(void) {
byte err, addr;
int nDevices = 0;
for (addr = 1; addr < 127; addr++) {
for (addr = 1; addr < 0x7F; addr++) {
Wire.beginTransmission(addr);
err = Wire.endTransmission();
if (err == 0) {
@ -511,9 +512,10 @@ void scanI2Cdevice(void) {
#endif
nDevices++;
if (addr == SSD1306_ADDRESS) {
ssd1306_found = true;
Serial.println("SSD1306 OLED display");
if (addr == 0x3C || addr == 0x78 || addr == 0x7E) {
oled_addr = addr;
oled_found = true;
Serial.printf("OLED at %02X\n", oled_addr);
}
if (addr == AXP192_SLAVE_ADDRESS) {
axp192_found = true;
@ -720,11 +722,11 @@ void setup() {
// Don't init display if we don't have one or we are waking headless due to a
// timer event
if (0 && wakeCause == ESP_SLEEP_WAKEUP_TIMER)
ssd1306_found = false; // forget we even have the hardware
oled_found = false; // forget we even have the hardware
// This creates the display object, so if we don't call it.. all screen ops are do-nothing.
if (ssd1306_found)
screen_setup();
if (oled_found)
screen_setup(oled_addr);
is_screen_on = true;
// GPS power on, so it has time to setttle.
@ -794,7 +796,7 @@ void low_power_sleep(uint32_t seconds) {
if (axp192_found) {
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // GPS power
// axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // OLED power
// if (ssd1306_found)
// if (oled_found)
// screen_setup();
}

Wyświetl plik

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <Wire.h>
#include "OLEDDisplay.h"
#include "SH1106Wire.h"
#include "SSD1306Wire.h"
#include "configuration.h"
#include "credentials.h"
@ -34,9 +35,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SCREEN_HEADER_HEIGHT 24
SSD1306Wire *display;
OLEDDisplay *display;
uint8_t _screen_line = SCREEN_HEADER_HEIGHT - 1;
enum display_types { DISPLAY_UNKNOWN, DISPLAY_SSD1306, DISPLAY_SH1106 };
enum display_types display_type = DISPLAY_UNKNOWN;
void screen_show_logo() {
if (!display)
return;
@ -99,9 +103,77 @@ void screen_update() {
display->display();
}
void screen_setup() {
/*
* The SSD1306 and SH1106 controllers are almost the same, but different.
* Most importantly here, the SH1106 allows reading from the frame buffer, while the SSD1306 does not.
* We exploit this by writing two bytes and reading them back. A mismatch probably means SSD1306.
* Probably.
*/
enum display_types display_get_type(uint8_t id) {
uint8_t err;
uint8_t b1, b2;
Wire.begin(I2C_SDA, I2C_SCL);
Wire.setClock(7000000);
Wire.beginTransmission(id);
uint8_t a[] = {0, 0, 0x10, 0xB0};
Wire.write(a, sizeof(a));
if ((err = Wire.endTransmission(false)) != 0) {
Serial.printf("err=%d EndTransmission=%d(%s)", err, Wire.lastError(), Wire.getErrorText(Wire.lastError()));
return DISPLAY_UNKNOWN;
}
Wire.beginTransmission(id);
uint8_t b[] = {0x40, 'M', 'P'};
Wire.write(b, sizeof(b));
if ((err = Wire.endTransmission(false)) != 0) {
Serial.printf("err=%d EndTransmission=%d(%s)", err, Wire.lastError(), Wire.getErrorText(Wire.lastError()));
return DISPLAY_UNKNOWN;
}
Wire.beginTransmission(id);
uint8_t c[] = {0, 0, 0x10};
Wire.write(c, sizeof(c));
if ((err = Wire.endTransmission(false)) != 0) {
Serial.printf("err=%d EndTransmission=%d(%s)", err, Wire.lastError(), Wire.getErrorText(Wire.lastError()));
return DISPLAY_UNKNOWN;
}
Wire.beginTransmission(id);
Wire.write(0x40);
if ((err = Wire.endTransmission(false)) != 0) {
Serial.printf("err=%d EndTransmission=%d(%s)", err, Wire.lastError(), Wire.getErrorText(Wire.lastError()));
return DISPLAY_UNKNOWN;
}
err = Wire.requestFrom((int)id, (int)3, (int)1);
if (err != 3) {
return DISPLAY_UNKNOWN;
}
Wire.read(); // Discard
b1 = Wire.read();
b2 = Wire.read();
Wire.endTransmission();
if (b1 == 'M' && b2 == 'P')
return DISPLAY_SH1106;
else
return DISPLAY_SSD1306;
}
void screen_setup(uint8_t addr) {
/* Attempt to determine which kind of display we're dealing with */
if (display_type == DISPLAY_UNKNOWN)
display_type = display_get_type(addr);
// Display instance
display = new SSD1306Wire(SSD1306_ADDRESS, I2C_SDA, I2C_SCL);
if (display_type == DISPLAY_SSD1306)
display = new SSD1306Wire(addr, I2C_SDA, I2C_SCL);
else if (display_type == DISPLAY_SH1106)
display = new SH1106Wire(addr, I2C_SDA, I2C_SCL);
else
return;
display->init();
display->flipScreenVertically();
display->setFont(Custom_ArialMT_Plain_10);

Wyświetl plik

@ -16,5 +16,5 @@ void screen_off(void);
void screen_on(void);
void screen_show_logo(void);
void screen_setup(void);
void screen_setup(uint8_t addr);
void screen_end(void);

Wyświetl plik

@ -13,7 +13,8 @@
"string": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"initializer_list": "cpp"
"initializer_list": "cpp",
"*.tcc": "cpp"
}
}
}