More memory optimizations
This commit is contained in:
parent
e1648a9a42
commit
1f7946c30e
26 changed files with 403 additions and 286 deletions
|
@ -1,5 +1,8 @@
|
|||
#include "epd.hpp"
|
||||
|
||||
int fgColor;
|
||||
int bgColor;
|
||||
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
|
||||
|
||||
int getBgColor()
|
||||
{
|
||||
|
@ -20,3 +23,83 @@ void setFgColor(int color)
|
|||
{
|
||||
fgColor = color;
|
||||
}
|
||||
|
||||
void showSetupQr(const String &ssid, const String &password)
|
||||
{
|
||||
char displayIndex = 6;
|
||||
|
||||
const String text = "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;";
|
||||
|
||||
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
|
||||
bool ok = qrcodegen_encodeText(text.c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
||||
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
||||
|
||||
const int size = qrcodegen_getSize(qrcode);
|
||||
|
||||
const int padding = floor(float(displays[displayIndex].width() - (size * 4)) / 2);
|
||||
const int paddingY = floor(float(displays[displayIndex].height() - (size * 4)) / 2);
|
||||
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
const int border = 0;
|
||||
|
||||
for (int y = -border; y < size * 4 + border; y++)
|
||||
{
|
||||
for (int x = -border; x < size * 4 + border; x++)
|
||||
{
|
||||
displays[displayIndex].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
|
||||
}
|
||||
}
|
||||
displays[displayIndex].display(true);
|
||||
|
||||
displayIndex = 4;
|
||||
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
displays[displayIndex].setTextColor(GxEPD_BLACK);
|
||||
displays[displayIndex].setCursor(0, 50);
|
||||
displays[displayIndex].setFont(&FreeSansBold9pt7b);
|
||||
displays[displayIndex].println(F("SSID:"));
|
||||
displays[displayIndex].setFont(&FreeSans9pt7b);
|
||||
displays[displayIndex].println(ssid);
|
||||
displays[displayIndex].println("");
|
||||
displays[displayIndex].setFont(&FreeSansBold9pt7b);
|
||||
displays[displayIndex].println(F("Password:"));
|
||||
displays[displayIndex].setFont(&FreeSans9pt7b);
|
||||
displays[displayIndex].println(password);
|
||||
displays[displayIndex].display(true);
|
||||
|
||||
displayIndex = 2;
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
displays[displayIndex].setTextColor(GxEPD_BLACK);
|
||||
displays[displayIndex].setCursor(0, 50);
|
||||
displays[displayIndex].setFont(&FreeSans9pt7b);
|
||||
displays[displayIndex].println(F("To setup\r\nscan QR or\r\nconnect\r\nmanually"));
|
||||
// displays[displayIndex].println(F("scan QR or"));
|
||||
// displays[displayIndex].println(F("connect"));
|
||||
// displays[displayIndex].println(F("manually"));
|
||||
displays[displayIndex].display(true);
|
||||
|
||||
displayIndex = 0;
|
||||
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
displays[displayIndex].setTextColor(GxEPD_BLACK);
|
||||
displays[displayIndex].setCursor(0, 50);
|
||||
displays[displayIndex].setFont(&FreeSansBold9pt7b);
|
||||
displays[displayIndex].println(F("Welcome!"));
|
||||
displays[displayIndex].display(true);
|
||||
|
||||
for (int i = 1; i < NUM_SCREENS; (i = i + 2))
|
||||
{
|
||||
displays[i].setPartialWindow(0, 0, displays[i].width(), displays[i].height());
|
||||
displays[i].fillScreen(GxEPD_WHITE);
|
||||
displays[i].display(true);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
displays[i].hibernate();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
#include "shared.hpp"
|
||||
#include "qrcodegen.h"
|
||||
|
||||
#include <Fonts/FreeSansBold9pt7b.h>
|
||||
#include <Fonts/FreeSans9pt7b.h>
|
||||
#ifdef IS_BW
|
||||
#include <GxEPD2_BW.h>
|
||||
#else
|
||||
#include <GxEPD2_3C.h>
|
||||
#endif
|
||||
|
||||
int getBgColor();
|
||||
int getFgColor();
|
||||
void setBgColor(int color);
|
||||
void setFgColor(int color);
|
||||
|
||||
void showSetupQr(const String& ssid, const String& password);
|
||||
|
|
|
@ -7,7 +7,7 @@ std::map<int, std::string> screenNameMap;
|
|||
|
||||
#ifndef NO_MCP
|
||||
Adafruit_MCP23X17 mcp;
|
||||
const int MCP_INT_PIN = 8;
|
||||
const char MCP_INT_PIN = 8;
|
||||
|
||||
#endif
|
||||
bool timerRunning = true;
|
||||
|
@ -27,7 +27,7 @@ Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
|||
|
||||
String softAP_SSID;
|
||||
String softAP_password;
|
||||
WiFiMulti wifiMulti;
|
||||
//WiFiMulti wifiMulti;
|
||||
|
||||
WiFiManager wm;
|
||||
bool screenVisible[5];
|
||||
|
@ -36,20 +36,20 @@ void setupSoftAP()
|
|||
{
|
||||
byte mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
softAP_SSID = String("BTClock" + String(mac[5], 16) + String(mac[6], 16));
|
||||
softAP_SSID = String("BTClock" + String(mac[5], 16) + String(mac[1], 16));
|
||||
WiFi.setHostname(softAP_SSID.c_str());
|
||||
softAP_password = base64::encode(String(mac[2], 16) + String(mac[4], 16) + String(mac[5], 16) + String(mac[6], 16)).substring(2, 10);
|
||||
softAP_password = base64::encode(String(mac[2], 16) + String(mac[4], 16) + String(mac[5], 16) + String(mac[1], 16)).substring(2, 10);
|
||||
}
|
||||
|
||||
void setupComponents()
|
||||
{
|
||||
if (psramInit())
|
||||
{
|
||||
Serial.println("\nPSRAM is correctly initialized");
|
||||
Serial.println(F("PSRAM is correctly initialized"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("PSRAM not available");
|
||||
Serial.println(F("PSRAM not available"));
|
||||
}
|
||||
#ifdef WITH_RGB_LED
|
||||
pixels.begin();
|
||||
|
@ -61,12 +61,12 @@ void setupComponents()
|
|||
#endif
|
||||
|
||||
// delay(3000);
|
||||
// Serial.println("Leds should be on");
|
||||
// Serial.println(F("Leds should be on"));
|
||||
|
||||
#ifndef NO_MCP
|
||||
if (!mcp.begin_I2C())
|
||||
{
|
||||
Serial.println("Error MCP23017");
|
||||
Serial.println(F("Error MCP23017"));
|
||||
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||
pixels.setPixelColor(1, pixels.Color(255, 0, 0));
|
||||
pixels.setPixelColor(2, pixels.Color(255, 0, 0));
|
||||
|
@ -77,7 +77,7 @@ void setupComponents()
|
|||
}
|
||||
else
|
||||
{
|
||||
Serial.println("MCP23017 ok");
|
||||
Serial.println(F("MCP23017 ok"));
|
||||
pixels.setPixelColor(0, pixels.Color(0, 255, 0));
|
||||
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
||||
pixels.setPixelColor(2, pixels.Color(0, 255, 0));
|
||||
|
@ -107,7 +107,7 @@ void synchronizeTime()
|
|||
{
|
||||
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0, NTP_SERVER);
|
||||
delay(500);
|
||||
Serial.println("Retry set time");
|
||||
Serial.println(F("Retry set time"));
|
||||
}
|
||||
|
||||
rtc.setTimeStruct(timeinfo);
|
||||
|
@ -134,7 +134,7 @@ void setupWifi()
|
|||
pixels.setPixelColor(2, pixels.Color(255, 0, 0));
|
||||
pixels.setPixelColor(3, pixels.Color(0, 0, 255));
|
||||
pixels.show();
|
||||
Serial.println("Erasing WiFi Config, restarting");
|
||||
Serial.println(F("Erasing WiFi Config, restarting"));
|
||||
wm.resetSettings();
|
||||
ESP.restart();
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ void toggleScreenTimer()
|
|||
|
||||
if (!timerRunning)
|
||||
{
|
||||
Serial.println("Stopping screen timer...");
|
||||
Serial.println(F("Stopping screen timer..."));
|
||||
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
|
||||
{
|
||||
for (int j = NEOPIXEL_COUNT; j >= 0; j--)
|
||||
|
@ -275,7 +275,7 @@ void toggleScreenTimer()
|
|||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Starting screen timer...");
|
||||
Serial.println(F("Starting screen timer..."));
|
||||
|
||||
pixels.setPixelColor(3, pixels.Color(0, 255, 0));
|
||||
pixels.setPixelColor(2, pixels.Color(0, 0, 0));
|
||||
|
@ -442,7 +442,7 @@ void setupI2C()
|
|||
|
||||
if (slaveMode)
|
||||
{
|
||||
Serial.println("I2C Slave Mode enabled");
|
||||
Serial.println(F("I2C Slave Mode enabled"));
|
||||
Wire.onReceive(onI2CReceive);
|
||||
Wire.begin((uint8_t)I2C_DEV_ADDR);
|
||||
}
|
||||
|
@ -461,5 +461,5 @@ void onI2CReceive(int len)
|
|||
void onI2CRequest()
|
||||
{
|
||||
Wire.print("I2C Packets.");
|
||||
Serial.println("onRequest");
|
||||
Serial.println(F("onRequest"));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <WiFi.h>
|
||||
#include <Arduino.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <WiFiMulti.h>
|
||||
//#include <WiFiMulti.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "shared.hpp"
|
||||
|
|
|
@ -9,10 +9,7 @@ void setupWebserver()
|
|||
// Initialize SPIFFS
|
||||
if (!SPIFFS.begin(true))
|
||||
{
|
||||
pinMode(47, OUTPUT);
|
||||
digitalWrite(47, HIGH);
|
||||
|
||||
Serial.println("An Error has occurred while mounting SPIFFS");
|
||||
Serial.println(F("An Error has occurred while mounting SPIFFS"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -57,14 +54,14 @@ void setupWebserver()
|
|||
server.begin();
|
||||
if (!MDNS.begin(HOSTNAME))
|
||||
{
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
Serial.println(F("Error setting up MDNS responder!"));
|
||||
while (1)
|
||||
{
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
Serial.println("Webserver should be running");
|
||||
Serial.println(F("Webserver should be running"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,7 +109,7 @@ void onApiStatus(AsyncWebServerRequest *request)
|
|||
void onApiActionPause(AsyncWebServerRequest *request)
|
||||
{
|
||||
timerRunning = false;
|
||||
Serial.println("Update timer paused");
|
||||
Serial.println(F("Update timer paused"));
|
||||
|
||||
request->send(200);
|
||||
};
|
||||
|
@ -137,7 +134,7 @@ void onApiActionTimerRestart(AsyncWebServerRequest *request)
|
|||
{
|
||||
// moment = millis();
|
||||
timerRunning = true;
|
||||
Serial.println("Update timer restarted");
|
||||
Serial.println(F("Update timer restarted"));
|
||||
|
||||
request->send(200);
|
||||
}
|
||||
|
@ -221,7 +218,7 @@ bool processEpdColorSettings(AsyncWebServerRequest *request)
|
|||
AsyncWebParameter *fgColor = request->getParam("fgColor", true);
|
||||
preferences.putUInt("fgColor", strtol(fgColor->value().c_str(), NULL, 16));
|
||||
setFgColor(int(strtol(fgColor->value().c_str(), NULL, 16)));
|
||||
Serial.print("Setting foreground color to ");
|
||||
Serial.print(F("Setting foreground color to "));
|
||||
Serial.println(fgColor->value().c_str());
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
@ -231,7 +228,7 @@ bool processEpdColorSettings(AsyncWebServerRequest *request)
|
|||
|
||||
preferences.putUInt("bgColor", strtol(bgColor->value().c_str(), NULL, 16));
|
||||
setBgColor(int(strtol(bgColor->value().c_str(), NULL, 16)));
|
||||
Serial.print("Setting background color to ");
|
||||
Serial.print(F("Setting background color to "));
|
||||
Serial.println(bgColor->value().c_str());
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
@ -250,7 +247,7 @@ void onApiEpdSettingsPost(AsyncWebServerRequest *request)
|
|||
{
|
||||
flashTemporaryLights(0, 255, 0);
|
||||
|
||||
Serial.println("Settings changed");
|
||||
Serial.println(F("Settings changed"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,7 +381,7 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
|||
{
|
||||
flashTemporaryLights(0, 255, 0);
|
||||
|
||||
Serial.println("Settings changed");
|
||||
Serial.println(F("Settings changed"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -504,7 +501,7 @@ void onApiLightsFlash(AsyncWebServerRequest *request)
|
|||
void onApiLightsSetColor(AsyncWebServerRequest *request)
|
||||
{
|
||||
String rgbColor = request->pathArg(0);
|
||||
int r, g, b;
|
||||
uint r, g, b;
|
||||
sscanf(rgbColor.c_str(), "%02x%02x%02x", &r, &g, &b);
|
||||
setLights(r, g, b);
|
||||
request->send(200, "text/plain", rgbColor);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "screens/blockheight.hpp"
|
||||
#include "screens/ticker.hpp"
|
||||
#include "screens/time.hpp"
|
||||
#include "screens/sats_per_dollar.hpp"
|
||||
//#include "screens/sats_per_dollar.hpp"
|
||||
#include "screens/halvingcountdown.hpp"
|
||||
|
||||
#include "tasks/ha.hpp"
|
||||
|
@ -26,7 +26,7 @@
|
|||
#include "tasks/button.hpp"
|
||||
#include "tasks/led_handler.hpp"
|
||||
|
||||
WiFiClient wifiClientInsecure;
|
||||
//WiFiClient wifiClientInsecure;
|
||||
WiFiClientSecure wifiClient;
|
||||
ESP32Time rtc(3600);
|
||||
|
||||
|
@ -63,8 +63,9 @@ void setup()
|
|||
|
||||
TimeScreen::init();
|
||||
BlockHeightScreen::init();
|
||||
HalvingCountdownScreen::init();
|
||||
TickerScreen::init();
|
||||
SatsPerDollarScreen::init();
|
||||
// SatsPerDollarScreen::init();
|
||||
|
||||
#ifdef WITH_BUTTONS
|
||||
setupButtonTask();
|
||||
|
@ -79,7 +80,7 @@ void setup()
|
|||
registerNewBlockCallback(BlockHeightScreen::onNewBlock);
|
||||
registerNewBlockCallback(HalvingCountdownScreen::onNewBlock);
|
||||
registerNewPriceCallback(TickerScreen::onPriceUpdate);
|
||||
registerNewPriceCallback(SatsPerDollarScreen::onPriceUpdate);
|
||||
// registerNewPriceCallback(SatsPerDollarScreen::onPriceUpdate);
|
||||
|
||||
setupDisplays();
|
||||
} else {
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
#include "blockheight.hpp"
|
||||
|
||||
uint BlockHeightScreen::blockNr = 0;
|
||||
std::array<String, NUM_SCREENS> BlockHeightScreen::epdContent = { "", "", "", "", "", "", "" };
|
||||
|
||||
//std::array<String, NUM_SCREENS> * BlockHeightScreen::epdContent = (std::array<String, NUM_SCREENS> * ) ps_malloc(7 * sizeof (std::array<String, NUM_SCREENS>));
|
||||
|
||||
char **BlockHeightScreen::epdContent;
|
||||
const int maxStringLength = 15;
|
||||
char* BlockHeightScreen::psramBuffer;
|
||||
|
||||
void BlockHeightScreen::init()
|
||||
{
|
||||
BlockHeightScreen::psramBuffer = (char*)ps_malloc(NUM_SCREENS * maxStringLength);
|
||||
|
||||
if (BlockHeightScreen::psramBuffer == nullptr)
|
||||
{
|
||||
Serial.println(F("Failed to allocate memory in PSRAM"));
|
||||
}
|
||||
BlockHeightScreen::epdContent = new char*[NUM_SCREENS];
|
||||
for (int i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
epdContent[i] = psramBuffer + i * maxStringLength;
|
||||
}
|
||||
BlockHeightScreen::blockNr = preferences.getUInt("blockHeight", 789000);
|
||||
setupBlockNotify();
|
||||
BlockHeightScreen::showScreen();
|
||||
|
@ -17,10 +27,14 @@ void BlockHeightScreen::showScreen()
|
|||
{
|
||||
std::string blockNrString = String(BlockHeightScreen::blockNr).c_str();
|
||||
blockNrString.insert(blockNrString.begin(), NUM_SCREENS - blockNrString.length(), ' ');
|
||||
epdContent[0] = "BLOCK/HEIGHT";
|
||||
// epdContent[0] = "BLOCK/HEIGHT";
|
||||
snprintf(BlockHeightScreen::epdContent[0], 13, "BLOCK/HEIGHT", 0);
|
||||
|
||||
for (uint i = 1; i < NUM_SCREENS; i++)
|
||||
{
|
||||
BlockHeightScreen::epdContent[i] = blockNrString[i];
|
||||
snprintf(BlockHeightScreen::epdContent[i], 2, &blockNrString[i], 0);
|
||||
|
||||
// BlockHeightScreen::epdContent[i] = blockNrString[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +45,16 @@ void BlockHeightScreen::onNewBlock(uint blockNr)
|
|||
BlockHeightScreen::showScreen();
|
||||
}
|
||||
|
||||
std::array<String, 7> BlockHeightScreen::getEpdContent() {
|
||||
return BlockHeightScreen::epdContent;
|
||||
std::array<String, NUM_SCREENS> BlockHeightScreen::getEpdContent()
|
||||
{
|
||||
std::array<String, NUM_SCREENS> ret;
|
||||
|
||||
for (int i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
ret[i] = BlockHeightScreen::epdContent[i];
|
||||
}
|
||||
|
||||
// std::copy(std::begin(BlockHeightScreen::epdContent), std::end(BlockHeightScreen::epdContent), std::begin(ret));
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -6,13 +6,15 @@
|
|||
#include "tasks/epd.hpp"
|
||||
#include "tasks/blocknotify.hpp"
|
||||
|
||||
class BlockHeightScreen {
|
||||
protected:
|
||||
static uint blockNr;
|
||||
static std::array<String, NUM_SCREENS> epdContent;
|
||||
public:
|
||||
static void init();
|
||||
static void showScreen();
|
||||
static void onNewBlock(uint blockNr);
|
||||
static std::array<String, NUM_SCREENS> getEpdContent();
|
||||
class BlockHeightScreen
|
||||
{
|
||||
protected:
|
||||
static uint blockNr;
|
||||
static char** epdContent;
|
||||
static char* psramBuffer;
|
||||
public:
|
||||
static void init();
|
||||
static void showScreen();
|
||||
static void onNewBlock(uint blockNr);
|
||||
static std::array<String, NUM_SCREENS> getEpdContent();
|
||||
};
|
|
@ -38,6 +38,6 @@ void CountdownScreen::countdownTask(void *pvParameters)
|
|||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
Serial.println("Countdown finished!");
|
||||
Serial.println(F("Countdown finished!"));
|
||||
vTaskDelete(NULL);
|
||||
}
|
|
@ -3,33 +3,63 @@
|
|||
uint HalvingCountdownScreen::currentBlockNr = 0;
|
||||
uint HalvingCountdownScreen::halvingBlockNr = 0;
|
||||
|
||||
std::array<String, NUM_SCREENS> HalvingCountdownScreen::epdContent = {"", "", "", "", "", "", ""};
|
||||
char **HalvingCountdownScreen::epdContentP;
|
||||
const int maxStringLength = 12;
|
||||
char *HalvingCountdownScreen::psramBuffer;
|
||||
|
||||
//char HalvingCountdownScreen::epdContent[NUM_SCREENS][maxStringLength];
|
||||
bool initialized = false;
|
||||
|
||||
void HalvingCountdownScreen::init()
|
||||
{
|
||||
HalvingCountdownScreen::currentBlockNr = preferences.getUInt("blockHeight", 789000);
|
||||
|
||||
HalvingCountdownScreen::psramBuffer = (char *)ps_malloc(NUM_SCREENS * maxStringLength);
|
||||
|
||||
if (HalvingCountdownScreen::psramBuffer == nullptr)
|
||||
{
|
||||
Serial.println(F("Failed to allocate memory in PSRAM (HalvingCountdownScreen)"));
|
||||
}
|
||||
HalvingCountdownScreen::epdContentP = new char*[NUM_SCREENS];
|
||||
|
||||
for (int i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
epdContentP[i] = HalvingCountdownScreen::psramBuffer + i * maxStringLength;
|
||||
// strcpy(epdContent[i], "x");
|
||||
strcpy(epdContentP[i], "x");
|
||||
}
|
||||
initialized = true;
|
||||
setupBlockNotify();
|
||||
HalvingCountdownScreen::showScreen();
|
||||
}
|
||||
|
||||
void HalvingCountdownScreen::showScreen()
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
uint minutesToHalving = HalvingCountdownScreen::getNextHalvingBlockNr() * 10;
|
||||
|
||||
int years = floor(minutesToHalving / 525600);
|
||||
int days = floor((minutesToHalving - (years * 525600)) / (24*60));
|
||||
int hours = floor((minutesToHalving - (years * 525600) - (days * (24*60))) / 60);
|
||||
int mins = floor(minutesToHalving - (years * 525600) - (days * (24*60)) - (hours * 60));
|
||||
// int secs = floor((minutesToHalving - (years * 525600) - (days * (24*60)) - (hours * 60) - mins) * 60);
|
||||
const int years = floor(minutesToHalving / 525600);
|
||||
const int days = floor((minutesToHalving - (years * 525600)) / (24 * 60));
|
||||
const int hours = floor((minutesToHalving - (years * 525600) - (days * (24 * 60))) / 60);
|
||||
const int mins = floor(minutesToHalving - (years * 525600) - (days * (24 * 60)) - (hours * 60));
|
||||
// int secs = floor((minutesToHalving - (years * 525600) - (days * (24*60)) - (hours * 60) - mins) * 60);
|
||||
|
||||
epdContent[0] = F("BIT/COIN");
|
||||
epdContent[1] = F("HALV/ING");
|
||||
epdContent[2] = String(years) + "/YRS";
|
||||
epdContent[3] = String(days) + "/DAYS";
|
||||
epdContent[4] = String(hours) + "/HRS";
|
||||
epdContent[5] = String(mins) + "/MINS";
|
||||
epdContent[6] = F("TO/GO");
|
||||
snprintf(HalvingCountdownScreen::epdContentP[0], maxStringLength, "BIT/COIN");
|
||||
snprintf(HalvingCountdownScreen::epdContentP[1], maxStringLength, "HALV/ING");
|
||||
snprintf(HalvingCountdownScreen::epdContentP[2], maxStringLength, "%d/YRS", years);
|
||||
|
||||
snprintf(HalvingCountdownScreen::epdContentP[3], maxStringLength, "%d/DAYS", days);
|
||||
snprintf(HalvingCountdownScreen::epdContentP[4], maxStringLength, "%d/HRS", hours);
|
||||
snprintf(HalvingCountdownScreen::epdContentP[5], maxStringLength, "%d/MINS", mins);
|
||||
snprintf(HalvingCountdownScreen::epdContentP[6], maxStringLength, "TO/GO");
|
||||
|
||||
// // strcpy(epdContent[2], sprintf(String(years) + "/YRS").c_str());
|
||||
// // snprintf(epdContent[2], sizeof(epdContent[2]), "%d/YRS", years);
|
||||
// // strcpy(epdContent[3], String(days) + "/DAYS");
|
||||
// // strcpy(epdContent[4], String(hours) + "/HRS");
|
||||
// // strcpy(epdContent[5], String(mins) + "/MINS");
|
||||
}
|
||||
|
||||
uint HalvingCountdownScreen::getNextHalvingBlockNr()
|
||||
|
@ -46,5 +76,14 @@ void HalvingCountdownScreen::onNewBlock(uint blockNr)
|
|||
|
||||
std::array<String, NUM_SCREENS> HalvingCountdownScreen::getEpdContent()
|
||||
{
|
||||
return HalvingCountdownScreen::epdContent;
|
||||
std::array<String, NUM_SCREENS> ret;
|
||||
|
||||
if (!initialized) return ret;
|
||||
|
||||
for (int i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
ret[i] = HalvingCountdownScreen::epdContentP[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -6,15 +6,21 @@
|
|||
#include "tasks/epd.hpp"
|
||||
#include "tasks/blocknotify.hpp"
|
||||
|
||||
class HalvingCountdownScreen {
|
||||
protected:
|
||||
static uint currentBlockNr;
|
||||
static uint halvingBlockNr;
|
||||
static std::array<String, NUM_SCREENS> epdContent;
|
||||
public:
|
||||
static void init();
|
||||
static void showScreen();
|
||||
static void onNewBlock(uint blockNr);
|
||||
static uint getNextHalvingBlockNr();
|
||||
static std::array<String, NUM_SCREENS> getEpdContent();
|
||||
class HalvingCountdownScreen
|
||||
{
|
||||
protected:
|
||||
static uint currentBlockNr;
|
||||
static uint halvingBlockNr;
|
||||
//static std::array<char*, NUM_SCREENS> epdContent;
|
||||
// static char epdContent[NUM_SCREENS][12];
|
||||
static char** epdContentP;
|
||||
// static char **epdContent;
|
||||
static char *psramBuffer;
|
||||
|
||||
public:
|
||||
static void init();
|
||||
static void showScreen();
|
||||
static void onNewBlock(uint blockNr);
|
||||
static uint getNextHalvingBlockNr();
|
||||
static std::array<String, NUM_SCREENS> getEpdContent();
|
||||
};
|
|
@ -1,30 +1,30 @@
|
|||
#include "sats_per_dollar.hpp"
|
||||
// #include "sats_per_dollar.hpp"
|
||||
|
||||
uint SatsPerDollarScreen::satsPerDollar = 0;
|
||||
std::array<String, NUM_SCREENS> SatsPerDollarScreen::epdContent = { "", "", "", "", "", "", "" };
|
||||
// uint SatsPerDollarScreen::satsPerDollar = 0;
|
||||
// std::array<String, NUM_SCREENS> SatsPerDollarScreen::epdContent = { "", "", "", "", "", "", "" };
|
||||
|
||||
void SatsPerDollarScreen::init() {
|
||||
SatsPerDollarScreen::satsPerDollar = int(round(1 / preferences.getFloat("btcPrice", 12345) * 10e7));
|
||||
setupGetPriceTask();
|
||||
SatsPerDollarScreen::showScreen();
|
||||
}
|
||||
// void SatsPerDollarScreen::init() {
|
||||
// SatsPerDollarScreen::satsPerDollar = int(round(1 / preferences.getFloat("btcPrice", 12345) * 10e7));
|
||||
// setupGetPriceTask();
|
||||
// SatsPerDollarScreen::showScreen();
|
||||
// }
|
||||
|
||||
void SatsPerDollarScreen::showScreen() {
|
||||
std::string satsPerDollarString = String(SatsPerDollarScreen::satsPerDollar).c_str();
|
||||
satsPerDollarString.insert(satsPerDollarString.begin(), 7 - satsPerDollarString.length(), ' ');
|
||||
epdContent[0] = "MSCW/TIME";
|
||||
for (uint i = 1; i < NUM_SCREENS; i++)
|
||||
{
|
||||
SatsPerDollarScreen::epdContent[i] = satsPerDollarString[i];
|
||||
}
|
||||
}
|
||||
// void SatsPerDollarScreen::showScreen() {
|
||||
// std::string satsPerDollarString = String(SatsPerDollarScreen::satsPerDollar).c_str();
|
||||
// satsPerDollarString.insert(satsPerDollarString.begin(), 7 - satsPerDollarString.length(), ' ');
|
||||
// epdContent[0] = "MSCW/TIME";
|
||||
// for (uint i = 1; i < NUM_SCREENS; i++)
|
||||
// {
|
||||
// SatsPerDollarScreen::epdContent[i] = satsPerDollarString[i];
|
||||
// }
|
||||
// }
|
||||
|
||||
void SatsPerDollarScreen::onPriceUpdate(uint price) {
|
||||
SatsPerDollarScreen::satsPerDollar = int(round(1 / float(price) * 10e7));
|
||||
// void SatsPerDollarScreen::onPriceUpdate(uint price) {
|
||||
// SatsPerDollarScreen::satsPerDollar = int(round(1 / float(price) * 10e7));
|
||||
|
||||
SatsPerDollarScreen::showScreen();
|
||||
}
|
||||
// SatsPerDollarScreen::showScreen();
|
||||
// }
|
||||
|
||||
std::array<String, NUM_SCREENS> SatsPerDollarScreen::getEpdContent() {
|
||||
return SatsPerDollarScreen::epdContent;
|
||||
}
|
||||
// std::array<String, NUM_SCREENS> SatsPerDollarScreen::getEpdContent() {
|
||||
// return SatsPerDollarScreen::epdContent;
|
||||
// }
|
|
@ -1,17 +1,17 @@
|
|||
#pragma once
|
||||
// #pragma once
|
||||
|
||||
#include "base.hpp"
|
||||
#include "config.h"
|
||||
#include "shared.hpp"
|
||||
#include "tasks/epd.hpp"
|
||||
// #include "base.hpp"
|
||||
// #include "config.h"
|
||||
// #include "shared.hpp"
|
||||
// #include "tasks/epd.hpp"
|
||||
|
||||
class SatsPerDollarScreen {
|
||||
protected:
|
||||
static uint satsPerDollar;
|
||||
static std::array<String, NUM_SCREENS> epdContent;
|
||||
public:
|
||||
static void init();
|
||||
static void showScreen();
|
||||
static void onPriceUpdate(uint price);
|
||||
static std::array<String, NUM_SCREENS> getEpdContent();
|
||||
};
|
||||
// class SatsPerDollarScreen {
|
||||
// protected:
|
||||
// static uint satsPerDollar;
|
||||
// static std::array<String, NUM_SCREENS> epdContent;
|
||||
// public:
|
||||
// static void init();
|
||||
// static void showScreen();
|
||||
// static void onPriceUpdate(uint price);
|
||||
// static std::array<String, NUM_SCREENS> getEpdContent();
|
||||
// };
|
|
@ -1,10 +1,15 @@
|
|||
#include "ticker.hpp"
|
||||
|
||||
uint TickerScreen::price = 12345;
|
||||
uint TickerScreen::satsPerDollar = 3000;
|
||||
|
||||
std::array<String, NUM_SCREENS> TickerScreen::epdContent = { "", "", "", "", "", "", "" };
|
||||
|
||||
void TickerScreen::init() {
|
||||
|
||||
TickerScreen::price = preferences.getFloat("btcPrice", 12345);;
|
||||
TickerScreen::satsPerDollar = int(round(1 / preferences.getFloat("btcPrice", 12345) * 10e7));
|
||||
|
||||
setupGetPriceTask();
|
||||
TickerScreen::showScreen();
|
||||
}
|
||||
|
@ -21,9 +26,26 @@ void TickerScreen::showScreen() {
|
|||
|
||||
void TickerScreen::onPriceUpdate(uint price) {
|
||||
TickerScreen::price = price;
|
||||
TickerScreen::satsPerDollar = int(round(1 / float(price) * 10e7));
|
||||
|
||||
TickerScreen::showScreen();
|
||||
}
|
||||
|
||||
std::array<String, NUM_SCREENS> TickerScreen::getEpdContent() {
|
||||
return TickerScreen::epdContent;
|
||||
}
|
||||
|
||||
std::array<String, NUM_SCREENS> TickerScreen::getEpdContentSats() {
|
||||
std::array<String, NUM_SCREENS> epdContentSats = { "", "", "", "", "", "", "" };
|
||||
|
||||
std::string satsPerDollarString = String(TickerScreen::satsPerDollar).c_str();
|
||||
satsPerDollarString.insert(satsPerDollarString.begin(), NUM_SCREENS - satsPerDollarString.length(), ' ');
|
||||
epdContentSats[0] = "MSCW/TIME";
|
||||
for (uint i = 1; i < NUM_SCREENS; i++)
|
||||
{
|
||||
epdContentSats[i] = satsPerDollarString[i];
|
||||
}
|
||||
|
||||
|
||||
return epdContentSats;
|
||||
}
|
|
@ -9,11 +9,13 @@ class TickerScreen
|
|||
{
|
||||
protected:
|
||||
static uint price;
|
||||
static std::array<String, NUM_SCREENS> epdContent;
|
||||
static uint satsPerDollar;
|
||||
|
||||
static std::array<String, NUM_SCREENS> epdContent;
|
||||
public:
|
||||
static void init();
|
||||
static void showScreen();
|
||||
static void onPriceUpdate(uint price);
|
||||
static std::array<String, NUM_SCREENS> getEpdContent();
|
||||
static std::array<String, NUM_SCREENS> getEpdContentSats();
|
||||
};
|
|
@ -1,11 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
#include <Arduino.h>
|
||||
//##include <Crypto.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <WiFi.h>
|
||||
#include <map>
|
||||
|
||||
#ifdef IS_BW
|
||||
#include <GxEPD2_BW.h>
|
||||
#else
|
||||
#include <GxEPD2_3C.h>
|
||||
#endif
|
||||
|
||||
#include <WiFiClientSecure.h>
|
||||
#ifndef NO_MCP
|
||||
#include <Adafruit_MCP23X17.h>
|
||||
|
@ -19,7 +26,7 @@
|
|||
typedef std::function<void()> EventCallback;
|
||||
typedef std::function<void(uint number)> EventCallbackWithNumber;
|
||||
|
||||
extern WiFiClient wifiClientInsecure;
|
||||
//extern WiFiClient wifiClientInsecure;
|
||||
extern WiFiClientSecure wifiClient;
|
||||
|
||||
extern ESP32Time rtc;
|
||||
|
@ -32,9 +39,11 @@ extern bool timerRunning;
|
|||
extern uint timerSeconds;
|
||||
extern uint32_t moment;
|
||||
|
||||
extern GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> displays[NUM_SCREENS];
|
||||
|
||||
#ifndef NO_MCP
|
||||
extern Adafruit_MCP23X17 mcp;
|
||||
extern const int MCP_INT_PIN;
|
||||
extern const char MCP_INT_PIN;
|
||||
#endif
|
||||
#ifdef WITH_RGB_LED
|
||||
extern Adafruit_NeoPixel pixels;
|
||||
|
@ -53,13 +62,17 @@ const PROGMEM int screens[5] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_B
|
|||
const uint screenCount = sizeof(screens) / sizeof(int);
|
||||
|
||||
struct SpiRamAllocator {
|
||||
void* allocate(size_t size) {
|
||||
return ps_malloc(size);
|
||||
void* allocate(size_t size) {
|
||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
}
|
||||
void deallocate(void* pointer) {
|
||||
free(pointer);
|
||||
}
|
||||
void deallocate(void* pointer) {
|
||||
heap_caps_free(pointer);
|
||||
}
|
||||
|
||||
void* reallocate(void* ptr, size_t new_size) {
|
||||
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
};
|
||||
|
||||
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
|
||||
|
|
|
@ -20,11 +20,11 @@ void checkBitcoinBlock(void *pvParameters)
|
|||
uint blockHeight = preferences.getUInt("blockHeight", currentBlockHeight);
|
||||
|
||||
|
||||
useBitcoind = preferences.getBool("useNode", false) && wifiClientInsecure.connect(preferences.getString("rpcHost", BITCOIND_HOST).c_str(), preferences.getUInt("rpcPort", BITCOIND_PORT));
|
||||
useBitcoind = preferences.getBool("useNode", false) && wifiClient.connect(preferences.getString("rpcHost", BITCOIND_HOST).c_str(), preferences.getUInt("rpcPort", BITCOIND_PORT));
|
||||
if (useBitcoind)
|
||||
Serial.println("bitcoind node is reachable, using this for blocks.");
|
||||
Serial.println(F("bitcoind node is reachable, using this for blocks."));
|
||||
else
|
||||
Serial.println("bitcoind node is not reachable, using mempool API instead.");
|
||||
Serial.println(F("bitcoind node is not reachable, using mempool API instead."));
|
||||
|
||||
IPAddress result;
|
||||
|
||||
|
@ -36,53 +36,53 @@ void checkBitcoinBlock(void *pvParameters)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
HTTPClient http;
|
||||
http.setUserAgent(USER_AGENT);
|
||||
HTTPClient *http = new HTTPClient();
|
||||
http->setUserAgent(USER_AGENT);
|
||||
|
||||
if (useBitcoind)
|
||||
{
|
||||
StaticJsonDocument<200> jsonDoc;
|
||||
|
||||
http.begin(preferences.getString("rpcHost", BITCOIND_HOST).c_str(), preferences.getUInt("rpcPort", BITCOIND_PORT));
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
http->begin(preferences.getString("rpcHost", BITCOIND_HOST).c_str(), preferences.getUInt("rpcPort", BITCOIND_PORT));
|
||||
http->addHeader("Content-Type", "application/json");
|
||||
|
||||
const String payload = "{\"jsonrpc\":\"1.0\",\"id\":\"current_block_height\",\"method\":\"getblockcount\",\"params\":[]}";
|
||||
const String authEncoded = base64::encode(preferences.getString("rpcUser", BITCOIND_RPC_USER) + ":" + preferences.getString("rpcPass", BITCOIND_RPC_PASS));
|
||||
http.addHeader("Authorization", "Basic " + authEncoded);
|
||||
http->addHeader("Authorization", "Basic " + authEncoded);
|
||||
|
||||
int httpCode = http.POST(payload);
|
||||
int httpCode = http->POST(payload);
|
||||
if (httpCode > 0 || httpCode != HTTP_CODE_UNAUTHORIZED)
|
||||
{
|
||||
String response = http.getString();
|
||||
String response = http->getString();
|
||||
deserializeJson(jsonDoc, response);
|
||||
blockHeight = jsonDoc["result"];
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Error in HTTP request to bitcoind");
|
||||
Serial.println(F("Error in HTTP request to bitcoind"));
|
||||
}
|
||||
|
||||
http.end();
|
||||
http->end();
|
||||
}
|
||||
else
|
||||
{
|
||||
http.begin("https://" + preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE) + "/api/blocks/tip/height");
|
||||
int httpCode = http.GET();
|
||||
http->begin("https://" + preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE) + "/api/blocks/tip/height");
|
||||
int httpCode = http->GET();
|
||||
|
||||
if (httpCode > 0 && httpCode == HTTP_CODE_OK)
|
||||
{
|
||||
String blockHeightStr = http.getString();
|
||||
String blockHeightStr = http->getString();
|
||||
blockHeight = blockHeightStr.toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("Error in HTTP request to mempool API: "));
|
||||
Serial.print(httpCode);
|
||||
Serial.println(http.errorToString(httpCode));
|
||||
Serial.println(http->errorToString(httpCode));
|
||||
|
||||
}
|
||||
|
||||
http.end();
|
||||
http->end();
|
||||
}
|
||||
if (blockHeight > currentBlockHeight)
|
||||
{
|
||||
|
@ -93,7 +93,7 @@ void checkBitcoinBlock(void *pvParameters)
|
|||
currentBlockHeight = blockHeight;
|
||||
preferences.putUInt("blockHeight", currentBlockHeight);
|
||||
}
|
||||
|
||||
delete http;
|
||||
vTaskDelay(pdMS_TO_TICKS(BLOCKNOTIFY_WAIT_TIME)); // wait 1 minute before checking again
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ void setupBlockNotify()
|
|||
// xTaskCreate(bitcoinEventHandler, "bitcoinEventHandler", 10000, NULL, 110, NULL);
|
||||
}
|
||||
|
||||
void registerNewBlockCallback(EventCallbackWithNumber cb)
|
||||
void registerNewBlockCallback(const EventCallbackWithNumber cb)
|
||||
{
|
||||
blockEventCallbacks.push_back(cb);
|
||||
}
|
|
@ -22,6 +22,6 @@ void checkBitcoinBlock(void *pvParameters);
|
|||
//void bitcoinEventHandler(void *pvParameters);
|
||||
void setupBlockNotify();
|
||||
|
||||
void registerNewBlockCallback(EventCallbackWithNumber cb);
|
||||
void registerNewBlockCallback(const EventCallbackWithNumber cb);
|
||||
int getBlockFromBitcoind();
|
||||
int getBlockFromMempoolSpace();
|
|
@ -47,7 +47,7 @@ void buttonTask(void *parameter)
|
|||
void IRAM_ATTR handleButtonInterrupt()
|
||||
{
|
||||
buttonPressed = true;
|
||||
// Serial.println("ISR");
|
||||
// Serial.println(F("ISR"));
|
||||
// uint pin = mcp.getLastInterruptPin();
|
||||
|
||||
// if (pin == 1)
|
||||
|
@ -70,7 +70,7 @@ void setupButtonTask()
|
|||
// attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, FALLING);
|
||||
}
|
||||
|
||||
void registerNewButtonCallback(EventCallback cb)
|
||||
void registerNewButtonCallback(const EventCallback cb)
|
||||
{
|
||||
buttonEventCallbacks.push_back(cb);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ extern TaskHandle_t buttonTaskHandle;
|
|||
|
||||
void buttonTask(void *pvParameters);
|
||||
void setupButtonTask();
|
||||
void registerNewButtonCallback(EventCallback cb);
|
||||
void registerNewButtonCallback(const EventCallback cb);
|
||||
void IRAM_ATTR handleButtonInterrupt();
|
||||
|
||||
#endif
|
|
@ -1,17 +1,12 @@
|
|||
#include "epd.hpp"
|
||||
|
||||
#ifdef IS_S3
|
||||
// reversed
|
||||
// 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_RESET_MPD[7] = {14, 13, 12, 11, 10, 9, 8};
|
||||
const char EPD_CS[NUM_SCREENS] = {2, 4, 6, 10, 33, 21, 17};
|
||||
const char EPD_BUSY[NUM_SCREENS] = {3, 5, 7, 9, 37, 18, 16};
|
||||
const char EPD_RESET_MPD[NUM_SCREENS] = {8, 9, 10, 11, 12, 13, 14};
|
||||
|
||||
const int EPD_CS[NUM_SCREENS] = {2, 4, 6, 10, 33, 21, 17};
|
||||
const int EPD_BUSY[NUM_SCREENS] = {3, 5, 7, 9, 37, 18, 16};
|
||||
const int EPD_RESET_MPD[NUM_SCREENS] = {8, 9, 10, 11, 12, 13, 14};
|
||||
|
||||
const int EPD_DC = 14;
|
||||
const int RST_PIN = 15;
|
||||
const char EPD_DC = 14;
|
||||
const char RST_PIN = 15;
|
||||
#elif defined(IS_S2)
|
||||
|
||||
// reversed
|
||||
|
@ -56,7 +51,7 @@ GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> displays[NUM_SCREENS] = {
|
|||
GxEPD2_213_B74(EPD_CS[6], EPD_DC, /*RST=*/-1, EPD_BUSY[6]),
|
||||
};
|
||||
|
||||
//GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> * displays2 = (GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> *) ps_malloc(7 * sizeof (GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT>));
|
||||
// GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> * displays2 = (GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> *) ps_malloc(7 * sizeof (GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT>));
|
||||
|
||||
const int SEM_WAIT_TIME = 10000;
|
||||
|
||||
|
@ -81,7 +76,10 @@ std::array<String, 7> currentEpdContent;
|
|||
std::array<String, 7> epdContent;
|
||||
TaskHandle_t tasks[NUM_SCREENS];
|
||||
SemaphoreHandle_t epdUpdateSemaphore[NUM_SCREENS];
|
||||
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
|
||||
//
|
||||
|
||||
//int *qrcode = (int *) ps_malloc(qrcodegen_BUFFER_LEN_MAX * sizeof(uint8_t));
|
||||
|
||||
|
||||
void setupDisplays()
|
||||
{
|
||||
|
@ -91,7 +89,7 @@ void setupDisplays()
|
|||
|
||||
void resetAllDisplays()
|
||||
{
|
||||
#ifdef NO_MCP
|
||||
#ifdef NO_MCP
|
||||
digitalWrite(RST_PIN, HIGH);
|
||||
pinMode(RST_PIN, OUTPUT);
|
||||
delay(20);
|
||||
|
@ -99,23 +97,24 @@ void resetAllDisplays()
|
|||
delay(20);
|
||||
digitalWrite(RST_PIN, HIGH);
|
||||
delay(200);
|
||||
#else
|
||||
for (int i = 0; i < NUM_SCREENS; i++) {
|
||||
#else
|
||||
for (int i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
resetSingleDisplay(i);
|
||||
}
|
||||
#endif NO_MCP
|
||||
#endif
|
||||
}
|
||||
|
||||
void resetSingleDisplay(int i)
|
||||
{
|
||||
#ifndef NO_MCP
|
||||
#ifndef NO_MCP
|
||||
mcp.digitalWrite(EPD_RESET_MPD[i], HIGH);
|
||||
delay(20);
|
||||
mcp.digitalWrite(EPD_RESET_MPD[i], LOW);
|
||||
delay(20);
|
||||
mcp.digitalWrite(EPD_RESET_MPD[i], HIGH);
|
||||
delay(200);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void initDisplays()
|
||||
|
@ -166,7 +165,7 @@ void taskEpd(void *pvParameters)
|
|||
epdContent = TickerScreen::getEpdContent();
|
||||
break;
|
||||
case SCREEN_MSCW_TIME:
|
||||
epdContent = SatsPerDollarScreen::getEpdContent();
|
||||
epdContent = TickerScreen::getEpdContentSats();
|
||||
break;
|
||||
case SCREEN_TIME:
|
||||
epdContent = TimeScreen::getEpdContent();
|
||||
|
@ -182,10 +181,8 @@ void taskEpd(void *pvParameters)
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
bool updatedThisCycle = false;
|
||||
|
||||
|
||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
if (epdContent[i].compareTo(currentEpdContent[i]) != 0)
|
||||
|
@ -214,12 +211,12 @@ void taskEpd(void *pvParameters)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_RGB_LED
|
||||
#ifdef WITH_RGB_LED
|
||||
if (updatedThisCycle && preferences.getBool("ledFlashOnUpd", false))
|
||||
{
|
||||
xTaskNotifyGive(ledHandlerTaskHandle);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
@ -321,7 +318,7 @@ void updateDisplay(void *pvParameters)
|
|||
bool updatePartial = true;
|
||||
|
||||
// Full Refresh every half hour
|
||||
if (!lastFullRefresh[epdIndex] || (millis() - lastFullRefresh[epdIndex]) > (preferences.getUInt("fullRefreshMin", 30) * 60 * 1000))
|
||||
if (!lastFullRefresh[epdIndex] || (millis() - lastFullRefresh[epdIndex]) > (preferences.getUInt("fullRefreshMin", 30) * 60 * 1000))
|
||||
{
|
||||
updatePartial = false;
|
||||
lastFullRefresh[epdIndex] = millis();
|
||||
|
@ -346,96 +343,3 @@ void updateDisplay(void *pvParameters)
|
|||
}
|
||||
}
|
||||
|
||||
void showSetupQr(String ssid, String password)
|
||||
{
|
||||
int displayIndex = 6;
|
||||
|
||||
const String text = "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;";
|
||||
|
||||
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
|
||||
bool ok = qrcodegen_encodeText(text.c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
||||
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
||||
|
||||
const int size = qrcodegen_getSize(qrcode);
|
||||
|
||||
const int padding = floor(float(displays[displayIndex].width() - (size * 4)) / 2);
|
||||
const int paddingY = floor(float(displays[displayIndex].height() - (size * 4)) / 2);
|
||||
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].firstPage();
|
||||
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
int border = 0;
|
||||
do
|
||||
{
|
||||
for (int y = -border; y < size * 4 + border; y++)
|
||||
{
|
||||
for (int x = -border; x < size * 4 + border; x++)
|
||||
{
|
||||
displays[displayIndex].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
|
||||
}
|
||||
}
|
||||
} while (displays[displayIndex].nextPage());
|
||||
|
||||
displayIndex = 4;
|
||||
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].firstPage();
|
||||
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
do
|
||||
{
|
||||
displays[displayIndex].setTextColor(GxEPD_BLACK);
|
||||
displays[displayIndex].setCursor(0, 50);
|
||||
displays[displayIndex].setFont(&FreeSansBold9pt7b);
|
||||
displays[displayIndex].println("SSID:");
|
||||
displays[displayIndex].setFont(&FreeSans9pt7b);
|
||||
displays[displayIndex].println(ssid);
|
||||
displays[displayIndex].println("");
|
||||
displays[displayIndex].setFont(&FreeSansBold9pt7b);
|
||||
displays[displayIndex].println("Password:");
|
||||
displays[displayIndex].setFont(&FreeSans9pt7b);
|
||||
displays[displayIndex].println(password);
|
||||
} while (displays[displayIndex].nextPage());
|
||||
|
||||
displayIndex = 2;
|
||||
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].firstPage();
|
||||
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
do
|
||||
{
|
||||
displays[displayIndex].setTextColor(GxEPD_BLACK);
|
||||
displays[displayIndex].setCursor(0, 50);
|
||||
displays[displayIndex].setFont(&FreeSans9pt7b);
|
||||
displays[displayIndex].println("To setup");
|
||||
displays[displayIndex].println("scan QR or");
|
||||
displays[displayIndex].println("connect");
|
||||
displays[displayIndex].println("manually");
|
||||
} while (displays[displayIndex].nextPage());
|
||||
|
||||
displayIndex = 0;
|
||||
|
||||
displays[displayIndex].setPartialWindow(0, 0, displays[displayIndex].width(), displays[displayIndex].height());
|
||||
displays[displayIndex].firstPage();
|
||||
|
||||
displays[displayIndex].fillScreen(GxEPD_WHITE);
|
||||
do
|
||||
{
|
||||
displays[displayIndex].setTextColor(GxEPD_BLACK);
|
||||
displays[displayIndex].setCursor(0, 50);
|
||||
displays[displayIndex].setFont(&FreeSansBold9pt7b);
|
||||
displays[displayIndex].println("Welcome!");
|
||||
} while (displays[displayIndex].nextPage());
|
||||
|
||||
for (int i = 1; i < NUM_SCREENS; (i = i+2)) {
|
||||
displays[i].setPartialWindow(0, 0, displays[i].width(), displays[i].height());
|
||||
displays[i].fillScreen(GxEPD_WHITE);
|
||||
displays[i].display(true);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_SCREENS; i++) {
|
||||
displays[i].hibernate();
|
||||
}
|
||||
}
|
|
@ -5,8 +5,7 @@
|
|||
#else
|
||||
#include <GxEPD2_3C.h>
|
||||
#endif
|
||||
#include <Fonts/FreeSansBold9pt7b.h>
|
||||
#include <Fonts/FreeSans9pt7b.h>
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "screens/blockheight.hpp"
|
||||
|
@ -17,7 +16,6 @@
|
|||
#include "screens/custom_text.hpp"
|
||||
#include "screens/halvingcountdown.hpp"
|
||||
|
||||
#include "qrcodegen.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
@ -47,4 +45,3 @@ void refreshDisplay(void *pvParameters);
|
|||
void fullRefresh(void *pvParameters);
|
||||
void updateDisplay(void *pvParameters);
|
||||
//void genQrCode(String text, uint8_t *qrcode[qrcodegen_BUFFER_LEN_MAX]);
|
||||
void showSetupQr(String ssid, String password);
|
|
@ -14,29 +14,37 @@ TaskHandle_t getPriceTaskHandle;
|
|||
|
||||
void taskGetPrice(void *pvParameters)
|
||||
{
|
||||
IPAddress result;
|
||||
|
||||
int err = WiFi.hostByName("api.coingecko.com", result) ;
|
||||
|
||||
if (err != 1) {
|
||||
flashTemporaryLights(255, 255, 0);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
HTTPClient http;
|
||||
http.setUserAgent(USER_AGENT);
|
||||
HTTPClient* http = new HTTPClient();
|
||||
http->setUserAgent(USER_AGENT);
|
||||
|
||||
if (true)
|
||||
{
|
||||
// Send HTTP request to CoinGecko API
|
||||
http.begin(cgApiUrl);
|
||||
http->begin(cgApiUrl);
|
||||
|
||||
int httpCode = http.GET();
|
||||
int httpCode = http->GET();
|
||||
|
||||
// Parse JSON response and extract average price
|
||||
float usdPrice, eurPrice;
|
||||
if (httpCode == 200)
|
||||
{
|
||||
String payload = http.getString();
|
||||
String payload = http->getString();
|
||||
SpiRamJsonDocument doc(768);
|
||||
deserializeJson(doc, payload);
|
||||
JsonObject bpi = doc["bitcoin"];
|
||||
usdPrice = bpi["usd"];
|
||||
eurPrice = bpi["eur"];
|
||||
for (auto &callback : priceEventCallbacks)
|
||||
for (EventCallbackWithNumber &callback : priceEventCallbacks)
|
||||
{ // Loop through all the event callbacks and call them
|
||||
callback(usdPrice);
|
||||
}
|
||||
|
@ -52,21 +60,21 @@ void taskGetPrice(void *pvParameters)
|
|||
} else {
|
||||
|
||||
// Send HTTP request to CoinDesk API
|
||||
http.begin(apiUrl);
|
||||
http->begin(apiUrl);
|
||||
|
||||
int httpCode = http.GET();
|
||||
int httpCode = http->GET();
|
||||
|
||||
// Parse JSON response and extract average price
|
||||
float usdPrice, eurPrice;
|
||||
if (httpCode == 200)
|
||||
{
|
||||
String payload = http.getString();
|
||||
String payload = http->getString();
|
||||
SpiRamJsonDocument doc(768);
|
||||
deserializeJson(doc, payload);
|
||||
JsonObject bpi = doc["bpi"];
|
||||
usdPrice = bpi["USD"]["rate_float"];
|
||||
eurPrice = bpi["EUR"]["rate_float"];
|
||||
for (auto &callback : priceEventCallbacks)
|
||||
for (EventCallbackWithNumber &callback : priceEventCallbacks)
|
||||
{ // Loop through all the event callbacks and call them
|
||||
callback(usdPrice);
|
||||
}
|
||||
|
@ -81,7 +89,9 @@ void taskGetPrice(void *pvParameters)
|
|||
}
|
||||
}
|
||||
|
||||
http.end();
|
||||
http->end();
|
||||
|
||||
delete http;
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(PRICE_WAIT_TIME));
|
||||
}
|
||||
|
@ -91,12 +101,12 @@ void setupGetPriceTask()
|
|||
{
|
||||
if (getPriceTaskHandle == nullptr)
|
||||
{
|
||||
xTaskCreate(taskGetPrice, "getPrice", 8192, NULL, 1, &getPriceTaskHandle);
|
||||
xTaskCreate(taskGetPrice, "getPrice", 6144, NULL, 1, &getPriceTaskHandle);
|
||||
vTaskSuspend(getPriceTaskHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void registerNewPriceCallback(EventCallbackWithNumber cb)
|
||||
void registerNewPriceCallback(const EventCallbackWithNumber cb)
|
||||
{
|
||||
priceEventCallbacks.push_back(cb);
|
||||
}
|
|
@ -6,9 +6,10 @@
|
|||
#include <freertos/task.h>
|
||||
#include "shared.hpp"
|
||||
#include "config.h"
|
||||
#include "lib/functions.hpp"
|
||||
|
||||
extern TaskHandle_t getPriceTaskHandle;
|
||||
|
||||
void taskGetPrice(void *pvParameters);
|
||||
void setupGetPriceTask();
|
||||
void registerNewPriceCallback(EventCallbackWithNumber cb);
|
||||
void registerNewPriceCallback(const EventCallbackWithNumber cb);
|
|
@ -38,7 +38,7 @@ void setupMinuteEvent()
|
|||
xTaskCreate(minuteTask, "MinuteTask", 2048, NULL, 1, &minuteTaskHandle); // Create the FreeRTOS task
|
||||
}
|
||||
|
||||
void registerNewMinuteCallback(EventCallback cb)
|
||||
void registerNewMinuteCallback(const EventCallback cb)
|
||||
{
|
||||
minuteEventCallbacks.push_back(cb);
|
||||
}
|
|
@ -11,4 +11,4 @@ extern TaskHandle_t minuteTaskHandle;
|
|||
|
||||
void minuteTask(void *pvParameters);
|
||||
void setupMinuteEvent();
|
||||
void registerNewMinuteCallback(EventCallback cb);
|
||||
void registerNewMinuteCallback(const EventCallback cb);
|
Loading…
Reference in a new issue