Make ScreenHandler class, fix button handling
This commit is contained in:
parent
698c3a3a43
commit
17fef80253
11 changed files with 484 additions and 410 deletions
|
@ -36,7 +36,7 @@ void taskBitaxeFetch(void *pvParameters)
|
|||
bitaxeHashrate = std::to_string(static_cast<int>(std::round(doc["hashRate"].as<float>())));
|
||||
bitaxeBestDiff = doc["bestDiff"].as<std::string>();
|
||||
|
||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BITAXE_HASHRATE || getCurrentScreen() == SCREEN_BITAXE_BESTDIFF))
|
||||
if (workQueue != nullptr && (ScreenHandler::getCurrentScreen() == SCREEN_BITAXE_HASHRATE || ScreenHandler::getCurrentScreen() == SCREEN_BITAXE_BESTDIFF))
|
||||
{
|
||||
WorkItem priceUpdate = {TASK_BITAXE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||
|
|
|
@ -200,7 +200,7 @@ void processNewBlock(uint newBlockHeight) {
|
|||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||
|
||||
if (getCurrentScreen() != SCREEN_BLOCK_HEIGHT &&
|
||||
if (ScreenHandler::getCurrentScreen() != SCREEN_BLOCK_HEIGHT &&
|
||||
preferences.getBool("stealFocus", DEFAULT_STEAL_FOCUS))
|
||||
{
|
||||
uint64_t timerPeriod = 0;
|
||||
|
@ -210,7 +210,7 @@ void processNewBlock(uint newBlockHeight) {
|
|||
timerPeriod = getTimerSeconds();
|
||||
esp_timer_stop(screenRotateTimer);
|
||||
}
|
||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||
ScreenHandler::setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||
if (timerPeriod > 0)
|
||||
{
|
||||
esp_timer_start_periodic(screenRotateTimer,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#include "button_handler.hpp"
|
||||
|
||||
TaskHandle_t buttonTaskHandle = NULL;
|
||||
const TickType_t debounceDelay = pdMS_TO_TICKS(50);
|
||||
TickType_t lastDebounceTime = 0;
|
||||
ButtonState buttonStates[4];
|
||||
|
||||
#ifdef IS_BTCLOCK_V8
|
||||
#define BTN_1 256
|
||||
|
@ -17,65 +16,134 @@ TickType_t lastDebounceTime = 0;
|
|||
#endif
|
||||
|
||||
void buttonTask(void *parameter) {
|
||||
while (1) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
while (1) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
TickType_t currentTime = xTaskGetTickCount();
|
||||
|
||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||
|
||||
if (!digitalRead(MCP_INT_PIN)) {
|
||||
uint16_t intFlags = mcp1.getInterruptFlagRegister();
|
||||
uint16_t intCap = mcp1.getInterruptCaptureRegister();
|
||||
|
||||
// Check button states
|
||||
if (intFlags & BTN_1) handleButtonPress(0);
|
||||
if (intFlags & BTN_2) handleButtonPress(1);
|
||||
if (intFlags & BTN_3) handleButtonPress(2);
|
||||
if (intFlags & BTN_4) handleButtonPress(3);
|
||||
|
||||
// Check for button releases
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (buttonStates[i].isPressed) {
|
||||
bool currentlyPressed = false;
|
||||
switch (i) {
|
||||
case 0: currentlyPressed = (intCap & BTN_1); break;
|
||||
case 1: currentlyPressed = (intCap & BTN_2); break;
|
||||
case 2: currentlyPressed = (intCap & BTN_3); break;
|
||||
case 3: currentlyPressed = (intCap & BTN_4); break;
|
||||
}
|
||||
if (!currentlyPressed) {
|
||||
handleButtonRelease(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for long press on pressed buttons
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (buttonStates[i].isPressed && !buttonStates[i].longPressHandled) {
|
||||
if ((currentTime - buttonStates[i].pressStartTime) >= longPressDelay) {
|
||||
handleLongPress(i);
|
||||
buttonStates[i].longPressHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear interrupt state
|
||||
while (!digitalRead(MCP_INT_PIN)) {
|
||||
mcp1.getInterruptCaptureRegister();
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleButtonPress(int buttonIndex) {
|
||||
TickType_t currentTime = xTaskGetTickCount();
|
||||
ButtonState &state = buttonStates[buttonIndex];
|
||||
|
||||
if ((currentTime - lastDebounceTime) >= debounceDelay) {
|
||||
lastDebounceTime = currentTime;
|
||||
|
||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||
|
||||
if (!digitalRead(MCP_INT_PIN)) {
|
||||
uint16_t intFlags = mcp1.getInterruptFlagRegister();
|
||||
uint16_t intCap = mcp1.getInterruptCaptureRegister();
|
||||
|
||||
// Check each button individually
|
||||
if (intFlags & BTN_1) handleButton1();
|
||||
if (intFlags & BTN_2) handleButton2();
|
||||
if (intFlags & BTN_3) handleButton3();
|
||||
if (intFlags & BTN_4) handleButton4();
|
||||
}
|
||||
if ((currentTime - state.lastPressTime) >= debounceDelay) {
|
||||
state.isPressed = true;
|
||||
state.pressStartTime = currentTime;
|
||||
state.longPressHandled = false;
|
||||
|
||||
// Check for double click
|
||||
if ((currentTime - state.lastPressTime) <= doubleClickDelay) {
|
||||
state.clickCount++;
|
||||
if (state.clickCount == 2) {
|
||||
handleDoubleClick(buttonIndex);
|
||||
state.clickCount = 0;
|
||||
}
|
||||
} else {
|
||||
state.clickCount = 1;
|
||||
}
|
||||
|
||||
state.lastPressTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
void handleButtonRelease(int buttonIndex) {
|
||||
TickType_t currentTime = xTaskGetTickCount();
|
||||
ButtonState &state = buttonStates[buttonIndex];
|
||||
|
||||
// Clear interrupt state
|
||||
while (!digitalRead(MCP_INT_PIN)) {
|
||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||
mcp1.getInterruptCaptureRegister();
|
||||
delay(1); // Small delay to prevent tight loop
|
||||
state.isPressed = false;
|
||||
|
||||
// If this wasn't a long press or double click, handle as single click
|
||||
if (!state.longPressHandled && state.clickCount == 1 &&
|
||||
(currentTime - state.pressStartTime) < longPressDelay) {
|
||||
handleSingleClick(buttonIndex);
|
||||
state.clickCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions to handle each button
|
||||
void handleButton1() {
|
||||
toggleTimerActive();
|
||||
// Button action handlers
|
||||
void handleSingleClick(int buttonIndex) {
|
||||
switch (buttonIndex) {
|
||||
case 0:
|
||||
toggleTimerActive();
|
||||
break;
|
||||
case 1:
|
||||
Serial.println("Button 2 single click");
|
||||
ScreenHandler::nextScreen();
|
||||
break;
|
||||
case 2:
|
||||
Serial.println("Button 3 single click");
|
||||
ScreenHandler::previousScreen();
|
||||
break;
|
||||
case 3:
|
||||
ScreenHandler::showSystemStatusScreen();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handleButton2() {
|
||||
nextScreen();
|
||||
void handleDoubleClick(int buttonIndex) {
|
||||
Serial.printf("Button %d double clicked\n", buttonIndex + 1);
|
||||
}
|
||||
|
||||
void handleButton3() {
|
||||
previousScreen();
|
||||
}
|
||||
|
||||
void handleButton4() {
|
||||
showSystemStatusScreen();
|
||||
void handleLongPress(int buttonIndex) {
|
||||
Serial.printf("Button %d long press detected\n", buttonIndex + 1);
|
||||
}
|
||||
|
||||
void IRAM_ATTR handleButtonInterrupt() {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
void setupButtonTask() {
|
||||
xTaskCreate(buttonTask, "ButtonTask", 3072, NULL, tskIDLE_PRIORITY,
|
||||
&buttonTaskHandle); // Create the FreeRTOS task
|
||||
// Use interrupt instead of task
|
||||
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
|
||||
xTaskCreate(buttonTask, "ButtonTask", 3072, NULL, tskIDLE_PRIORITY,
|
||||
&buttonTaskHandle);
|
||||
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, FALLING);
|
||||
}
|
||||
|
|
|
@ -18,3 +18,37 @@ void handleButton1();
|
|||
void handleButton2();
|
||||
void handleButton3();
|
||||
void handleButton4();
|
||||
|
||||
// New features
|
||||
const TickType_t debounceDelay = pdMS_TO_TICKS(50);
|
||||
const TickType_t doubleClickDelay = pdMS_TO_TICKS(300); // Maximum time between clicks for double click
|
||||
const TickType_t longPressDelay = pdMS_TO_TICKS(1000); // Time to hold for long press
|
||||
|
||||
// Track timing for each button
|
||||
struct ButtonState {
|
||||
TickType_t lastPressTime = 0;
|
||||
TickType_t pressStartTime = 0;
|
||||
bool isPressed = false;
|
||||
uint8_t clickCount = 0;
|
||||
bool longPressHandled = false;
|
||||
};
|
||||
|
||||
extern ButtonState buttonStates[4];
|
||||
|
||||
#ifdef IS_BTCLOCK_V8
|
||||
#define BTN_1 256
|
||||
#define BTN_2 512
|
||||
#define BTN_3 1024
|
||||
#define BTN_4 2048
|
||||
#else
|
||||
#define BTN_1 2048
|
||||
#define BTN_2 1024
|
||||
#define BTN_3 512
|
||||
#define BTN_4 256
|
||||
#endif
|
||||
|
||||
void handleButtonPress(int buttonIndex);
|
||||
void handleButtonRelease(int buttonIndex);
|
||||
void handleSingleClick(int buttonIndex);
|
||||
void handleDoubleClick(int buttonIndex);
|
||||
void handleLongPress(int buttonIndex);
|
||||
|
|
|
@ -285,9 +285,9 @@ void setupPreferences()
|
|||
setPrice(preferences.getUInt("lastPrice", INITIAL_LAST_PRICE), CURRENCY_USD);
|
||||
|
||||
if (preferences.getBool("ownDataSource", DEFAULT_OWN_DATA_SOURCE))
|
||||
setCurrentCurrency(preferences.getUChar("lastCurrency", CURRENCY_USD));
|
||||
ScreenHandler::setCurrentCurrency(preferences.getUChar("lastCurrency", CURRENCY_USD));
|
||||
else
|
||||
setCurrentCurrency(CURRENCY_USD);
|
||||
ScreenHandler::setCurrentCurrency(CURRENCY_USD);
|
||||
|
||||
if (!preferences.isKey("flDisable")) {
|
||||
preferences.putBool("flDisable", isWhiteVersion() ? false : true);
|
||||
|
@ -482,7 +482,7 @@ void setupHardware()
|
|||
Serial.printf("Error setting pin %d to input pull up\n", i);
|
||||
}
|
||||
// Enable interrupt on CHANGE for each pin
|
||||
if (!mcp1.enableInterrupt(i, CHANGE)) {
|
||||
if (!mcp1.enableInterrupt(i, FALLING)) {
|
||||
Serial.printf("Error enabling interrupt for pin %d\n", i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ void taskMiningPoolStatsFetch(void *pvParameters)
|
|||
miningPoolStatsDailyEarnings = 0; // or any other default value
|
||||
}
|
||||
|
||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_MINING_POOL_STATS_HASHRATE || getCurrentScreen() == SCREEN_MINING_POOL_STATS_EARNINGS))
|
||||
if (workQueue != nullptr && (ScreenHandler::getCurrentScreen() == SCREEN_MINING_POOL_STATS_HASHRATE || ScreenHandler::getCurrentScreen() == SCREEN_MINING_POOL_STATS_EARNINGS))
|
||||
{
|
||||
WorkItem priceUpdate = {TASK_MINING_POOL_STATS_UPDATE, 0};
|
||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||
|
@ -78,7 +78,7 @@ void downloadMiningPoolLogoTask(void *pvParameters) {
|
|||
PoolFactory::downloadPoolLogo(poolName, poolInterface.get());
|
||||
|
||||
// If we're on the mining pool stats screen, trigger a display update
|
||||
if (getCurrentScreen() == SCREEN_MINING_POOL_STATS_HASHRATE) {
|
||||
if (ScreenHandler::getCurrentScreen() == SCREEN_MINING_POOL_STATS_HASHRATE) {
|
||||
WorkItem priceUpdate = {TASK_MINING_POOL_STATS_UPDATE, 0};
|
||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ void handleNostrZapCallback(const String &subId, nostr::SignedNostrEvent *event)
|
|||
timerPeriod = getTimerSeconds();
|
||||
esp_timer_stop(screenRotateTimer);
|
||||
}
|
||||
setCurrentScreen(SCREEN_CUSTOM);
|
||||
ScreenHandler::setCurrentScreen(SCREEN_CUSTOM);
|
||||
|
||||
setEpdContent(textEpdContent);
|
||||
vTaskDelay(pdMS_TO_TICKS(315 * NUM_SCREENS) + pdMS_TO_TICKS(250));
|
||||
|
|
|
@ -133,9 +133,9 @@ void processNewPrice(uint newPrice, char currency)
|
|||
}
|
||||
lastUpdateMap[currency] = currentTime;
|
||||
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER ||
|
||||
getCurrentScreen() == SCREEN_SATS_PER_CURRENCY ||
|
||||
getCurrentScreen() == SCREEN_MARKET_CAP))
|
||||
if (workQueue != nullptr && (ScreenHandler::getCurrentScreen() == SCREEN_BTC_TICKER ||
|
||||
ScreenHandler::getCurrentScreen() == SCREEN_SATS_PER_CURRENCY ||
|
||||
ScreenHandler::getCurrentScreen() == SCREEN_MARKET_CAP))
|
||||
{
|
||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, currency};
|
||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||
|
|
|
@ -1,343 +1,315 @@
|
|||
#include "screen_handler.hpp"
|
||||
|
||||
// TaskHandle_t priceUpdateTaskHandle;
|
||||
// TaskHandle_t blockUpdateTaskHandle;
|
||||
// TaskHandle_t timeUpdateTaskHandle;
|
||||
TaskHandle_t taskScreenRotateTaskHandle;
|
||||
TaskHandle_t workerTaskHandle;
|
||||
|
||||
|
||||
std::array<std::string, NUM_SCREENS> taskEpdContent = {};
|
||||
std::string priceString;
|
||||
|
||||
#define WORK_QUEUE_SIZE 10
|
||||
QueueHandle_t workQueue = NULL;
|
||||
|
||||
uint currentScreen = SCREEN_BLOCK_HEIGHT;
|
||||
uint currentCurrency = CURRENCY_USD;
|
||||
// Initialize static members
|
||||
uint ScreenHandler::currentScreen = SCREEN_BLOCK_HEIGHT;
|
||||
uint ScreenHandler::currentCurrency = CURRENCY_USD;
|
||||
|
||||
void workerTask(void *pvParameters) {
|
||||
WorkItem receivedItem;
|
||||
std::array<std::string, NUM_SCREENS> taskEpdContent = {};
|
||||
|
||||
while (1) {
|
||||
// Wait for a work item to be available in the queue
|
||||
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY)) {
|
||||
// Process the work item based on its type
|
||||
switch (receivedItem.type) {
|
||||
case TASK_BITAXE_UPDATE: {
|
||||
if (getCurrentScreen() == SCREEN_BITAXE_HASHRATE) {
|
||||
taskEpdContent =
|
||||
parseBitaxeHashRate(getBitAxeHashRate());
|
||||
} else if (getCurrentScreen() == SCREEN_BITAXE_BESTDIFF) {
|
||||
taskEpdContent =
|
||||
parseBitaxeBestDiff(getBitaxeBestDiff());
|
||||
}
|
||||
setEpdContent(taskEpdContent);
|
||||
break;
|
||||
}
|
||||
case TASK_MINING_POOL_STATS_UPDATE: {
|
||||
if (getCurrentScreen() == SCREEN_MINING_POOL_STATS_HASHRATE) {
|
||||
taskEpdContent =
|
||||
parseMiningPoolStatsHashRate(getMiningPoolStatsHashRate(), *getMiningPool());
|
||||
} else if (getCurrentScreen() == SCREEN_MINING_POOL_STATS_EARNINGS) {
|
||||
taskEpdContent =
|
||||
parseMiningPoolStatsDailyEarnings(getMiningPoolStatsDailyEarnings(), getMiningPool()->getDailyEarningsLabel(), *getMiningPool());
|
||||
}
|
||||
setEpdContent(taskEpdContent);
|
||||
break;
|
||||
}
|
||||
case TASK_PRICE_UPDATE: {
|
||||
uint currency = getCurrentCurrency();
|
||||
uint price = getPrice(currency);
|
||||
|
||||
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
||||
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE),
|
||||
preferences.getBool("mowMode", DEFAULT_MOW_MODE),
|
||||
preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT)
|
||||
);
|
||||
} else if (getCurrentScreen() == SCREEN_SATS_PER_CURRENCY) {
|
||||
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
||||
} else {
|
||||
taskEpdContent =
|
||||
parseMarketCap(getBlockHeight(), price, currency,
|
||||
preferences.getBool("mcapBigChar", DEFAULT_MCAP_BIG_CHAR));
|
||||
}
|
||||
|
||||
setEpdContent(taskEpdContent);
|
||||
break;
|
||||
}
|
||||
case TASK_FEE_UPDATE: {
|
||||
if (getCurrentScreen() == SCREEN_BLOCK_FEE_RATE) {
|
||||
taskEpdContent = parseBlockFees(static_cast<std::uint16_t>(getBlockMedianFee()));
|
||||
setEpdContent(taskEpdContent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TASK_BLOCK_UPDATE: {
|
||||
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN) {
|
||||
taskEpdContent = parseBlockHeight(getBlockHeight());
|
||||
} else {
|
||||
taskEpdContent = parseHalvingCountdown(getBlockHeight(), preferences.getBool("useBlkCountdown", DEFAULT_USE_BLOCK_COUNTDOWN));
|
||||
}
|
||||
|
||||
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN ||
|
||||
getCurrentScreen() == SCREEN_BLOCK_HEIGHT) {
|
||||
setEpdContent(taskEpdContent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TASK_TIME_UPDATE: {
|
||||
if (getCurrentScreen() == SCREEN_TIME) {
|
||||
time_t currentTime;
|
||||
struct tm timeinfo;
|
||||
time(¤tTime);
|
||||
localtime_r(¤tTime, &timeinfo);
|
||||
std::string timeString;
|
||||
|
||||
String minute = String(timeinfo.tm_min);
|
||||
if (minute.length() < 2) {
|
||||
minute = "0" + minute;
|
||||
}
|
||||
|
||||
timeString =
|
||||
std::to_string(timeinfo.tm_hour) + ":" + minute.c_str();
|
||||
timeString.insert(timeString.begin(),
|
||||
NUM_SCREENS - timeString.length(), ' ');
|
||||
taskEpdContent[0] = std::to_string(timeinfo.tm_mday) + "/" +
|
||||
std::to_string(timeinfo.tm_mon + 1);
|
||||
|
||||
for (uint i = 1; i < NUM_SCREENS; i++) {
|
||||
taskEpdContent[i] = timeString[i];
|
||||
}
|
||||
setEpdContent(taskEpdContent);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// Add more cases for additional task types
|
||||
}
|
||||
// Convert existing functions to static member functions
|
||||
void ScreenHandler::setCurrentScreen(uint newScreen) {
|
||||
if (newScreen != SCREEN_CUSTOM) {
|
||||
preferences.putUInt("currentScreen", newScreen);
|
||||
}
|
||||
currentScreen = newScreen;
|
||||
|
||||
switch (currentScreen) {
|
||||
case SCREEN_TIME: {
|
||||
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case SCREEN_HALVING_COUNTDOWN:
|
||||
case SCREEN_BLOCK_HEIGHT: {
|
||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case SCREEN_MARKET_CAP:
|
||||
case SCREEN_SATS_PER_CURRENCY:
|
||||
case SCREEN_BTC_TICKER: {
|
||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case SCREEN_BLOCK_FEE_RATE: {
|
||||
WorkItem blockUpdate = {TASK_FEE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case SCREEN_BITAXE_BESTDIFF:
|
||||
case SCREEN_BITAXE_HASHRATE: {
|
||||
if (preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED)) {
|
||||
WorkItem bitaxeUpdate = {TASK_BITAXE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &bitaxeUpdate, portMAX_DELAY);
|
||||
} else {
|
||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCREEN_MINING_POOL_STATS_HASHRATE:
|
||||
case SCREEN_MINING_POOL_STATS_EARNINGS: {
|
||||
if (preferences.getBool("miningPoolStats", DEFAULT_MINING_POOL_STATS_ENABLED)) {
|
||||
WorkItem miningPoolStatsUpdate = {TASK_MINING_POOL_STATS_UPDATE, 0};
|
||||
xQueueSend(workQueue, &miningPoolStatsUpdate, portMAX_DELAY);
|
||||
} else {
|
||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventSourceTaskHandle != NULL) xTaskNotifyGive(eventSourceTaskHandle);
|
||||
}
|
||||
|
||||
void ScreenHandler::setCurrentCurrency(char currency) {
|
||||
currentCurrency = currency;
|
||||
preferences.putUChar("lastCurrency", currency);
|
||||
}
|
||||
|
||||
bool ScreenHandler::isCurrencySpecific(uint screen) {
|
||||
switch (screen) {
|
||||
case SCREEN_BTC_TICKER:
|
||||
case SCREEN_SATS_PER_CURRENCY:
|
||||
case SCREEN_MARKET_CAP:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenHandler::handleCurrencyRotation(bool forward) {
|
||||
if (preferences.getBool("ownDataSource", DEFAULT_OWN_DATA_SOURCE) && isCurrencySpecific(getCurrentScreen())) {
|
||||
std::vector<std::string> ac = getActiveCurrencies();
|
||||
if (ac.empty()) return false;
|
||||
|
||||
std::string curCode = getCurrencyCode(getCurrentCurrency());
|
||||
auto it = std::find(ac.begin(), ac.end(), curCode);
|
||||
|
||||
if (it == ac.end()) {
|
||||
// Current currency not found in active currencies - initialize based on direction
|
||||
setCurrentCurrency(getCurrencyChar(forward ? ac.front() : ac.back()));
|
||||
setCurrentScreen(getCurrentScreen());
|
||||
return true;
|
||||
} else if (forward && curCode != ac.back()) {
|
||||
// Moving forward and not at last currency
|
||||
setCurrentCurrency(getCurrencyChar(ac.at(std::distance(ac.begin(), it) + 1)));
|
||||
setCurrentScreen(getCurrentScreen());
|
||||
return true;
|
||||
} else if (!forward && curCode != ac.front()) {
|
||||
// Moving backward and not at first currency
|
||||
setCurrentCurrency(getCurrencyChar(ac.at(std::distance(ac.begin(), it) - 1)));
|
||||
setCurrentScreen(getCurrentScreen());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ScreenHandler::findNextVisibleScreen(int currentScreen, bool forward) {
|
||||
std::vector<ScreenMapping> screenMappings = getScreenNameMap();
|
||||
int newScreen;
|
||||
|
||||
if (forward) {
|
||||
newScreen = (currentScreen < screenMappings.size() - 1) ?
|
||||
screenMappings[currentScreen + 1].value : screenMappings.front().value;
|
||||
} else {
|
||||
newScreen = (currentScreen > 0) ?
|
||||
screenMappings[currentScreen - 1].value : screenMappings.back().value;
|
||||
}
|
||||
|
||||
String key = "screen" + String(newScreen) + "Visible";
|
||||
while (!preferences.getBool(key.c_str(), true)) {
|
||||
currentScreen = findScreenIndexByValue(newScreen);
|
||||
if (forward) {
|
||||
newScreen = (currentScreen < screenMappings.size() - 1) ?
|
||||
screenMappings[currentScreen + 1].value : screenMappings.front().value;
|
||||
} else {
|
||||
newScreen = (currentScreen > 0) ?
|
||||
screenMappings[currentScreen - 1].value : screenMappings.back().value;
|
||||
}
|
||||
key = "screen" + String(newScreen) + "Visible";
|
||||
}
|
||||
|
||||
return newScreen;
|
||||
}
|
||||
|
||||
void ScreenHandler::nextScreen() {
|
||||
if (handleCurrencyRotation(true)) return;
|
||||
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
||||
setCurrentScreen(findNextVisibleScreen(currentIndex, true));
|
||||
}
|
||||
|
||||
void ScreenHandler::previousScreen() {
|
||||
if (handleCurrencyRotation(false)) return;
|
||||
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
||||
setCurrentScreen(findNextVisibleScreen(currentIndex, false));
|
||||
}
|
||||
|
||||
void ScreenHandler::showSystemStatusScreen() {
|
||||
std::array<String, NUM_SCREENS> sysStatusEpdContent;
|
||||
std::fill(sysStatusEpdContent.begin(), sysStatusEpdContent.end(), "");
|
||||
|
||||
String ipAddr = WiFi.localIP().toString();
|
||||
String subNet = WiFi.subnetMask().toString();
|
||||
|
||||
sysStatusEpdContent[0] = "IP/Subnet";
|
||||
|
||||
int ipAddrPos = 0;
|
||||
int subnetPos = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sysStatusEpdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) +
|
||||
"/" + subNet.substring(0, subNet.indexOf('.'));
|
||||
ipAddrPos = ipAddr.indexOf('.') + 1;
|
||||
subnetPos = subNet.indexOf('.') + 1;
|
||||
ipAddr = ipAddr.substring(ipAddrPos);
|
||||
subNet = subNet.substring(subnetPos);
|
||||
}
|
||||
sysStatusEpdContent[NUM_SCREENS - 2] = "RAM/Status";
|
||||
|
||||
sysStatusEpdContent[NUM_SCREENS - 1] =
|
||||
String((int)round(ESP.getFreeHeap() / 1024)) + "/" +
|
||||
(int)round(ESP.getHeapSize() / 1024);
|
||||
setCurrentScreen(SCREEN_CUSTOM);
|
||||
setEpdContent(sysStatusEpdContent);
|
||||
}
|
||||
|
||||
// Keep these as free functions
|
||||
void workerTask(void *pvParameters) {
|
||||
WorkItem receivedItem;
|
||||
|
||||
while (1) {
|
||||
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY)) {
|
||||
uint currentScreenValue = ScreenHandler::getCurrentScreen();
|
||||
|
||||
switch (receivedItem.type) {
|
||||
case TASK_BITAXE_UPDATE: {
|
||||
if (currentScreenValue != SCREEN_BITAXE_HASHRATE &&
|
||||
currentScreenValue != SCREEN_BITAXE_BESTDIFF) break;
|
||||
|
||||
taskEpdContent = (currentScreenValue == SCREEN_BITAXE_HASHRATE) ?
|
||||
parseBitaxeHashRate(getBitAxeHashRate()) :
|
||||
parseBitaxeBestDiff(getBitaxeBestDiff());
|
||||
setEpdContent(taskEpdContent);
|
||||
break;
|
||||
}
|
||||
|
||||
case TASK_MINING_POOL_STATS_UPDATE: {
|
||||
if (currentScreenValue != SCREEN_MINING_POOL_STATS_HASHRATE &&
|
||||
currentScreenValue != SCREEN_MINING_POOL_STATS_EARNINGS) break;
|
||||
|
||||
taskEpdContent = (currentScreenValue == SCREEN_MINING_POOL_STATS_HASHRATE) ?
|
||||
parseMiningPoolStatsHashRate(getMiningPoolStatsHashRate(), *getMiningPool()) :
|
||||
parseMiningPoolStatsDailyEarnings(getMiningPoolStatsDailyEarnings(),
|
||||
getMiningPool()->getDailyEarningsLabel(), *getMiningPool());
|
||||
setEpdContent(taskEpdContent);
|
||||
break;
|
||||
}
|
||||
|
||||
case TASK_PRICE_UPDATE: {
|
||||
uint currency = ScreenHandler::getCurrentCurrency();
|
||||
uint price = getPrice(currency);
|
||||
|
||||
if (currentScreenValue == SCREEN_BTC_TICKER) {
|
||||
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE),
|
||||
preferences.getBool("mowMode", DEFAULT_MOW_MODE),
|
||||
preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT)
|
||||
);
|
||||
} else if (currentScreenValue == SCREEN_SATS_PER_CURRENCY) {
|
||||
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
||||
} else {
|
||||
taskEpdContent =
|
||||
parseMarketCap(getBlockHeight(), price, currency,
|
||||
preferences.getBool("mcapBigChar", DEFAULT_MCAP_BIG_CHAR));
|
||||
}
|
||||
|
||||
setEpdContent(taskEpdContent);
|
||||
break;
|
||||
}
|
||||
case TASK_FEE_UPDATE: {
|
||||
if (currentScreenValue == SCREEN_BLOCK_FEE_RATE) {
|
||||
taskEpdContent = parseBlockFees(static_cast<std::uint16_t>(getBlockMedianFee()));
|
||||
setEpdContent(taskEpdContent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TASK_BLOCK_UPDATE: {
|
||||
if (currentScreenValue != SCREEN_HALVING_COUNTDOWN) {
|
||||
taskEpdContent = parseBlockHeight(getBlockHeight());
|
||||
} else {
|
||||
taskEpdContent = parseHalvingCountdown(getBlockHeight(), preferences.getBool("useBlkCountdown", DEFAULT_USE_BLOCK_COUNTDOWN));
|
||||
}
|
||||
|
||||
if (currentScreenValue == SCREEN_HALVING_COUNTDOWN ||
|
||||
currentScreenValue == SCREEN_BLOCK_HEIGHT) {
|
||||
setEpdContent(taskEpdContent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TASK_TIME_UPDATE: {
|
||||
if (currentScreenValue == SCREEN_TIME) {
|
||||
time_t currentTime;
|
||||
struct tm timeinfo;
|
||||
time(¤tTime);
|
||||
localtime_r(¤tTime, &timeinfo);
|
||||
std::string timeString;
|
||||
|
||||
String minute = String(timeinfo.tm_min);
|
||||
if (minute.length() < 2) {
|
||||
minute = "0" + minute;
|
||||
}
|
||||
|
||||
timeString =
|
||||
std::to_string(timeinfo.tm_hour) + ":" + minute.c_str();
|
||||
timeString.insert(timeString.begin(),
|
||||
NUM_SCREENS - timeString.length(), ' ');
|
||||
taskEpdContent[0] = std::to_string(timeinfo.tm_mday) + "/" +
|
||||
std::to_string(timeinfo.tm_mon + 1);
|
||||
|
||||
for (uint i = 1; i < NUM_SCREENS; i++) {
|
||||
taskEpdContent[i] = timeString[i];
|
||||
}
|
||||
setEpdContent(taskEpdContent);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// Add more cases for additional task types
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void taskScreenRotate(void *pvParameters) {
|
||||
for (;;) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
nextScreen();
|
||||
}
|
||||
for (;;) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
ScreenHandler::nextScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void setupTasks() {
|
||||
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
||||
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
||||
|
||||
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY,
|
||||
&workerTaskHandle);
|
||||
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY,
|
||||
&workerTaskHandle);
|
||||
|
||||
xTaskCreate(taskScreenRotate, "rotateScreen", 4096, NULL, tskIDLE_PRIORITY,
|
||||
&taskScreenRotateTaskHandle);
|
||||
xTaskCreate(taskScreenRotate, "rotateScreen", 4096, NULL, tskIDLE_PRIORITY,
|
||||
&taskScreenRotateTaskHandle);
|
||||
|
||||
waitUntilNoneBusy();
|
||||
waitUntilNoneBusy();
|
||||
|
||||
if (findScreenIndexByValue(preferences.getUInt("currentScreen", DEFAULT_CURRENT_SCREEN)) != -1)
|
||||
setCurrentScreen(preferences.getUInt("currentScreen", DEFAULT_CURRENT_SCREEN));
|
||||
if (findScreenIndexByValue(preferences.getUInt("currentScreen", DEFAULT_CURRENT_SCREEN)) != -1)
|
||||
ScreenHandler::setCurrentScreen(preferences.getUInt("currentScreen", DEFAULT_CURRENT_SCREEN));
|
||||
}
|
||||
|
||||
uint getCurrentScreen() { return currentScreen; }
|
||||
|
||||
void setCurrentScreen(uint newScreen) {
|
||||
if (newScreen != SCREEN_CUSTOM) {
|
||||
preferences.putUInt("currentScreen", newScreen);
|
||||
}
|
||||
|
||||
currentScreen = newScreen;
|
||||
|
||||
switch (currentScreen) {
|
||||
case SCREEN_TIME: {
|
||||
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
||||
// xTaskNotifyGive(timeUpdateTaskHandle);
|
||||
break;
|
||||
}
|
||||
case SCREEN_HALVING_COUNTDOWN:
|
||||
case SCREEN_BLOCK_HEIGHT: {
|
||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||
break;
|
||||
}
|
||||
case SCREEN_MARKET_CAP:
|
||||
case SCREEN_SATS_PER_CURRENCY:
|
||||
case SCREEN_BTC_TICKER: {
|
||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||
// xTaskNotifyGive(priceUpdateTaskHandle);
|
||||
break;
|
||||
}
|
||||
case SCREEN_BLOCK_FEE_RATE: {
|
||||
WorkItem blockUpdate = {TASK_FEE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case SCREEN_BITAXE_BESTDIFF:
|
||||
case SCREEN_BITAXE_HASHRATE: {
|
||||
if (preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED)) {
|
||||
WorkItem bitaxeUpdate = {TASK_BITAXE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &bitaxeUpdate, portMAX_DELAY);
|
||||
} else {
|
||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCREEN_MINING_POOL_STATS_HASHRATE:
|
||||
case SCREEN_MINING_POOL_STATS_EARNINGS: {
|
||||
if (preferences.getBool("miningPoolStats", DEFAULT_MINING_POOL_STATS_ENABLED)) {
|
||||
WorkItem miningPoolStatsUpdate = {TASK_MINING_POOL_STATS_UPDATE, 0};
|
||||
xQueueSend(workQueue, &miningPoolStatsUpdate, portMAX_DELAY);
|
||||
} else {
|
||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventSourceTaskHandle != NULL) xTaskNotifyGive(eventSourceTaskHandle);
|
||||
}
|
||||
|
||||
bool isCurrencySpecific(uint screen) {
|
||||
switch (screen) {
|
||||
case SCREEN_BTC_TICKER:
|
||||
case SCREEN_SATS_PER_CURRENCY:
|
||||
case SCREEN_MARKET_CAP:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void nextScreen() {
|
||||
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
||||
std::vector<ScreenMapping> screenMappings = getScreenNameMap();
|
||||
|
||||
if (preferences.getBool("ownDataSource", DEFAULT_OWN_DATA_SOURCE) && isCurrencySpecific(getCurrentScreen())) {
|
||||
std::vector<std::string> ac = getActiveCurrencies();
|
||||
std::string curCode = getCurrencyCode(getCurrentCurrency());
|
||||
if (getCurrencyCode(getCurrentCurrency()) != ac.back()) {
|
||||
auto it = std::find(ac.begin(), ac.end(), curCode);
|
||||
if (it != ac.end()) {
|
||||
size_t index = std::distance(ac.begin(), it);
|
||||
setCurrentCurrency(getCurrencyChar(ac.at(index+1)));
|
||||
setCurrentScreen(getCurrentScreen());
|
||||
return;
|
||||
}
|
||||
}
|
||||
setCurrentCurrency(getCurrencyChar(ac.front()));
|
||||
}
|
||||
|
||||
int newCurrentScreen;
|
||||
|
||||
if (currentIndex < screenMappings.size() - 1) {
|
||||
newCurrentScreen = (screenMappings[currentIndex + 1].value);
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.front().value;
|
||||
}
|
||||
|
||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
|
||||
while (!preferences.getBool(key.c_str(), true)) {
|
||||
currentIndex = findScreenIndexByValue(newCurrentScreen);
|
||||
if (currentIndex < screenMappings.size() - 1) {
|
||||
newCurrentScreen = (screenMappings[currentIndex + 1].value);
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.front().value;
|
||||
}
|
||||
|
||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
}
|
||||
|
||||
setCurrentScreen(newCurrentScreen);
|
||||
}
|
||||
|
||||
void previousScreen() {
|
||||
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
||||
std::vector<ScreenMapping> screenMappings = getScreenNameMap();
|
||||
|
||||
if (preferences.getBool("ownDataSource", DEFAULT_OWN_DATA_SOURCE) && isCurrencySpecific(getCurrentScreen())) {
|
||||
std::vector<std::string> ac = getActiveCurrencies();
|
||||
std::string curCode = getCurrencyCode(getCurrentCurrency());
|
||||
if (getCurrencyCode(getCurrentCurrency()) != ac.front()) {
|
||||
auto it = std::find(ac.begin(), ac.end(), curCode);
|
||||
if (it != ac.end()) {
|
||||
size_t index = std::distance(ac.begin(), it);
|
||||
setCurrentCurrency(getCurrencyChar(ac.at(index-1)));
|
||||
setCurrentScreen(getCurrentScreen());
|
||||
return;
|
||||
}
|
||||
}
|
||||
setCurrentCurrency(getCurrencyChar(ac.back()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
int newCurrentScreen;
|
||||
|
||||
if (currentIndex > 0) {
|
||||
newCurrentScreen = screenMappings[currentIndex - 1].value;
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.back().value;
|
||||
}
|
||||
|
||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
|
||||
while (!preferences.getBool(key.c_str(), true)) {
|
||||
int currentIndex = findScreenIndexByValue(newCurrentScreen);
|
||||
if (currentIndex > 0) {
|
||||
newCurrentScreen = screenMappings[currentIndex - 1].value;
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.back().value;
|
||||
}
|
||||
|
||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
}
|
||||
setCurrentScreen(newCurrentScreen);
|
||||
}
|
||||
|
||||
void showSystemStatusScreen() {
|
||||
std::array<String, NUM_SCREENS> sysStatusEpdContent;
|
||||
std::fill(sysStatusEpdContent.begin(), sysStatusEpdContent.end(), "");
|
||||
|
||||
|
||||
String ipAddr = WiFi.localIP().toString();
|
||||
String subNet = WiFi.subnetMask().toString();
|
||||
|
||||
sysStatusEpdContent[0] = "IP/Subnet";
|
||||
|
||||
int ipAddrPos = 0;
|
||||
int subnetPos = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sysStatusEpdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) +
|
||||
"/" + subNet.substring(0, subNet.indexOf('.'));
|
||||
ipAddrPos = ipAddr.indexOf('.') + 1;
|
||||
subnetPos = subNet.indexOf('.') + 1;
|
||||
ipAddr = ipAddr.substring(ipAddrPos);
|
||||
subNet = subNet.substring(subnetPos);
|
||||
}
|
||||
sysStatusEpdContent[NUM_SCREENS - 2] = "RAM/Status";
|
||||
|
||||
sysStatusEpdContent[NUM_SCREENS - 1] =
|
||||
String((int)round(ESP.getFreeHeap() / 1024)) + "/" +
|
||||
(int)round(ESP.getHeapSize() / 1024);
|
||||
setCurrentScreen(SCREEN_CUSTOM);
|
||||
setEpdContent(sysStatusEpdContent);
|
||||
}
|
||||
|
||||
void setCurrentCurrency(char currency) {
|
||||
currentCurrency = currency;
|
||||
preferences.putUChar("lastCurrency", currency);
|
||||
}
|
||||
|
||||
uint getCurrentCurrency() {
|
||||
return currentCurrency;
|
||||
void cleanup() {
|
||||
vQueueDelete(workQueue);
|
||||
// Add any other cleanup needed
|
||||
}
|
|
@ -11,12 +11,10 @@
|
|||
#include "lib/epd.hpp"
|
||||
#include "lib/shared.hpp"
|
||||
|
||||
// extern TaskHandle_t priceUpdateTaskHandle;
|
||||
// extern TaskHandle_t blockUpdateTaskHandle;
|
||||
// extern TaskHandle_t timeUpdateTaskHandle;
|
||||
#define WORK_QUEUE_SIZE 10
|
||||
|
||||
extern TaskHandle_t workerTaskHandle;
|
||||
extern TaskHandle_t taskScreenRotateTaskHandle;
|
||||
|
||||
extern QueueHandle_t workQueue;
|
||||
|
||||
typedef enum {
|
||||
|
@ -33,24 +31,26 @@ typedef struct {
|
|||
char data;
|
||||
} WorkItem;
|
||||
|
||||
class ScreenHandler {
|
||||
private:
|
||||
static uint currentScreen;
|
||||
static uint currentCurrency;
|
||||
|
||||
public:
|
||||
static uint getCurrentScreen() { return currentScreen; }
|
||||
static uint getCurrentCurrency() { return currentCurrency; }
|
||||
static void setCurrentScreen(uint newScreen);
|
||||
static void setCurrentCurrency(char currency);
|
||||
static void nextScreen();
|
||||
static void previousScreen();
|
||||
static void showSystemStatusScreen();
|
||||
static bool isCurrencySpecific(uint screen);
|
||||
static bool handleCurrencyRotation(bool forward);
|
||||
static int findNextVisibleScreen(int currentScreen, bool forward);
|
||||
};
|
||||
|
||||
// Keep as free functions since they deal with FreeRTOS tasks
|
||||
void workerTask(void *pvParameters);
|
||||
uint getCurrentScreen();
|
||||
void setCurrentScreen(uint newScreen);
|
||||
void nextScreen();
|
||||
void previousScreen();
|
||||
|
||||
void showSystemStatusScreen();
|
||||
|
||||
|
||||
|
||||
// void taskPriceUpdate(void *pvParameters);
|
||||
// void taskBlockUpdate(void *pvParameters);
|
||||
// void taskTimeUpdate(void *pvParameters);
|
||||
void taskScreenRotate(void *pvParameters);
|
||||
|
||||
|
||||
|
||||
void setupTasks();
|
||||
void setCurrentCurrency(char currency);
|
||||
|
||||
uint getCurrentCurrency();
|
||||
void cleanup();
|
|
@ -228,7 +228,7 @@ JsonDocument getStatusObject()
|
|||
{
|
||||
JsonDocument root;
|
||||
|
||||
root["currentScreen"] = getCurrentScreen();
|
||||
root["currentScreen"] = ScreenHandler::getCurrentScreen();
|
||||
root["numScreens"] = NUM_SCREENS;
|
||||
root["timerRunning"] = isTimerActive();
|
||||
root["espUptime"] = esp_timer_get_time() / 1000000;
|
||||
|
@ -248,7 +248,7 @@ JsonDocument getStatusObject()
|
|||
conStatus["nostr"] = nostrConnected();
|
||||
|
||||
root["rssi"] = WiFi.RSSI();
|
||||
root["currency"] = getCurrencyCode(getCurrentCurrency());
|
||||
root["currency"] = getCurrencyCode(ScreenHandler::getCurrentCurrency());
|
||||
#ifdef HAS_FRONTLIGHT
|
||||
std::vector<uint16_t> statuses = frontlightGetStatus();
|
||||
uint16_t arr[NUM_SCREENS];
|
||||
|
@ -386,7 +386,7 @@ void onApiShowScreen(AsyncWebServerRequest *request)
|
|||
{
|
||||
const AsyncWebParameter *p = request->getParam("s");
|
||||
uint currentScreen = p->value().toInt();
|
||||
setCurrentScreen(currentScreen);
|
||||
ScreenHandler::setCurrentScreen(currentScreen);
|
||||
}
|
||||
request->send(HTTP_OK);
|
||||
}
|
||||
|
@ -398,9 +398,9 @@ void onApiShowScreen(AsyncWebServerRequest *request)
|
|||
void onApiScreenControl(AsyncWebServerRequest *request) {
|
||||
const String& action = request->url();
|
||||
if (action.endsWith("/next")) {
|
||||
nextScreen();
|
||||
ScreenHandler::nextScreen();
|
||||
} else if (action.endsWith("/previous")) {
|
||||
previousScreen();
|
||||
ScreenHandler::previousScreen();
|
||||
}
|
||||
request->send(HTTP_OK);
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ void onApiShowText(AsyncWebServerRequest *request)
|
|||
|
||||
setEpdContent(textEpdContent);
|
||||
}
|
||||
setCurrentScreen(SCREEN_CUSTOM);
|
||||
ScreenHandler::setCurrentScreen(SCREEN_CUSTOM);
|
||||
request->send(HTTP_OK);
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ void onApiShowTextAdvanced(AsyncWebServerRequest *request, JsonVariant &json)
|
|||
|
||||
setEpdContent(epdContent);
|
||||
|
||||
setCurrentScreen(SCREEN_CUSTOM);
|
||||
ScreenHandler::setCurrentScreen(SCREEN_CUSTOM);
|
||||
request->send(HTTP_OK);
|
||||
}
|
||||
|
||||
|
@ -998,8 +998,8 @@ void onApiShowCurrency(AsyncWebServerRequest *request)
|
|||
|
||||
char curChar = getCurrencyChar(currency);
|
||||
|
||||
setCurrentCurrency(curChar);
|
||||
setCurrentScreen(getCurrentScreen());
|
||||
ScreenHandler::setCurrentCurrency(curChar);
|
||||
ScreenHandler::setCurrentScreen(ScreenHandler::getCurrentScreen());
|
||||
|
||||
request->send(HTTP_OK);
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue