Button functionality using MCP23017 interrupts and bugfixes

This commit is contained in:
Djuri Baars 2023-06-18 15:40:42 +02:00
parent cae31628c0
commit fb1cd73acf
9 changed files with 121 additions and 46 deletions

View File

@ -7,6 +7,8 @@ std::map<int, std::string> screenNameMap;
#ifndef NO_MCP #ifndef NO_MCP
Adafruit_MCP23X17 mcp; Adafruit_MCP23X17 mcp;
const int MCP_INT_PIN = 8;
#endif #endif
bool timerRunning = true; bool timerRunning = true;
int fgColor; int fgColor;
@ -49,6 +51,8 @@ void setupComponents()
else else
{ {
Serial.println("MCP23017 ok"); Serial.println("MCP23017 ok");
pinMode(MCP_INT_PIN, INPUT);
mcp.setupInterrupts(true, false, LOW);
} }
#endif #endif
@ -65,6 +69,7 @@ void setupComponents()
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
mcp.pinMode(i, INPUT_PULLUP); mcp.pinMode(i, INPUT_PULLUP);
mcp.setupInterruptPin(i, LOW);
} }
#endif #endif
} }
@ -117,7 +122,8 @@ void setupPreferences()
{SCREEN_TIME, "Time"}, {SCREEN_TIME, "Time"},
{SCREEN_HALVING_COUNTDOWN, "Halving countdown"}}; {SCREEN_HALVING_COUNTDOWN, "Halving countdown"}};
for (int i = 0; i < screenNameMap.size() ; i++) { for (int i = 0; i < screenNameMap.size(); i++)
{
String key = "screen" + String(i) + "Visible"; String key = "screen" + String(i) + "Visible";
screenVisible[i] = preferences.getBool(key.c_str(), true); // Default to true if not set screenVisible[i] = preferences.getBool(key.c_str(), true); // Default to true if not set
} }
@ -149,8 +155,9 @@ void handleScreenTasks(uint screen)
switch (currentScreen) switch (currentScreen)
{ {
case SCREEN_BLOCK_HEIGHT: case SCREEN_BLOCK_HEIGHT:
if (blockNotifyTaskHandle) if (blockNotifyTaskHandle) {
vTaskResume(blockNotifyTaskHandle); vTaskResume(blockNotifyTaskHandle);
}
break; break;
case SCREEN_HALVING_COUNTDOWN: case SCREEN_HALVING_COUNTDOWN:
if (blockNotifyTaskHandle) if (blockNotifyTaskHandle)
@ -165,8 +172,10 @@ void handleScreenTasks(uint screen)
vTaskResume(getPriceTaskHandle); vTaskResume(getPriceTaskHandle);
break; break;
case SCREEN_TIME: case SCREEN_TIME:
if (minuteTaskHandle) if (minuteTaskHandle) {
TimeScreen::onActivate();
vTaskResume(minuteTaskHandle); vTaskResume(minuteTaskHandle);
}
break; break;
} }
} }
@ -192,7 +201,8 @@ void timebasedChangeTask(void *parameter)
int newCurrentScreen = (getCurrentScreen() + 1) % screenCount; int newCurrentScreen = (getCurrentScreen() + 1) % screenCount;
String key = "screen" + String(newCurrentScreen) + "Visible"; String key = "screen" + String(newCurrentScreen) + "Visible";
while (!preferences.getBool(key.c_str(), true)) { while (!preferences.getBool(key.c_str(), true))
{
newCurrentScreen = (newCurrentScreen + 1) % screenCount; newCurrentScreen = (newCurrentScreen + 1) % screenCount;
key = "screen" + String(newCurrentScreen) + "Visible"; key = "screen" + String(newCurrentScreen) + "Visible";
} }
@ -203,6 +213,36 @@ void timebasedChangeTask(void *parameter)
} }
} }
int modulo(int x,int N) {
return (x % N + N) %N;
}
void nextScreen()
{
int newCurrentScreen = (getCurrentScreen() + 1) % screenCount;
String key = "screen" + String(newCurrentScreen) + "Visible";
while (!preferences.getBool(key.c_str(), true))
{
newCurrentScreen = (newCurrentScreen + 1) % screenCount;
key = "screen" + String(newCurrentScreen) + "Visible";
}
setCurrentScreen(newCurrentScreen);
}
void previousScreen()
{
int newCurrentScreen = modulo(getCurrentScreen() - 1, screenCount);
String key = "screen" + String(newCurrentScreen) + "Visible";
while (!preferences.getBool(key.c_str(), true))
{
newCurrentScreen = modulo(newCurrentScreen - 1, screenCount);
key = "screen" + String(newCurrentScreen) + "Visible";
}
setCurrentScreen(newCurrentScreen);
}
void setLights(int r, int g, int b) void setLights(int r, int g, int b)
{ {
#ifdef WITH_RGB_LED #ifdef WITH_RGB_LED

View File

@ -28,3 +28,6 @@ int getBgColor();
int getFgColor(); int getFgColor();
void setupSoftAP(); void setupSoftAP();
void nextScreen();
void previousScreen();
int modulo(int x,int N);

View File

@ -33,9 +33,6 @@ ESP32Time rtc(3600);
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
#ifdef ARDUINO_LOLIN_S3
delay(2500);
#endif
#ifdef ARDUINO_ESP32S3_DEV #ifdef ARDUINO_ESP32S3_DEV
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);

View File

@ -26,6 +26,10 @@ void TimeScreen::onNewMinute() {
TimeScreen::showScreen(); TimeScreen::showScreen();
} }
void TimeScreen::onActivate() {
TimeScreen::showScreen();
}
std::array<String, 7> TimeScreen::getEpdContent() { std::array<String, 7> TimeScreen::getEpdContent() {
return TimeScreen::epdContent; return TimeScreen::epdContent;
} }

View File

@ -15,6 +15,7 @@ class TimeScreen {
static void init(); static void init();
static void showScreen(); static void showScreen();
static void onNewMinute(); static void onNewMinute();
static void onActivate();
static std::array<String, 7> getEpdContent(); static std::array<String, 7> getEpdContent();
static TimeScreen* getInstance(); static TimeScreen* getInstance();
}; };

View File

@ -34,6 +34,7 @@ extern uint32_t moment;
#ifndef NO_MCP #ifndef NO_MCP
extern Adafruit_MCP23X17 mcp; extern Adafruit_MCP23X17 mcp;
extern const int MCP_INT_PIN;
#endif #endif
#ifdef WITH_RGB_LED #ifdef WITH_RGB_LED
extern Adafruit_NeoPixel pixels; extern Adafruit_NeoPixel pixels;

View File

@ -1,30 +1,68 @@
/**
* Button 1: No functionality
* Button 2: Next Screen
* Button 3: Previous Screen
* Button 4: Queue full EPD update
*/
#include "button.hpp" #include "button.hpp"
#ifndef NO_MCP #ifndef NO_MCP
TaskHandle_t buttonTaskHandle = NULL; TaskHandle_t buttonTaskHandle = NULL;
// Define a type for the event callback // Define a type for the event callback
std::vector<EventCallback> buttonEventCallbacks; // Define a vector to hold multiple event callbacks std::vector<EventCallback> buttonEventCallbacks; // Define a vector to hold multiple event callbacks
volatile boolean buttonPressed = false;
void buttonTask(void *parameter) void buttonTask(void *parameter)
{ {
while (1) while (1)
{ {
for (int i = 0; i < 4; i++) if (!digitalRead(MCP_INT_PIN))
{ {
if (!mcp.digitalRead(i)) uint pin = mcp.getLastInterruptPin();
{ if (pin == 3) {
Serial.println("Button " + String(i) + " Pressed!"); xTaskCreate(fullRefresh, "FullRefresh", 2048, NULL, 1, NULL);
delay(250);
} }
else if (pin == 1)
{
nextScreen();
}
else if (pin == 2)
{
previousScreen();
}
vTaskDelay(250); // debounce
mcp.clearInterrupts(); // clear
} }
vTaskDelay(pdMS_TO_TICKS(250)); vTaskDelay(pdMS_TO_TICKS(250));
} }
} }
void IRAM_ATTR handleButtonInterrupt()
{
buttonPressed = true;
// Serial.println("ISR");
// uint pin = mcp.getLastInterruptPin();
// if (pin == 1)
// {
// nextScreen();
// }
// else if (pin == 2)
// {
// previousScreen();
// }
// vTaskDelay(pdMS_TO_TICKS(250));
// mcp.clearInterrupts();
}
void setupButtonTask() void setupButtonTask()
{ {
xTaskCreate(buttonTask, "MinuteTask", 2048, NULL, 1, &buttonTaskHandle); // Create the FreeRTOS task xTaskCreate(buttonTask, "ButtonTask", 4096, NULL, 1, &buttonTaskHandle); // Create the FreeRTOS task
// Use interrupt instead of task
// attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, FALLING);
} }
void registerNewButtonCallback(EventCallback cb) void registerNewButtonCallback(EventCallback cb)

View File

@ -7,6 +7,7 @@
#include <freertos/task.h> #include <freertos/task.h>
#include <vector> #include <vector>
#include "shared.hpp" #include "shared.hpp"
#include "lib/functions.hpp"
extern TaskHandle_t buttonTaskHandle; extern TaskHandle_t buttonTaskHandle;
@ -14,4 +15,6 @@ extern TaskHandle_t buttonTaskHandle;
void buttonTask(void *pvParameters); void buttonTask(void *pvParameters);
void setupButtonTask(); void setupButtonTask();
void registerNewButtonCallback(EventCallback cb); void registerNewButtonCallback(EventCallback cb);
void IRAM_ATTR handleButtonInterrupt();
#endif #endif

View File

@ -2,15 +2,14 @@
#ifdef IS_S3 #ifdef IS_S3
// reversed // reversed
const int EPD_CS[7] = {17, 21, 33, 10, 6, 4, 2}; // const int EPD_CS[7] = {17, 21, 33, 10, 6, 4, 2};
const int EPD_BUSY[7] = {16, 18, 37, 9, 7, 5, 3}; // const int EPD_BUSY[7] = {16, 18, 37, 9, 7, 5, 3};
const int EPD_RESET_MPD[7] = {14, 13, 12, 11, 10, 9, 8}; // const int EPD_RESET_MPD[7] = {14, 13, 12, 11, 10, 9, 8};
const int EPD_CS[7] = {2, 4, 6, 10, 33, 21, 17};
const int EPD_BUSY[7] = {3, 5, 7, 9, 37, 18, 16};
const int EPD_RESET_MPD[7] = {8, 9, 10, 11, 12, 13, 14};
//const int EPD_CS[7] = {2, 4, 6, 10, 33, 21, 17};
//const int EPD_BUSY[7] = {3, 5, 7, 9, 37, 18, 16};
//const int EPD_RESET_MPD[7] = {8, 9, 10, 11, 12, 13, 14};
// const int EPD_CS[7] = {2, 4, 10, 38, 34, 21, 17};
// const int EPD_BUSY[7] = {3, 5, 9, 36, 35, 18, 16};
const int EPD_DC = 14; const int EPD_DC = 14;
const int RST_PIN = 15; const int RST_PIN = 15;
#elif defined(IS_S2) #elif defined(IS_S2)
@ -90,6 +89,7 @@ void setupDisplays()
void resetAllDisplays() void resetAllDisplays()
{ {
#ifdef NO_MCP
digitalWrite(RST_PIN, HIGH); digitalWrite(RST_PIN, HIGH);
pinMode(RST_PIN, OUTPUT); pinMode(RST_PIN, OUTPUT);
delay(20); delay(20);
@ -97,16 +97,11 @@ void resetAllDisplays()
delay(20); delay(20);
digitalWrite(RST_PIN, HIGH); digitalWrite(RST_PIN, HIGH);
delay(200); delay(200);
#else
// for (int i = 8; i < 16; i++) { for (int i = 0; i < displaySize; i++) {
// mcp.digitalWrite(i, HIGH); resetSingleDisplay(i);
// mcp.pinMode(i, OUTPUT); }
// delay(20); #endif NO_MCP
// mcp.digitalWrite(i, LOW);
// delay(20);
// mcp.digitalWrite(i, HIGH);
// delay(200);
// }
} }
void resetSingleDisplay(int i) void resetSingleDisplay(int i)
@ -318,10 +313,8 @@ void updateDisplay(void *pvParameters)
if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0) if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0)
{ {
currentEpdContent[epdIndex] = epdContent[epdIndex]; currentEpdContent[epdIndex] = epdContent[epdIndex];
// resetSingleDisplay(epdIndex);
#ifndef NO_MCP #ifndef NO_MCP
displays[epdIndex].init(0, false); displays[epdIndex].init(0, false);
delay(displays[epdIndex].epd2.power_on_time);
resetSingleDisplay(epdIndex); resetSingleDisplay(epdIndex);
#endif #endif
// displays[epdIndex].init(0, false); // displays[epdIndex].init(0, false);
@ -344,7 +337,6 @@ void updateDisplay(void *pvParameters)
} }
displays[epdIndex].display(updatePartial); displays[epdIndex].display(updatePartial);
// displays[epdIndex].powerOff();
displays[epdIndex].hibernate(); displays[epdIndex].hibernate();
#endif #endif
} }
@ -356,9 +348,8 @@ void showSetupQr(String ssid, String password)
{ {
int displayIndex = 6; int displayIndex = 6;
const String text = "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;"; // User-supplied text const String text = "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;";
// genQrCode(text, &qrcode);
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText(text.c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW, bool ok = qrcodegen_encodeText(text.c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true); qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
@ -367,8 +358,7 @@ void showSetupQr(String ssid, String password)
const int padding = floor(float(displays[displayIndex].width() - (size * 4)) / 2); const int padding = floor(float(displays[displayIndex].width() - (size * 4)) / 2);
const int paddingY = floor(float(displays[displayIndex].height() - (size * 4)) / 2); const int paddingY = floor(float(displays[displayIndex].height() - (size * 4)) / 2);
// displays[displayIndex].setRotation(0);
// displays[displayIndex].setFullWindow();
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height()); displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
displays[displayIndex].firstPage(); displays[displayIndex].firstPage();
@ -439,8 +429,6 @@ void showSetupQr(String ssid, String password)
for (int i = 1; i < displaySize; (i = i+2)) { for (int i = 1; i < displaySize; (i = i+2)) {
displays[i].setPartialWindow(0, 0, displays[i].width(), displays[i].height()); displays[i].setPartialWindow(0, 0, displays[i].width(), displays[i].height());
// displays[i].firstPage();
displays[i].fillScreen(GxEPD_WHITE); displays[i].fillScreen(GxEPD_WHITE);
displays[i].display(true); displays[i].display(true);
} }