Compare commits

..

2 commits

Author SHA1 Message Date
Djuri Baars
4fdd6b6b4f Fix button handling 2024-12-21 17:36:07 +01:00
Djuri Baars
8a818c66a0 Update readme
All checks were successful
BTClock CI / build (push) Successful in 10m20s
BTClock CI / merge (map[name:btclock_rev_b version:esp32s3], 213epd) (push) Successful in 20s
BTClock CI / merge (map[name:btclock_v8 version:esp32s3], 213epd) (push) Successful in 27s
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 29epd) (push) Successful in 25s
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 213epd) (push) Successful in 19s
BTClock CI / release (push) Successful in 35s
2024-12-21 01:15:59 +01:00
4 changed files with 73 additions and 50 deletions

View file

@ -16,21 +16,21 @@ Biggest differences with v2 are:
New features: New features:
- BitAxe integration - BitAxe integration
- Zap notifier - Nostr Zap notifier
- Braiins Pool and Ocean mining stats integration - Multiple mining pool stats integrations
"Steal focus on new block" means that when a new block is mined, the display will switch to the block height screen if it's not on it already. "Steal focus on new block" means that when a new block is mined, the display will switch to the block height screen if it's not on it already.
Most [information](https://github.com/btclock/btclock_v2/wiki) about BTClock v2 is still valid for this version. See the [docs](https://git.btclock.dev/btclock/docs) repo for more information and building instructions.
**NOTE**: The software assumes that the hardware is run in a controlled private network. ~~The Web UI and the OTA update mechanism are not password protected and accessible to anyone in the network. Also, since the device only fetches numbers through WebSockets it will skip server certificate verification to save resources.~~ Since 3.2.0 the WebUI is password protectable and all certificates are verified. OTA update mechanism is not password-protected. **NOTE**: The software assumes that the hardware is run in a controlled private network. ~~The Web UI and the OTA update mechanism are not password protected and accessible to anyone in the network. Also, since the device only fetches numbers through WebSockets it will skip server certificate verification to save resources.~~ Since 3.2.0 the WebUI is password protectable and all certificates are verified. OTA update mechanism is not password-protected.
## Building ## Building
Use PlatformIO to build it yourself. Make sure you fetch the [WebUI](https://github.com/btclock/webui) submodule. Use PlatformIO to build it yourself. Make sure you fetch the [WebUI](https://git.btclock.dev/btclock/webui) submodule.
## Braiins Pool and Ocean integration ## Mining pool stats
Enable mining pool stats by accessing your btclock's web UI (point a web browser at the device's IP address). Enable mining pool stats by accessing your btclock's web UI (point a web browser at the device's IP address).
Under Settings -> Extra Features: toggle Enable Mining Pool Stats. Under Settings -> Extra Features: toggle Enable Mining Pool Stats.
@ -41,6 +41,8 @@ The Mining Pool Earnings screen displays:
* Braiins: Today's mining reward thus far * Braiins: Today's mining reward thus far
* Ocean: Your estimated earnings if the pool were to find a block right now * Ocean: Your estimated earnings if the pool were to find a block right now
For solo mining pools, there are no earning estimations. Your username is the onchain withdrawal address, without the worker name.
### Braiins Pool integration ### Braiins Pool integration
Create an API key based on the steps [here](https://academy.braiins.com/en/braiins-pool/monitoring/#api-configuration). Create an API key based on the steps [here](https://academy.braiins.com/en/braiins-pool/monitoring/#api-configuration).

View file

@ -19,41 +19,52 @@ TickType_t lastDebounceTime = 0;
void buttonTask(void *parameter) { void buttonTask(void *parameter) {
while (1) { while (1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
std::lock_guard<std::mutex> lock(mcpMutex);
TickType_t currentTime = xTaskGetTickCount(); TickType_t currentTime = xTaskGetTickCount();
if ((currentTime - lastDebounceTime) >= debounceDelay) { if ((currentTime - lastDebounceTime) >= debounceDelay) {
lastDebounceTime = currentTime; lastDebounceTime = currentTime;
std::lock_guard<std::mutex> lock(mcpMutex);
if (!digitalRead(MCP_INT_PIN)) { if (!digitalRead(MCP_INT_PIN)) {
uint pin = mcp1.getInterruptFlagRegister(); uint16_t intFlags = mcp1.getInterruptFlagRegister();
uint16_t intCap = mcp1.getInterruptCaptureRegister();
switch (pin) {
case BTN_1: // Check each button individually
toggleTimerActive(); if (intFlags & BTN_1) handleButton1();
break; if (intFlags & BTN_2) handleButton2();
case BTN_2: if (intFlags & BTN_3) handleButton3();
nextScreen(); if (intFlags & BTN_4) handleButton4();
break;
case BTN_3:
previousScreen();
break;
case BTN_4:
showSystemStatusScreen();
break;
}
} }
mcp1.getInterruptCaptureRegister();
} else {
} }
// Very ugly, but for some reason this is necessary
// Clear interrupt state
while (!digitalRead(MCP_INT_PIN)) { while (!digitalRead(MCP_INT_PIN)) {
std::lock_guard<std::mutex> lock(mcpMutex);
mcp1.getInterruptCaptureRegister(); mcp1.getInterruptCaptureRegister();
delay(1); // Small delay to prevent tight loop
} }
} }
} }
// Helper functions to handle each button
void handleButton1() {
toggleTimerActive();
}
void handleButton2() {
nextScreen();
}
void handleButton3() {
previousScreen();
}
void handleButton4() {
showSystemStatusScreen();
}
void IRAM_ATTR handleButtonInterrupt() { void IRAM_ATTR handleButtonInterrupt() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken); xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
@ -67,4 +78,5 @@ void setupButtonTask() {
&buttonTaskHandle); // Create the FreeRTOS task &buttonTaskHandle); // Create the FreeRTOS task
// Use interrupt instead of task // Use interrupt instead of task
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE); attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
Serial.printf("Button task created\n");
} }

View file

@ -8,6 +8,13 @@
extern TaskHandle_t buttonTaskHandle; extern TaskHandle_t buttonTaskHandle;
// Task and setup functions
void buttonTask(void *pvParameters); void buttonTask(void *pvParameters);
void IRAM_ATTR handleButtonInterrupt(); void IRAM_ATTR handleButtonInterrupt();
void setupButtonTask(); void setupButtonTask();
// Individual button handlers
void handleButton1();
void handleButton2();
void handleButton3();
void handleButton4();

View file

@ -466,32 +466,34 @@ void setupHardware()
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000); Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
if (!mcp1.begin()) if (!mcp1.begin()) {
{
Serial.println(F("Error MCP23017 1")); Serial.println(F("Error MCP23017 1"));
} else {
// while (1)
// ;
}
else
{
pinMode(MCP_INT_PIN, INPUT_PULLUP); pinMode(MCP_INT_PIN, INPUT_PULLUP);
// mcp1.setupInterrupts(false, false, LOW);
mcp1.enableControlRegister(MCP23x17_IOCR_ODR); // Enable mirrored interrupts (both INTA and INTB pins signal any interrupt)
if (!mcp1.mirrorInterrupts(true)) {
mcp1.mirrorInterrupts(true); Serial.println(F("Error setting up mirrored interrupts"));
for (int i = 0; i < 4; i++)
{
mcp1.pinMode1(i, INPUT_PULLUP);
mcp1.enableInterrupt(i, LOW);
} }
#ifndef IS_BTCLOCK_V8
for (int i = 8; i <= 14; i++) // Configure all 4 button pins as inputs with pullups and interrupts
{ for (int i = 0; i < 4; i++) {
mcp1.pinMode1(i, OUTPUT); if (!mcp1.pinMode1(i, INPUT_PULLUP)) {
Serial.printf("Error setting pin %d to input pull up\n", i);
}
// Enable interrupt on CHANGE for each pin
if (!mcp1.enableInterrupt(i, CHANGE)) {
Serial.printf("Error enabling interrupt for pin %d\n", i);
}
} }
#endif
// Set interrupt pins as open drain with active-low polarity
if (!mcp1.setInterruptPolarity(2)) { // 2 = Open drain
Serial.println(F("Error setting interrupt polarity"));
}
// Clear any pending interrupts
mcp1.getInterruptCaptureRegister();
} }
#ifdef IS_HW_REV_B #ifdef IS_HW_REV_B