mirror of
https://github.com/btclock/btclock_v3.git
synced 2024-11-19 06:20:02 +01:00
Add sats symbol option, add countdown in blocks, add decimal point for market cap, add hostname to setup screen
This commit is contained in:
parent
e4a39de5fc
commit
c49b8edcb8
2
data
2
data
@ -1 +1 @@
|
|||||||
Subproject commit 3f20d67f1abc10b20ddecfb5aa0ff4eb78c4c149
|
Subproject commit 1b8ab93da64dd7383a2fb34c967b75fdab072718
|
@ -1,11 +1,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
esp_littlefs:
|
esp_littlefs:
|
||||||
component_hash: 0e4812e62ac02a17f2b6a2bb3b6daf9b39e9599a6e319c745ef2a2817c15a073
|
component_hash: 66d5afe7ad323d0159d04e296c14ffa0e39156502bc15e0520eff2af392d3aa4
|
||||||
source:
|
source:
|
||||||
git: https://github.com/joltwallet/esp_littlefs.git
|
git: https://github.com/joltwallet/esp_littlefs.git
|
||||||
path: .
|
path: .
|
||||||
type: git
|
type: git
|
||||||
version: 5a0a9a0a39549ac55fd51d55bd3f895ffe700a0a
|
version: 41873c20fb5cdbcf28d7d6cc04e4bcb4a1305317
|
||||||
idf:
|
idf:
|
||||||
component_hash: null
|
component_hash: null
|
||||||
source:
|
source:
|
||||||
|
@ -5,7 +5,7 @@ std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char cu
|
|||||||
std::array<std::string, NUM_SCREENS> ret;
|
std::array<std::string, NUM_SCREENS> ret;
|
||||||
std::string priceString;
|
std::string priceString;
|
||||||
if (std::to_string(price).length() >= NUM_SCREENS) {
|
if (std::to_string(price).length() >= NUM_SCREENS) {
|
||||||
priceString = formatNumberWithSuffix(price);
|
priceString = formatNumberWithSuffix(price, NUM_SCREENS-2);
|
||||||
} else {
|
} else {
|
||||||
priceString = currencySymbol + std::to_string(price);
|
priceString = currencySymbol + std::to_string(price);
|
||||||
}
|
}
|
||||||
@ -32,15 +32,18 @@ std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char cu
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol)
|
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol)
|
||||||
{
|
{
|
||||||
std::array<std::string, NUM_SCREENS> ret;
|
std::array<std::string, NUM_SCREENS> ret;
|
||||||
std::string priceString = std::to_string(int(round(1 / float(price) * 10e7)));
|
std::string priceString = std::to_string(int(round(1 / float(price) * 10e7)));
|
||||||
std::uint32_t firstIndex = 0;
|
std::uint32_t firstIndex = 0;
|
||||||
|
uint insertSatSymbol = NUM_SCREENS - priceString.length() - 1;
|
||||||
|
|
||||||
if (priceString.length() < (NUM_SCREENS))
|
if (priceString.length() < (NUM_SCREENS))
|
||||||
{
|
{
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
|
||||||
|
|
||||||
if (currencySymbol == '[')
|
if (currencySymbol == '[')
|
||||||
{
|
{
|
||||||
ret[0] = "SATS/EUR";
|
ret[0] = "SATS/EUR";
|
||||||
@ -55,6 +58,10 @@ std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, c
|
|||||||
{
|
{
|
||||||
ret[i] = priceString[i];
|
ret[i] = priceString[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (withSatsSymbol) {
|
||||||
|
ret[insertSatSymbol] = "STS";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -80,24 +87,43 @@ std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight)
|
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks)
|
||||||
{
|
{
|
||||||
std::array<std::string, NUM_SCREENS> ret;
|
std::array<std::string, NUM_SCREENS> ret;
|
||||||
|
|
||||||
const std::uint32_t nextHalvingBlock = 210000 - (blockHeight % 210000);
|
const std::uint32_t nextHalvingBlock = 210000 - (blockHeight % 210000);
|
||||||
const std::uint32_t minutesToHalving = nextHalvingBlock * 10;
|
const std::uint32_t minutesToHalving = nextHalvingBlock * 10;
|
||||||
|
|
||||||
|
if (asBlocks) {
|
||||||
|
std::string blockNrString = std::to_string(nextHalvingBlock);
|
||||||
|
std::uint32_t firstIndex = 0;
|
||||||
|
|
||||||
|
if (blockNrString.length() < NUM_SCREENS)
|
||||||
|
{
|
||||||
|
blockNrString.insert(blockNrString.begin(), NUM_SCREENS - blockNrString.length(), ' ');
|
||||||
|
ret[0] = "HAL/VING";
|
||||||
|
firstIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
|
ret[i] = blockNrString[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
|
||||||
const int years = floor(minutesToHalving / 525600);
|
const int years = floor(minutesToHalving / 525600);
|
||||||
const int days = floor((minutesToHalving - (years * 525600)) / (24 * 60));
|
const int days = floor((minutesToHalving - (years * 525600)) / (24 * 60));
|
||||||
const int hours = floor((minutesToHalving - (years * 525600) - (days * (24 * 60))) / 60);
|
const int hours = floor((minutesToHalving - (years * 525600) - (days * (24 * 60))) / 60);
|
||||||
const int mins = floor(minutesToHalving - (years * 525600) - (days * (24 * 60)) - (hours * 60));
|
const int mins = floor(minutesToHalving - (years * 525600) - (days * (24 * 60)) - (hours * 60));
|
||||||
ret[0] = "BIT/COIN";
|
ret[0] = "BIT/COIN";
|
||||||
ret[1] = "HALV/ING";
|
ret[1] = "HAL/VING";
|
||||||
ret[(NUM_SCREENS - 5)] = std::to_string(years) + "/YRS";
|
ret[(NUM_SCREENS - 5)] = std::to_string(years) + "/YRS";
|
||||||
ret[(NUM_SCREENS - 4)] = std::to_string(days) + "/DAYS";
|
ret[(NUM_SCREENS - 4)] = std::to_string(days) + "/DAYS";
|
||||||
ret[(NUM_SCREENS - 3)] = std::to_string(hours) + "/HRS";
|
ret[(NUM_SCREENS - 3)] = std::to_string(hours) + "/HRS";
|
||||||
ret[(NUM_SCREENS - 2)] = std::to_string(mins) + "/MINS";
|
ret[(NUM_SCREENS - 2)] = std::to_string(mins) + "/MINS";
|
||||||
ret[(NUM_SCREENS - 1)] = "TO/GO";
|
ret[(NUM_SCREENS - 1)] = "TO/GO";
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -120,8 +146,9 @@ std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, s
|
|||||||
if (bigChars)
|
if (bigChars)
|
||||||
{
|
{
|
||||||
firstIndex = 1;
|
firstIndex = 1;
|
||||||
|
// Serial.print("Market cap: ");
|
||||||
std::string priceString = currencySymbol + formatNumberWithSuffix(marketCap);
|
// Serial.println(marketCap);
|
||||||
|
std::string priceString = currencySymbol + formatNumberWithSuffix(marketCap, (NUM_SCREENS-2));
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
|
||||||
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol);
|
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol);
|
||||||
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol);
|
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol);
|
||||||
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight);
|
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight);
|
||||||
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight);
|
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks);
|
||||||
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars);
|
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars);
|
@ -5,8 +5,10 @@ int modulo(int x, int N)
|
|||||||
return (x % N + N) % N;
|
return (x % N + N) % N;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getSupplyAtBlock(std::uint32_t blockNr) {
|
double getSupplyAtBlock(std::uint32_t blockNr)
|
||||||
if (blockNr >= 33 * 210000) {
|
{
|
||||||
|
if (blockNr >= 33 * 210000)
|
||||||
|
{
|
||||||
return 20999999.9769;
|
return 20999999.9769;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,7 +18,8 @@ double getSupplyAtBlock(std::uint32_t blockNr) {
|
|||||||
int halvingCount = blockNr / halvingInterval;
|
int halvingCount = blockNr / halvingInterval;
|
||||||
double totalBitcoinInCirculation = 0;
|
double totalBitcoinInCirculation = 0;
|
||||||
|
|
||||||
for (int i = 0; i < halvingCount; ++i) {
|
for (int i = 0; i < halvingCount; ++i)
|
||||||
|
{
|
||||||
totalBitcoinInCirculation += halvingInterval * initialBlockReward * std::pow(0.5, i);
|
totalBitcoinInCirculation += halvingInterval * initialBlockReward * std::pow(0.5, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,24 +28,58 @@ double getSupplyAtBlock(std::uint32_t blockNr) {
|
|||||||
return totalBitcoinInCirculation;
|
return totalBitcoinInCirculation;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string formatNumberWithSuffix(std::uint64_t num) {
|
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters)
|
||||||
|
{
|
||||||
|
static char result[20]; // Adjust size as needed
|
||||||
const long long quadrillion = 1000000000000000LL;
|
const long long quadrillion = 1000000000000000LL;
|
||||||
const long long trillion = 1000000000000LL;
|
const long long trillion = 1000000000000LL;
|
||||||
const long long billion = 1000000000;
|
const long long billion = 1000000000;
|
||||||
const long long million = 1000000;
|
const long long million = 1000000;
|
||||||
const long long thousand = 1000;
|
const long long thousand = 1000;
|
||||||
|
|
||||||
if (num >= quadrillion) {
|
double numDouble = (double)num;
|
||||||
return std::to_string(num / quadrillion) + "Q";
|
int numDigits = (int)log10(num) + 1;
|
||||||
} else if (num >= trillion) {
|
char suffix;
|
||||||
return std::to_string(num / trillion) + "T";
|
|
||||||
} else if (num >= billion) {
|
if (num >= quadrillion || numDigits > 15)
|
||||||
return std::to_string(num / billion) + "B";
|
{
|
||||||
} else if (num >= million) {
|
numDouble /= quadrillion;
|
||||||
return std::to_string(num / million) + "M";
|
suffix = 'Q';
|
||||||
} else if (num >= thousand) {
|
|
||||||
return std::to_string(num / thousand) + "K";
|
|
||||||
} else {
|
|
||||||
return std::to_string(num);
|
|
||||||
}
|
}
|
||||||
|
else if (num >= trillion || numDigits > 12)
|
||||||
|
{
|
||||||
|
numDouble /= trillion;
|
||||||
|
suffix = 'T';
|
||||||
|
}
|
||||||
|
else if (num >= billion || numDigits > 9)
|
||||||
|
{
|
||||||
|
numDouble /= billion;
|
||||||
|
suffix = 'B';
|
||||||
|
}
|
||||||
|
else if (num >= million || numDigits > 6)
|
||||||
|
{
|
||||||
|
numDouble /= million;
|
||||||
|
suffix = 'M';
|
||||||
|
}
|
||||||
|
else if (num >= thousand || numDigits > 3)
|
||||||
|
{
|
||||||
|
numDouble /= thousand;
|
||||||
|
suffix = 'K';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(result, "%llu", (unsigned long long)num);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add suffix
|
||||||
|
int len = snprintf(result, sizeof(result), "%.0f%c", numDouble, suffix);
|
||||||
|
|
||||||
|
// If there's room, add decimal places
|
||||||
|
if (len < numCharacters)
|
||||||
|
{
|
||||||
|
snprintf(result, sizeof(result), "%.*f%c", numCharacters - len - 1, numDouble, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
@ -3,9 +3,11 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
int modulo(int x,int N);
|
int modulo(int x,int N);
|
||||||
|
|
||||||
double getSupplyAtBlock(std::uint32_t blockNr);
|
double getSupplyAtBlock(std::uint32_t blockNr);
|
||||||
|
|
||||||
std::string formatNumberWithSuffix(std::uint64_t num);
|
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters = 4);
|
@ -5046,7 +5046,7 @@ const GFXglyph Antonio_SemiBold90pt7bGlyphs[] PROGMEM = {
|
|||||||
{9988, 53, 55, 63, 5, -94}, // 0x2B '+'
|
{9988, 53, 55, 63, 5, -94}, // 0x2B '+'
|
||||||
{10353, 23, 50, 41, 10, -20}, // 0x2C ','
|
{10353, 23, 50, 41, 10, -20}, // 0x2C ','
|
||||||
{10497, 39, 14, 60, 8, -75}, // 0x2D '-'
|
{10497, 39, 14, 60, 8, -75}, // 0x2D '-'
|
||||||
{10566, 17, 19, 46, 14, -18}, // 0x2E '.'
|
{10566, 17, 19, 46, 14, 106}, // 0x2E '.'
|
||||||
{10607, 55, 152, 66, 6, 105}, // 0x2F '/'
|
{10607, 55, 152, 66, 6, 105}, // 0x2F '/'
|
||||||
{11652, 59, 155, 79, 10, 104}, // 0x30 '0'
|
{11652, 59, 155, 79, 10, 104}, // 0x30 '0'
|
||||||
{12796, 41, 151, 67, 8, 106}, // 0x31 '1'
|
{12796, 41, 151, 67, 8, 106}, // 0x31 '1'
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "antonio-semibold30.h"
|
#include "antonio-semibold30.h"
|
||||||
#include "antonio-semibold40.h"
|
#include "antonio-semibold40.h"
|
||||||
#include "antonio-semibold90.h"
|
#include "antonio-semibold90.h"
|
||||||
|
#include "sats-symbol.h"
|
||||||
|
|
||||||
// #include "oswald-20.h"
|
// #include "oswald-20.h"
|
||||||
// #include "oswald-30.h"
|
// #include "oswald-30.h"
|
||||||
// #include "oswald-90.h"
|
// #include "oswald-90.h"
|
||||||
|
201
src/fonts/sats-symbol.h
Normal file
201
src/fonts/sats-symbol.h
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
const uint8_t Satoshi_Symbol90pt7bBitmaps[] PROGMEM = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
|
||||||
|
0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF,
|
||||||
|
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF,
|
||||||
|
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||||
|
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
|
||||||
|
0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF,
|
||||||
|
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF,
|
||||||
|
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
|
||||||
|
0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF,
|
||||||
|
0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
|
||||||
|
0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF,
|
||||||
|
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF8,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F,
|
||||||
|
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF,
|
||||||
|
0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||||
|
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFC,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
|
||||||
|
0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
|
||||||
|
0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF,
|
||||||
|
0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xE0 };
|
||||||
|
|
||||||
|
const GFXglyph Satoshi_Symbol90pt7bGlyphs[] PROGMEM = {
|
||||||
|
{ 0, 82, 127, 99, 8, -126 }, { 1302, 71, 109, 93, 0, -117 } }; // 0x53 'S'
|
||||||
|
|
||||||
|
const GFXfont Satoshi_Symbol90pt7b PROGMEM = {
|
||||||
|
(uint8_t *)Satoshi_Symbol90pt7bBitmaps,
|
||||||
|
(GFXglyph *)Satoshi_Symbol90pt7bGlyphs,
|
||||||
|
0x53, 0x53, 192 };
|
||||||
|
|
||||||
|
// Approx. 2284 bytes
|
@ -162,8 +162,7 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_BLOCK_HEIGHT &&
|
if (preferences.getBool("ledFlashOnUpd", false)) {
|
||||||
preferences.getBool("ledFlashOnUpd", false)) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
||||||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,19 @@ Adafruit_MCP23X17 mcp2;
|
|||||||
std::vector<std::string> screenNameMap(SCREEN_COUNT);
|
std::vector<std::string> screenNameMap(SCREEN_COUNT);
|
||||||
std::mutex mcpMutex;
|
std::mutex mcpMutex;
|
||||||
|
|
||||||
void setup() {
|
void setup()
|
||||||
|
{
|
||||||
setupPreferences();
|
setupPreferences();
|
||||||
setupHardware();
|
setupHardware();
|
||||||
setupDisplays();
|
setupDisplays();
|
||||||
if (preferences.getBool("ledTestOnPower", true)) {
|
if (preferences.getBool("ledTestOnPower", true))
|
||||||
|
{
|
||||||
queueLedEffect(LED_POWER_TEST);
|
queueLedEffect(LED_POWER_TEST);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
if (mcp1.digitalRead(3) == LOW) {
|
if (mcp1.digitalRead(3) == LOW)
|
||||||
|
{
|
||||||
preferences.putBool("wifiConfigured", false);
|
preferences.putBool("wifiConfigured", false);
|
||||||
preferences.remove("txPower");
|
preferences.remove("txPower");
|
||||||
|
|
||||||
@ -49,12 +52,25 @@ void setup() {
|
|||||||
forceFullRefresh();
|
forceFullRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tryImprovSetup() {
|
void tryImprovSetup()
|
||||||
|
{
|
||||||
WiFi.onEvent(WiFiEvent);
|
WiFi.onEvent(WiFiEvent);
|
||||||
|
WiFi.setAutoConnect(true);
|
||||||
|
WiFi.setAutoReconnect(true);
|
||||||
|
WiFi.begin();
|
||||||
|
if (preferences.getInt("txPower", 0))
|
||||||
|
{
|
||||||
|
if (WiFi.setTxPower(
|
||||||
|
static_cast<wifi_power_t>(preferences.getInt("txPower", 0))))
|
||||||
|
{
|
||||||
|
Serial.printf("WiFi max tx power set to %d\n",
|
||||||
|
preferences.getInt("txPower", 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (!preferences.getBool("wifiConfigured", false))
|
||||||
|
{
|
||||||
|
|
||||||
if (!preferences.getBool("wifiConfigured", false)) {
|
|
||||||
setFgColor(GxEPD_BLACK);
|
|
||||||
setBgColor(GxEPD_WHITE);
|
|
||||||
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
|
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
|
||||||
|
|
||||||
uint8_t x_buffer[16];
|
uint8_t x_buffer[16];
|
||||||
@ -84,13 +100,15 @@ void tryImprovSetup() {
|
|||||||
wm.setDebugOutput(false);
|
wm.setDebugOutput(false);
|
||||||
wm.setConfigPortalBlocking(true);
|
wm.setConfigPortalBlocking(true);
|
||||||
|
|
||||||
wm.setAPCallback([&](WiFiManager *wifiManager) {
|
wm.setAPCallback([&](WiFiManager *wifiManager)
|
||||||
|
{
|
||||||
// Serial.printf("Entered config mode:ip=%s, ssid='%s', pass='%s'\n",
|
// Serial.printf("Entered config mode:ip=%s, ssid='%s', pass='%s'\n",
|
||||||
// WiFi.softAPIP().toString().c_str(),
|
// WiFi.softAPIP().toString().c_str(),
|
||||||
// wifiManager->getConfigPortalSSID().c_str(),
|
// wifiManager->getConfigPortalSSID().c_str(),
|
||||||
// softAP_password.c_str());
|
// softAP_password.c_str());
|
||||||
// delay(6000);
|
// delay(6000);
|
||||||
|
setFgColor(GxEPD_BLACK);
|
||||||
|
setBgColor(GxEPD_WHITE);
|
||||||
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() +
|
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() +
|
||||||
";T:WPA;P:" + softAP_password.c_str() + ";;";
|
";T:WPA;P:" + softAP_password.c_str() + ";;";
|
||||||
const String explainText = "*SSID: *\r\n" +
|
const String explainText = "*SSID: *\r\n" +
|
||||||
@ -102,18 +120,17 @@ void tryImprovSetup() {
|
|||||||
"To setup\r\nscan QR or\r\nconnect\r\nmanually",
|
"To setup\r\nscan QR or\r\nconnect\r\nmanually",
|
||||||
"Para\r\nconfigurar\r\nescanear QR\r\no conectar\r\nmanualmente",
|
"Para\r\nconfigurar\r\nescanear QR\r\no conectar\r\nmanualmente",
|
||||||
explainText,
|
explainText,
|
||||||
" ",
|
"*Hostname*:\r\n" + getMyHostname(),
|
||||||
qrText};
|
qrText};
|
||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent); });
|
||||||
});
|
|
||||||
|
|
||||||
wm.setSaveConfigCallback([]() {
|
wm.setSaveConfigCallback([]()
|
||||||
|
{
|
||||||
preferences.putBool("wifiConfigured", true);
|
preferences.putBool("wifiConfigured", true);
|
||||||
|
|
||||||
delay(1000);
|
delay(1000);
|
||||||
// just restart after succes
|
// just restart after succes
|
||||||
ESP.restart();
|
ESP.restart(); });
|
||||||
});
|
|
||||||
|
|
||||||
bool ac = wm.autoConnect(softAP_SSID.c_str(), softAP_password.c_str());
|
bool ac = wm.autoConnect(softAP_SSID.c_str(), softAP_password.c_str());
|
||||||
|
|
||||||
@ -154,31 +171,26 @@ void tryImprovSetup() {
|
|||||||
}
|
}
|
||||||
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
||||||
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
||||||
} else {
|
|
||||||
WiFi.setAutoConnect(true);
|
|
||||||
WiFi.setAutoReconnect(true);
|
|
||||||
WiFi.begin();
|
|
||||||
if (preferences.getInt("txPower", 0)) {
|
|
||||||
if (WiFi.setTxPower(
|
|
||||||
static_cast<wifi_power_t>(preferences.getInt("txPower", 0)))) {
|
|
||||||
Serial.printf("WiFi max tx power set to %d\n",
|
|
||||||
preferences.getInt("txPower", 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
// while (WiFi.status() != WL_CONNECTED)
|
||||||
vTaskDelay(pdMS_TO_TICKS(400));
|
// {
|
||||||
}
|
// vTaskDelay(pdMS_TO_TICKS(400));
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
// queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
// queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTime() {
|
void setupTime()
|
||||||
|
{
|
||||||
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0,
|
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0,
|
||||||
NTP_SERVER);
|
NTP_SERVER);
|
||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
|
|
||||||
while (!getLocalTime(&timeinfo)) {
|
while (!getLocalTime(&timeinfo))
|
||||||
|
{
|
||||||
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0,
|
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0,
|
||||||
NTP_SERVER);
|
NTP_SERVER);
|
||||||
delay(500);
|
delay(500);
|
||||||
@ -186,7 +198,8 @@ void setupTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPreferences() {
|
void setupPreferences()
|
||||||
|
{
|
||||||
preferences.begin("btclock", false);
|
preferences.begin("btclock", false);
|
||||||
|
|
||||||
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
||||||
@ -202,36 +215,46 @@ void setupPreferences() {
|
|||||||
screenNameMap[SCREEN_MARKET_CAP] = "Market Cap";
|
screenNameMap[SCREEN_MARKET_CAP] = "Market Cap";
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupWebsocketClients(void *pvParameters) {
|
void setupWebsocketClients(void *pvParameters)
|
||||||
|
{
|
||||||
setupBlockNotify();
|
setupBlockNotify();
|
||||||
|
|
||||||
if (preferences.getBool("fetchEurPrice", false)) {
|
if (preferences.getBool("fetchEurPrice", false))
|
||||||
|
{
|
||||||
setupPriceFetchTask();
|
setupPriceFetchTask();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
setupPriceNotify();
|
setupPriceNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTimers() {
|
void setupTimers()
|
||||||
|
{
|
||||||
xTaskCreate(setupTimeUpdateTimer, "setupTimeUpdateTimer", 2048, NULL,
|
xTaskCreate(setupTimeUpdateTimer, "setupTimeUpdateTimer", 2048, NULL,
|
||||||
tskIDLE_PRIORITY, NULL);
|
tskIDLE_PRIORITY, NULL);
|
||||||
xTaskCreate(setupScreenRotateTimer, "setupScreenRotateTimer", 2048, NULL,
|
xTaskCreate(setupScreenRotateTimer, "setupScreenRotateTimer", 2048, NULL,
|
||||||
tskIDLE_PRIORITY, NULL);
|
tskIDLE_PRIORITY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void finishSetup() {
|
void finishSetup()
|
||||||
if (preferences.getBool("ledStatus", false)) {
|
{
|
||||||
|
if (preferences.getBool("ledStatus", false))
|
||||||
|
{
|
||||||
restoreLedState();
|
restoreLedState();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
clearLeds();
|
clearLeds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getScreenNameMap() { return screenNameMap; }
|
std::vector<std::string> getScreenNameMap() { return screenNameMap; }
|
||||||
|
|
||||||
void setupMcp() {
|
void setupMcp()
|
||||||
|
{
|
||||||
#ifdef IS_BTCLOCK_S3
|
#ifdef IS_BTCLOCK_S3
|
||||||
const int mcp1AddrPins[] = {MCP1_A0_PIN, MCP1_A1_PIN, MCP1_A2_PIN};
|
const int mcp1AddrPins[] = {MCP1_A0_PIN, MCP1_A1_PIN, MCP1_A2_PIN};
|
||||||
const int mcp1AddrValues[] = {LOW, LOW, LOW};
|
const int mcp1AddrValues[] = {LOW, LOW, LOW};
|
||||||
@ -242,7 +265,8 @@ void setupMcp() {
|
|||||||
pinMode(MCP_RESET_PIN, OUTPUT);
|
pinMode(MCP_RESET_PIN, OUTPUT);
|
||||||
digitalWrite(MCP_RESET_PIN, HIGH);
|
digitalWrite(MCP_RESET_PIN, HIGH);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
pinMode(mcp1AddrPins[i], OUTPUT);
|
pinMode(mcp1AddrPins[i], OUTPUT);
|
||||||
digitalWrite(mcp1AddrPins[i], mcp1AddrValues[i]);
|
digitalWrite(mcp1AddrPins[i], mcp1AddrValues[i]);
|
||||||
|
|
||||||
@ -256,19 +280,23 @@ void setupMcp() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupHardware() {
|
void setupHardware()
|
||||||
if (!LittleFS.begin(true)) {
|
{
|
||||||
|
if (!LittleFS.begin(true))
|
||||||
|
{
|
||||||
Serial.println(F("An Error has occurred while mounting LittleFS"));
|
Serial.println(F("An Error has occurred while mounting LittleFS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LittleFS.open("/index.html.gz", "r")) {
|
if (!LittleFS.open("/index.html.gz", "r"))
|
||||||
|
{
|
||||||
Serial.println("Error loading WebUI");
|
Serial.println("Error loading WebUI");
|
||||||
}
|
}
|
||||||
|
|
||||||
setupLeds();
|
setupLeds();
|
||||||
|
|
||||||
WiFi.setHostname(getMyHostname().c_str());
|
WiFi.setHostname(getMyHostname().c_str());
|
||||||
if (!psramInit()) {
|
if (!psramInit())
|
||||||
|
{
|
||||||
Serial.println(F("PSRAM not available"));
|
Serial.println(F("PSRAM not available"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,28 +304,34 @@ void setupHardware() {
|
|||||||
|
|
||||||
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
|
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
|
||||||
|
|
||||||
if (!mcp1.begin_I2C(0x20)) {
|
if (!mcp1.begin_I2C(0x20))
|
||||||
|
{
|
||||||
Serial.println(F("Error MCP23017"));
|
Serial.println(F("Error MCP23017"));
|
||||||
|
|
||||||
// while (1)
|
// while (1)
|
||||||
// ;
|
// ;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
pinMode(MCP_INT_PIN, INPUT_PULLUP);
|
pinMode(MCP_INT_PIN, INPUT_PULLUP);
|
||||||
mcp1.setupInterrupts(false, false, LOW);
|
mcp1.setupInterrupts(false, false, LOW);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
mcp1.pinMode(i, INPUT_PULLUP);
|
mcp1.pinMode(i, INPUT_PULLUP);
|
||||||
mcp1.setupInterruptPin(i, LOW);
|
mcp1.setupInterruptPin(i, LOW);
|
||||||
}
|
}
|
||||||
#ifndef IS_BTCLOCK_S3
|
#ifndef IS_BTCLOCK_S3
|
||||||
for (int i = 8; i <= 14; i++) {
|
for (int i = 8; i <= 14; i++)
|
||||||
|
{
|
||||||
mcp1.pinMode(i, OUTPUT);
|
mcp1.pinMode(i, OUTPUT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IS_BTCLOCK_S3
|
#ifdef IS_BTCLOCK_S3
|
||||||
if (!mcp2.begin_I2C(0x21)) {
|
if (!mcp2.begin_I2C(0x21))
|
||||||
|
{
|
||||||
Serial.println(F("Error MCP23017"));
|
Serial.println(F("Error MCP23017"));
|
||||||
|
|
||||||
// while (1)
|
// while (1)
|
||||||
@ -306,10 +340,12 @@ void setupHardware() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void improvGetAvailableWifiNetworks() {
|
void improvGetAvailableWifiNetworks()
|
||||||
|
{
|
||||||
int networkNum = WiFi.scanNetworks();
|
int networkNum = WiFi.scanNetworks();
|
||||||
|
|
||||||
for (int id = 0; id < networkNum; ++id) {
|
for (int id = 0; id < networkNum; ++id)
|
||||||
|
{
|
||||||
std::vector<uint8_t> data = improv::build_rpc_response(
|
std::vector<uint8_t> data = improv::build_rpc_response(
|
||||||
improv::GET_WIFI_NETWORKS,
|
improv::GET_WIFI_NETWORKS,
|
||||||
{WiFi.SSID(id), String(WiFi.RSSI(id)),
|
{WiFi.SSID(id), String(WiFi.RSSI(id)),
|
||||||
@ -323,15 +359,18 @@ void improvGetAvailableWifiNetworks() {
|
|||||||
improv_send_response(data);
|
improv_send_response(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool improv_connectWifi(std::string ssid, std::string password) {
|
bool improv_connectWifi(std::string ssid, std::string password)
|
||||||
|
{
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
|
|
||||||
WiFi.begin(ssid.c_str(), password.c_str());
|
WiFi.begin(ssid.c_str(), password.c_str());
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
blinkDelay(500, 2);
|
blinkDelay(500, 2);
|
||||||
|
|
||||||
if (count > MAX_ATTEMPTS_WIFI_CONNECTION) {
|
if (count > MAX_ATTEMPTS_WIFI_CONNECTION)
|
||||||
|
{
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -341,7 +380,8 @@ bool improv_connectWifi(std::string ssid, std::string password) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onImprovErrorCallback(improv::Error err) {
|
void onImprovErrorCallback(improv::Error err)
|
||||||
|
{
|
||||||
blinkDelayColor(100, 1, 255, 0, 0);
|
blinkDelayColor(100, 1, 255, 0, 0);
|
||||||
// pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
// pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||||
// pixels.setPixelColor(1, pixels.Color(255, 0, 0));
|
// pixels.setPixelColor(1, pixels.Color(255, 0, 0));
|
||||||
@ -355,29 +395,38 @@ void onImprovErrorCallback(improv::Error err) {
|
|||||||
// vTaskDelay(pdMS_TO_TICKS(100));
|
// vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getLocalUrl() {
|
std::vector<std::string> getLocalUrl()
|
||||||
|
{
|
||||||
return {// URL where user can finish onboarding or use device
|
return {// URL where user can finish onboarding or use device
|
||||||
// Recommended to use website hosted by device
|
// Recommended to use website hosted by device
|
||||||
String("http://" + WiFi.localIP().toString()).c_str()};
|
String("http://" + WiFi.localIP().toString()).c_str()};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onImprovCommandCallback(improv::ImprovCommand cmd) {
|
bool onImprovCommandCallback(improv::ImprovCommand cmd)
|
||||||
switch (cmd.command) {
|
{
|
||||||
case improv::Command::GET_CURRENT_STATE: {
|
switch (cmd.command)
|
||||||
if ((WiFi.status() == WL_CONNECTED)) {
|
{
|
||||||
|
case improv::Command::GET_CURRENT_STATE:
|
||||||
|
{
|
||||||
|
if ((WiFi.status() == WL_CONNECTED))
|
||||||
|
{
|
||||||
improv_set_state(improv::State::STATE_PROVISIONED);
|
improv_set_state(improv::State::STATE_PROVISIONED);
|
||||||
std::vector<uint8_t> data = improv::build_rpc_response(
|
std::vector<uint8_t> data = improv::build_rpc_response(
|
||||||
improv::GET_CURRENT_STATE, getLocalUrl(), false);
|
improv::GET_CURRENT_STATE, getLocalUrl(), false);
|
||||||
improv_send_response(data);
|
improv_send_response(data);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
improv_set_state(improv::State::STATE_AUTHORIZED);
|
improv_set_state(improv::State::STATE_AUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case improv::Command::WIFI_SETTINGS: {
|
case improv::Command::WIFI_SETTINGS:
|
||||||
if (cmd.ssid.length() == 0) {
|
{
|
||||||
|
if (cmd.ssid.length() == 0)
|
||||||
|
{
|
||||||
improv_set_error(improv::Error::ERROR_INVALID_RPC);
|
improv_set_error(improv::Error::ERROR_INVALID_RPC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -385,7 +434,8 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd) {
|
|||||||
improv_set_state(improv::STATE_PROVISIONING);
|
improv_set_state(improv::STATE_PROVISIONING);
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECTING);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECTING);
|
||||||
|
|
||||||
if (improv_connectWifi(cmd.ssid, cmd.password)) {
|
if (improv_connectWifi(cmd.ssid, cmd.password))
|
||||||
|
{
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||||
|
|
||||||
// std::array<String, NUM_SCREENS> epdContent = {"S", "U", "C", "C",
|
// std::array<String, NUM_SCREENS> epdContent = {"S", "U", "C", "C",
|
||||||
@ -401,7 +451,9 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd) {
|
|||||||
delay(2500);
|
delay(2500);
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
setupWebserver();
|
setupWebserver();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
||||||
|
|
||||||
improv_set_state(improv::STATE_STOPPED);
|
improv_set_state(improv::STATE_STOPPED);
|
||||||
@ -411,7 +463,8 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case improv::Command::GET_DEVICE_INFO: {
|
case improv::Command::GET_DEVICE_INFO:
|
||||||
|
{
|
||||||
std::vector<std::string> infos = {// Firmware name
|
std::vector<std::string> infos = {// Firmware name
|
||||||
"BTClock",
|
"BTClock",
|
||||||
// Firmware version
|
// Firmware version
|
||||||
@ -426,14 +479,16 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case improv::Command::GET_WIFI_NETWORKS: {
|
case improv::Command::GET_WIFI_NETWORKS:
|
||||||
|
{
|
||||||
improvGetAvailableWifiNetworks();
|
improvGetAvailableWifiNetworks();
|
||||||
// std::array<String, NUM_SCREENS> epdContent = {"W", "E", "B", "W", "I",
|
// std::array<String, NUM_SCREENS> epdContent = {"W", "E", "B", "W", "I",
|
||||||
// "F", "I"}; setEpdContent(epdContent);
|
// "F", "I"}; setEpdContent(epdContent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default:
|
||||||
|
{
|
||||||
improv_set_error(improv::ERROR_UNKNOWN_RPC);
|
improv_set_error(improv::ERROR_UNKNOWN_RPC);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -442,7 +497,8 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void improv_set_state(improv::State state) {
|
void improv_set_state(improv::State state)
|
||||||
|
{
|
||||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||||
data.resize(11);
|
data.resize(11);
|
||||||
data[6] = improv::IMPROV_SERIAL_VERSION;
|
data[6] = improv::IMPROV_SERIAL_VERSION;
|
||||||
@ -451,13 +507,15 @@ void improv_set_state(improv::State state) {
|
|||||||
data[9] = state;
|
data[9] = state;
|
||||||
|
|
||||||
uint8_t checksum = 0x00;
|
uint8_t checksum = 0x00;
|
||||||
for (uint8_t d : data) checksum += d;
|
for (uint8_t d : data)
|
||||||
|
checksum += d;
|
||||||
data[10] = checksum;
|
data[10] = checksum;
|
||||||
|
|
||||||
Serial.write(data.data(), data.size());
|
Serial.write(data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void improv_send_response(std::vector<uint8_t> &response) {
|
void improv_send_response(std::vector<uint8_t> &response)
|
||||||
|
{
|
||||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||||
data.resize(9);
|
data.resize(9);
|
||||||
data[6] = improv::IMPROV_SERIAL_VERSION;
|
data[6] = improv::IMPROV_SERIAL_VERSION;
|
||||||
@ -466,13 +524,15 @@ void improv_send_response(std::vector<uint8_t> &response) {
|
|||||||
data.insert(data.end(), response.begin(), response.end());
|
data.insert(data.end(), response.begin(), response.end());
|
||||||
|
|
||||||
uint8_t checksum = 0x00;
|
uint8_t checksum = 0x00;
|
||||||
for (uint8_t d : data) checksum += d;
|
for (uint8_t d : data)
|
||||||
|
checksum += d;
|
||||||
data.push_back(checksum);
|
data.push_back(checksum);
|
||||||
|
|
||||||
Serial.write(data.data(), data.size());
|
Serial.write(data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void improv_set_error(improv::Error error) {
|
void improv_set_error(improv::Error error)
|
||||||
|
{
|
||||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||||
data.resize(11);
|
data.resize(11);
|
||||||
data[6] = improv::IMPROV_SERIAL_VERSION;
|
data[6] = improv::IMPROV_SERIAL_VERSION;
|
||||||
@ -481,18 +541,21 @@ void improv_set_error(improv::Error error) {
|
|||||||
data[9] = error;
|
data[9] = error;
|
||||||
|
|
||||||
uint8_t checksum = 0x00;
|
uint8_t checksum = 0x00;
|
||||||
for (uint8_t d : data) checksum += d;
|
for (uint8_t d : data)
|
||||||
|
checksum += d;
|
||||||
data[10] = checksum;
|
data[10] = checksum;
|
||||||
|
|
||||||
Serial.write(data.data(), data.size());
|
Serial.write(data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
|
||||||
|
{
|
||||||
static bool first_connect = true;
|
static bool first_connect = true;
|
||||||
|
|
||||||
Serial.printf("[WiFi-event] event: %d\n", event);
|
Serial.printf("[WiFi-event] event: %d\n", event);
|
||||||
|
|
||||||
switch (event) {
|
switch (event)
|
||||||
|
{
|
||||||
case ARDUINO_EVENT_WIFI_READY:
|
case ARDUINO_EVENT_WIFI_READY:
|
||||||
Serial.println("WiFi interface ready");
|
Serial.println("WiFi interface ready");
|
||||||
break;
|
break;
|
||||||
@ -508,8 +571,10 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||||
Serial.println("Connected to access point");
|
Serial.println("Connected to access point");
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: {
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
if (!first_connect) {
|
{
|
||||||
|
if (!first_connect)
|
||||||
|
{
|
||||||
Serial.println("Disconnected from WiFi access point");
|
Serial.println("Disconnected from WiFi access point");
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
||||||
uint8_t reason = info.wifi_sta_disconnected.reason;
|
uint8_t reason = info.wifi_sta_disconnected.reason;
|
||||||
@ -522,10 +587,12 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||||||
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
||||||
Serial.println("Authentication mode of access point has changed");
|
Serial.println("Authentication mode of access point has changed");
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP: {
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
|
{
|
||||||
Serial.print("Obtained IP address: ");
|
Serial.print("Obtained IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
if (!first_connect) queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
if (!first_connect)
|
||||||
|
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||||
first_connect = false;
|
first_connect = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -563,7 +630,8 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getMyHostname() {
|
String getMyHostname()
|
||||||
|
{
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
// WiFi.macAddress(mac);
|
// WiFi.macAddress(mac);
|
||||||
esp_efuse_mac_get_default(mac);
|
esp_efuse_mac_get_default(mac);
|
||||||
|
235
src/lib/epd.cpp
235
src/lib/epd.cpp
@ -16,12 +16,21 @@ Native_Pin EPD_CS[NUM_SCREENS] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
Native_Pin EPD_BUSY[NUM_SCREENS] = {
|
Native_Pin EPD_BUSY[NUM_SCREENS] = {
|
||||||
Native_Pin(3), Native_Pin(5), Native_Pin(7), Native_Pin(9),
|
Native_Pin(3),
|
||||||
Native_Pin(37), Native_Pin(18), Native_Pin(16),
|
Native_Pin(5),
|
||||||
|
Native_Pin(7),
|
||||||
|
Native_Pin(9),
|
||||||
|
Native_Pin(37),
|
||||||
|
Native_Pin(18),
|
||||||
|
Native_Pin(16),
|
||||||
};
|
};
|
||||||
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp1, 8), MCP23X17_Pin(mcp1, 9), MCP23X17_Pin(mcp1, 10),
|
MCP23X17_Pin(mcp1, 8),
|
||||||
MCP23X17_Pin(mcp1, 11), MCP23X17_Pin(mcp1, 12), MCP23X17_Pin(mcp1, 13),
|
MCP23X17_Pin(mcp1, 9),
|
||||||
|
MCP23X17_Pin(mcp1, 10),
|
||||||
|
MCP23X17_Pin(mcp1, 11),
|
||||||
|
MCP23X17_Pin(mcp1, 12),
|
||||||
|
MCP23X17_Pin(mcp1, 13),
|
||||||
MCP23X17_Pin(mcp1, 14),
|
MCP23X17_Pin(mcp1, 14),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,9 +39,14 @@ Native_Pin EPD_DC = Native_Pin(14);
|
|||||||
Native_Pin EPD_DC = Native_Pin(38);
|
Native_Pin EPD_DC = Native_Pin(38);
|
||||||
|
|
||||||
MCP23X17_Pin EPD_BUSY[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_BUSY[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp1, 8), MCP23X17_Pin(mcp1, 9), MCP23X17_Pin(mcp1, 10),
|
MCP23X17_Pin(mcp1, 8),
|
||||||
MCP23X17_Pin(mcp1, 11), MCP23X17_Pin(mcp1, 12), MCP23X17_Pin(mcp1, 13),
|
MCP23X17_Pin(mcp1, 9),
|
||||||
MCP23X17_Pin(mcp1, 14), MCP23X17_Pin(mcp1, 4),
|
MCP23X17_Pin(mcp1, 10),
|
||||||
|
MCP23X17_Pin(mcp1, 11),
|
||||||
|
MCP23X17_Pin(mcp1, 12),
|
||||||
|
MCP23X17_Pin(mcp1, 13),
|
||||||
|
MCP23X17_Pin(mcp1, 14),
|
||||||
|
MCP23X17_Pin(mcp1, 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
|
||||||
@ -41,9 +55,14 @@ MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
|
|||||||
MCP23X17_Pin(mcp2, 4), MCP23X17_Pin(mcp2, 6)};
|
MCP23X17_Pin(mcp2, 4), MCP23X17_Pin(mcp2, 6)};
|
||||||
|
|
||||||
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp2, 9), MCP23X17_Pin(mcp2, 11), MCP23X17_Pin(mcp2, 13),
|
MCP23X17_Pin(mcp2, 9),
|
||||||
MCP23X17_Pin(mcp2, 15), MCP23X17_Pin(mcp2, 1), MCP23X17_Pin(mcp2, 3),
|
MCP23X17_Pin(mcp2, 11),
|
||||||
MCP23X17_Pin(mcp2, 5), MCP23X17_Pin(mcp2, 7),
|
MCP23X17_Pin(mcp2, 13),
|
||||||
|
MCP23X17_Pin(mcp2, 15),
|
||||||
|
MCP23X17_Pin(mcp2, 1),
|
||||||
|
MCP23X17_Pin(mcp2, 3),
|
||||||
|
MCP23X17_Pin(mcp2, 5),
|
||||||
|
MCP23X17_Pin(mcp2, 7),
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -78,24 +97,30 @@ int bgColor = GxEPD_BLACK;
|
|||||||
#define FONT_SMALL Antonio_SemiBold20pt7b
|
#define FONT_SMALL Antonio_SemiBold20pt7b
|
||||||
#define FONT_BIG Antonio_SemiBold90pt7b
|
#define FONT_BIG Antonio_SemiBold90pt7b
|
||||||
#define FONT_MEDIUM Antonio_SemiBold40pt7b
|
#define FONT_MEDIUM Antonio_SemiBold40pt7b
|
||||||
|
#define FONT_SATSYMBOL Satoshi_Symbol90pt7b
|
||||||
std::mutex epdUpdateMutex;
|
std::mutex epdUpdateMutex;
|
||||||
std::mutex epdMutex[NUM_SCREENS];
|
std::mutex epdMutex[NUM_SCREENS];
|
||||||
|
|
||||||
uint8_t qrcode[800];
|
uint8_t qrcode[800];
|
||||||
|
|
||||||
void forceFullRefresh() {
|
void forceFullRefresh()
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++) {
|
{
|
||||||
|
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
lastFullRefresh[i] = NULL;
|
lastFullRefresh[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshFromMemory() {
|
void refreshFromMemory()
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++) {
|
{
|
||||||
|
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
int *taskParam = new int;
|
int *taskParam = new int;
|
||||||
*taskParam = i;
|
*taskParam = i;
|
||||||
|
|
||||||
xTaskCreate(
|
xTaskCreate(
|
||||||
[](void *pvParameters) {
|
[](void *pvParameters)
|
||||||
|
{
|
||||||
const int epdIndex = *(int *)pvParameters;
|
const int epdIndex = *(int *)pvParameters;
|
||||||
delete (int *)pvParameters;
|
delete (int *)pvParameters;
|
||||||
displays[epdIndex].refresh(false);
|
displays[epdIndex].refresh(false);
|
||||||
@ -105,10 +130,12 @@ void refreshFromMemory() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupDisplays() {
|
void setupDisplays()
|
||||||
|
{
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++) {
|
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
displays[i].init(0, true, 30);
|
displays[i].init(0, true, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +143,8 @@ void setupDisplays() {
|
|||||||
|
|
||||||
xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", 4096, NULL, 11, NULL);
|
xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", 4096, NULL, 11, NULL);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++) {
|
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
// epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
// epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
||||||
// xSemaphoreGive(epdUpdateSemaphore[i]);
|
// xSemaphoreGive(epdUpdateSemaphore[i]);
|
||||||
|
|
||||||
@ -132,14 +160,17 @@ void setupDisplays() {
|
|||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent) {
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent)
|
||||||
|
{
|
||||||
setEpdContent(newEpdContent, false);
|
setEpdContent(newEpdContent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent) {
|
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent)
|
||||||
|
{
|
||||||
std::array<String, NUM_SCREENS> conv;
|
std::array<String, NUM_SCREENS> conv;
|
||||||
|
|
||||||
for (size_t i = 0; i < newEpdContent.size(); ++i) {
|
for (size_t i = 0; i < newEpdContent.size(); ++i)
|
||||||
|
{
|
||||||
conv[i] = String(newEpdContent[i].c_str());
|
conv[i] = String(newEpdContent[i].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,13 +178,16 @@ void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent,
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent,
|
||||||
bool forceUpdate) {
|
bool forceUpdate)
|
||||||
|
{
|
||||||
std::lock_guard<std::mutex> lock(epdUpdateMutex);
|
std::lock_guard<std::mutex> lock(epdUpdateMutex);
|
||||||
|
|
||||||
waitUntilNoneBusy();
|
waitUntilNoneBusy();
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++) {
|
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||||
if (newEpdContent[i].compareTo(currentEpdContent[i]) != 0 || forceUpdate) {
|
{
|
||||||
|
if (newEpdContent[i].compareTo(currentEpdContent[i]) != 0 || forceUpdate)
|
||||||
|
{
|
||||||
epdContent[i] = newEpdContent[i];
|
epdContent[i] = newEpdContent[i];
|
||||||
UpdateDisplayTaskItem dispUpdate = {i};
|
UpdateDisplayTaskItem dispUpdate = {i};
|
||||||
xQueueSend(updateQueue, &dispUpdate, portMAX_DELAY);
|
xQueueSend(updateQueue, &dispUpdate, portMAX_DELAY);
|
||||||
@ -161,12 +195,15 @@ void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareDisplayUpdateTask(void *pvParameters) {
|
void prepareDisplayUpdateTask(void *pvParameters)
|
||||||
|
{
|
||||||
UpdateDisplayTaskItem receivedItem;
|
UpdateDisplayTaskItem receivedItem;
|
||||||
|
|
||||||
while (1) {
|
while (1)
|
||||||
|
{
|
||||||
// Wait for a work item to be available in the queue
|
// Wait for a work item to be available in the queue
|
||||||
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY)) {
|
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY))
|
||||||
|
{
|
||||||
uint epdIndex = receivedItem.dispNum;
|
uint epdIndex = receivedItem.dispNum;
|
||||||
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
||||||
// displays[epdIndex].init(0, false); // Little longer reset duration
|
// displays[epdIndex].init(0, false); // Little longer reset duration
|
||||||
@ -174,23 +211,43 @@ void prepareDisplayUpdateTask(void *pvParameters) {
|
|||||||
|
|
||||||
bool updatePartial = true;
|
bool updatePartial = true;
|
||||||
|
|
||||||
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL) {
|
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL)
|
||||||
|
{
|
||||||
String top = epdContent[epdIndex].substring(
|
String top = epdContent[epdIndex].substring(
|
||||||
0, epdContent[epdIndex].indexOf("/"));
|
0, epdContent[epdIndex].indexOf("/"));
|
||||||
String bottom = epdContent[epdIndex].substring(
|
String bottom = epdContent[epdIndex].substring(
|
||||||
epdContent[epdIndex].indexOf("/") + 1);
|
epdContent[epdIndex].indexOf("/") + 1);
|
||||||
splitText(epdIndex, top, bottom, updatePartial);
|
splitText(epdIndex, top, bottom, updatePartial);
|
||||||
} else if (epdContent[epdIndex].startsWith(F("qr"))) {
|
}
|
||||||
|
else if (epdContent[epdIndex].startsWith(F("qr")))
|
||||||
|
{
|
||||||
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
} else if (epdContent[epdIndex].length() > 5) {
|
}
|
||||||
|
else if (epdContent[epdIndex].length() > 5)
|
||||||
|
{
|
||||||
renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
} else {
|
}
|
||||||
if (epdContent[epdIndex].length() > 1) {
|
else
|
||||||
|
{
|
||||||
|
if (epdContent[epdIndex].length() > 1 && epdContent[epdIndex].indexOf(".") == -1)
|
||||||
|
{
|
||||||
|
if (epdContent[epdIndex].equals("STS"))
|
||||||
|
{
|
||||||
|
showDigit(epdIndex, 'S', updatePartial,
|
||||||
|
&FONT_SATSYMBOL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
showChars(epdIndex, epdContent[epdIndex], updatePartial,
|
showChars(epdIndex, epdContent[epdIndex], updatePartial,
|
||||||
&FONT_MEDIUM);
|
&FONT_MEDIUM);
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial,
|
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial,
|
||||||
&FONT_BIG);
|
&FONT_BIG);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,11 +256,13 @@ void prepareDisplayUpdateTask(void *pvParameters) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void updateDisplay(void *pvParameters) noexcept {
|
extern "C" void updateDisplay(void *pvParameters) noexcept
|
||||||
|
{
|
||||||
const int epdIndex = *(int *)pvParameters;
|
const int epdIndex = *(int *)pvParameters;
|
||||||
delete (int *)pvParameters;
|
delete (int *)pvParameters;
|
||||||
|
|
||||||
for (;;) {
|
for (;;)
|
||||||
|
{
|
||||||
// Wait for the task notification
|
// Wait for the task notification
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
@ -215,7 +274,8 @@ extern "C" void updateDisplay(void *pvParameters) noexcept {
|
|||||||
displays[epdIndex].init(0, false, 40);
|
displays[epdIndex].init(0, false, 40);
|
||||||
}
|
}
|
||||||
uint count = 0;
|
uint count = 0;
|
||||||
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10) {
|
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10)
|
||||||
|
{
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@ -227,16 +287,20 @@ extern "C" void updateDisplay(void *pvParameters) noexcept {
|
|||||||
(millis() - lastFullRefresh[epdIndex]) >
|
(millis() - lastFullRefresh[epdIndex]) >
|
||||||
(preferences.getUInt("fullRefreshMin",
|
(preferences.getUInt("fullRefreshMin",
|
||||||
DEFAULT_MINUTES_FULL_REFRESH) *
|
DEFAULT_MINUTES_FULL_REFRESH) *
|
||||||
60 * 1000)) {
|
60 * 1000))
|
||||||
|
{
|
||||||
updatePartial = false;
|
updatePartial = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char tries = 0;
|
char tries = 0;
|
||||||
while (tries < 3) {
|
while (tries < 3)
|
||||||
if (displays[epdIndex].displayWithReturn(updatePartial)) {
|
{
|
||||||
|
if (displays[epdIndex].displayWithReturn(updatePartial))
|
||||||
|
{
|
||||||
displays[epdIndex].powerOff();
|
displays[epdIndex].powerOff();
|
||||||
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
||||||
if (!updatePartial) lastFullRefresh[epdIndex] = millis();
|
if (!updatePartial)
|
||||||
|
lastFullRefresh[epdIndex] = millis();
|
||||||
|
|
||||||
if (eventSourceTaskHandle != NULL)
|
if (eventSourceTaskHandle != NULL)
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
@ -251,7 +315,8 @@ extern "C" void updateDisplay(void *pvParameters) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void splitText(const uint dispNum, const String &top, const String &bottom,
|
void splitText(const uint dispNum, const String &top, const String &bottom,
|
||||||
bool partial) {
|
bool partial)
|
||||||
|
{
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(&FONT_SMALL);
|
displays[dispNum].setFont(&FONT_SMALL);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
@ -290,24 +355,67 @@ void splitText(const uint dispNum, const String &top, const String &bottom,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial,
|
void showDigit(const uint dispNum, char chr, bool partial,
|
||||||
const GFXfont *font) {
|
const GFXfont *font)
|
||||||
|
{
|
||||||
String str(chr);
|
String str(chr);
|
||||||
|
|
||||||
|
if (chr == '.')
|
||||||
|
{
|
||||||
|
str = "!";
|
||||||
|
}
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(font);
|
displays[dispNum].setFont(font);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
int16_t tbx, tby;
|
int16_t tbx, tby;
|
||||||
uint16_t tbw, tbh;
|
uint16_t tbw, tbh;
|
||||||
|
|
||||||
displays[dispNum].getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh);
|
displays[dispNum].getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||||
|
|
||||||
// center the bounding box by transposition of the origin:
|
// center the bounding box by transposition of the origin:
|
||||||
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
||||||
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
||||||
|
|
||||||
|
// if (str.equals("."))
|
||||||
|
// {
|
||||||
|
// // int16_t yAdvance = font->yAdvance;
|
||||||
|
// // uint8_t charIndex = 46 - font->first;
|
||||||
|
// // GFXglyph *glyph = (&font->glyph)[charIndex];
|
||||||
|
// int16_t tbx2, tby2;
|
||||||
|
// uint16_t tbw2, tbh2;
|
||||||
|
// displays[dispNum].getTextBounds(".!", 0, 0, &tbx2, &tby2, &tbw2, &tbh2);
|
||||||
|
|
||||||
|
// y = ((displays[dispNum].height() - tbh2) / 2) - tby2;
|
||||||
|
// // Serial.print("yAdvance");
|
||||||
|
// // Serial.println(yAdvance);
|
||||||
|
// // if (glyph != nullptr) {
|
||||||
|
// // Serial.print("height");
|
||||||
|
// // Serial.println(glyph->height);
|
||||||
|
// // Serial.print("yOffset");
|
||||||
|
// // Serial.println(glyph->yOffset);
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // y = 250-99+18+19;
|
||||||
|
// }
|
||||||
|
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
displays[dispNum].fillScreen(getBgColor());
|
||||||
|
|
||||||
displays[dispNum].setCursor(x, y);
|
displays[dispNum].setCursor(x, y);
|
||||||
displays[dispNum].print(str);
|
displays[dispNum].print(str);
|
||||||
|
|
||||||
|
if (chr == '.')
|
||||||
|
{
|
||||||
|
displays[dispNum].fillRect(x,y,displays[dispNum].width(),round(displays[dispNum].height() * 0.9), getBgColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
// displays[dispNum].setCursor(10, 3);
|
||||||
|
// displays[dispNum].setFont(&FONT_SMALL);
|
||||||
|
// displays[dispNum].setTextColor(getFgColor());
|
||||||
|
// displays[dispNum].println("Y = " + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showChars(const uint dispNum, const String &chars, bool partial,
|
void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
const GFXfont *font) {
|
const GFXfont *font)
|
||||||
|
{
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(font);
|
displays[dispNum].setFont(font);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
@ -330,10 +438,12 @@ void setBgColor(int color) { bgColor = color; }
|
|||||||
|
|
||||||
void setFgColor(int color) { fgColor = color; }
|
void setFgColor(int color) { fgColor = color; }
|
||||||
|
|
||||||
std::array<String, NUM_SCREENS> getCurrentEpdContent() {
|
std::array<String, NUM_SCREENS> getCurrentEpdContent()
|
||||||
|
{
|
||||||
return currentEpdContent;
|
return currentEpdContent;
|
||||||
}
|
}
|
||||||
void renderText(const uint dispNum, const String &text, bool partial) {
|
void renderText(const uint dispNum, const String &text, bool partial)
|
||||||
|
{
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
||||||
displays[dispNum].height());
|
displays[dispNum].height());
|
||||||
@ -346,20 +456,25 @@ void renderText(const uint dispNum, const String &text, bool partial) {
|
|||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
while (std::getline(ss, line, '\n')) {
|
while (std::getline(ss, line, '\n'))
|
||||||
if (line.rfind("*", 0) == 0) {
|
{
|
||||||
|
if (line.rfind("*", 0) == 0)
|
||||||
|
{
|
||||||
line.erase(std::remove(line.begin(), line.end(), '*'), line.end());
|
line.erase(std::remove(line.begin(), line.end(), '*'), line.end());
|
||||||
|
|
||||||
displays[dispNum].setFont(&FreeSansBold9pt7b);
|
displays[dispNum].setFont(&FreeSansBold9pt7b);
|
||||||
displays[dispNum].println(line.c_str());
|
displays[dispNum].println(line.c_str());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
displays[dispNum].setFont(&FreeSans9pt7b);
|
displays[dispNum].setFont(&FreeSans9pt7b);
|
||||||
displays[dispNum].println(line.c_str());
|
displays[dispNum].println(line.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQr(const uint dispNum, const String &text, bool partial) {
|
void renderQr(const uint dispNum, const String &text, bool partial)
|
||||||
|
{
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
|
|
||||||
uint8_t tempBuffer[800];
|
uint8_t tempBuffer[800];
|
||||||
@ -379,8 +494,10 @@ void renderQr(const uint dispNum, const String &text, bool partial) {
|
|||||||
displays[dispNum].fillScreen(GxEPD_WHITE);
|
displays[dispNum].fillScreen(GxEPD_WHITE);
|
||||||
const int border = 0;
|
const int border = 0;
|
||||||
|
|
||||||
for (int y = -border; y < size * 4 + border; y++) {
|
for (int y = -border; y < size * 4 + border; y++)
|
||||||
for (int x = -border; x < size * 4 + border; x++) {
|
{
|
||||||
|
for (int x = -border; x < size * 4 + border; x++)
|
||||||
|
{
|
||||||
displays[dispNum].drawPixel(
|
displays[dispNum].drawPixel(
|
||||||
padding + x, paddingY + y,
|
padding + x, paddingY + y,
|
||||||
qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4))
|
qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4))
|
||||||
@ -391,16 +508,22 @@ void renderQr(const uint dispNum, const String &text, bool partial) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitUntilNoneBusy() {
|
void waitUntilNoneBusy()
|
||||||
for (int i = 0; i < NUM_SCREENS; i++) {
|
{
|
||||||
|
for (int i = 0; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
uint count = 0;
|
uint count = 0;
|
||||||
while (EPD_BUSY[i].digitalRead()) {
|
while (EPD_BUSY[i].digitalRead())
|
||||||
|
{
|
||||||
count++;
|
count++;
|
||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
if (count == 200) {
|
if (count == 200)
|
||||||
|
{
|
||||||
// displays[i].init(0, false);
|
// displays[i].init(0, false);
|
||||||
vTaskDelay(100);
|
vTaskDelay(100);
|
||||||
} else if (count > 205) {
|
}
|
||||||
|
else if (count > 205)
|
||||||
|
{
|
||||||
Serial.printf("Busy timeout %d", i);
|
Serial.printf("Busy timeout %d", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ void workerTask(void *pvParameters) {
|
|||||||
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
||||||
taskEpdContent = parsePriceData(price, priceSymbol);
|
taskEpdContent = parsePriceData(price, priceSymbol);
|
||||||
} else if (getCurrentScreen() == SCREEN_MSCW_TIME) {
|
} else if (getCurrentScreen() == SCREEN_MSCW_TIME) {
|
||||||
taskEpdContent = parseSatsPerCurrency(price, priceSymbol);
|
taskEpdContent = parseSatsPerCurrency(price, priceSymbol, preferences.getBool("useSatsSymbol", false));
|
||||||
} else {
|
} else {
|
||||||
taskEpdContent =
|
taskEpdContent =
|
||||||
parseMarketCap(getBlockHeight(), price, priceSymbol,
|
parseMarketCap(getBlockHeight(), price, priceSymbol,
|
||||||
@ -50,7 +50,7 @@ void workerTask(void *pvParameters) {
|
|||||||
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN) {
|
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN) {
|
||||||
taskEpdContent = parseBlockHeight(getBlockHeight());
|
taskEpdContent = parseBlockHeight(getBlockHeight());
|
||||||
} else {
|
} else {
|
||||||
taskEpdContent = parseHalvingCountdown(getBlockHeight());
|
taskEpdContent = parseHalvingCountdown(getBlockHeight(), preferences.getBool("useBlkCountdown", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN ||
|
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN ||
|
||||||
|
@ -11,7 +11,7 @@ void setupWebserver() {
|
|||||||
server.addHandler(&events);
|
server.addHandler(&events);
|
||||||
|
|
||||||
// server.serveStatic("/css", LittleFS, "/css/");
|
// server.serveStatic("/css", LittleFS, "/css/");
|
||||||
// server.serveStatic("/js", LittleFS, "/js/");
|
server.serveStatic("/fonts", LittleFS, "/fonts/");
|
||||||
server.serveStatic("/build", LittleFS, "/build");
|
server.serveStatic("/build", LittleFS, "/build");
|
||||||
server.serveStatic("/swagger.json", LittleFS, "/swagger.json");
|
server.serveStatic("/swagger.json", LittleFS, "/swagger.json");
|
||||||
server.serveStatic("/api.html", LittleFS, "/api.html");
|
server.serveStatic("/api.html", LittleFS, "/api.html");
|
||||||
@ -320,7 +320,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json) {
|
|||||||
|
|
||||||
String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd",
|
String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd",
|
||||||
"mdnsEnabled", "otaEnabled", "stealFocus",
|
"mdnsEnabled", "otaEnabled", "stealFocus",
|
||||||
"mcapBigChar"};
|
"mcapBigChar", "useSatsSymbol", "useBlkCountdown"};
|
||||||
|
|
||||||
for (String setting : boolSettings) {
|
for (String setting : boolSettings) {
|
||||||
if (settings.containsKey(setting)) {
|
if (settings.containsKey(setting)) {
|
||||||
@ -402,11 +402,14 @@ void onApiSettingsGet(AsyncWebServerRequest *request) {
|
|||||||
root["ledTestOnPower"] = preferences.getBool("ledTestOnPower", true);
|
root["ledTestOnPower"] = preferences.getBool("ledTestOnPower", true);
|
||||||
root["ledFlashOnUpd"] = preferences.getBool("ledFlashOnUpd", false);
|
root["ledFlashOnUpd"] = preferences.getBool("ledFlashOnUpd", false);
|
||||||
root["ledBrightness"] = preferences.getUInt("ledBrightness", 128);
|
root["ledBrightness"] = preferences.getUInt("ledBrightness", 128);
|
||||||
root["stealFocus"] = preferences.getBool("stealFocus", true);
|
root["stealFocus"] = preferences.getBool("stealFocus", false);
|
||||||
root["mcapBigChar"] = preferences.getBool("mcapBigChar", true);
|
root["mcapBigChar"] = preferences.getBool("mcapBigChar", true);
|
||||||
root["mdnsEnabled"] = preferences.getBool("mdnsEnabled", true);
|
root["mdnsEnabled"] = preferences.getBool("mdnsEnabled", true);
|
||||||
root["otaEnabled"] = preferences.getBool("otaEnabled", true);
|
root["otaEnabled"] = preferences.getBool("otaEnabled", true);
|
||||||
root["fetchEurPrice"] = preferences.getBool("fetchEurPrice", false);
|
root["fetchEurPrice"] = preferences.getBool("fetchEurPrice", false);
|
||||||
|
root["useSatsSymbol"] = preferences.getBool("useSatsSymbol", false);
|
||||||
|
root["useBlkCountdown"] = preferences.getBool("useBlkCountdown", false);
|
||||||
|
|
||||||
root["hostnamePrefix"] = preferences.getString("hostnamePrefix", "btclock");
|
root["hostnamePrefix"] = preferences.getString("hostnamePrefix", "btclock");
|
||||||
root["hostname"] = getMyHostname();
|
root["hostname"] = getMyHostname();
|
||||||
root["ip"] = WiFi.localIP();
|
root["ip"] = WiFi.localIP();
|
||||||
|
@ -10,7 +10,7 @@ void tearDown(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_CorrectSatsPerDollarConversion(void) {
|
void test_CorrectSatsPerDollarConversion(void) {
|
||||||
std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(37253, '$');
|
std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(37253, '$', false);
|
||||||
TEST_ASSERT_EQUAL_STRING("MSCW/TIME", output[0].c_str());
|
TEST_ASSERT_EQUAL_STRING("MSCW/TIME", output[0].c_str());
|
||||||
TEST_ASSERT_EQUAL_STRING("2", output[NUM_SCREENS-4].c_str());
|
TEST_ASSERT_EQUAL_STRING("2", output[NUM_SCREENS-4].c_str());
|
||||||
TEST_ASSERT_EQUAL_STRING("6", output[NUM_SCREENS-3].c_str());
|
TEST_ASSERT_EQUAL_STRING("6", output[NUM_SCREENS-3].c_str());
|
||||||
@ -40,13 +40,49 @@ void test_PriceOf100kusd(void) {
|
|||||||
void test_PriceOf1MillionUsd(void) {
|
void test_PriceOf1MillionUsd(void) {
|
||||||
std::array<std::string, NUM_SCREENS> output = parsePriceData(1000000, '$');
|
std::array<std::string, NUM_SCREENS> output = parsePriceData(1000000, '$');
|
||||||
TEST_ASSERT_EQUAL_STRING("BTC/USD", output[0].c_str());
|
TEST_ASSERT_EQUAL_STRING("BTC/USD", output[0].c_str());
|
||||||
for (int i = 1; i <= NUM_SCREENS-3; i++) {
|
|
||||||
TEST_ASSERT_EQUAL_STRING(" ", output[i].c_str());
|
TEST_ASSERT_EQUAL_STRING("1", output[NUM_SCREENS-5].c_str());
|
||||||
}
|
TEST_ASSERT_EQUAL_STRING(".", output[NUM_SCREENS-4].c_str());
|
||||||
TEST_ASSERT_EQUAL_STRING("1", output[NUM_SCREENS-2].c_str());
|
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS-3].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS-2].c_str());
|
||||||
TEST_ASSERT_EQUAL_STRING("M", output[NUM_SCREENS-1].c_str());
|
TEST_ASSERT_EQUAL_STRING("M", output[NUM_SCREENS-1].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_McapLowerUsd(void) {
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parseMarketCap(810000, 26000, '$', true);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("USD/MCAP", output[0].c_str());
|
||||||
|
|
||||||
|
// TEST_ASSERT_EQUAL_STRING("$", output[NUM_SCREENS-6].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("$", output[NUM_SCREENS-5].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("5", output[NUM_SCREENS-4].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS-3].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("7", output[NUM_SCREENS-2].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("B", output[NUM_SCREENS-1].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_Mcap1TrillionUsd(void) {
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parseMarketCap(831000, 52000, '$', true);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("USD/MCAP", output[0].c_str());
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_STRING("$", output[NUM_SCREENS-6].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("1", output[NUM_SCREENS-5].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING(".", output[NUM_SCREENS-4].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS-3].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("2", output[NUM_SCREENS-2].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("T", output[NUM_SCREENS-1].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_Mcap1TrillionEur(void) {
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parseMarketCap(831000, 52000, '[', true);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("EUR/MCAP", output[0].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("[", output[NUM_SCREENS-6].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("1", output[NUM_SCREENS-5].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING(".", output[NUM_SCREENS-4].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS-3].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("2", output[NUM_SCREENS-2].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("T", output[NUM_SCREENS-1].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// not needed when using generate_test_runner.rb
|
// not needed when using generate_test_runner.rb
|
||||||
int runUnityTests(void) {
|
int runUnityTests(void) {
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
@ -54,7 +90,10 @@ int runUnityTests(void) {
|
|||||||
RUN_TEST(test_SixCharacterBlockHeight);
|
RUN_TEST(test_SixCharacterBlockHeight);
|
||||||
RUN_TEST(test_SevenCharacterBlockHeight);
|
RUN_TEST(test_SevenCharacterBlockHeight);
|
||||||
RUN_TEST(test_PriceOf100kusd);
|
RUN_TEST(test_PriceOf100kusd);
|
||||||
RUN_TEST(test_PriceOf1MillionUsd);
|
RUN_TEST(test_McapLowerUsd);
|
||||||
|
RUN_TEST(test_Mcap1TrillionUsd);
|
||||||
|
RUN_TEST(test_Mcap1TrillionEur);
|
||||||
|
//RUN_TEST(test_Mcap1MillionEur);
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user