Skip to content

Commit 63b2044

Browse files
committed
Add I2C RST and Vext to 4LD usermod
- proper implementation for wled#5633 - RST pin check bugfix
1 parent 481596a commit 63b2044

1 file changed

Lines changed: 41 additions & 39 deletions

File tree

usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#define LINE_BUFFER_SIZE 16+1
7373
#define MAX_JSON_CHARS 19+1
7474
#define MAX_MODE_LINE_SPACE 13+1
75+
#define MAX_PINS 4
7576

7677

7778
#ifdef ARDUINO_ARCH_ESP32
@@ -112,10 +113,10 @@ class FourLineDisplayUsermod : public Usermod {
112113
U8X8 *u8x8 = nullptr; // pointer to U8X8 display object
113114

114115
#ifndef FLD_SPI_DEFAULT
115-
int8_t ioPin[3] = {-1, -1, -1}; // I2C pins: SCL, SDA
116+
int8_t ioPin[MAX_PINS] = {-1, -1, -1, -1}; // I2C pins: SCL, SDA, RST, Vext
116117
uint32_t ioFrequency = 400000; // in Hz (minimum is 100000, baseline is 400000 and maximum should be 3400000)
117118
#else
118-
int8_t ioPin[3] = {FLD_PIN_CS, FLD_PIN_DC, FLD_PIN_RESET}; // custom SPI pins: CS, DC, RST
119+
int8_t ioPin[MAX_PINS] = {FLD_PIN_CS, FLD_PIN_DC, FLD_PIN_RESET, -1}; // custom SPI pins: CS, DC, RST, Vext
119120
uint32_t ioFrequency = 1000000; // in Hz (minimum is 500kHz, baseline is 1MHz and maximum should be 20MHz)
120121
#endif
121122

@@ -537,25 +538,30 @@ void FourLineDisplayUsermod::setup() {
537538

538539
// check if pins are -1 and disable usermod as PinManager::allocateMultiplePins() will accept -1 as a valid pin
539540
if (isSPI) {
540-
if (spi_sclk<0 || spi_mosi<0 || ioPin[0]<0 || ioPin[1]<0 || ioPin[1]<0) {
541-
type = NONE;
542-
} else {
543-
PinManagerPinType cspins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } };
544-
if (!PinManager::allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { type = NONE; }
545-
}
541+
if (spi_sclk<0 || spi_mosi<0 || ioPin[0]<0 || ioPin[1]<0 || ioPin[2]<0) { type = NONE; }
546542
} else {
547-
if (i2c_scl<0 || i2c_sda<0) { type=NONE; }
543+
if (i2c_scl<0 || i2c_sda<0) { type = NONE; }
544+
}
545+
if (!PinManager::allocateMultiplePins(ioPin, MAX_PINS, PinOwner::UM_FourLineDisplay, true)) { type = NONE; }
546+
547+
// Pull the Vext power rail enable pin LOW before display init.
548+
// Required on boards like the Heltec WiFi LoRa 32 V3 where the OLED is
549+
// powered via a switchable rail (GPIO36) rather than always-on VCC.
550+
if (ioPin[3] >= 0) {
551+
pinMode(ioPin[3], OUTPUT);
552+
digitalWrite(ioPin[3], LOW);
553+
delay(5);
548554
}
549555

550556
DEBUGUM_PRINTLN(F("Allocating display."));
551557
switch (type) {
552558
// U8X8 uses Wire (or Wire1 with 2ND constructor) and will use existing Wire properties (calls Wire.begin() though)
553-
case SSD1306: u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(); break;
554-
case SH1106: u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(); break;
555-
case SSD1306_64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(); break;
556-
case SSD1305: u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(); break;
557-
case SSD1305_64: u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(); break;
558-
case SSD1309_64: u8x8 = (U8X8 *) new U8X8_SSD1309_128X64_NONAME0_HW_I2C(); break;
559+
case SSD1306: u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(ioPin[2]); break;
560+
case SH1106: u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(ioPin[2]); break;
561+
case SSD1306_64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(ioPin[2]); break;
562+
case SSD1305: u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(ioPin[2]); break;
563+
case SSD1305_64: u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(ioPin[2]); break;
564+
case SSD1309_64: u8x8 = (U8X8 *) new U8X8_SSD1309_128X64_NONAME0_HW_I2C(ioPin[2]); break;
559565
// U8X8 uses global SPI variable that is attached to VSPI bus on ESP32
560566
case SSD1306_SPI: u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
561567
case SSD1306_SPI64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
@@ -566,9 +572,7 @@ void FourLineDisplayUsermod::setup() {
566572

567573
if (nullptr == u8x8) {
568574
DEBUGUM_PRINTLN(F("Display init failed."));
569-
if (isSPI) {
570-
PinManager::deallocateMultiplePins((const uint8_t*)ioPin, 3, PinOwner::UM_FourLineDisplay);
571-
}
575+
PinManager::deallocateMultiplePins((const uint8_t*)ioPin, 4, PinOwner::UM_FourLineDisplay);
572576
type = NONE;
573577
return;
574578
}
@@ -1214,7 +1218,8 @@ void FourLineDisplayUsermod::appendConfigData() {
12141218
oappend(F("addInfo('4LineDisplay:type',1,'<br><i class=\"warn\">Change may require reboot</i>','');"));
12151219
oappend(F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
12161220
oappend(F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
1217-
oappend(F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
1221+
oappend(F("addInfo('4LineDisplay:pin[]',2,'','SPI/I2C RST');"));
1222+
oappend(F("addInfo('4LineDisplay:pin[]',3,'','Vext');"));
12181223
}
12191224

12201225
/*
@@ -1237,7 +1242,7 @@ void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
12371242

12381243
top["type"] = type;
12391244
JsonArray io_pin = top.createNestedArray("pin");
1240-
for (int i=0; i<3; i++) io_pin.add(ioPin[i]);
1245+
for (int i = 0; i < MAX_PINS; i++) io_pin.add(ioPin[i]);
12411246
top[FPSTR(_flip)] = (bool) flip;
12421247
top[FPSTR(_contrast)] = contrast;
12431248
top[FPSTR(_contrastFix)] = (bool) contrastFix;
@@ -1263,7 +1268,7 @@ void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
12631268
bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
12641269
bool needsRedraw = false;
12651270
DisplayType newType = type;
1266-
int8_t oldPin[3]; for (unsigned i=0; i<3; i++) oldPin[i] = ioPin[i];
1271+
int8_t oldPin[MAX_PINS]; for (int i = 0; i < MAX_PINS; i++) oldPin[i] = ioPin[i];
12671272

12681273
JsonObject top = root[FPSTR(_name)];
12691274
if (top.isNull()) {
@@ -1274,7 +1279,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
12741279

12751280
enabled = top[FPSTR(_enabled)] | enabled;
12761281
newType = top["type"] | newType;
1277-
for (unsigned i=0; i<3; i++) ioPin[i] = top["pin"][i] | ioPin[i];
1282+
for (int i = 0; i < MAX_PINS; i++) ioPin[i] = top["pin"][i] | ioPin[i];
12781283
flip = top[FPSTR(_flip)] | flip;
12791284
contrast = top[FPSTR(_contrast)] | contrast;
12801285
#ifndef ARDUINO_ARCH_ESP32
@@ -1300,58 +1305,55 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
13001305
DEBUGUM_PRINTLN(F(" config (re)loaded."));
13011306
// changing parameters from settings page
13021307
bool pinsChanged = false;
1303-
for (unsigned i=0; i<3; i++) if (ioPin[i] != oldPin[i]) { pinsChanged = true; break; }
1308+
for (int i = 0; i < MAX_PINS; i++) if (ioPin[i] != oldPin[i]) { pinsChanged = true; break; }
13041309
if (pinsChanged || type!=newType) {
13051310
bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64 || type == SSD1309_SPI64);
13061311
bool newSPI = (newType == SSD1306_SPI || newType == SSD1306_SPI64 || newType == SSD1309_SPI64);
1312+
if (pinsChanged) PinManager::deallocateMultiplePins((const uint8_t*)oldPin, MAX_PINS, PinOwner::UM_FourLineDisplay);
13071313
if (isSPI) {
1308-
if (pinsChanged || !newSPI) PinManager::deallocateMultiplePins((const uint8_t*)oldPin, 3, PinOwner::UM_FourLineDisplay);
13091314
if (!newSPI) {
13101315
// was SPI but is no longer SPI
1311-
if (i2c_scl<0 || i2c_sda<0) { newType=NONE; }
1316+
if (i2c_scl<0 || i2c_sda<0) { newType = NONE; }
13121317
} else {
13131318
// still SPI but pins changed
1314-
PinManagerPinType cspins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } };
1315-
if (ioPin[0]<0 || ioPin[1]<0 || ioPin[1]<0) { newType=NONE; }
1316-
else if (!PinManager::allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; }
1319+
if (ioPin[0]<0 || ioPin[1]<0 || ioPin[2]<0) { newType = NONE; }
13171320
}
13181321
} else if (newSPI) {
13191322
// was I2C but is now SPI
13201323
if (spi_sclk<0 || spi_mosi<0) {
1321-
newType=NONE;
1324+
newType = NONE;
13221325
} else {
1323-
PinManagerPinType pins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } };
1324-
if (ioPin[0]<0 || ioPin[1]<0 || ioPin[1]<0) { newType=NONE; }
1325-
else if (!PinManager::allocateMultiplePins(pins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; }
1326+
if (ioPin[0]<0 || ioPin[1]<0 || ioPin[2]<0) { newType = NONE; }
13261327
}
13271328
} else {
1328-
// just I2C type changed
1329+
// just I2C type changed (but may have RST and Vext pins set)
13291330
}
1331+
if (!PinManager::allocateMultiplePins(ioPin, MAX_PINS, PinOwner::UM_FourLineDisplay, true)) { newType = NONE; }
13301332
type = newType;
13311333
switch (type) {
13321334
case SSD1306:
13331335
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1306_128x32_univision, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
1334-
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
1336+
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), ioPin[2], U8X8_PIN_NONE, U8X8_PIN_NONE);
13351337
break;
13361338
case SH1106:
13371339
u8x8_Setup(u8x8->getU8x8(), u8x8_d_sh1106_128x64_winstar, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
1338-
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
1340+
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), ioPin[2], U8X8_PIN_NONE, U8X8_PIN_NONE);
13391341
break;
13401342
case SSD1306_64:
13411343
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
1342-
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
1344+
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), ioPin[2], U8X8_PIN_NONE, U8X8_PIN_NONE);
13431345
break;
13441346
case SSD1305:
13451347
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1305_128x32_adafruit, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
1346-
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
1348+
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), ioPin[2], U8X8_PIN_NONE, U8X8_PIN_NONE);
13471349
break;
13481350
case SSD1305_64:
13491351
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1305_128x64_adafruit, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
1350-
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
1352+
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), ioPin[2], U8X8_PIN_NONE, U8X8_PIN_NONE);
13511353
break;
13521354
case SSD1309_64:
13531355
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1309_128x64_noname0, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
1354-
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
1356+
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), ioPin[2], U8X8_PIN_NONE, U8X8_PIN_NONE);
13551357
break;
13561358
case SSD1306_SPI:
13571359
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1306_128x32_univision, u8x8_cad_001, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino);

0 commit comments

Comments
 (0)