Merge remote-tracking branch 'upstream/develop' into fix/tlora-pager-rotary-amplifier

This commit is contained in:
WillyJL
2025-09-21 21:12:06 +02:00
21 changed files with 878 additions and 714 deletions
+43
View File
@@ -0,0 +1,43 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_16MB.csv",
"memory_type": "qio_qspi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "qspi",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "heltec_v4"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "heltec_wifi_lora_32 v4 (16 MB FLASH, 2 MB PSRAM)",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 2097152,
"maximum_size": 16777216,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "https://heltec.org/",
"vendor": "heltec"
}
+2
View File
@@ -516,6 +516,7 @@ bool GPS::setup()
} }
} }
// Rare Serial Speeds // Rare Serial Speeds
#ifndef CONFIG_IDF_TARGET_ESP32C6
if (probeTries == GPS_PROBETRIES) { if (probeTries == GPS_PROBETRIES) {
LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]); LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]);
gnssModel = probe(rareSerialSpeeds[speedSelect]); gnssModel = probe(rareSerialSpeeds[speedSelect]);
@@ -526,6 +527,7 @@ bool GPS::setup()
} }
} }
} }
#endif
} }
if (gnssModel != GNSS_MODEL_UNKNOWN) { if (gnssModel != GNSS_MODEL_UNKNOWN) {
+75 -78
View File
@@ -953,7 +953,6 @@ void Screen::setFrames(FrameFocus focus)
} }
#if defined(DISPLAY_CLOCK_FRAME) #if defined(DISPLAY_CLOCK_FRAME)
if (!hiddenFrames.clock) {
if (!hiddenFrames.clock) { if (!hiddenFrames.clock) {
fsi.positions.clock = numframes; fsi.positions.clock = numframes;
#if defined(M5STACK_UNITC6L) #if defined(M5STACK_UNITC6L)
@@ -963,6 +962,7 @@ void Screen::setFrames(FrameFocus focus)
: graphics::ClockRenderer::drawDigitalClockFrame; : graphics::ClockRenderer::drawDigitalClockFrame;
#endif #endif
indicatorIcons.push_back(digital_icon_clock); indicatorIcons.push_back(digital_icon_clock);
}
#endif #endif
// Declare this early so its available in FOCUS_PRESERVE block // Declare this early so its available in FOCUS_PRESERVE block
@@ -1037,7 +1037,7 @@ void Screen::setFrames(FrameFocus focus)
if (!hiddenFrames.chirpy) { if (!hiddenFrames.chirpy) {
fsi.positions.chirpy = numframes; fsi.positions.chirpy = numframes;
normalFrames[numframes++] = graphics::DebugRenderer::drawChirpy; normalFrames[numframes++] = graphics::DebugRenderer::drawChirpy;
indicatorIcons.push_back(small_chirpy); indicatorIcons.push_back(chirpy_small);
} }
#if HAS_WIFI && !defined(ARCH_PORTDUINO) #if HAS_WIFI && !defined(ARCH_PORTDUINO)
@@ -1116,8 +1116,7 @@ void Screen::setFrames(FrameFocus focus)
ui->disableAllIndicators(); ui->disableAllIndicators();
// Add overlays: frame icons and alert banner) // Add overlays: frame icons and alert banner)
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
NotificationRenderer::drawBannercallback};
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list just changed) prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list just changed)
@@ -1164,17 +1163,17 @@ void Screen::setFrames(FrameFocus focus)
this->framesetInfo = fsi; this->framesetInfo = fsi;
setFastFramerate(); // Draw ASAP setFastFramerate(); // Draw ASAP
} }
void Screen::setFrameImmediateDraw(FrameCallback * drawFrames) void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
{ {
ui->disableAllIndicators(); ui->disableAllIndicators();
ui->setFrames(drawFrames, 1); ui->setFrames(drawFrames, 1);
setFastFramerate(); setFastFramerate();
} }
void Screen::toggleFrameVisibility(const std::string &frameName) void Screen::toggleFrameVisibility(const std::string &frameName)
{ {
#ifndef USE_EINK #ifndef USE_EINK
if (frameName == "nodelist") { if (frameName == "nodelist") {
hiddenFrames.nodelist = !hiddenFrames.nodelist; hiddenFrames.nodelist = !hiddenFrames.nodelist;
@@ -1211,10 +1210,10 @@ void Screen::setFrames(FrameFocus focus)
if (frameName == "chirpy") { if (frameName == "chirpy") {
hiddenFrames.chirpy = !hiddenFrames.chirpy; hiddenFrames.chirpy = !hiddenFrames.chirpy;
} }
} }
bool Screen::isFrameHidden(const std::string &frameName) const bool Screen::isFrameHidden(const std::string &frameName) const
{ {
#ifndef USE_EINK #ifndef USE_EINK
if (frameName == "nodelist") if (frameName == "nodelist")
return hiddenFrames.nodelist; return hiddenFrames.nodelist;
@@ -1243,13 +1242,13 @@ void Screen::setFrames(FrameFocus focus)
return hiddenFrames.chirpy; return hiddenFrames.chirpy;
return false; return false;
} }
// Dismisses the currently displayed screen frame, if possible // Dismisses the currently displayed screen frame, if possible
// Relevant for text message, waypoint, others in future? // Relevant for text message, waypoint, others in future?
// Triggered with a CardKB keycombo // Triggered with a CardKB keycombo
void Screen::hideCurrentFrame() void Screen::hideCurrentFrame()
{ {
uint8_t currentFrame = ui->getUiState()->currentFrame; uint8_t currentFrame = ui->getUiState()->currentFrame;
bool dismissed = false; bool dismissed = false;
if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) { if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) {
@@ -1274,20 +1273,20 @@ void Screen::setFrames(FrameFocus focus)
if (dismissed) { if (dismissed) {
setFrames(FOCUS_DEFAULT); // You could also use FOCUS_PRESERVE setFrames(FOCUS_DEFAULT); // You could also use FOCUS_PRESERVE
} }
} }
void Screen::handleStartFirmwareUpdateScreen() void Screen::handleStartFirmwareUpdateScreen()
{ {
LOG_DEBUG("Show firmware screen"); LOG_DEBUG("Show firmware screen");
showingNormalScreen = false; showingNormalScreen = false;
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame
static FrameCallback frames[] = {graphics::NotificationRenderer::drawFrameFirmware}; static FrameCallback frames[] = {graphics::NotificationRenderer::drawFrameFirmware};
setFrameImmediateDraw(frames); setFrameImmediateDraw(frames);
} }
void Screen::blink() void Screen::blink()
{ {
setFastFramerate(); setFastFramerate();
uint8_t count = 10; uint8_t count = 10;
dispdev->setBrightness(254); dispdev->setBrightness(254);
@@ -1303,10 +1302,10 @@ void Screen::setFrames(FrameFocus focus)
// The dispdev->setBrightness does not work for t-deck display, it seems to run the setBrightness function in // The dispdev->setBrightness does not work for t-deck display, it seems to run the setBrightness function in
// OLEDDisplay. // OLEDDisplay.
dispdev->setBrightness(brightness); dispdev->setBrightness(brightness);
} }
void Screen::increaseBrightness() void Screen::increaseBrightness()
{ {
brightness = ((brightness + 62) > 254) ? brightness : (brightness + 62); brightness = ((brightness + 62) > 254) ? brightness : (brightness + 62);
#if defined(ST7789_CS) #if defined(ST7789_CS)
@@ -1315,10 +1314,10 @@ void Screen::setFrames(FrameFocus focus)
#endif #endif
/* TO DO: add little popup in center of screen saying what brightness level it is set to*/ /* TO DO: add little popup in center of screen saying what brightness level it is set to*/
} }
void Screen::decreaseBrightness() void Screen::decreaseBrightness()
{ {
brightness = (brightness < 70) ? brightness : (brightness - 62); brightness = (brightness < 70) ? brightness : (brightness - 62);
#if defined(ST7789_CS) #if defined(ST7789_CS)
@@ -1326,10 +1325,10 @@ void Screen::setFrames(FrameFocus focus)
#endif #endif
/* TO DO: add little popup in center of screen saying what brightness level it is set to*/ /* TO DO: add little popup in center of screen saying what brightness level it is set to*/
} }
void Screen::setFunctionSymbol(std::string sym) void Screen::setFunctionSymbol(std::string sym)
{ {
if (std::find(functionSymbol.begin(), functionSymbol.end(), sym) == functionSymbol.end()) { if (std::find(functionSymbol.begin(), functionSymbol.end(), sym) == functionSymbol.end()) {
functionSymbol.push_back(sym); functionSymbol.push_back(sym);
functionSymbolString = ""; functionSymbolString = "";
@@ -1338,20 +1337,20 @@ void Screen::setFrames(FrameFocus focus)
} }
setFastFramerate(); setFastFramerate();
} }
} }
void Screen::removeFunctionSymbol(std::string sym) void Screen::removeFunctionSymbol(std::string sym)
{ {
functionSymbol.erase(std::remove(functionSymbol.begin(), functionSymbol.end(), sym), functionSymbol.end()); functionSymbol.erase(std::remove(functionSymbol.begin(), functionSymbol.end(), sym), functionSymbol.end());
functionSymbolString = ""; functionSymbolString = "";
for (auto symbol : functionSymbol) { for (auto symbol : functionSymbol) {
functionSymbolString = symbol + " " + functionSymbolString; functionSymbolString = symbol + " " + functionSymbolString;
} }
setFastFramerate(); setFastFramerate();
} }
void Screen::handleOnPress() void Screen::handleOnPress()
{ {
// If screen was off, just wake it, otherwise advance to next frame // If screen was off, just wake it, otherwise advance to next frame
// If we are in a transition, the press must have bounced, drop it. // If we are in a transition, the press must have bounced, drop it.
if (ui->getUiState()->frameState == FIXED) { if (ui->getUiState()->frameState == FIXED) {
@@ -1359,10 +1358,10 @@ void Screen::setFrames(FrameFocus focus)
lastScreenTransition = millis(); lastScreenTransition = millis();
setFastFramerate(); setFastFramerate();
} }
} }
void Screen::handleShowPrevFrame() void Screen::handleShowPrevFrame()
{ {
// If screen was off, just wake it, otherwise go back to previous frame // If screen was off, just wake it, otherwise go back to previous frame
// If we are in a transition, the press must have bounced, drop it. // If we are in a transition, the press must have bounced, drop it.
if (ui->getUiState()->frameState == FIXED) { if (ui->getUiState()->frameState == FIXED) {
@@ -1370,10 +1369,10 @@ void Screen::setFrames(FrameFocus focus)
lastScreenTransition = millis(); lastScreenTransition = millis();
setFastFramerate(); setFastFramerate();
} }
} }
void Screen::handleShowNextFrame() void Screen::handleShowNextFrame()
{ {
// If screen was off, just wake it, otherwise advance to next frame // If screen was off, just wake it, otherwise advance to next frame
// If we are in a transition, the press must have bounced, drop it. // If we are in a transition, the press must have bounced, drop it.
if (ui->getUiState()->frameState == FIXED) { if (ui->getUiState()->frameState == FIXED) {
@@ -1381,14 +1380,14 @@ void Screen::setFrames(FrameFocus focus)
lastScreenTransition = millis(); lastScreenTransition = millis();
setFastFramerate(); setFastFramerate();
} }
} }
#ifndef SCREEN_TRANSITION_FRAMERATE #ifndef SCREEN_TRANSITION_FRAMERATE
#define SCREEN_TRANSITION_FRAMERATE 30 // fps #define SCREEN_TRANSITION_FRAMERATE 30 // fps
#endif #endif
void Screen::setFastFramerate() void Screen::setFastFramerate()
{ {
#if defined(M5STACK_UNITC6L) #if defined(M5STACK_UNITC6L)
dispdev->clear(); dispdev->clear();
dispdev->display(); dispdev->display();
@@ -1399,10 +1398,10 @@ void Screen::setFrames(FrameFocus focus)
ui->setTargetFPS(targetFramerate); ui->setTargetFPS(targetFramerate);
setInterval(0); // redraw ASAP setInterval(0); // redraw ASAP
runASAP = true; runASAP = true;
} }
int Screen::handleStatusUpdate(const meshtastic::Status *arg) int Screen::handleStatusUpdate(const meshtastic::Status *arg)
{ {
// LOG_DEBUG("Screen got status update %d", arg->getStatusType()); // LOG_DEBUG("Screen got status update %d", arg->getStatusType());
switch (arg->getStatusType()) { switch (arg->getStatusType()) {
case STATUS_TYPE_NODE: case STATUS_TYPE_NODE:
@@ -1414,11 +1413,11 @@ void Screen::setFrames(FrameFocus focus)
} }
return 0; return 0;
} }
// Handles when message is received; will jump to text message frame. // Handles when message is received; will jump to text message frame.
int Screen::handleTextMessage(const meshtastic_MeshPacket *packet) int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
{ {
if (showingNormalScreen) { if (showingNormalScreen) {
if (packet->from == 0) { if (packet->from == 0) {
// Outgoing message (likely sent from phone) // Outgoing message (likely sent from phone)
@@ -1485,11 +1484,11 @@ void Screen::setFrames(FrameFocus focus)
} }
return 0; return 0;
} }
// Triggered by MeshModules // Triggered by MeshModules
int Screen::handleUIFrameEvent(const UIFrameEvent *event) int Screen::handleUIFrameEvent(const UIFrameEvent *event)
{ {
// Block UI frame events when virtual keyboard is active // Block UI frame events when virtual keyboard is active
if (NotificationRenderer::current_notification_type == notificationTypeEnum::text_input) { if (NotificationRenderer::current_notification_type == notificationTypeEnum::text_input) {
return 0; return 0;
@@ -1510,18 +1509,17 @@ void Screen::setFrames(FrameFocus focus)
} }
return 0; return 0;
} }
int Screen::handleInputEvent(const InputEvent *event) int Screen::handleInputEvent(const InputEvent *event)
{ {
if (!screenOn) if (!screenOn)
return 0; return 0;
// Handle text input notifications specially - pass input to virtual keyboard // Handle text input notifications specially - pass input to virtual keyboard
if (NotificationRenderer::current_notification_type == notificationTypeEnum::text_input) { if (NotificationRenderer::current_notification_type == notificationTypeEnum::text_input) {
NotificationRenderer::inEvent = *event; NotificationRenderer::inEvent = *event;
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
NotificationRenderer::drawBannercallback};
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
setFastFramerate(); // Draw ASAP setFastFramerate(); // Draw ASAP
ui->update(); ui->update();
@@ -1536,8 +1534,7 @@ void Screen::setFrames(FrameFocus focus)
#endif #endif
if (NotificationRenderer::isOverlayBannerShowing()) { if (NotificationRenderer::isOverlayBannerShowing()) {
NotificationRenderer::inEvent = *event; NotificationRenderer::inEvent = *event;
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
NotificationRenderer::drawBannercallback};
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
setFastFramerate(); // Draw ASAP setFastFramerate(); // Draw ASAP
ui->update(); ui->update();
@@ -1609,10 +1606,10 @@ void Screen::setFrames(FrameFocus focus)
} }
return 0; return 0;
} }
int Screen::handleAdminMessage(AdminModule_ObserverData * arg) int Screen::handleAdminMessage(AdminModule_ObserverData *arg)
{ {
switch (arg->request->which_payload_variant) { switch (arg->request->which_payload_variant) {
// Node removed manually (i.e. via app) // Node removed manually (i.e. via app)
case meshtastic_AdminMessage_remove_by_nodenum_tag: case meshtastic_AdminMessage_remove_by_nodenum_tag:
@@ -1625,21 +1622,21 @@ void Screen::setFrames(FrameFocus focus)
break; break;
} }
return 0; return 0;
} }
bool Screen::isOverlayBannerShowing() bool Screen::isOverlayBannerShowing()
{ {
return NotificationRenderer::isOverlayBannerShowing(); return NotificationRenderer::isOverlayBannerShowing();
} }
} // namespace graphics } // namespace graphics
#else #else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {} graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN #endif // HAS_SCREEN
bool shouldWakeOnReceivedMessage() bool shouldWakeOnReceivedMessage()
{ {
/* /*
The goal here is to determine when we do NOT wake up the screen on message received: The goal here is to determine when we do NOT wake up the screen on message received:
- Any ext. notifications are turned on - Any ext. notifications are turned on
@@ -1658,4 +1655,4 @@ graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig
return false; return false;
} }
return true; return true;
} }
+8 -6
View File
@@ -20,7 +20,9 @@
// External variables // External variables
extern graphics::Screen *screen; extern graphics::Screen *screen;
#if defined(M5STACK_UNITC6L)
static uint32_t lastSwitchTime = 0; static uint32_t lastSwitchTime = 0;
#endif
namespace graphics namespace graphics
{ {
NodeNum UIRenderer::currentFavoriteNodeNum = 0; NodeNum UIRenderer::currentFavoriteNodeNum = 0;
@@ -126,8 +128,10 @@ void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y,
strcpy(displayLine, "No GPS present"); strcpy(displayLine, "No GPS present");
display->drawString(x, y, displayLine); display->drawString(x, y, displayLine);
} else if (!gps->getHasLock() && !config.position.fixed_position) { } else if (!gps->getHasLock() && !config.position.fixed_position) {
if (strcmp(mode, "line1") == 0) {
strcpy(displayLine, "No GPS Lock"); strcpy(displayLine, "No GPS Lock");
display->drawString(x, y, displayLine); display->drawString(x, y, displayLine);
}
} else { } else {
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude())); geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
@@ -285,9 +289,9 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
meshtastic_NodeInfoLite *node = favoritedNodes[nodeIndex]; meshtastic_NodeInfoLite *node = favoritedNodes[nodeIndex];
if (!node || node->num == nodeDB->getNodeNum() || !node->is_favorite) if (!node || node->num == nodeDB->getNodeNum() || !node->is_favorite)
return; return;
uint32_t now = millis();
display->clear(); display->clear();
#if defined(M5STACK_UNITC6L) #if defined(M5STACK_UNITC6L)
uint32_t now = millis();
if (now - lastSwitchTime >= 10000) // 10000 ms = 10 秒 if (now - lastSwitchTime >= 10000) // 10000 ms = 10 秒
{ {
display->display(); display->display();
@@ -732,7 +736,6 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
int textWidth = 0; int textWidth = 0;
int nameX = 0; int nameX = 0;
int yOffset = (isHighResolution) ? 0 : 5; int yOffset = (isHighResolution) ? 0 : 5;
const char *longName = nullptr;
std::string longNameStr; std::string longNameStr;
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum()); meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
@@ -1277,14 +1280,13 @@ void UIRenderer::drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *sta
const int totalWidth = (pageEnd - pageStart) * iconSize + (pageEnd - pageStart - 1) * spacing; const int totalWidth = (pageEnd - pageStart) * iconSize + (pageEnd - pageStart - 1) * spacing;
const int xStart = (SCREEN_WIDTH - totalWidth) / 2; const int xStart = (SCREEN_WIDTH - totalWidth) / 2;
// Only show bar briefly after switching frames
static uint32_t navBarLastShown = 0;
static bool cosmeticRefreshDone = false;
bool navBarVisible = millis() - lastFrameChangeTime <= ICON_DISPLAY_DURATION_MS; bool navBarVisible = millis() - lastFrameChangeTime <= ICON_DISPLAY_DURATION_MS;
int y = navBarVisible ? (SCREEN_HEIGHT - iconSize - 1) : SCREEN_HEIGHT; int y = navBarVisible ? (SCREEN_HEIGHT - iconSize - 1) : SCREEN_HEIGHT;
#if defined(USE_EINK) #if defined(USE_EINK)
// Only show bar briefly after switching frames
static uint32_t navBarLastShown = 0;
static bool cosmeticRefreshDone = false;
static bool navBarPrevVisible = false; static bool navBarPrevVisible = false;
if (navBarVisible && !navBarPrevVisible) { if (navBarVisible && !navBarPrevVisible) {
+7 -6
View File
@@ -287,12 +287,10 @@ const uint8_t digital_icon_clock[] PROGMEM = {0b00111100, 0b01000010, 0b10000101
#define analog_icon_clock_height 8 #define analog_icon_clock_height 8
const uint8_t analog_icon_clock[] PROGMEM = {0b11111111, 0b01000010, 0b00100100, 0b00011000, const uint8_t analog_icon_clock[] PROGMEM = {0b11111111, 0b01000010, 0b00100100, 0b00011000,
0b00100100, 0b01000010, 0b01000010, 0b11111111}; 0b00100100, 0b01000010, 0b01000010, 0b11111111};
#ifdef M5STACK_UNITC6L
#include "img/icon_small.xbm"
#else
#define chirpy_width 38 #define chirpy_width 38
#define chirpy_height 50 #define chirpy_height 50
static unsigned char chirpy[] = { const uint8_t chirpy[] = {
0xfe, 0xff, 0xff, 0xff, 0xdf, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01,
0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0x00, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0x00,
0x00, 0x00, 0xe0, 0x81, 0xff, 0xff, 0x7f, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xcf, 0x7f, 0x00, 0x00, 0xe0, 0x81, 0xff, 0xff, 0x7f, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xcf, 0x7f,
@@ -308,7 +306,7 @@ static unsigned char chirpy[] = {
#define chirpy_width_hirez 76 #define chirpy_width_hirez 76
#define chirpy_height_hirez 100 #define chirpy_height_hirez 100
static unsigned char chirpy_hirez[] = { const uint8_t chirpy_hirez[] = {
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
@@ -360,8 +358,11 @@ static unsigned char chirpy_hirez[] = {
#define chirpy_small_image_width 8 #define chirpy_small_image_width 8
#define chirpy_small_image_height 8 #define chirpy_small_image_height 8
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f}; const uint8_t chirpy_small[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
#ifdef M5STACK_UNITC6L
#include "img/icon_small.xbm"
#else
#include "img/icon.xbm" #include "img/icon.xbm"
#endif #endif
static_assert(sizeof(icon_bits) >= 0, "Silence unused variable warning"); static_assert(sizeof(icon_bits) >= 0, "Silence unused variable warning");
-86
View File
@@ -28,89 +28,3 @@ static uint8_t icon_bits[] = {
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 }; 0x00, 0x00, 0x00, 0x00 };
#endif #endif
// Chirpy image definitions for M5STACK_UNITC6L compatibility
#define chirpy_width 38
#define chirpy_height 50
static unsigned char chirpy[] = {
0xfe, 0xff, 0xff, 0xff, 0xdf, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01,
0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0x00,
0x00, 0x00, 0xe0, 0x81, 0xff, 0xff, 0x7f, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xcf, 0x7f,
0xfe, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc,
0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0,
0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1,
0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0xcf, 0x7f, 0xfe, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0x81, 0xff,
0xff, 0x7f, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xc3, 0x00, 0xe0, 0x01, 0x00, 0xc3,
0x00, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0xc0, 0x30, 0x03, 0xe0, 0x01, 0xc0, 0x30, 0x03,
0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0,
0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01,
0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xdf};
#define chirpy_width_hirez 76
#define chirpy_height_hirez 100
static unsigned char chirpy_hirez[] = {
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc,
0x03, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f,
0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe,
0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff,
0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f,
0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0,
0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f,
0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00,
0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc,
0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f,
0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe,
0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff,
0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f,
0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0,
0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f,
0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00,
0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc,
0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x1f,
0xff, 0xff, 0xff, 0xf8, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff,
0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00,
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x80, 0x87, 0xe1, 0x01, 0x00,
0x00, 0xfc, 0x03, 0x00, 0x00, 0x80, 0x87, 0xe1, 0x01, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x00, 0x00,
0xfc, 0x03, 0x00, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x00, 0xfc,
0x03, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x03,
0x00, 0x00, 0xf0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x78, 0x00, 0x00, 0x1e, 0x00, 0x00, 0xfc, 0x03, 0x00,
0x00, 0x78, 0x00, 0x00, 0x1e, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x1e,
0x00, 0x00, 0x78, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0x00,
0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x80, 0x07, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xfc, 0x03, 0x00, 0x80, 0x07, 0x00, 0x00,
0xe0, 0x01, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0,
0x03, 0x00, 0xfc, 0x03, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0x07, 0x00, 0xfc, 0x03, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0x07,
0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0xfc, 0x03, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xfc, 0x03, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xfc,
0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x03,
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xfc, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xfc, 0x03, 0x80, 0x07,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xfc, 0x03, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xfc, 0x03, 0xc0, 0x03, 0x00,
0x00, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0xe0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x80, 0x07, 0xfc, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3
};
#define chirpy_small_image_width 8
#define chirpy_small_image_height 8
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
+1 -1
View File
@@ -27,7 +27,7 @@ void RotaryEncoderInterruptBase::init(
if (!isRAK || pinPress != 0) { if (!isRAK || pinPress != 0) {
pinMode(pinPress, INPUT_PULLUP); pinMode(pinPress, INPUT_PULLUP);
attachInterrupt(pinPress, onIntPress, RISING); attachInterrupt(pinPress, onIntPress, CHANGE);
} }
if (!isRAK || this->_pinA != 0) { if (!isRAK || this->_pinA != 0) {
pinMode(this->_pinA, INPUT_PULLUP); pinMode(this->_pinA, INPUT_PULLUP);
+2 -2
View File
@@ -428,8 +428,8 @@ bool Channels::setDefaultPresetCryptoForHash(ChannelHash channelHash)
// Iterate all known presets // Iterate all known presets
for (int preset = _meshtastic_Config_LoRaConfig_ModemPreset_MIN; preset <= _meshtastic_Config_LoRaConfig_ModemPreset_MAX; for (int preset = _meshtastic_Config_LoRaConfig_ModemPreset_MIN; preset <= _meshtastic_Config_LoRaConfig_ModemPreset_MAX;
++preset) { ++preset) {
const char *name = const char *name = DisplayFormatters::getModemPresetDisplayName((meshtastic_Config_LoRaConfig_ModemPreset)preset, false,
DisplayFormatters::getModemPresetDisplayName((meshtastic_Config_LoRaConfig_ModemPreset)preset, false, false); config.lora.use_preset);
if (!name) if (!name)
continue; continue;
if (strcmp(name, "Invalid") == 0) if (strcmp(name, "Invalid") == 0)
+14 -7
View File
@@ -97,17 +97,18 @@ bool ReliableRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
{ {
if (isToUs(p)) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability) if (isToUs(p)) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability)
if (!MeshModule::currentReply) {
if (p->want_ack) { if (p->want_ack) {
if (MeshModule::currentReply) { if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
LOG_DEBUG("Another module replied to this message, no need for 2nd ack"); /* A response may be set to want_ack for retransmissions, but we don't need to ACK a response if it received
} else if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { an implicit ACK already. If we received it directly or via NextHopRouter, only ACK with a hop limit of 0 to
// A response may be set to want_ack for retransmissions, but we don't need to ACK a response if it received an make sure the other side stops retransmitting. */
// implicit ACK already. If we received it directly, only ACK with a hop limit of 0 if (!p->decoded.request_id && !p->decoded.reply_id) {
if (!p->decoded.request_id)
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit)); routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
else if (p->hop_start > 0 && p->hop_start == p->hop_limit) } else if ((p->hop_start > 0 && p->hop_start == p->hop_limit) || p->next_hop != NO_NEXT_HOP_PREFERENCE) {
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0); sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
}
} else if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag && p->channel == 0 && } else if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag && p->channel == 0 &&
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) { (nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY"); LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY");
@@ -118,6 +119,12 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(), sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit)); routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
} }
} else if (p->next_hop == nodeDB->getLastByteOfNodeNum(getNodeNum()) && p->hop_limit > 0) {
// No wantAck, but we need to ACK with hop limit of 0 if we were the next hop to stop their retransmissions
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
}
} else {
LOG_DEBUG("Another module replied to this message, no need for 2nd ack");
} }
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && c && if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && c &&
c->error_reason == meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY) { c->error_reason == meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY) {
+34 -2
View File
@@ -52,6 +52,16 @@ template <typename T> bool SX126xInterface<T>::init()
pinMode(SX126X_POWER_EN, OUTPUT); pinMode(SX126X_POWER_EN, OUTPUT);
#endif #endif
#ifdef HELTEC_V4
pinMode(LORA_PA_POWER, OUTPUT);
digitalWrite(LORA_PA_POWER, HIGH);
pinMode(LORA_PA_EN, OUTPUT);
digitalWrite(LORA_PA_EN, LOW);
pinMode(LORA_PA_TX_EN, OUTPUT);
digitalWrite(LORA_PA_TX_EN, LOW);
#endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
tcxoVoltage = (float)portduino_config.dio3_tcxo_voltage / 1000; tcxoVoltage = (float)portduino_config.dio3_tcxo_voltage / 1000;
if (portduino_config.lora_sx126x_ant_sw_pin.pin != RADIOLIB_NC) { if (portduino_config.lora_sx126x_ant_sw_pin.pin != RADIOLIB_NC) {
@@ -63,7 +73,7 @@ template <typename T> bool SX126xInterface<T>::init()
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage"); LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage");
else else
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V", tcxoVoltage); LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V", tcxoVoltage);
setTransmitEnable(false);
// FIXME: May want to set depending on a definition, currently all SX126x variant files use the DC-DC regulator option // FIXME: May want to set depending on a definition, currently all SX126x variant files use the DC-DC regulator option
bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC? bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC?
@@ -259,6 +269,7 @@ template <typename T> void SX126xInterface<T>::addReceiveMetadata(meshtastic_Mes
*/ */
template <typename T> void SX126xInterface<T>::configHardwareForSend() template <typename T> void SX126xInterface<T>::configHardwareForSend()
{ {
setTransmitEnable(true);
RadioLibInterface::configHardwareForSend(); RadioLibInterface::configHardwareForSend();
} }
@@ -271,6 +282,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
sleep(); sleep();
#else #else
setTransmitEnable(false);
setStandby(); setStandby();
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly. // We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
@@ -298,7 +310,7 @@ template <typename T> bool SX126xInterface<T>::isChannelActive()
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS, .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK}}; .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK}};
int16_t result; int16_t result;
setTransmitEnable(false);
setStandby(); setStandby();
result = lora.scanChannel(cfg); result = lora.scanChannel(cfg);
if (result == RADIOLIB_LORA_DETECTED) if (result == RADIOLIB_LORA_DETECTED)
@@ -337,6 +349,26 @@ template <typename T> bool SX126xInterface<T>::sleep()
digitalWrite(SX126X_POWER_EN, LOW); digitalWrite(SX126X_POWER_EN, LOW);
#endif #endif
#ifdef HELTEC_V4
/*
* Do not switch the power on and off frequently.
* After turning off LORA_PA_EN, the power consumption has dropped to the uA level.
* // digitalWrite(LORA_PA_POWER, LOW);
*/
digitalWrite(LORA_PA_EN, LOW);
digitalWrite(LORA_PA_TX_EN, LOW);
#endif
return true; return true;
} }
/** Some boards require GPIO control of tx vs rx paths */
template <typename T> void SX126xInterface<T>::setTransmitEnable(bool txon)
{
#ifdef HELTEC_V4
digitalWrite(LORA_PA_POWER, HIGH);
digitalWrite(LORA_PA_EN, HIGH);
digitalWrite(LORA_PA_TX_EN, txon ? 1 : 0);
#endif
}
#endif #endif
+4
View File
@@ -71,5 +71,9 @@ template <class T> class SX126xInterface : public RadioLibInterface
virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override; virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override;
virtual void setStandby() override; virtual void setStandby() override;
private:
/** Some boards require GPIO control of tx vs rx paths */
void setTransmitEnable(bool txon);
}; };
#endif #endif
+1 -1
View File
@@ -55,7 +55,7 @@ HTTPClient httpClient;
// We need to specify some content-type mapping, so the resources get delivered with the // We need to specify some content-type mapping, so the resources get delivered with the
// right content type and are displayed correctly in the browser // right content type and are displayed correctly in the browser
char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"}, char const *contentTypes[][2] = {{".txt", "text/plain"}, {".html", "text/html"},
{".js", "text/javascript"}, {".png", "image/png"}, {".js", "text/javascript"}, {".png", "image/png"},
{".jpg", "image/jpg"}, {".gz", "application/gzip"}, {".jpg", "image/jpg"}, {".gz", "application/gzip"},
{".gif", "image/gif"}, {".json", "application/json"}, {".gif", "image/gif"}, {".json", "application/json"},
+1 -1
View File
@@ -241,7 +241,7 @@ void setupModules()
#if HAS_TELEMETRY #if HAS_TELEMETRY
new DeviceTelemetryModule(); new DeviceTelemetryModule();
#endif #endif
#if HAS_SENSOR && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR #if HAS_TELEMETRY && HAS_SENSOR && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (moduleConfig.has_telemetry && if (moduleConfig.has_telemetry &&
(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) { (moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) {
new EnvironmentTelemetryModule(); new EnvironmentTelemetryModule();
+7
View File
@@ -231,6 +231,10 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
{ {
LOG_INFO("BLE disconnect"); LOG_INFO("BLE disconnect");
#endif #endif
#ifdef NIMBLE_TWO
if (ble->isDeInit)
return;
#endif
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED); meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED);
bluetoothStatus->updateStatus(&newStatus); bluetoothStatus->updateStatus(&newStatus);
@@ -270,6 +274,7 @@ void NimbleBluetooth::deinit()
{ {
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
LOG_INFO("Disable bluetooth until reboot"); LOG_INFO("Disable bluetooth until reboot");
isDeInit = true;
#ifdef BLE_LED #ifdef BLE_LED
#ifdef BLE_LED_INVERTED #ifdef BLE_LED_INVERTED
@@ -278,8 +283,10 @@ void NimbleBluetooth::deinit()
digitalWrite(BLE_LED, LOW); digitalWrite(BLE_LED, LOW);
#endif #endif
#endif #endif
#ifndef NIMBLE_TWO
NimBLEDevice::deinit(); NimBLEDevice::deinit();
#endif #endif
#endif
} }
// Has initial setup been completed // Has initial setup been completed
+1
View File
@@ -15,6 +15,7 @@ class NimbleBluetooth : BluetoothApi
#if defined(NIMBLE_TWO) #if defined(NIMBLE_TWO)
void startAdvertising(); void startAdvertising();
#endif #endif
bool isDeInit = false;
private: private:
void setupService(); void setupService();
+2
View File
@@ -197,6 +197,8 @@
#define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO #define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO
#elif defined(T_LORA_PAGER) #elif defined(T_LORA_PAGER)
#define HW_VENDOR meshtastic_HardwareModel_T_LORA_PAGER #define HW_VENDOR meshtastic_HardwareModel_T_LORA_PAGER
#elif defined(HELTEC_V4)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_V4
#elif defined(M5STACK_UNITC6L) #elif defined(M5STACK_UNITC6L)
#define HW_VENDOR meshtastic_HardwareModel_M5STACK_C6L #define HW_VENDOR meshtastic_HardwareModel_M5STACK_C6L
#endif #endif
+6
View File
@@ -545,6 +545,12 @@ void enableLoraInterrupt()
gpio_pullup_en((gpio_num_t)LORA_CS); gpio_pullup_en((gpio_num_t)LORA_CS);
#endif #endif
#ifdef HELTEC_V4
gpio_pullup_en((gpio_num_t)LORA_PA_POWER);
gpio_pullup_en((gpio_num_t)LORA_PA_EN);
gpio_pulldown_en((gpio_num_t)LORA_PA_TX_EN);
#endif
LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt", LORA_DIO1); LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt", LORA_DIO1);
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL);
+70
View File
@@ -0,0 +1,70 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 35;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
static const uint8_t TX = 43;
static const uint8_t RX = 44;
static const uint8_t SDA = 3;
static const uint8_t SCL = 4;
static const uint8_t SS = 8;
static const uint8_t MOSI = 10;
static const uint8_t MISO = 11;
static const uint8_t SCK = 9;
static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A6 = 7;
static const uint8_t A7 = 8;
static const uint8_t A8 = 9;
static const uint8_t A9 = 10;
static const uint8_t A10 = 11;
static const uint8_t A11 = 12;
static const uint8_t A12 = 13;
static const uint8_t A13 = 14;
static const uint8_t A14 = 15;
static const uint8_t A15 = 16;
static const uint8_t A16 = 17;
static const uint8_t A17 = 18;
static const uint8_t A18 = 19;
static const uint8_t A19 = 20;
static const uint8_t T1 = 1;
static const uint8_t T2 = 2;
static const uint8_t T3 = 3;
static const uint8_t T4 = 4;
static const uint8_t T5 = 5;
static const uint8_t T6 = 6;
static const uint8_t T7 = 7;
static const uint8_t T8 = 8;
static const uint8_t T9 = 9;
static const uint8_t T10 = 10;
static const uint8_t T11 = 11;
static const uint8_t T12 = 12;
static const uint8_t T13 = 13;
static const uint8_t T14 = 14;
static const uint8_t Vext = 36;
static const uint8_t LED = 35;
static const uint8_t RST_OLED = 21;
static const uint8_t SCL_OLED = 18;
static const uint8_t SDA_OLED = 17;
static const uint8_t RST_LoRa = 12;
static const uint8_t BUSY_LoRa = 13;
static const uint8_t DIO0 = 14;
#endif /* Pins_Arduino_h */
+10
View File
@@ -0,0 +1,10 @@
[env:heltec-v4]
extends = esp32s3_base
board = heltec_v4
board_check = true
build_flags =
${esp32s3_base.build_flags}
-D HELTEC_V4
-I variants/esp32s3/heltec_v4
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-D SX126X_MAX_POWER=11
+58
View File
@@ -0,0 +1,58 @@
#define LED_PIN 35
#define USE_SSD1306 // Heltec_v4 has an SSD1315 display (compatible with SSD1306 driver)
#define RESET_OLED 21
#define I2C_SDA 17 // I2C pins for this board
#define I2C_SCL 18
#define VEXT_ENABLE 36 // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0
#define ADC_CTRL 37
#define ADC_CTRL_ENABLED HIGH
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
#define ADC_MULTIPLIER 4.9 * 1.045
#define USE_SX1262
#define LORA_DIO0 -1 // a No connect on the SX1262 module
#define LORA_RESET 12
#define LORA_DIO1 14 // SX1262 IRQ
#define LORA_DIO2 13 // SX1262 BUSY
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TCXO is enabled
#define LORA_SCK 9
#define LORA_MISO 11
#define LORA_MOSI 10
#define LORA_CS 8
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define LORA_PA_POWER 7 // power en
#define LORA_PA_EN 2
#define LORA_PA_TX_EN 46 // enable tx
/*
* GPS pins
*/
#define GPS_L76K
#define PIN_GPS_RESET (42) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define GPS_RESET_MODE LOW
#define PIN_GPS_EN (34)
#define GPS_EN_ACTIVE LOW
#define PERIPHERAL_WARMUP_MS 1000 // Make sure I2C QuickLink has stable power before continuing
#define PIN_GPS_STANDBY (40) // An output to wake GPS, low means allow sleep, high means force wake
#define PIN_GPS_PPS (41)
// Seems to be missing on this new board
#define GPS_TX_PIN (38) // This is for bits going TOWARDS the CPU
#define GPS_RX_PIN (39) // This is for bits going TOWARDS the GPS
#define GPS_THREAD_INTERVAL 50
@@ -16,3 +16,11 @@ lib_deps =
debug_tool = jlink debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
;upload_protocol = jlink ;upload_protocol = jlink
; Seeed Xiao BLE but with GPS undefined, and therefore i2c active
[env:seeed_xiao_nrf52840_kit_i2c]
extends = env:seeed_xiao_nrf52840_kit
board_level = extra
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags}
-DSEEED_XIAO_NRF52840_KIT
build_unflags = -DGPS_L76K