mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-27 11:31:47 +00:00
Jason's cleanup
This commit is contained in:
parent
f60c4ec5bc
commit
99ca59b8a1
@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#if !MESHTASTIC_EXCLUDE_GPS
|
#if !MESHTASTIC_EXCLUDE_GPS
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "FSCommon.h"
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@ -50,7 +51,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "modules/WaypointModule.h"
|
#include "modules/WaypointModule.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include "FSCommon.h"
|
|
||||||
|
|
||||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||||
#include "mesh/wifi/WiFiAPClient.h"
|
#include "mesh/wifi/WiFiAPClient.h"
|
||||||
@ -119,6 +119,18 @@ static bool heartbeat = false;
|
|||||||
#define SCREEN_WIDTH display->getWidth()
|
#define SCREEN_WIDTH display->getWidth()
|
||||||
#define SCREEN_HEIGHT display->getHeight()
|
#define SCREEN_HEIGHT display->getHeight()
|
||||||
|
|
||||||
|
// Pre-defined lines; this is intended to be used AFTER the common header
|
||||||
|
#define compactFirstLine (FONT_HEIGHT_SMALL - 3) * 1
|
||||||
|
#define compactSecondLine (FONT_HEIGHT_SMALL - 3) * 2
|
||||||
|
#define compactThirdLine (FONT_HEIGHT_SMALL - 3) * 3
|
||||||
|
#define compactFourthLine (FONT_HEIGHT_SMALL - 3) * 4
|
||||||
|
#define compactFifthLine (FONT_HEIGHT_SMALL - 3) * 5
|
||||||
|
|
||||||
|
#define standardFirstLine (FONT_HEIGHT_SMALL + 1) * 1
|
||||||
|
#define standardSecondLine (FONT_HEIGHT_SMALL + 1) * 2
|
||||||
|
#define standardThirdLine (FONT_HEIGHT_SMALL + 1) * 3
|
||||||
|
#define standardFourthLine (FONT_HEIGHT_SMALL + 1) * 4
|
||||||
|
|
||||||
#include "graphics/ScreenFonts.h"
|
#include "graphics/ScreenFonts.h"
|
||||||
#include <Throttle.h>
|
#include <Throttle.h>
|
||||||
|
|
||||||
@ -445,8 +457,10 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
|
|||||||
int screenWidth = display->getWidth();
|
int screenWidth = display->getWidth();
|
||||||
int scale = 1;
|
int scale = 1;
|
||||||
|
|
||||||
if (screenWidth >= 200) scale = 2;
|
if (screenWidth >= 200)
|
||||||
if (screenWidth >= 300) scale = 2; // Do NOT go higher than 2
|
scale = 2;
|
||||||
|
if (screenWidth >= 300)
|
||||||
|
scale = 2; // Do NOT go higher than 2
|
||||||
|
|
||||||
// Draw scaled battery image (16 columns × 8 rows)
|
// Draw scaled battery image (16 columns × 8 rows)
|
||||||
for (int col = 0; col < 16; col++) {
|
for (int col = 0; col < 16; col++) {
|
||||||
@ -1159,7 +1173,8 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
|||||||
|
|
||||||
if (x + maxDrawWidth > SCREEN_WIDTH) {
|
if (x + maxDrawWidth > SCREEN_WIDTH) {
|
||||||
x = SCREEN_WIDTH - maxDrawWidth;
|
x = SCREEN_WIDTH - maxDrawWidth;
|
||||||
if (x < 0) x = 0; // Clamp to screen
|
if (x < 0)
|
||||||
|
x = 0; // Clamp to screen
|
||||||
}
|
}
|
||||||
|
|
||||||
display->drawFastImage(x, y, 6, 8, gps->getHasLock() ? imgPositionSolid : imgPositionEmpty);
|
display->drawFastImage(x, y, 6, 8, gps->getHasLock() ? imgPositionSolid : imgPositionEmpty);
|
||||||
@ -1196,7 +1211,6 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Draw status when GPS is disabled or not present
|
// Draw status when GPS is disabled or not present
|
||||||
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||||
{
|
{
|
||||||
@ -1353,10 +1367,14 @@ void Screen::drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t com
|
|||||||
display->drawLine(leftArrow.x, leftArrow.y, tail.x, tail.y);
|
display->drawLine(leftArrow.x, leftArrow.y, tail.x, tail.y);
|
||||||
display->drawLine(rightArrow.x, rightArrow.y, tail.x, tail.y);
|
display->drawLine(rightArrow.x, rightArrow.y, tail.x, tail.y);
|
||||||
*/
|
*/
|
||||||
Serial.print("🔥 Arrow Tail X: "); Serial.print(tail.x);
|
Serial.print("🔥 Arrow Tail X: ");
|
||||||
Serial.print(" | Y: "); Serial.print(tail.y);
|
Serial.print(tail.x);
|
||||||
Serial.print(" | Tip X: "); Serial.print(tip.x);
|
Serial.print(" | Y: ");
|
||||||
Serial.print(" | Tip Y: "); Serial.println(tip.y);
|
Serial.print(tail.y);
|
||||||
|
Serial.print(" | Tip X: ");
|
||||||
|
Serial.print(tip.x);
|
||||||
|
Serial.print(" | Tip Y: ");
|
||||||
|
Serial.println(tip.y);
|
||||||
#ifdef USE_EINK
|
#ifdef USE_EINK
|
||||||
display->drawTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
|
display->drawTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
|
||||||
#else
|
#else
|
||||||
@ -1418,9 +1436,10 @@ void Screen::drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t co
|
|||||||
rosePoints[i]->translate(compassX, compassY);
|
rosePoints[i]->translate(compassX, compassY);
|
||||||
}
|
}
|
||||||
display->drawCircle(NC1.x, NC1.y, 4); // North sign circle, 4px radius is sufficient for all displays.
|
display->drawCircle(NC1.x, NC1.y, 4); // North sign circle, 4px radius is sufficient for all displays.
|
||||||
Serial.print("🔥 North Marker X: "); Serial.print(NC1.x);
|
Serial.print("🔥 North Marker X: ");
|
||||||
Serial.print(" | Y: "); Serial.println(NC1.y);
|
Serial.print(NC1.x);
|
||||||
|
Serial.print(" | Y: ");
|
||||||
|
Serial.println(NC1.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Screen::getCompassDiam(uint32_t displayWidth, uint32_t displayHeight)
|
uint16_t Screen::getCompassDiam(uint32_t displayWidth, uint32_t displayHeight)
|
||||||
@ -1568,7 +1587,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// h! Makes header invert rounder
|
// h! Makes header invert rounder
|
||||||
void drawRoundedHighlight(OLEDDisplay *display, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r) {
|
void drawRoundedHighlight(OLEDDisplay *display, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r)
|
||||||
|
{
|
||||||
// Center rectangles
|
// Center rectangles
|
||||||
display->fillRect(x + r, y, w - 2 * r, h);
|
display->fillRect(x + r, y, w - 2 * r, h);
|
||||||
display->fillRect(x, y + r, r, h - 2 * r);
|
display->fillRect(x, y + r, r, h - 2 * r);
|
||||||
@ -1587,7 +1607,8 @@ struct NodeEntry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// h! Calculates bearing between two lat/lon points (used for compass)
|
// h! Calculates bearing between two lat/lon points (used for compass)
|
||||||
float calculateBearing(double lat1, double lon1, double lat2, double lon2) {
|
float calculateBearing(double lat1, double lon1, double lat2, double lon2)
|
||||||
|
{
|
||||||
double dLon = (lon2 - lon1) * DEG_TO_RAD;
|
double dLon = (lon2 - lon1) * DEG_TO_RAD;
|
||||||
lat1 = lat1 * DEG_TO_RAD;
|
lat1 = lat1 * DEG_TO_RAD;
|
||||||
lat2 = lat2 * DEG_TO_RAD;
|
lat2 = lat2 * DEG_TO_RAD;
|
||||||
@ -1603,15 +1624,18 @@ float calculateBearing(double lat1, double lon1, double lat2, double lon2) {
|
|||||||
static int scrollIndex = 0;
|
static int scrollIndex = 0;
|
||||||
|
|
||||||
// Helper: Calculates max scroll index based on total entries
|
// Helper: Calculates max scroll index based on total entries
|
||||||
int calculateMaxScroll(int totalEntries, int visibleRows) {
|
int calculateMaxScroll(int totalEntries, int visibleRows)
|
||||||
|
{
|
||||||
int totalRows = (totalEntries + 1) / 2;
|
int totalRows = (totalEntries + 1) / 2;
|
||||||
return std::max(0, totalRows - visibleRows);
|
return std::max(0, totalRows - visibleRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Draw vertical scrollbar matching CannedMessageModule style
|
// Helper: Draw vertical scrollbar matching CannedMessageModule style
|
||||||
void drawScrollbar(OLEDDisplay *display, int visibleNodeRows, int totalEntries, int scrollIndex, int columns, int rowYOffset) {
|
void drawScrollbar(OLEDDisplay *display, int visibleNodeRows, int totalEntries, int scrollIndex, int columns, int rowYOffset)
|
||||||
|
{
|
||||||
int totalPages = (totalEntries + columns - 1) / columns;
|
int totalPages = (totalEntries + columns - 1) / columns;
|
||||||
if (totalPages <= visibleNodeRows) return; // no scrollbar needed
|
if (totalPages <= visibleNodeRows)
|
||||||
|
return; // no scrollbar needed
|
||||||
|
|
||||||
int scrollAreaHeight = visibleNodeRows * (FONT_HEIGHT_SMALL - 3); // true pixel height used per row
|
int scrollAreaHeight = visibleNodeRows * (FONT_HEIGHT_SMALL - 3); // true pixel height used per row
|
||||||
int scrollbarX = display->getWidth() - 6;
|
int scrollbarX = display->getWidth() - 6;
|
||||||
@ -1625,27 +1649,33 @@ void drawScrollbar(OLEDDisplay *display, int visibleNodeRows, int totalEntries,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grabs all nodes from the DB and sorts them (favorites and most recently heard first)
|
// Grabs all nodes from the DB and sorts them (favorites and most recently heard first)
|
||||||
void retrieveAndSortNodes(std::vector<NodeEntry> &nodeList) {
|
void retrieveAndSortNodes(std::vector<NodeEntry> &nodeList)
|
||||||
|
{
|
||||||
size_t numNodes = nodeDB->getNumMeshNodes();
|
size_t numNodes = nodeDB->getNumMeshNodes();
|
||||||
|
|
||||||
for (size_t i = 0; i < numNodes; i++) {
|
for (size_t i = 0; i < numNodes; i++) {
|
||||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
||||||
if (!node || node->num == nodeDB->getNodeNum()) continue; // Skip self
|
if (!node || node->num == nodeDB->getNodeNum())
|
||||||
|
continue; // Skip self
|
||||||
nodeList.push_back({node, sinceLastSeen(node)});
|
nodeList.push_back({node, sinceLastSeen(node)});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(nodeList.begin(), nodeList.end(), [](const NodeEntry &a, const NodeEntry &b) {
|
std::sort(nodeList.begin(), nodeList.end(), [](const NodeEntry &a, const NodeEntry &b) {
|
||||||
bool aFav = a.node->is_favorite;
|
bool aFav = a.node->is_favorite;
|
||||||
bool bFav = b.node->is_favorite;
|
bool bFav = b.node->is_favorite;
|
||||||
if (aFav != bFav) return aFav > bFav;
|
if (aFav != bFav)
|
||||||
if (a.lastHeard == 0 || a.lastHeard == UINT32_MAX) return false;
|
return aFav > bFav;
|
||||||
if (b.lastHeard == 0 || b.lastHeard == UINT32_MAX) return true;
|
if (a.lastHeard == 0 || a.lastHeard == UINT32_MAX)
|
||||||
|
return false;
|
||||||
|
if (b.lastHeard == 0 || b.lastHeard == UINT32_MAX)
|
||||||
|
return true;
|
||||||
return a.lastHeard < b.lastHeard;
|
return a.lastHeard < b.lastHeard;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Fallback-NodeID if emote is on ShortName for display purposes
|
// Helper: Fallback-NodeID if emote is on ShortName for display purposes
|
||||||
String getSafeNodeName(meshtastic_NodeInfoLite *node) {
|
String getSafeNodeName(meshtastic_NodeInfoLite *node)
|
||||||
|
{
|
||||||
String nodeName = "?";
|
String nodeName = "?";
|
||||||
|
|
||||||
if (node->has_user && strlen(node->user.short_name) > 0) {
|
if (node->has_user && strlen(node->user.short_name) > 0) {
|
||||||
@ -1670,12 +1700,14 @@ String getSafeNodeName(meshtastic_NodeInfoLite *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->is_favorite) nodeName = "*" + nodeName;
|
if (node->is_favorite)
|
||||||
|
nodeName = "*" + nodeName;
|
||||||
return nodeName;
|
return nodeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draws the top header bar (optionally inverted or bold)
|
// Draws the top header bar (optionally inverted or bold)
|
||||||
void drawScreenHeader(OLEDDisplay *display, const char *title, int16_t x, int16_t y) {
|
void drawScreenHeader(OLEDDisplay *display, const char *title, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
bool isInverted = (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED);
|
bool isInverted = (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED);
|
||||||
bool isBold = config.display.heading_bold;
|
bool isBold = config.display.heading_bold;
|
||||||
|
|
||||||
@ -1699,25 +1731,31 @@ void drawScreenHeader(OLEDDisplay *display, const char *title, int16_t x, int16_
|
|||||||
|
|
||||||
// Draw text centered vertically and horizontally
|
// Draw text centered vertically and horizontally
|
||||||
display->drawString(titleX, textY, title);
|
display->drawString(titleX, textY, title);
|
||||||
if (isBold) display->drawString(titleX + 1, textY, title);
|
if (isBold)
|
||||||
|
display->drawString(titleX + 1, textY, title);
|
||||||
|
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draws separator line
|
// Draws separator line
|
||||||
void drawColumnSeparator(OLEDDisplay *display, int16_t x, int16_t yStart, int16_t yEnd) {
|
void drawColumnSeparator(OLEDDisplay *display, int16_t x, int16_t yStart, int16_t yEnd)
|
||||||
|
{
|
||||||
int columnWidth = display->getWidth() / 2;
|
int columnWidth = display->getWidth() / 2;
|
||||||
int separatorX = x + columnWidth - 2;
|
int separatorX = x + columnWidth - 2;
|
||||||
display->drawLine(separatorX, yStart, separatorX, yEnd - 3);
|
display->drawLine(separatorX, yStart, separatorX, yEnd - 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draws node name with how long ago it was last heard from
|
// Draws node name with how long ago it was last heard from
|
||||||
void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth) {
|
void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||||
|
{
|
||||||
int screenWidth = display->getWidth();
|
int screenWidth = display->getWidth();
|
||||||
bool isLeftCol = (x < screenWidth / 2);
|
bool isLeftCol = (x < screenWidth / 2);
|
||||||
|
|
||||||
// Adjust offset based on column and screen width
|
// Adjust offset based on column and screen width
|
||||||
int timeOffset = (screenWidth > 128) ? (isLeftCol ? 41 : 45) : (isLeftCol ? 24 : 30);//offset large screen (?Left:Right column), offset small screen (?Left:Right column)
|
int timeOffset =
|
||||||
|
(screenWidth > 128)
|
||||||
|
? (isLeftCol ? 41 : 45)
|
||||||
|
: (isLeftCol ? 24 : 30); // offset large screen (?Left:Right column), offset small screen (?Left:Right column)
|
||||||
|
|
||||||
String nodeName = getSafeNodeName(node);
|
String nodeName = getSafeNodeName(node);
|
||||||
|
|
||||||
@ -1728,7 +1766,12 @@ void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
|||||||
} else {
|
} else {
|
||||||
uint32_t minutes = seconds / 60, hours = minutes / 60, days = hours / 24;
|
uint32_t minutes = seconds / 60, hours = minutes / 60, days = hours / 24;
|
||||||
snprintf(timeStr, sizeof(timeStr), (days > 365 ? "?" : "%d%c"),
|
snprintf(timeStr, sizeof(timeStr), (days > 365 ? "?" : "%d%c"),
|
||||||
(days ? days : hours ? hours : minutes), (days ? 'd' : hours ? 'h' : 'm'));
|
(days ? days
|
||||||
|
: hours ? hours
|
||||||
|
: minutes),
|
||||||
|
(days ? 'd'
|
||||||
|
: hours ? 'h'
|
||||||
|
: 'm'));
|
||||||
}
|
}
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
@ -1737,13 +1780,20 @@ void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
|||||||
display->drawString(x + columnWidth - timeOffset, y, timeStr);
|
display->drawString(x + columnWidth - timeOffset, y, timeStr);
|
||||||
}
|
}
|
||||||
// Draws each node's name, hop count, and signal bars
|
// Draws each node's name, hop count, and signal bars
|
||||||
void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth) {
|
void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||||
|
{
|
||||||
int screenWidth = display->getWidth();
|
int screenWidth = display->getWidth();
|
||||||
bool isLeftCol = (x < screenWidth / 2);
|
bool isLeftCol = (x < screenWidth / 2);
|
||||||
|
|
||||||
int nameMaxWidth = columnWidth - 25;
|
int nameMaxWidth = columnWidth - 25;
|
||||||
int barsOffset = (screenWidth > 128) ? (isLeftCol ? 26 : 30) : (isLeftCol ? 17 : 19);//offset large screen (?Left:Right column), offset small screen (?Left:Right column)
|
int barsOffset =
|
||||||
int hopOffset = (screenWidth > 128) ? (isLeftCol ? 32 : 38) : (isLeftCol ? 18 : 20);//offset large screen (?Left:Right column), offset small screen (?Left:Right column)
|
(screenWidth > 128)
|
||||||
|
? (isLeftCol ? 26 : 30)
|
||||||
|
: (isLeftCol ? 17 : 19); // offset large screen (?Left:Right column), offset small screen (?Left:Right column)
|
||||||
|
int hopOffset =
|
||||||
|
(screenWidth > 128)
|
||||||
|
? (isLeftCol ? 32 : 38)
|
||||||
|
: (isLeftCol ? 18 : 20); // offset large screen (?Left:Right column), offset small screen (?Left:Right column)
|
||||||
|
|
||||||
int barsXOffset = columnWidth - barsOffset;
|
int barsXOffset = columnWidth - barsOffset;
|
||||||
|
|
||||||
@ -1780,7 +1830,9 @@ void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
|||||||
typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int);
|
typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int);
|
||||||
|
|
||||||
// Shared function that renders all node screens (LastHeard, Hop/Signal)
|
// Shared function that renders all node screens (LastHeard, Hop/Signal)
|
||||||
void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title, EntryRenderer renderer) {
|
void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title,
|
||||||
|
EntryRenderer renderer)
|
||||||
|
{
|
||||||
int columnWidth = display->getWidth() / 2;
|
int columnWidth = display->getWidth() / 2;
|
||||||
int totalRowsAvailable = (display->getHeight() - y - FONT_HEIGHT_SMALL) / (FONT_HEIGHT_SMALL - 3);
|
int totalRowsAvailable = (display->getHeight() - y - FONT_HEIGHT_SMALL) / (FONT_HEIGHT_SMALL - 3);
|
||||||
int visibleNodeRows = std::min(6, totalRowsAvailable);
|
int visibleNodeRows = std::min(6, totalRowsAvailable);
|
||||||
@ -1815,7 +1867,8 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
if (y + yOffset > display->getHeight() - FONT_HEIGHT_SMALL) {
|
if (y + yOffset > display->getHeight() - FONT_HEIGHT_SMALL) {
|
||||||
yOffset = rowYOffset;
|
yOffset = rowYOffset;
|
||||||
col++;
|
col++;
|
||||||
if (col > 1) break;
|
if (col > 1)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1824,21 +1877,20 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Public screen function: shows how recently nodes were heard
|
// Public screen function: shows how recently nodes were heard
|
||||||
static void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
static void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
drawNodeListScreen(display, state, x, y, "Node List", drawEntryLastHeard);
|
drawNodeListScreen(display, state, x, y, "Node List", drawEntryLastHeard);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public screen function: shows hop count + signal strength
|
// Public screen function: shows hop count + signal strength
|
||||||
static void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
static void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
drawNodeListScreen(display, state, x, y, "Hops/Signal", drawEntryHopSignal);
|
drawNodeListScreen(display, state, x, y, "Hops/Signal", drawEntryHopSignal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function: Draw a single node entry for Node List (Modified for Compass Screen)
|
// Helper function: Draw a single node entry for Node List (Modified for Compass Screen)
|
||||||
void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth) {
|
void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||||
|
{
|
||||||
int screenWidth = display->getWidth();
|
int screenWidth = display->getWidth();
|
||||||
bool isLeftCol = (x < screenWidth / 2);
|
bool isLeftCol = (x < screenWidth / 2);
|
||||||
|
|
||||||
@ -1853,10 +1905,14 @@ void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extra compass element drawer (injects compass arrows)
|
// Extra compass element drawer (injects compass arrows)
|
||||||
typedef void (*CompassExtraRenderer)(OLEDDisplay*, meshtastic_NodeInfoLite*, int16_t, int16_t, int columnWidth, float myHeading, double userLat, double userLon);
|
typedef void (*CompassExtraRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int columnWidth, float myHeading,
|
||||||
|
double userLat, double userLon);
|
||||||
|
|
||||||
void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth, float myHeading, double userLat, double userLon) {
|
void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth, float myHeading,
|
||||||
if (!nodeDB->hasValidPosition(node)) return;
|
double userLat, double userLon)
|
||||||
|
{
|
||||||
|
if (!nodeDB->hasValidPosition(node))
|
||||||
|
return;
|
||||||
|
|
||||||
int screenWidth = display->getWidth();
|
int screenWidth = display->getWidth();
|
||||||
bool isLeftCol = (x < screenWidth / 2);
|
bool isLeftCol = (x < screenWidth / 2);
|
||||||
@ -1885,7 +1941,8 @@ void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
|||||||
|
|
||||||
// Generic node+compass renderer (like drawNodeListScreen but with compass support)
|
// Generic node+compass renderer (like drawNodeListScreen but with compass support)
|
||||||
void drawNodeListWithExtrasScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title,
|
void drawNodeListWithExtrasScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title,
|
||||||
EntryRenderer renderer, CompassExtraRenderer extras) {
|
EntryRenderer renderer, CompassExtraRenderer extras)
|
||||||
|
{
|
||||||
int columnWidth = display->getWidth() / 2;
|
int columnWidth = display->getWidth() / 2;
|
||||||
int totalRowsAvailable = (display->getHeight() - y - FONT_HEIGHT_SMALL) / (FONT_HEIGHT_SMALL - 3);
|
int totalRowsAvailable = (display->getHeight() - y - FONT_HEIGHT_SMALL) / (FONT_HEIGHT_SMALL - 3);
|
||||||
int visibleNodeRows = std::min(6, totalRowsAvailable);
|
int visibleNodeRows = std::min(6, totalRowsAvailable);
|
||||||
@ -1936,7 +1993,8 @@ void drawNodeListWithExtrasScreen(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||||||
if (y + yOffset > display->getHeight() - FONT_HEIGHT_SMALL) {
|
if (y + yOffset > display->getHeight() - FONT_HEIGHT_SMALL) {
|
||||||
yOffset = rowYOffset;
|
yOffset = rowYOffset;
|
||||||
col++;
|
col++;
|
||||||
if (col > 1) break;
|
if (col > 1)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1944,13 +2002,14 @@ void drawNodeListWithExtrasScreen(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||||||
drawScrollbar(display, visibleNodeRows, totalEntries, scrollIndex, 2, rowYOffset);
|
drawScrollbar(display, visibleNodeRows, totalEntries, scrollIndex, 2, rowYOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Public screen entry for compass
|
// Public screen entry for compass
|
||||||
static void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
static void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
drawNodeListWithExtrasScreen(display, state, x, y, "Bearings", drawEntryCompass, drawCompassArrow);
|
drawNodeListWithExtrasScreen(display, state, x, y, "Bearings", drawEntryCompass, drawCompassArrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth) {
|
void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||||
|
{
|
||||||
int screenWidth = display->getWidth();
|
int screenWidth = display->getWidth();
|
||||||
bool isLeftCol = (x < screenWidth / 2);
|
bool isLeftCol = (x < screenWidth / 2);
|
||||||
int nameMaxWidth = columnWidth - (screenWidth > 128 ? (isLeftCol ? 25 : 28) : (isLeftCol ? 20 : 22));
|
int nameMaxWidth = columnWidth - (screenWidth > 128 ? (isLeftCol ? 25 : 28) : (isLeftCol ? 20 : 22));
|
||||||
@ -1970,9 +2029,8 @@ void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
|||||||
double dLat = (lat2 - lat1) * DEG_TO_RAD;
|
double dLat = (lat2 - lat1) * DEG_TO_RAD;
|
||||||
double dLon = (lon2 - lon1) * DEG_TO_RAD;
|
double dLon = (lon2 - lon1) * DEG_TO_RAD;
|
||||||
|
|
||||||
double a = sin(dLat / 2) * sin(dLat / 2) +
|
double a =
|
||||||
cos(lat1 * DEG_TO_RAD) * cos(lat2 * DEG_TO_RAD) *
|
sin(dLat / 2) * sin(dLat / 2) + cos(lat1 * DEG_TO_RAD) * cos(lat2 * DEG_TO_RAD) * sin(dLon / 2) * sin(dLon / 2);
|
||||||
sin(dLon / 2) * sin(dLon / 2);
|
|
||||||
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
||||||
double distanceKm = earthRadiusKm * c;
|
double distanceKm = earthRadiusKm * c;
|
||||||
|
|
||||||
@ -2006,12 +2064,13 @@ void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
static void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
drawNodeListScreen(display, state, x, y, "Distances", drawNodeDistance);
|
drawNodeListScreen(display, state, x, y, "Distances", drawNodeDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y)
|
||||||
void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y) {
|
{
|
||||||
const bool isInverted = (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED);
|
const bool isInverted = (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED);
|
||||||
const bool isBold = config.display.heading_bold;
|
const bool isBold = config.display.heading_bold;
|
||||||
const int xOffset = 3;
|
const int xOffset = 3;
|
||||||
@ -2039,7 +2098,8 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y) {
|
|||||||
const int batteryOffset = screenWidth > 128 ? 34 : 16;
|
const int batteryOffset = screenWidth > 128 ? 34 : 16;
|
||||||
const int percentX = x + xOffset + batteryOffset;
|
const int percentX = x + xOffset + batteryOffset;
|
||||||
display->drawString(percentX, textY, percentStr);
|
display->drawString(percentX, textY, percentStr);
|
||||||
if (isBold) display->drawString(percentX + 1, textY, percentStr);
|
if (isBold)
|
||||||
|
display->drawString(percentX + 1, textY, percentStr);
|
||||||
|
|
||||||
// Time (right side)
|
// Time (right side)
|
||||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true);
|
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true);
|
||||||
@ -2050,21 +2110,23 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y) {
|
|||||||
|
|
||||||
bool isPM = hour >= 12;
|
bool isPM = hour >= 12;
|
||||||
hour = hour % 12;
|
hour = hour % 12;
|
||||||
if (hour == 0) hour = 12;
|
if (hour == 0)
|
||||||
|
hour = 12;
|
||||||
|
|
||||||
char timeStr[10];
|
char timeStr[10];
|
||||||
snprintf(timeStr, sizeof(timeStr), "%d:%02d%s", hour, minute, isPM ? "PM" : "AM");
|
snprintf(timeStr, sizeof(timeStr), "%d:%02d%s", hour, minute, isPM ? "PM" : "AM");
|
||||||
|
|
||||||
int timeX = x + screenWidth - xOffset - display->getStringWidth(timeStr);
|
int timeX = x + screenWidth - xOffset - display->getStringWidth(timeStr);
|
||||||
display->drawString(timeX, textY, timeStr);
|
display->drawString(timeX, textY, timeStr);
|
||||||
if (isBold) display->drawString(timeX + 1, textY, timeStr);
|
if (isBold)
|
||||||
|
display->drawString(timeX + 1, textY, timeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drawDefaultScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
static void drawDefaultScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
{
|
||||||
display->clear();
|
display->clear();
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
@ -2083,7 +2145,8 @@ static void drawDefaultScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
if (config.position.fixed_position) {
|
if (config.position.fixed_position) {
|
||||||
drawGPS(display, SCREEN_WIDTH - 44, secondRowY, gpsStatus);
|
drawGPS(display, SCREEN_WIDTH - 44, secondRowY, gpsStatus);
|
||||||
} else if (!gpsStatus || !gpsStatus->getIsConnected()) {
|
} else if (!gpsStatus || !gpsStatus->getIsConnected()) {
|
||||||
String displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
String displayLine =
|
||||||
|
config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||||
int posX = SCREEN_WIDTH - display->getStringWidth(displayLine) - 2;
|
int posX = SCREEN_WIDTH - display->getStringWidth(displayLine) - 2;
|
||||||
display->drawString(posX, secondRowY, displayLine);
|
display->drawString(posX, secondRowY, displayLine);
|
||||||
} else {
|
} else {
|
||||||
@ -2112,8 +2175,14 @@ static void drawDefaultScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
snprintf(uptimeStr, sizeof(uptimeStr), "?");
|
snprintf(uptimeStr, sizeof(uptimeStr), "?");
|
||||||
} else {
|
} else {
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), "%d%c",
|
snprintf(uptimeStr, sizeof(uptimeStr), "%d%c",
|
||||||
days ? days : hours ? hours : minutes ? minutes : (int)uptime,
|
days ? days
|
||||||
days ? 'd' : hours ? 'h' : minutes ? 'm' : 's');
|
: hours ? hours
|
||||||
|
: minutes ? minutes
|
||||||
|
: (int)uptime,
|
||||||
|
days ? 'd'
|
||||||
|
: hours ? 'h'
|
||||||
|
: minutes ? 'm'
|
||||||
|
: 's');
|
||||||
}
|
}
|
||||||
|
|
||||||
char uptimeFullStr[16];
|
char uptimeFullStr[16];
|
||||||
@ -2122,6 +2191,155 @@ static void drawDefaultScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
int uptimeY = y + (FONT_HEIGHT_SMALL + 1) * 3;
|
int uptimeY = y + (FONT_HEIGHT_SMALL + 1) * 3;
|
||||||
display->drawString(uptimeX, uptimeY, uptimeFullStr);
|
display->drawString(uptimeX, uptimeY, uptimeFullStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ****************************
|
||||||
|
// * Device Focused Screen *
|
||||||
|
// ****************************
|
||||||
|
static void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
display->clear();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
|
||||||
|
// === Header ===
|
||||||
|
drawCommonHeader(display, x, y);
|
||||||
|
|
||||||
|
// === First Row: Node and GPS ===
|
||||||
|
bool origBold = config.display.heading_bold;
|
||||||
|
config.display.heading_bold = false;
|
||||||
|
|
||||||
|
drawNodes(display, x, compactFirstLine + 3, nodeStatus);
|
||||||
|
|
||||||
|
#if HAS_GPS
|
||||||
|
if (config.position.fixed_position) {
|
||||||
|
drawGPS(display, SCREEN_WIDTH - 44, compactFirstLine + 3, gpsStatus);
|
||||||
|
} else if (!gpsStatus || !gpsStatus->getIsConnected()) {
|
||||||
|
String displayLine =
|
||||||
|
config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||||
|
int posX = SCREEN_WIDTH - display->getStringWidth(displayLine) - 2;
|
||||||
|
display->drawString(posX, compactFirstLine + 3, displayLine);
|
||||||
|
} else {
|
||||||
|
drawGPS(display, SCREEN_WIDTH - 44, compactFirstLine + 3, gpsStatus);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
config.display.heading_bold = origBold;
|
||||||
|
|
||||||
|
// === Second Row: MAC ID and Channel Utilization ===
|
||||||
|
|
||||||
|
// Get our hardware ID
|
||||||
|
uint8_t dmac[6];
|
||||||
|
getMacAddr(dmac);
|
||||||
|
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
|
||||||
|
|
||||||
|
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||||
|
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
|
display->drawFastImage(x, compactSecondLine + 3, 12, 8, imgInfoL1);
|
||||||
|
display->drawFastImage(x, compactSecondLine + 11, 12, 8, imgInfoL2);
|
||||||
|
#else
|
||||||
|
display->drawFastImage(x, compactSecondLine + 2, 8, 8, imgInfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
display->drawString(x + 14, compactSecondLine, ourId);
|
||||||
|
|
||||||
|
// Display Channel Utilization
|
||||||
|
char chUtil[13];
|
||||||
|
snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||||
|
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), compactSecondLine, chUtil);
|
||||||
|
|
||||||
|
// === Third Row: LongName Centered ===
|
||||||
|
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
|
if (ourNode && ourNode->has_user && strlen(ourNode->user.long_name) > 0) {
|
||||||
|
const char *longName = ourNode->user.long_name;
|
||||||
|
int textWidth = display->getStringWidth(longName);
|
||||||
|
int nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
|
int nameY = y + (FONT_HEIGHT_SMALL + 1) * 3;
|
||||||
|
display->drawString(nameX, compactThirdLine, longName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Fourth Row: Uptime ===
|
||||||
|
uint32_t uptime = millis() / 1000;
|
||||||
|
char uptimeStr[6];
|
||||||
|
uint32_t minutes = uptime / 60, hours = minutes / 60, days = hours / 24;
|
||||||
|
|
||||||
|
if (days > 365) {
|
||||||
|
snprintf(uptimeStr, sizeof(uptimeStr), "?");
|
||||||
|
} else {
|
||||||
|
snprintf(uptimeStr, sizeof(uptimeStr), "%d%c",
|
||||||
|
days ? days
|
||||||
|
: hours ? hours
|
||||||
|
: minutes ? minutes
|
||||||
|
: (int)uptime,
|
||||||
|
days ? 'd'
|
||||||
|
: hours ? 'h'
|
||||||
|
: minutes ? 'm'
|
||||||
|
: 's');
|
||||||
|
}
|
||||||
|
|
||||||
|
char uptimeFullStr[16];
|
||||||
|
snprintf(uptimeFullStr, sizeof(uptimeFullStr), "Uptime: %s", uptimeStr);
|
||||||
|
int uptimeX = (SCREEN_WIDTH - display->getStringWidth(uptimeFullStr)) / 2;
|
||||||
|
display->drawString(uptimeX, compactFourthLine, uptimeFullStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ****************************
|
||||||
|
// * LoRa Focused Screen *
|
||||||
|
// ****************************
|
||||||
|
static void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
display->clear();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
|
||||||
|
// === Header ===
|
||||||
|
drawCommonHeader(display, x, y);
|
||||||
|
|
||||||
|
// === First Row: MAC ID and Region ===
|
||||||
|
bool origBold = config.display.heading_bold;
|
||||||
|
config.display.heading_bold = false;
|
||||||
|
|
||||||
|
// Get our hardware ID
|
||||||
|
uint8_t dmac[6];
|
||||||
|
getMacAddr(dmac);
|
||||||
|
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
|
||||||
|
|
||||||
|
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||||
|
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
|
display->drawFastImage(x, compactFirstLine + 5, 12, 8, imgInfoL1);
|
||||||
|
display->drawFastImage(x, compactFirstLine + 12, 12, 8, imgInfoL2);
|
||||||
|
#else
|
||||||
|
display->drawFastImage(x, compactFirstLine + 3, 8, 8, imgInfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
display->drawString(x + 14, compactFirstLine, ourId);
|
||||||
|
|
||||||
|
const char *region = myRegion ? myRegion->name : NULL;
|
||||||
|
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(region), compactFirstLine, region);
|
||||||
|
|
||||||
|
config.display.heading_bold = origBold;
|
||||||
|
|
||||||
|
// === Second Row: Channel and Channel Utilization ===
|
||||||
|
char chUtil[13];
|
||||||
|
snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||||
|
display->drawString(x, compactSecondLine, chUtil);
|
||||||
|
|
||||||
|
char channelStr[20];
|
||||||
|
{
|
||||||
|
snprintf(channelStr, sizeof(channelStr), "#%s", channels.getName(channels.getPrimaryIndex()));
|
||||||
|
}
|
||||||
|
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(channelStr), compactSecondLine, channelStr);
|
||||||
|
|
||||||
|
// === Third Row: Node Name ===
|
||||||
|
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
|
if (ourNode && ourNode->has_user && strlen(ourNode->user.long_name) > 0) {
|
||||||
|
const char *longName = ourNode->user.long_name;
|
||||||
|
int uptimeX = (SCREEN_WIDTH - display->getStringWidth(longName)) / 2;
|
||||||
|
display->drawString(uptimeX, compactThirdLine, longName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ****************************
|
// ****************************
|
||||||
// * BatteryDeviceLoRa Screen *
|
// * BatteryDeviceLoRa Screen *
|
||||||
// ****************************
|
// ****************************
|
||||||
@ -2239,7 +2457,8 @@ static void drawActivity(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
// ****************************
|
// ****************************
|
||||||
// * My Position Screen *
|
// * My Position Screen *
|
||||||
// ****************************
|
// ****************************
|
||||||
static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
display->clear();
|
display->clear();
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
@ -2258,11 +2477,8 @@ static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiStat
|
|||||||
|
|
||||||
#if HAS_GPS
|
#if HAS_GPS
|
||||||
// === Update GeoCoord ===
|
// === Update GeoCoord ===
|
||||||
geoCoord.updateCoords(
|
geoCoord.updateCoords(int32_t(gpsStatus->getLatitude()), int32_t(gpsStatus->getLongitude()),
|
||||||
int32_t(gpsStatus->getLatitude()),
|
int32_t(gpsStatus->getAltitude()));
|
||||||
int32_t(gpsStatus->getLongitude()),
|
|
||||||
int32_t(gpsStatus->getAltitude())
|
|
||||||
);
|
|
||||||
|
|
||||||
// === Determine Compass Heading ===
|
// === Determine Compass Heading ===
|
||||||
float heading;
|
float heading;
|
||||||
@ -2329,7 +2545,8 @@ static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiStat
|
|||||||
// ****************************
|
// ****************************
|
||||||
// * Memory Screen *
|
// * Memory Screen *
|
||||||
// ****************************
|
// ****************************
|
||||||
static void drawMemoryScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
static void drawMemoryScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
display->clear();
|
display->clear();
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
@ -2367,7 +2584,8 @@ static void drawMemoryScreen(OLEDDisplay *display, OLEDDisplayUiState *state, in
|
|||||||
int rowY = y + rowYOffset;
|
int rowY = y + rowYOffset;
|
||||||
|
|
||||||
auto drawUsageRow = [&](const char *label, uint32_t used, uint32_t total) {
|
auto drawUsageRow = [&](const char *label, uint32_t used, uint32_t total) {
|
||||||
if (total == 0) return;
|
if (total == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
int percent = (used * 100) / total;
|
int percent = (used * 100) / total;
|
||||||
|
|
||||||
@ -2380,7 +2598,8 @@ static void drawMemoryScreen(OLEDDisplay *display, OLEDDisplayUiState *state, in
|
|||||||
|
|
||||||
int textWidth = display->getStringWidth(combinedStr);
|
int textWidth = display->getStringWidth(combinedStr);
|
||||||
int adjustedBarWidth = SCREEN_WIDTH - barX - textWidth - 6;
|
int adjustedBarWidth = SCREEN_WIDTH - barX - textWidth - 6;
|
||||||
if (adjustedBarWidth < 10) adjustedBarWidth = 10; // prevent weird bar if display is too small
|
if (adjustedBarWidth < 10)
|
||||||
|
adjustedBarWidth = 10; // prevent weird bar if display is too small
|
||||||
|
|
||||||
int fillWidth = (used * adjustedBarWidth) / total;
|
int fillWidth = (used * adjustedBarWidth) / total;
|
||||||
|
|
||||||
@ -2393,7 +2612,8 @@ static void drawMemoryScreen(OLEDDisplay *display, OLEDDisplayUiState *state, in
|
|||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
display->drawRect(barX, barY, adjustedBarWidth, barHeight);
|
display->drawRect(barX, barY, adjustedBarWidth, barHeight);
|
||||||
|
|
||||||
if (percent >= 80) display->setColor(BLACK);
|
if (percent >= 80)
|
||||||
|
display->setColor(BLACK);
|
||||||
display->fillRect(barX, barY, fillWidth, barHeight);
|
display->fillRect(barX, barY, fillWidth, barHeight);
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
|
|
||||||
@ -2431,12 +2651,13 @@ static void drawMemoryScreen(OLEDDisplay *display, OLEDDisplayUiState *state, in
|
|||||||
drawUsageRow("Heap:", heapUsed, heapTotal);
|
drawUsageRow("Heap:", heapUsed, heapTotal);
|
||||||
drawUsageRow("PSRAM:", psramUsed, psramTotal);
|
drawUsageRow("PSRAM:", psramUsed, psramTotal);
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
if (flashTotal > 0) drawUsageRow("Flash:", flashUsed, flashTotal);
|
if (flashTotal > 0)
|
||||||
|
drawUsageRow("Flash:", flashUsed, flashTotal);
|
||||||
#endif
|
#endif
|
||||||
if (hasSD && sdTotal > 0) drawUsageRow("SD:", sdUsed, sdTotal);
|
if (hasSD && sdTotal > 0)
|
||||||
|
drawUsageRow("SD:", sdUsed, sdTotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(ESP_PLATFORM) && defined(USE_ST7789)
|
#if defined(ESP_PLATFORM) && defined(USE_ST7789)
|
||||||
SPIClass SPI1(HSPI);
|
SPIClass SPI1(HSPI);
|
||||||
#endif
|
#endif
|
||||||
@ -3063,32 +3284,34 @@ void Screen::setFrames(FrameFocus focus)
|
|||||||
normalFrames[numframes++] = drawTextMessageFrame;
|
normalFrames[numframes++] = drawTextMessageFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
normalFrames[numframes++] = drawDefaultScreen;
|
// normalFrames[numframes++] = drawDefaultScreen;
|
||||||
|
normalFrames[numframes++] = drawDeviceFocused;
|
||||||
normalFrames[numframes++] = drawLastHeardScreen;
|
normalFrames[numframes++] = drawLastHeardScreen;
|
||||||
normalFrames[numframes++] = drawDistanceScreen;
|
normalFrames[numframes++] = drawDistanceScreen;
|
||||||
normalFrames[numframes++] = drawNodeListWithCompasses;
|
normalFrames[numframes++] = drawNodeListWithCompasses;
|
||||||
normalFrames[numframes++] = drawHopSignalScreen;
|
normalFrames[numframes++] = drawHopSignalScreen;
|
||||||
normalFrames[numframes++] = drawBatteryDeviceLoRa;
|
// normalFrames[numframes++] = drawBatteryDeviceLoRa;
|
||||||
|
normalFrames[numframes++] = drawLoRaFocused;
|
||||||
normalFrames[numframes++] = drawCompassAndLocationScreen;
|
normalFrames[numframes++] = drawCompassAndLocationScreen;
|
||||||
normalFrames[numframes++] = drawMemoryScreen;
|
normalFrames[numframes++] = drawMemoryScreen;
|
||||||
normalFrames[numframes++] = drawActivity;
|
normalFrames[numframes++] = drawActivity;
|
||||||
|
|
||||||
// then all the nodes
|
// then all the nodes
|
||||||
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
|
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
|
||||||
size_t numToShow = min(numMeshNodes, 4U);
|
// size_t numToShow = min(numMeshNodes, 4U);
|
||||||
for (size_t i = 0; i < numToShow; i++)
|
// for (size_t i = 0; i < numToShow; i++)
|
||||||
normalFrames[numframes++] = drawNodeInfo;
|
// normalFrames[numframes++] = drawNodeInfo;
|
||||||
|
|
||||||
// then the debug info
|
// then the debug info
|
||||||
//
|
//
|
||||||
// Since frames are basic function pointers, we have to use a helper to
|
// Since frames are basic function pointers, we have to use a helper to
|
||||||
// call a method on debugInfo object.
|
// call a method on debugInfo object.
|
||||||
fsi.positions.log = numframes;
|
// fsi.positions.log = numframes;
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoTrampoline;
|
// normalFrames[numframes++] = &Screen::drawDebugInfoTrampoline;
|
||||||
|
|
||||||
// call a method on debugInfoScreen object (for more details)
|
// call a method on debugInfoScreen object (for more details)
|
||||||
fsi.positions.settings = numframes;
|
// fsi.positions.settings = numframes;
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
// normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
||||||
|
|
||||||
fsi.positions.wifi = numframes;
|
fsi.positions.wifi = numframes;
|
||||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||||
|
Loading…
Reference in New Issue
Block a user