Improved QR-code setup, added MCAP screen
This commit is contained in:
parent
f611d2f5f8
commit
705f27fda9
25 changed files with 1197 additions and 88 deletions
|
@ -2,10 +2,12 @@
|
|||
|
||||
char *wsServer;
|
||||
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
||||
unsigned long int currentBlockHeight;
|
||||
unsigned long int currentBlockHeight = 816000;
|
||||
|
||||
void setupBlockNotify()
|
||||
{
|
||||
currentBlockHeight = preferences.getULong("blockHeight", 816000);
|
||||
|
||||
IPAddress result;
|
||||
|
||||
int dnsErr = -1;
|
||||
|
@ -87,7 +89,8 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
|||
|
||||
currentBlockHeight = block["height"].as<long>();
|
||||
|
||||
Serial.printf("New block found: %d\r\n", block["height"].as<long>());
|
||||
Serial.printf("New block found: %d\r\n", block["height"].as<long>());
|
||||
preferences.putULong("blockHeight", currentBlockHeight);
|
||||
|
||||
if (blockUpdateTaskHandle != nullptr) {
|
||||
xTaskNotifyGive(blockUpdateTaskHandle);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "shared.hpp"
|
||||
#include "screen_handler.hpp"
|
||||
|
||||
|
|
|
@ -10,15 +10,19 @@ void setup()
|
|||
{
|
||||
setupPreferences();
|
||||
setupHardware();
|
||||
setupDisplays();
|
||||
if (preferences.getBool("ledTestOnPower", true))
|
||||
{
|
||||
queueLedEffect(LED_POWER_TEST);
|
||||
}
|
||||
if (mcp.digitalRead(3) == LOW)
|
||||
{
|
||||
preferences.putBool("wifiConfigured", false);
|
||||
|
||||
WiFi.eraseAP();
|
||||
blinkDelay(100, 3);
|
||||
queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
|
||||
}
|
||||
|
||||
setupDisplays();
|
||||
tryImprovSetup();
|
||||
|
||||
setupWebserver();
|
||||
|
@ -33,19 +37,23 @@ void setup()
|
|||
xTaskCreate(setupWebsocketClients, "setupWebsocketClients", 4096, NULL, tskIDLE_PRIORITY, NULL);
|
||||
|
||||
setupButtonTask();
|
||||
Serial.printf("Number of free Preferences entries %d", preferences.freeEntries());
|
||||
|
||||
}
|
||||
|
||||
void tryImprovSetup()
|
||||
{
|
||||
if (!preferences.getBool("wifiConfigured", false))
|
||||
{
|
||||
setFgColor(GxEPD_BLACK);
|
||||
setBgColor(GxEPD_WHITE);
|
||||
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
|
||||
|
||||
uint8_t x_buffer[16];
|
||||
uint8_t x_position = 0;
|
||||
|
||||
// Hold second button to start QR code wifi config
|
||||
if (!mcp.digitalRead(2) == LOW)
|
||||
if (mcp.digitalRead(2) == LOW)
|
||||
{
|
||||
WiFiManager wm;
|
||||
|
||||
|
@ -65,25 +73,32 @@ void tryImprovSetup()
|
|||
wifiManager->getConfigPortalSSID().c_str(),
|
||||
softAP_password.c_str());
|
||||
// vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
delay(1000);
|
||||
delay(6000);
|
||||
|
||||
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() + ";T:WPA;P:" + softAP_password.c_str() + ";;";
|
||||
const String explainText = "*SSID: *\r\n" + wifiManager->getConfigPortalSSID() + "\r\n\r\n*Password:*\r\n" + softAP_password;
|
||||
std::array<String, NUM_SCREENS> epdContent = {"Welcome!", "", "To setup\r\nscan QR or\r\nconnect\r\nmanually", "", explainText, "", qrText};
|
||||
setEpdContent(epdContent);
|
||||
delay(3000);
|
||||
Serial.println("xTask");
|
||||
xTaskNotifyGive(epdTaskHandle); });
|
||||
|
||||
});
|
||||
|
||||
wm.setSaveConfigCallback([]() {
|
||||
wm.setSaveConfigCallback([]()
|
||||
{
|
||||
preferences.putBool("wifiConfigured", true);
|
||||
});
|
||||
|
||||
delay(1000);
|
||||
// just restart after succes
|
||||
ESP.restart(); });
|
||||
|
||||
bool ac = wm.autoConnect(softAP_SSID.c_str(), softAP_password.c_str());
|
||||
wm.server->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
waitUntilNoneBusy();
|
||||
std::array<String, NUM_SCREENS> epdContent = {"Welcome!", "", "Use\r\nweb-interface\r\nto configure", "", "Or restart\r\nwhile\r\nholding\r\n2nd button\r\r\nto start\r\n QR-config", "", ""};
|
||||
setEpdContent(epdContent);
|
||||
esp_task_wdt_init(30, false);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
if (Serial.available() > 0)
|
||||
|
@ -99,9 +114,12 @@ void tryImprovSetup()
|
|||
x_position = 0;
|
||||
}
|
||||
}
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
esp_task_wdt_deinit();
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
||||
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -112,7 +130,7 @@ void tryImprovSetup()
|
|||
vTaskDelay(pdMS_TO_TICKS(400));
|
||||
}
|
||||
}
|
||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||
// queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||
}
|
||||
|
||||
void setupTime()
|
||||
|
@ -134,6 +152,7 @@ void setupPreferences()
|
|||
{
|
||||
preferences.begin("btclock", false);
|
||||
|
||||
|
||||
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
||||
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
||||
|
||||
|
@ -142,6 +161,7 @@ void setupPreferences()
|
|||
screenNameMap[SCREEN_BTC_TICKER] = "Ticker";
|
||||
screenNameMap[SCREEN_TIME] = "Time";
|
||||
screenNameMap[SCREEN_HALVING_COUNTDOWN] = "Halving countdown";
|
||||
screenNameMap[SCREEN_MARKET_CAP] = "Market Cap";
|
||||
}
|
||||
|
||||
void setupWebsocketClients(void *pvParameters)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <Preferences.h>
|
||||
#include <Adafruit_MCP23X17.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "shared.hpp"
|
||||
#include "epd.hpp"
|
||||
#include "improv.hpp"
|
||||
|
|
|
@ -80,7 +80,7 @@ void setupDisplays()
|
|||
int *taskParam = new int;
|
||||
*taskParam = i;
|
||||
|
||||
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 10000, taskParam, tskIDLE_PRIORITY, &tasks[i]); // create task
|
||||
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 4096, taskParam, tskIDLE_PRIORITY, &tasks[i]); // create task
|
||||
}
|
||||
|
||||
xTaskCreate(taskEpd, "epd_task", 2048, NULL, tskIDLE_PRIORITY, &epdTaskHandle);
|
||||
|
@ -202,7 +202,11 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
|
|||
#ifdef PAGED_WRITE
|
||||
showDigitPaged(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
||||
#else
|
||||
if (epdContent[epdIndex].length() > 1) {
|
||||
showChars(epdIndex, epdContent[epdIndex], updatePartial, &Antonio_SemiBold30pt7b);
|
||||
} else {
|
||||
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -335,6 +339,21 @@ void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
|||
displays[dispNum].print(str);
|
||||
}
|
||||
|
||||
void showChars(const uint dispNum, const String& chars, bool partial, const GFXfont *font) {
|
||||
displays[dispNum].setRotation(2);
|
||||
displays[dispNum].setFont(font);
|
||||
displays[dispNum].setTextColor(getFgColor());
|
||||
int16_t tbx, tby;
|
||||
uint16_t tbw, tbh;
|
||||
displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||
// center the bounding box by transposition of the origin:
|
||||
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
||||
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
||||
displays[dispNum].fillScreen(getBgColor());
|
||||
displays[dispNum].setCursor(x, y);
|
||||
displays[dispNum].print(chars);
|
||||
}
|
||||
|
||||
void showDigitPaged(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
||||
{
|
||||
String str(chr);
|
||||
|
@ -426,11 +445,13 @@ void renderText(const uint dispNum, const String &text, bool partial)
|
|||
}
|
||||
}
|
||||
|
||||
displays[dispNum].display(partial);
|
||||
//displays[dispNum].display(partial);
|
||||
}
|
||||
|
||||
void renderQr(const uint dispNum, const String &text, bool partial)
|
||||
{
|
||||
#ifdef USE_QR
|
||||
|
||||
uint8_t tempBuffer[800];
|
||||
bool ok = qrcodegen_encodeText(text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
||||
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
||||
|
@ -452,5 +473,17 @@ void renderQr(const uint dispNum, const String &text, bool partial)
|
|||
displays[dispNum].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
|
||||
}
|
||||
}
|
||||
displays[dispNum].display(partial);
|
||||
//displays[dispNum].display(partial);
|
||||
|
||||
//free(tempBuffer);
|
||||
//free(qrcode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void waitUntilNoneBusy() {
|
||||
for (int i = 0; i < NUM_SCREENS; i++) {
|
||||
while (EPD_BUSY[i].digitalRead()) {
|
||||
vTaskDelay(10);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,10 @@
|
|||
#include <Fonts/FreeSans9pt7b.h>
|
||||
#include <regex>
|
||||
|
||||
#ifdef USE_QR
|
||||
#include "qrcodegen.h"
|
||||
#endif
|
||||
extern TaskHandle_t epdTaskHandle;
|
||||
|
||||
void setupDisplays();
|
||||
void taskEpd(void *pvParameters);
|
||||
|
@ -19,6 +22,8 @@ void splitText(const uint dispNum, const String& top, const String& bottom, bo
|
|||
void splitTextPaged(const uint dispNum, String top, String bottom, bool partial);
|
||||
|
||||
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
||||
void showChars(const uint dispNum, const String& chars, bool partial, const GFXfont *font);
|
||||
|
||||
void showDigitPaged(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
||||
|
||||
extern "C" void updateDisplay(void *pvParameters) noexcept;
|
||||
|
@ -34,3 +39,4 @@ void renderQr(const uint dispNum, const String& text, bool partial);
|
|||
|
||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent);
|
||||
std::array<String, NUM_SCREENS> getCurrentEpdContent();
|
||||
void waitUntilNoneBusy();
|
|
@ -3,7 +3,7 @@
|
|||
TaskHandle_t ledTaskHandle = NULL;
|
||||
QueueHandle_t ledTaskQueue = NULL;
|
||||
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
||||
unsigned long ledTaskParams;
|
||||
uint ledTaskParams;
|
||||
|
||||
void ledTask(void *parameter)
|
||||
{
|
||||
|
@ -23,6 +23,14 @@ void ledTask(void *parameter)
|
|||
|
||||
switch (ledTaskParams)
|
||||
{
|
||||
case LED_POWER_TEST:
|
||||
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
||||
pixels.setPixelColor(2, pixels.Color(0, 0, 255));
|
||||
pixels.setPixelColor(3, pixels.Color(255, 255, 255));
|
||||
pixels.show();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
case LED_EFFECT_WIFI_CONNECT_ERROR:
|
||||
case LED_FLASH_ERROR:
|
||||
blinkDelayColor(250, 3, 255, 0, 0);
|
||||
|
@ -39,6 +47,9 @@ void ledTask(void *parameter)
|
|||
case LED_EFFECT_WIFI_WAIT_FOR_CONFIG:
|
||||
blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236), pixels.Color(156, 225, 240));
|
||||
break;
|
||||
case LED_EFFECT_WIFI_ERASE_SETTINGS:
|
||||
blinkDelay(100, 3);
|
||||
break;
|
||||
case LED_EFFECT_WIFI_CONNECTING:
|
||||
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
|
||||
{
|
||||
|
@ -109,13 +120,16 @@ void ledTask(void *parameter)
|
|||
break;
|
||||
}
|
||||
|
||||
// revert to previous state
|
||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
||||
{
|
||||
pixels.setPixelColor(i, oldLights[i]);
|
||||
}
|
||||
// revert to previous state unless power test
|
||||
|
||||
pixels.show();
|
||||
if (ledTaskParams != LED_POWER_TEST) {
|
||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
||||
{
|
||||
pixels.setPixelColor(i, oldLights[i]);
|
||||
}
|
||||
|
||||
pixels.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,25 +138,24 @@ void ledTask(void *parameter)
|
|||
void setupLeds()
|
||||
{
|
||||
pixels.begin();
|
||||
if (preferences.getBool("ledTestOnPower", true))
|
||||
{
|
||||
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
|
||||
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
||||
pixels.setPixelColor(2, pixels.Color(0, 0, 255));
|
||||
pixels.setPixelColor(3, pixels.Color(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels.clear();
|
||||
}
|
||||
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
|
||||
pixels.clear();
|
||||
pixels.show();
|
||||
setupLedTask();
|
||||
if (preferences.getBool("ledTestOnPower", true))
|
||||
{
|
||||
while (!ledTaskQueue)
|
||||
{
|
||||
delay(1);
|
||||
// wait until queue is available
|
||||
}
|
||||
queueLedEffect(LED_POWER_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void setupLedTask()
|
||||
{
|
||||
ledTaskQueue = xQueueCreate(2, sizeof(char));
|
||||
ledTaskQueue = xQueueCreate(5, sizeof(uint));
|
||||
|
||||
xTaskCreate(ledTask, "LedTask", 2048, NULL, tskIDLE_PRIORITY, &ledTaskHandle);
|
||||
}
|
||||
|
@ -249,6 +262,6 @@ bool queueLedEffect(uint effect)
|
|||
return false;
|
||||
}
|
||||
|
||||
char flashType = effect;
|
||||
uint flashType = effect;
|
||||
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include "shared.hpp"
|
||||
|
||||
|
@ -23,7 +21,8 @@ const int LED_EFFECT_WIFI_WAIT_FOR_CONFIG = 100;
|
|||
const int LED_EFFECT_WIFI_CONNECTING = 101;
|
||||
const int LED_EFFECT_WIFI_CONNECT_ERROR = 102;
|
||||
const int LED_EFFECT_WIFI_CONNECT_SUCCESS = 103;
|
||||
|
||||
const int LED_EFFECT_WIFI_ERASE_SETTINGS = 104;
|
||||
const int LED_POWER_TEST = 999;
|
||||
extern TaskHandle_t ledTaskHandle;
|
||||
|
||||
void ledTask(void *pvParameters);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin";
|
||||
// WebsocketsClient client;
|
||||
esp_websocket_client_handle_t clientPrice = NULL;
|
||||
unsigned long int currentPrice;
|
||||
unsigned long int lastPriceUpdate = 0;
|
||||
unsigned long int currentPrice = 30000;
|
||||
unsigned long int lastPriceUpdate;
|
||||
|
||||
void setupPriceNotify()
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data)
|
|||
|
||||
lastPriceUpdate = currentTime;
|
||||
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
||||
if (priceUpdateTaskHandle != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME))
|
||||
if (priceUpdateTaskHandle != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || getCurrentScreen() == SCREEN_MARKET_CAP))
|
||||
xTaskNotifyGive(priceUpdateTaskHandle);
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ void taskPriceUpdate(void *pvParameters)
|
|||
firstIndex = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (getCurrentScreen() == SCREEN_MSCW_TIME)
|
||||
{
|
||||
priceString = String(int(round(1 / float(price) * 10e7))).c_str();
|
||||
|
||||
|
@ -45,10 +45,39 @@ void taskPriceUpdate(void *pvParameters)
|
|||
firstIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = firstIndex; i < NUM_SCREENS; i++)
|
||||
else
|
||||
{
|
||||
taskEpdContent[i] = priceString[i];
|
||||
double supply = getSupplyAtBlock(getBlockHeight());
|
||||
int64_t marketCap = static_cast<std::int64_t>(supply * double(price));
|
||||
std::string stringValue = std::to_string(marketCap);
|
||||
size_t mcLength = stringValue.length();
|
||||
size_t leadingSpaces = (3 - mcLength % 3) % 3;
|
||||
stringValue = std::string(leadingSpaces, ' ') + stringValue;
|
||||
|
||||
taskEpdContent[0] = "USD/MCAP";
|
||||
|
||||
uint groups = (mcLength + leadingSpaces) / 3;
|
||||
|
||||
if (groups < NUM_SCREENS) {
|
||||
firstIndex = 1;
|
||||
}
|
||||
|
||||
for (int i = firstIndex; i < NUM_SCREENS-groups-1; i++) {
|
||||
taskEpdContent[i] = "";
|
||||
}
|
||||
|
||||
taskEpdContent[NUM_SCREENS-groups-1] = " $ ";
|
||||
for (uint i = 0; i < groups; i ++)
|
||||
{
|
||||
taskEpdContent[(NUM_SCREENS-groups+i)] = stringValue.substr(i*3, 3).c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (getCurrentScreen() != SCREEN_MARKET_CAP) {
|
||||
for (uint i = firstIndex; i < NUM_SCREENS; i++)
|
||||
{
|
||||
taskEpdContent[i] = priceString[i];
|
||||
}
|
||||
}
|
||||
|
||||
setEpdContent(taskEpdContent);
|
||||
|
@ -179,7 +208,7 @@ void IRAM_ATTR screenRotateTimerISR(void *arg)
|
|||
|
||||
void setupTasks()
|
||||
{
|
||||
xTaskCreate(taskPriceUpdate, "updatePrice", 2048, NULL, tskIDLE_PRIORITY, &priceUpdateTaskHandle);
|
||||
xTaskCreate(taskPriceUpdate, "updatePrice", 3072, NULL, tskIDLE_PRIORITY, &priceUpdateTaskHandle);
|
||||
xTaskCreate(taskBlockUpdate, "updateBlock", 2048, NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
||||
xTaskCreate(taskTimeUpdate, "updateTime", 4096, NULL, tskIDLE_PRIORITY, &timeUpdateTaskHandle);
|
||||
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY, &taskScreenRotateTaskHandle);
|
||||
|
@ -283,6 +312,7 @@ void setCurrentScreen(uint newScreen)
|
|||
case SCREEN_BLOCK_HEIGHT:
|
||||
xTaskNotifyGive(blockUpdateTaskHandle);
|
||||
break;
|
||||
case SCREEN_MARKET_CAP:
|
||||
case SCREEN_MSCW_TIME:
|
||||
case SCREEN_BTC_TICKER:
|
||||
xTaskNotifyGive(priceUpdateTaskHandle);
|
||||
|
@ -308,6 +338,7 @@ void nextScreen()
|
|||
|
||||
void previousScreen()
|
||||
{
|
||||
|
||||
int newCurrentScreen = modulo(getCurrentScreen() - 1, SCREEN_COUNT);
|
||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
#include "lib/block_notify.hpp"
|
||||
#include "lib/price_notify.hpp"
|
||||
#include "shared.hpp"
|
||||
#include "lib/epd.hpp"
|
||||
|
||||
extern TaskHandle_t priceUpdateTaskHandle;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <Adafruit_MCP23X17.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Preferences.h>
|
||||
|
@ -13,10 +15,12 @@ const PROGMEM int SCREEN_MSCW_TIME = 1;
|
|||
const PROGMEM int SCREEN_BTC_TICKER = 2;
|
||||
const PROGMEM int SCREEN_TIME = 3;
|
||||
const PROGMEM int SCREEN_HALVING_COUNTDOWN = 4;
|
||||
const PROGMEM int SCREEN_MARKET_CAP = 5;
|
||||
|
||||
const PROGMEM int SCREEN_COUNTDOWN = 98;
|
||||
const PROGMEM int SCREEN_CUSTOM = 99;
|
||||
const PROGMEM int screens[5] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN };
|
||||
const int SCREEN_COUNT = 5;
|
||||
const int SCREEN_COUNT = 6;
|
||||
const PROGMEM int screens[SCREEN_COUNT] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP };
|
||||
|
||||
struct SpiRamAllocator {
|
||||
void* allocate(size_t size) {
|
||||
|
|
|
@ -9,4 +9,24 @@ String getMyHostname() {
|
|||
byte mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
return "btclock" + String(mac[4], 16) = String(mac[5], 16);
|
||||
}
|
||||
|
||||
double getSupplyAtBlock(uint blockNr) {
|
||||
if (blockNr >= 33 * 210000) {
|
||||
return 20999999.9769;
|
||||
}
|
||||
|
||||
const int initialBlockReward = 50; // Initial block reward
|
||||
const int halvingInterval = 210000; // Number of blocks before halving
|
||||
|
||||
int halvingCount = blockNr / halvingInterval;
|
||||
double totalBitcoinInCirculation = 0;
|
||||
|
||||
for (int i = 0; i < halvingCount; ++i) {
|
||||
totalBitcoinInCirculation += halvingInterval * initialBlockReward * std::pow(0.5, i);
|
||||
}
|
||||
|
||||
totalBitcoinInCirculation += (blockNr % halvingInterval) * initialBlockReward * std::pow(0.5, halvingCount);
|
||||
|
||||
return totalBitcoinInCirculation;
|
||||
}
|
|
@ -4,4 +4,7 @@
|
|||
#include "shared.hpp"
|
||||
|
||||
int modulo(int x,int N);
|
||||
|
||||
double getSupplyAtBlock(uint blockNr);
|
||||
|
||||
String getMyHostname();
|
|
@ -186,7 +186,7 @@ void onApiShowText(AsyncWebServerRequest *request)
|
|||
|
||||
setEpdContent(textEpdContent);
|
||||
}
|
||||
// setCurrentScreen(SCREEN_CUSTOM);
|
||||
setCurrentScreen(SCREEN_CUSTOM);
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ void onApiRestart(AsyncWebServerRequest *request)
|
|||
*/
|
||||
void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||
{
|
||||
StaticJsonDocument<768> root;
|
||||
StaticJsonDocument<1536> root;
|
||||
root["numScreens"] = NUM_SCREENS;
|
||||
root["fgColor"] = getFgColor();
|
||||
root["bgColor"] = getBgColor();
|
||||
|
@ -214,11 +214,11 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
|||
root["wpTimeout"] = preferences.getUInt("wpTimeout", 600);
|
||||
root["tzOffset"] = preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS) / 60;
|
||||
root["useBitcoinNode"] = preferences.getBool("useNode", false);
|
||||
root["rpcPort"] = preferences.getUInt("rpcPort", BITCOIND_PORT);
|
||||
root["rpcUser"] = preferences.getString("rpcUser", BITCOIND_RPC_USER);
|
||||
root["rpcHost"] = preferences.getString("rpcHost", BITCOIND_HOST);
|
||||
// root["rpcPort"] = preferences.getUInt("rpcPort", BITCOIND_PORT);
|
||||
// root["rpcUser"] = preferences.getString("rpcUser", BITCOIND_RPC_USER);
|
||||
// root["rpcHost"] = preferences.getString("rpcHost", BITCOIND_HOST);
|
||||
root["mempoolInstance"] = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
||||
|
||||
root["ledTestOnPower"] = preferences.getBool("ledTestOnPower", true);
|
||||
root["ledFlashOnUpdate"] = preferences.getBool("ledFlashOnUpd", false);
|
||||
root["ledBrightness"] = preferences.getUInt("ledBrightness", 128);
|
||||
|
||||
|
@ -374,33 +374,33 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
|||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (request->hasParam("useBitcoinNode", true))
|
||||
{
|
||||
AsyncWebParameter *p = request->getParam("useBitcoinNode", true);
|
||||
bool useBitcoinNode = p->value().toInt();
|
||||
preferences.putBool("useNode", useBitcoinNode);
|
||||
settingsChanged = true;
|
||||
// if (request->hasParam("useBitcoinNode", true))
|
||||
// {
|
||||
// AsyncWebParameter *p = request->getParam("useBitcoinNode", true);
|
||||
// bool useBitcoinNode = p->value().toInt();
|
||||
// preferences.putBool("useNode", useBitcoinNode);
|
||||
// settingsChanged = true;
|
||||
|
||||
String rpcVars[] = {"rpcHost", "rpcPort", "rpcUser", "rpcPass"};
|
||||
// String rpcVars[] = {"rpcHost", "rpcPort", "rpcUser", "rpcPass"};
|
||||
|
||||
for (String v : rpcVars)
|
||||
{
|
||||
if (request->hasParam(v, true))
|
||||
{
|
||||
AsyncWebParameter *pv = request->getParam(v, true);
|
||||
// Don't store an empty password, probably new settings save
|
||||
if (!(v.equals("rpcPass") && pv->value().length() == 0))
|
||||
{
|
||||
preferences.putString(v.c_str(), pv->value().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
preferences.putBool("useNode", false);
|
||||
settingsChanged = true;
|
||||
}
|
||||
// for (String v : rpcVars)
|
||||
// {
|
||||
// if (request->hasParam(v, true))
|
||||
// {
|
||||
// AsyncWebParameter *pv = request->getParam(v, true);
|
||||
// // Don't store an empty password, probably new settings save
|
||||
// if (!(v.equals("rpcPass") && pv->value().length() == 0))
|
||||
// {
|
||||
// preferences.putString(v.c_str(), pv->value().c_str());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// preferences.putBool("useNode", false);
|
||||
// settingsChanged = true;
|
||||
// }
|
||||
|
||||
request->send(200);
|
||||
if (settingsChanged)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue