Usermod fixes
- 4LD: prevent corruption on fast Rotary changes - Rotary: implement ISR for I2C reading
This commit is contained in:
parent
24537c4fdc
commit
b6d9fd8030
@ -1,11 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
#undef U8X8_NO_HW_I2C // borrowed from WLEDMM: we do want I2C hardware drivers - if possible
|
||||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||||
#include "4LD_wled_fonts.c"
|
#include "4LD_wled_fonts.c"
|
||||||
|
|
||||||
|
#ifndef FLD_ESP32_NO_THREADS
|
||||||
|
#define FLD_ESP32_USE_THREADS // comment out to use 0.13.x behviour without parallel update task - slower, but more robust. May delay other tasks like LEDs or audioreactive!!
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Insired by the usermod_v2_four_line_display
|
// Inspired by the usermod_v2_four_line_display
|
||||||
//
|
//
|
||||||
// v2 usermod for using 128x32 or 128x64 i2c
|
// v2 usermod for using 128x32 or 128x64 i2c
|
||||||
// OLED displays to provide a four line display
|
// OLED displays to provide a four line display
|
||||||
@ -88,9 +93,11 @@ typedef enum {
|
|||||||
|
|
||||||
|
|
||||||
class FourLineDisplayUsermod : public Usermod {
|
class FourLineDisplayUsermod : public Usermod {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
public:
|
public:
|
||||||
FourLineDisplayUsermod() { if (!instance) instance = this; }
|
FourLineDisplayUsermod() { if (!instance) instance = this; }
|
||||||
static FourLineDisplayUsermod* getInstance(void) { return instance; }
|
static FourLineDisplayUsermod* getInstance(void) { return instance; }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -215,9 +222,7 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
//function to update lastredraw
|
//function to update lastredraw
|
||||||
void updateRedrawTime() {
|
inline void updateRedrawTime() { lastRedraw = millis(); }
|
||||||
lastRedraw = millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redraw the screen (but only if things have changed
|
* Redraw the screen (but only if things have changed
|
||||||
@ -352,10 +357,13 @@ const char FourLineDisplayUsermod::_showSeconds[] PROGMEM = "showSeconds";
|
|||||||
const char FourLineDisplayUsermod::_busClkFrequency[] PROGMEM = "i2c-freq-kHz";
|
const char FourLineDisplayUsermod::_busClkFrequency[] PROGMEM = "i2c-freq-kHz";
|
||||||
const char FourLineDisplayUsermod::_contrastFix[] PROGMEM = "contrastFix";
|
const char FourLineDisplayUsermod::_contrastFix[] PROGMEM = "contrastFix";
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
FourLineDisplayUsermod *FourLineDisplayUsermod::instance = nullptr;
|
FourLineDisplayUsermod *FourLineDisplayUsermod::instance = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
// some displays need this to properly apply contrast
|
// some displays need this to properly apply contrast
|
||||||
void FourLineDisplayUsermod::setVcomh(bool highContrast) {
|
void FourLineDisplayUsermod::setVcomh(bool highContrast) {
|
||||||
|
if (type == NONE || !enabled) return;
|
||||||
u8x8_t *u8x8_struct = u8x8->getU8x8();
|
u8x8_t *u8x8_struct = u8x8->getU8x8();
|
||||||
u8x8_cad_StartTransfer(u8x8_struct);
|
u8x8_cad_StartTransfer(u8x8_struct);
|
||||||
u8x8_cad_SendCmd(u8x8_struct, 0x0db); //address of value
|
u8x8_cad_SendCmd(u8x8_struct, 0x0db); //address of value
|
||||||
@ -364,6 +372,7 @@ void FourLineDisplayUsermod::setVcomh(bool highContrast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FourLineDisplayUsermod::startDisplay() {
|
void FourLineDisplayUsermod::startDisplay() {
|
||||||
|
if (type == NONE || !enabled) return;
|
||||||
lineHeight = u8x8->getRows() > 4 ? 2 : 1;
|
lineHeight = u8x8->getRows() > 4 ? 2 : 1;
|
||||||
DEBUG_PRINTLN(F("Starting display."));
|
DEBUG_PRINTLN(F("Starting display."));
|
||||||
u8x8->setBusClock(ioFrequency); // can be used for SPI too
|
u8x8->setBusClock(ioFrequency); // can be used for SPI too
|
||||||
@ -590,7 +599,7 @@ void FourLineDisplayUsermod::connected() {
|
|||||||
* Da loop.
|
* Da loop.
|
||||||
*/
|
*/
|
||||||
void FourLineDisplayUsermod::loop() {
|
void FourLineDisplayUsermod::loop() {
|
||||||
#ifndef ARDUINO_ARCH_ESP32
|
#if !(defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS))
|
||||||
if (!enabled || strip.isUpdating()) return;
|
if (!enabled || strip.isUpdating()) return;
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
if (now < nextUpdate) return;
|
if (now < nextUpdate) return;
|
||||||
@ -716,6 +725,11 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FourLineDisplayUsermod::updateBrightness() {
|
void FourLineDisplayUsermod::updateBrightness() {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
|
unsigned long now = millis();
|
||||||
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
knownBrightness = bri;
|
knownBrightness = bri;
|
||||||
if (overlayUntil == 0) {
|
if (overlayUntil == 0) {
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
@ -728,6 +742,11 @@ void FourLineDisplayUsermod::updateBrightness() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FourLineDisplayUsermod::updateSpeed() {
|
void FourLineDisplayUsermod::updateSpeed() {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
|
unsigned long now = millis();
|
||||||
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
knownEffectSpeed = effectSpeed;
|
knownEffectSpeed = effectSpeed;
|
||||||
if (overlayUntil == 0) {
|
if (overlayUntil == 0) {
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
@ -740,6 +759,11 @@ void FourLineDisplayUsermod::updateSpeed() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FourLineDisplayUsermod::updateIntensity() {
|
void FourLineDisplayUsermod::updateIntensity() {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
|
unsigned long now = millis();
|
||||||
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
knownEffectIntensity = effectIntensity;
|
knownEffectIntensity = effectIntensity;
|
||||||
if (overlayUntil == 0) {
|
if (overlayUntil == 0) {
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
@ -752,6 +776,11 @@ void FourLineDisplayUsermod::updateIntensity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FourLineDisplayUsermod::drawStatusIcons() {
|
void FourLineDisplayUsermod::drawStatusIcons() {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
|
unsigned long now = millis();
|
||||||
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
uint8_t col = 15;
|
uint8_t col = 15;
|
||||||
uint8_t row = 0;
|
uint8_t row = 0;
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
@ -775,6 +804,11 @@ void FourLineDisplayUsermod::setMarkLine(byte newMarkLineNum, byte newMarkColNum
|
|||||||
|
|
||||||
//Draw the arrow for the current setting beiong changed
|
//Draw the arrow for the current setting beiong changed
|
||||||
void FourLineDisplayUsermod::drawArrow() {
|
void FourLineDisplayUsermod::drawArrow() {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
|
unsigned long now = millis();
|
||||||
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1);
|
if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1);
|
||||||
lockRedraw = false;
|
lockRedraw = false;
|
||||||
@ -783,6 +817,11 @@ void FourLineDisplayUsermod::drawArrow() {
|
|||||||
//Display the current effect or palette (desiredEntry)
|
//Display the current effect or palette (desiredEntry)
|
||||||
// on the appropriate line (row).
|
// on the appropriate line (row).
|
||||||
void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
|
void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
|
unsigned long now = millis();
|
||||||
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
char lineBuffer[MAX_JSON_CHARS];
|
char lineBuffer[MAX_JSON_CHARS];
|
||||||
if (overlayUntil == 0) {
|
if (overlayUntil == 0) {
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
@ -851,9 +890,11 @@ void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const c
|
|||||||
bool FourLineDisplayUsermod::wakeDisplay() {
|
bool FourLineDisplayUsermod::wakeDisplay() {
|
||||||
if (type == NONE || !enabled) return false;
|
if (type == NONE || !enabled) return false;
|
||||||
if (displayTurnedOff) {
|
if (displayTurnedOff) {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
if (drawing) return false;
|
if (drawing || lockRedraw) return false;
|
||||||
|
#endif
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
clear();
|
clear();
|
||||||
// Turn the display back on
|
// Turn the display back on
|
||||||
@ -870,9 +911,11 @@ bool FourLineDisplayUsermod::wakeDisplay() {
|
|||||||
* Used in Rotary Encoder usermod.
|
* Used in Rotary Encoder usermod.
|
||||||
*/
|
*/
|
||||||
void FourLineDisplayUsermod::overlay(const char* line1, long showHowLong, byte glyphType) {
|
void FourLineDisplayUsermod::overlay(const char* line1, long showHowLong, byte glyphType) {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
if (drawing) return;
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
// Turn the display back on
|
// Turn the display back on
|
||||||
if (!wakeDisplay()) clear();
|
if (!wakeDisplay()) clear();
|
||||||
@ -895,9 +938,11 @@ void FourLineDisplayUsermod::overlay(const char* line1, long showHowLong, byte g
|
|||||||
* Clears the screen and prints.
|
* Clears the screen and prints.
|
||||||
*/
|
*/
|
||||||
void FourLineDisplayUsermod::overlayLogo(long showHowLong) {
|
void FourLineDisplayUsermod::overlayLogo(long showHowLong) {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
if (drawing) return;
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
// Turn the display back on
|
// Turn the display back on
|
||||||
if (!wakeDisplay()) clear();
|
if (!wakeDisplay()) clear();
|
||||||
@ -957,9 +1002,11 @@ void FourLineDisplayUsermod::overlayLogo(long showHowLong) {
|
|||||||
* Used in Auto Save usermod
|
* Used in Auto Save usermod
|
||||||
*/
|
*/
|
||||||
void FourLineDisplayUsermod::overlay(const char* line1, const char* line2, long showHowLong) {
|
void FourLineDisplayUsermod::overlay(const char* line1, const char* line2, long showHowLong) {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
if (drawing) return;
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
// Turn the display back on
|
// Turn the display back on
|
||||||
if (!wakeDisplay()) clear();
|
if (!wakeDisplay()) clear();
|
||||||
@ -979,9 +1026,11 @@ void FourLineDisplayUsermod::overlay(const char* line1, const char* line2, long
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FourLineDisplayUsermod::networkOverlay(const char* line1, long showHowLong) {
|
void FourLineDisplayUsermod::networkOverlay(const char* line1, long showHowLong) {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||||
if (drawing) return;
|
if (drawing || lockRedraw) return;
|
||||||
|
#endif
|
||||||
lockRedraw = true;
|
lockRedraw = true;
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
@ -1098,7 +1147,7 @@ bool FourLineDisplayUsermod::handleButton(uint8_t b) {
|
|||||||
#define ARDUINO_RUNNING_CORE 1
|
#define ARDUINO_RUNNING_CORE 1
|
||||||
#endif
|
#endif
|
||||||
void FourLineDisplayUsermod::onUpdateBegin(bool init) {
|
void FourLineDisplayUsermod::onUpdateBegin(bool init) {
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
if (init && Display_Task) {
|
if (init && Display_Task) {
|
||||||
vTaskSuspend(Display_Task); // update is about to begin, disable task to prevent crash
|
vTaskSuspend(Display_Task); // update is about to begin, disable task to prevent crash
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,6 +57,10 @@
|
|||||||
#define PCF8574_ADDRESS 0x20 // some may start at 0x38
|
#define PCF8574_ADDRESS 0x20 // some may start at 0x38
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PCF8574_INT_PIN
|
||||||
|
#define PCF8574_INT_PIN -1 // GPIO connected to INT pin on PCF8574
|
||||||
|
#endif
|
||||||
|
|
||||||
// The last UI state, remove color and saturation option if display not active (too many options)
|
// The last UI state, remove color and saturation option if display not active (too many options)
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
#define LAST_UI_STATE 11
|
#define LAST_UI_STATE 11
|
||||||
@ -125,6 +129,21 @@ static int re_qstringCmp(const void *ap, const void *bp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static volatile uint8_t pcfPortData = 0; // port expander port state
|
||||||
|
static volatile uint8_t addrPcf8574 = PCF8574_ADDRESS; // has to be accessible in ISR
|
||||||
|
|
||||||
|
// Interrupt routine to read I2C rotary state
|
||||||
|
// if we are to use PCF8574 port expander we will need to rely on interrupts as polling I2C every 2ms
|
||||||
|
// is a waste of resources and causes 4LD to fail.
|
||||||
|
// in such case rely on ISR to read pin values and store them into static variable
|
||||||
|
static void IRAM_ATTR i2cReadingISR() {
|
||||||
|
Wire.requestFrom(addrPcf8574, 1U);
|
||||||
|
if (Wire.available()) {
|
||||||
|
pcfPortData = Wire.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class RotaryEncoderUIUsermod : public Usermod {
|
class RotaryEncoderUIUsermod : public Usermod {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -186,7 +205,7 @@ class RotaryEncoderUIUsermod : public Usermod {
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
bool usePcf8574;
|
bool usePcf8574;
|
||||||
uint8_t addrPcf8574;
|
int8_t pinIRQ;
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
static const char _name[];
|
static const char _name[];
|
||||||
@ -199,6 +218,7 @@ class RotaryEncoderUIUsermod : public Usermod {
|
|||||||
static const char _applyToAll[];
|
static const char _applyToAll[];
|
||||||
static const char _pcf8574[];
|
static const char _pcf8574[];
|
||||||
static const char _pcfAddress[];
|
static const char _pcfAddress[];
|
||||||
|
static const char _pcfINTpin[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* readPin() - read rotary encoder pin value
|
* readPin() - read rotary encoder pin value
|
||||||
@ -254,7 +274,7 @@ class RotaryEncoderUIUsermod : public Usermod {
|
|||||||
, initDone(false)
|
, initDone(false)
|
||||||
, enabled(true)
|
, enabled(true)
|
||||||
, usePcf8574(USE_PCF8574)
|
, usePcf8574(USE_PCF8574)
|
||||||
, addrPcf8574(PCF8574_ADDRESS)
|
, pinIRQ(PCF8574_INT_PIN)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -356,15 +376,7 @@ class RotaryEncoderUIUsermod : public Usermod {
|
|||||||
*/
|
*/
|
||||||
byte RotaryEncoderUIUsermod::readPin(uint8_t pin) {
|
byte RotaryEncoderUIUsermod::readPin(uint8_t pin) {
|
||||||
if (usePcf8574) {
|
if (usePcf8574) {
|
||||||
byte _data = 0;
|
return (pcfPortData>>pin) & 1;
|
||||||
if (pin < 8) {
|
|
||||||
Wire.requestFrom(addrPcf8574, 1U);
|
|
||||||
if (Wire.available()) {
|
|
||||||
_data = Wire.read();
|
|
||||||
_data = (_data>>pin) & 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _data;
|
|
||||||
} else {
|
} else {
|
||||||
return digitalRead(pin);
|
return digitalRead(pin);
|
||||||
}
|
}
|
||||||
@ -460,14 +472,25 @@ void RotaryEncoderUIUsermod::setup()
|
|||||||
{
|
{
|
||||||
DEBUG_PRINTLN(F("Usermod Rotary Encoder init."));
|
DEBUG_PRINTLN(F("Usermod Rotary Encoder init."));
|
||||||
|
|
||||||
if (!usePcf8574) {
|
if (usePcf8574) {
|
||||||
|
if ((i2c_sda == i2c_scl && i2c_sda == -1) || pinA<0 || pinB<0 || pinC<0) {
|
||||||
|
DEBUG_PRINTLN(F("I2C and/or PCF8574 pins unused, disabling."));
|
||||||
|
enabled = false;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (pinIRQ >= 0 && pinManager.allocatePin(pinIRQ, false, PinOwner::UM_RotaryEncoderUI)) {
|
||||||
|
attachInterrupt(pinIRQ, i2cReadingISR, CHANGE); // RISING, FALLING, CHANGE, ONLOW, ONHIGH
|
||||||
|
DEBUG_PRINTLN(F("Interrupt attached."));
|
||||||
|
} else {
|
||||||
|
DEBUG_PRINTLN(F("Unable to allocate interrupt pin, disabling."));
|
||||||
|
pinIRQ = -1;
|
||||||
|
enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
|
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
|
||||||
if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
||||||
// BUG: configuring this usermod with conflicting pins
|
|
||||||
// will cause it to de-allocate pins it does not own
|
|
||||||
// (at second config)
|
|
||||||
// This is the exact type of bug solved by pinManager
|
|
||||||
// tracking the owner tags....
|
|
||||||
pinA = pinB = pinC = -1;
|
pinA = pinB = pinC = -1;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
return;
|
return;
|
||||||
@ -479,12 +502,6 @@ void RotaryEncoderUIUsermod::setup()
|
|||||||
pinMode(pinA, USERMOD_ROTARY_ENCODER_GPIO);
|
pinMode(pinA, USERMOD_ROTARY_ENCODER_GPIO);
|
||||||
pinMode(pinB, USERMOD_ROTARY_ENCODER_GPIO);
|
pinMode(pinB, USERMOD_ROTARY_ENCODER_GPIO);
|
||||||
pinMode(pinC, USERMOD_ROTARY_ENCODER_GPIO);
|
pinMode(pinC, USERMOD_ROTARY_ENCODER_GPIO);
|
||||||
} else {
|
|
||||||
if ((i2c_sda == i2c_scl && i2c_sda == -1) || pinA<0 || pinB<0 || pinC<0) {
|
|
||||||
DEBUG_PRINTLN(F("Pins unused, disabling."));
|
|
||||||
enabled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loopTime = millis();
|
loopTime = millis();
|
||||||
@ -536,7 +553,7 @@ void RotaryEncoderUIUsermod::loop()
|
|||||||
currentEffectAndPaletteInitialized = false;
|
currentEffectAndPaletteInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTime >= (loopTime + 20)) // 20ms since last check of encoder = 50Hz
|
if (currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
||||||
{
|
{
|
||||||
bool buttonPressed = !readPin(pinC); //0=pressed, 1=released
|
bool buttonPressed = !readPin(pinC); //0=pressed, 1=released
|
||||||
if (buttonPressed) {
|
if (buttonPressed) {
|
||||||
@ -645,8 +662,6 @@ void RotaryEncoderUIUsermod::loop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||||
DEBUG_PRINTF("Inputs: A:%d B:%d SW:%d\n", (int)Enc_A, (int)Enc_B, (int)!buttonPressed);
|
|
||||||
|
|
||||||
loopTime = currentTime; // Updates loopTime
|
loopTime = currentTime; // Updates loopTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1051,6 +1066,7 @@ void RotaryEncoderUIUsermod::addToConfig(JsonObject &root) {
|
|||||||
top[FPSTR(_applyToAll)] = applyToAll;
|
top[FPSTR(_applyToAll)] = applyToAll;
|
||||||
top[FPSTR(_pcf8574)] = usePcf8574;
|
top[FPSTR(_pcf8574)] = usePcf8574;
|
||||||
top[FPSTR(_pcfAddress)] = addrPcf8574;
|
top[FPSTR(_pcfAddress)] = addrPcf8574;
|
||||||
|
top[FPSTR(_pcfINTpin)] = pinIRQ;
|
||||||
DEBUG_PRINTLN(F("Rotary Encoder config saved."));
|
DEBUG_PRINTLN(F("Rotary Encoder config saved."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,6 +1090,7 @@ bool RotaryEncoderUIUsermod::readFromConfig(JsonObject &root) {
|
|||||||
int8_t newDTpin = top[FPSTR(_DT_pin)] | pinA;
|
int8_t newDTpin = top[FPSTR(_DT_pin)] | pinA;
|
||||||
int8_t newCLKpin = top[FPSTR(_CLK_pin)] | pinB;
|
int8_t newCLKpin = top[FPSTR(_CLK_pin)] | pinB;
|
||||||
int8_t newSWpin = top[FPSTR(_SW_pin)] | pinC;
|
int8_t newSWpin = top[FPSTR(_SW_pin)] | pinC;
|
||||||
|
int8_t newIRQpin = top[FPSTR(_pcfINTpin)] | pinIRQ;
|
||||||
bool oldPcf8574 = usePcf8574;
|
bool oldPcf8574 = usePcf8574;
|
||||||
|
|
||||||
presetHigh = top[FPSTR(_presetHigh)] | presetHigh;
|
presetHigh = top[FPSTR(_presetHigh)] | presetHigh;
|
||||||
@ -1097,8 +1114,15 @@ bool RotaryEncoderUIUsermod::readFromConfig(JsonObject &root) {
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||||
// changing parameters from settings page
|
// changing parameters from settings page
|
||||||
if (pinA!=newDTpin || pinB!=newCLKpin || pinC!=newSWpin) {
|
if (pinA!=newDTpin || pinB!=newCLKpin || pinC!=newSWpin || pinIRQ!=newIRQpin) {
|
||||||
if (!oldPcf8574) {
|
if (oldPcf8574) {
|
||||||
|
if (pinIRQ >= 0) {
|
||||||
|
detachInterrupt(pinIRQ);
|
||||||
|
pinManager.deallocatePin(pinIRQ, PinOwner::UM_RotaryEncoderUI);
|
||||||
|
DEBUG_PRINTLN(F("Deallocated old IRQ pin."));
|
||||||
|
}
|
||||||
|
pinIRQ = newIRQpin;
|
||||||
|
} else {
|
||||||
pinManager.deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI);
|
pinManager.deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI);
|
||||||
pinManager.deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI);
|
pinManager.deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI);
|
||||||
pinManager.deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI);
|
pinManager.deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI);
|
||||||
@ -1115,7 +1139,7 @@ bool RotaryEncoderUIUsermod::readFromConfig(JsonObject &root) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||||
return !top[FPSTR(_pcf8574)].isNull();
|
return !top[FPSTR(_pcfINTpin)].isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1130,3 +1154,4 @@ const char RotaryEncoderUIUsermod::_presetLow[] PROGMEM = "preset-low";
|
|||||||
const char RotaryEncoderUIUsermod::_applyToAll[] PROGMEM = "apply-2-all-seg";
|
const char RotaryEncoderUIUsermod::_applyToAll[] PROGMEM = "apply-2-all-seg";
|
||||||
const char RotaryEncoderUIUsermod::_pcf8574[] PROGMEM = "use-PCF8574";
|
const char RotaryEncoderUIUsermod::_pcf8574[] PROGMEM = "use-PCF8574";
|
||||||
const char RotaryEncoderUIUsermod::_pcfAddress[] PROGMEM = "PCF8574-address";
|
const char RotaryEncoderUIUsermod::_pcfAddress[] PROGMEM = "PCF8574-address";
|
||||||
|
const char RotaryEncoderUIUsermod::_pcfINTpin[] PROGMEM = "PCF8574-INT-pin";
|
||||||
|
Loading…
Reference in New Issue
Block a user