mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-08 22:22:05 +00:00
GPS tittle offset
-GPS Enabled -GPS Disabled -GPS Not Present -GPS Disabled with Fixed Position -GPS Not Present with Fixed Position -GPS Enabled - Toggle off and on -GPS Disabled - Toggle on and off
This commit is contained in:
parent
f1f6b63380
commit
9e4847840a
@ -1006,7 +1006,7 @@ constexpr uint32_t mailBlinkInterval = 500;
|
||||
void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y)
|
||||
{
|
||||
LOG_INFO("drawCommonHeader: hasUnreadMessage = %s", hasUnreadMessage ? "true" : "false");
|
||||
constexpr int HEADER_OFFSET_Y = 2;
|
||||
constexpr int HEADER_OFFSET_Y = 1;
|
||||
y += HEADER_OFFSET_Y;
|
||||
|
||||
const bool isInverted = (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED);
|
||||
@ -1038,7 +1038,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y)
|
||||
if (useHorizontalBattery) {
|
||||
// === Horizontal battery ===
|
||||
int batteryX = 2;
|
||||
int batteryY = 4;
|
||||
int batteryY = HEADER_OFFSET_Y + 2;
|
||||
|
||||
display->drawXbm(batteryX, batteryY, 29, 15, batteryBitmap_h);
|
||||
|
||||
@ -1055,7 +1055,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y)
|
||||
} else {
|
||||
// === Vertical battery ===
|
||||
int batteryX = 1;
|
||||
int batteryY = 3;
|
||||
int batteryY = HEADER_OFFSET_Y + 1;
|
||||
|
||||
display->drawXbm(batteryX, batteryY, 7, 11, batteryBitmap_v);
|
||||
|
||||
@ -1404,10 +1404,19 @@ void Screen::drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char
|
||||
}
|
||||
|
||||
// Draw nodes status
|
||||
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStatus *nodeStatus)
|
||||
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStatus *nodeStatus, int node_offset = 0,
|
||||
bool show_total = true)
|
||||
{
|
||||
char usersString[20];
|
||||
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
||||
int nodes_online = (nodeStatus->getNumOnline() > 0) ? nodeStatus->getNumOnline() + node_offset : 0;
|
||||
|
||||
snprintf(usersString, sizeof(usersString), "%d", nodes_online);
|
||||
|
||||
if (show_total) {
|
||||
int nodes_total = (nodeStatus->getNumTotal() > 0) ? nodeStatus->getNumTotal() + node_offset : 0;
|
||||
snprintf(usersString, sizeof(usersString), "%d/%d", nodes_online, nodes_total);
|
||||
}
|
||||
|
||||
#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)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
@ -1416,8 +1425,12 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
|
||||
display->drawFastImage(x, y, 8, 8, imgUser);
|
||||
#endif
|
||||
display->drawString(x + 10, y - 2, usersString);
|
||||
if (config.display.heading_bold)
|
||||
display->drawString(x + 11, y - 2, usersString);
|
||||
int string_offset = (SCREEN_WIDTH > 128) ? 2 : 1;
|
||||
if (!show_total) {
|
||||
display->drawString(x + 10 + display->getStringWidth(usersString) + string_offset, y - 2, "online");
|
||||
if (config.display.heading_bold)
|
||||
display->drawString(x + 11 + display->getStringWidth(usersString) + string_offset, y - 2, "online");
|
||||
}
|
||||
}
|
||||
#if HAS_GPS
|
||||
// Draw GPS status summary
|
||||
@ -1892,7 +1905,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int);
|
||||
typedef void (*NodeExtrasRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int, float, double, double);
|
||||
|
||||
|
||||
struct NodeEntry {
|
||||
meshtastic_NodeInfoLite *node;
|
||||
uint32_t lastHeard;
|
||||
@ -1902,20 +1914,16 @@ struct NodeEntry {
|
||||
// =============================
|
||||
// Shared Enums and Timing Logic
|
||||
// =============================
|
||||
enum NodeListMode {
|
||||
MODE_LAST_HEARD = 0,
|
||||
MODE_HOP_SIGNAL = 1,
|
||||
MODE_DISTANCE = 2,
|
||||
MODE_COUNT = 3
|
||||
};
|
||||
enum NodeListMode { MODE_LAST_HEARD = 0, MODE_HOP_SIGNAL = 1, MODE_DISTANCE = 2, MODE_COUNT = 3 };
|
||||
|
||||
static NodeListMode currentMode = MODE_LAST_HEARD;
|
||||
static unsigned long lastModeSwitchTime = 0;
|
||||
static int scrollIndex = 0;
|
||||
|
||||
// Use dynamic timing based on mode
|
||||
unsigned long getModeCycleIntervalMs() {
|
||||
//return (currentMode == MODE_DISTANCE) ? 3000 : 2000;
|
||||
unsigned long getModeCycleIntervalMs()
|
||||
{
|
||||
// return (currentMode == MODE_DISTANCE) ? 3000 : 2000;
|
||||
return 2000;
|
||||
}
|
||||
|
||||
@ -1963,7 +1971,8 @@ String getSafeNodeName(meshtastic_NodeInfoLite *node)
|
||||
nodeName = String(idStr);
|
||||
}
|
||||
}
|
||||
if (node->is_favorite) nodeName = "*" + nodeName;
|
||||
if (node->is_favorite)
|
||||
nodeName = "*" + nodeName;
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
@ -1975,7 +1984,8 @@ void retrieveAndSortNodes(std::vector<NodeEntry> &nodeList)
|
||||
size_t numNodes = nodeDB->getNumMeshNodes();
|
||||
for (size_t i = 0; i < numNodes; i++) {
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
||||
if (!node || node->num == nodeDB->getNodeNum()) continue;
|
||||
if (!node || node->num == nodeDB->getNodeNum())
|
||||
continue;
|
||||
|
||||
NodeEntry entry;
|
||||
entry.node = node;
|
||||
@ -1991,7 +2001,8 @@ void retrieveAndSortNodes(std::vector<NodeEntry> &nodeList)
|
||||
|
||||
float dLat = (lat2 - lat1) * DEG_TO_RAD;
|
||||
float dLon = (lon2 - lon1) * DEG_TO_RAD;
|
||||
float a = sin(dLat / 2) * sin(dLat / 2) + cos(lat1 * DEG_TO_RAD) * cos(lat2 * DEG_TO_RAD) * sin(dLon / 2) * sin(dLon / 2);
|
||||
float a =
|
||||
sin(dLat / 2) * sin(dLat / 2) + cos(lat1 * DEG_TO_RAD) * cos(lat2 * DEG_TO_RAD) * sin(dLon / 2) * sin(dLon / 2);
|
||||
float c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
||||
entry.cachedDistance = 6371.0f * c; // Earth radius in km
|
||||
}
|
||||
@ -2002,16 +2013,16 @@ void retrieveAndSortNodes(std::vector<NodeEntry> &nodeList)
|
||||
std::sort(nodeList.begin(), nodeList.end(), [](const NodeEntry &a, const NodeEntry &b) {
|
||||
bool aFav = a.node->is_favorite;
|
||||
bool bFav = b.node->is_favorite;
|
||||
if (aFav != bFav) return aFav > bFav;
|
||||
if (a.lastHeard == 0 || a.lastHeard == UINT32_MAX) return false;
|
||||
if (b.lastHeard == 0 || b.lastHeard == UINT32_MAX) return true;
|
||||
if (aFav != bFav)
|
||||
return aFav > bFav;
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void drawColumnSeparator(OLEDDisplay *display, int16_t x, int16_t yStart, int16_t yEnd)
|
||||
{
|
||||
int columnWidth = display->getWidth() / 2;
|
||||
@ -2023,7 +2034,8 @@ void drawScrollbar(OLEDDisplay *display, int visibleNodeRows, int totalEntries,
|
||||
{
|
||||
const int rowHeight = FONT_HEIGHT_SMALL - 3;
|
||||
const int totalVisualRows = (totalEntries + columns - 1) / columns;
|
||||
if (totalVisualRows <= visibleNodeRows) return;
|
||||
if (totalVisualRows <= visibleNodeRows)
|
||||
return;
|
||||
const int scrollAreaHeight = visibleNodeRows * rowHeight;
|
||||
const int scrollbarX = display->getWidth() - 6;
|
||||
const int scrollbarWidth = 4;
|
||||
@ -2052,7 +2064,7 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
||||
|
||||
// === Manually draw the centered title within the header ===
|
||||
const int highlightHeight = COMMON_HEADER_HEIGHT;
|
||||
const int textY = y + 2 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const int textY = y + 1 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const int centerX = x + SCREEN_WIDTH / 2;
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
@ -2136,8 +2148,12 @@ void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
||||
} else {
|
||||
uint32_t minutes = seconds / 60, hours = minutes / 60, days = hours / 24;
|
||||
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);
|
||||
@ -2155,7 +2171,7 @@ void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
||||
|
||||
int nameMaxWidth = columnWidth - 25;
|
||||
int barsOffset = (SCREEN_WIDTH > 128) ? (isLeftCol ? 26 : 30) : (isLeftCol ? 17 : 19);
|
||||
int hopOffset = (SCREEN_WIDTH > 128) ? (isLeftCol ? 32 : 38) : (isLeftCol ? 18 : 20);
|
||||
int hopOffset = (SCREEN_WIDTH > 128) ? (isLeftCol ? 32 : 38) : (isLeftCol ? 18 : 20);
|
||||
int barsXOffset = columnWidth - barsOffset;
|
||||
|
||||
String nodeName = getSafeNodeName(node);
|
||||
@ -2208,7 +2224,8 @@ void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
||||
double dLat = (lat2 - lat1) * DEG_TO_RAD;
|
||||
double dLon = (lon2 - lon1) * DEG_TO_RAD;
|
||||
|
||||
double a = sin(dLat / 2) * sin(dLat / 2) + cos(lat1 * DEG_TO_RAD) * cos(lat2 * DEG_TO_RAD) * sin(dLon / 2) * sin(dLon / 2);
|
||||
double a =
|
||||
sin(dLat / 2) * sin(dLat / 2) + cos(lat1 * DEG_TO_RAD) * cos(lat2 * DEG_TO_RAD) * sin(dLon / 2) * sin(dLon / 2);
|
||||
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
||||
double distanceKm = earthRadiusKm * c;
|
||||
|
||||
@ -2246,31 +2263,31 @@ void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
||||
void drawEntryDynamic(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||
{
|
||||
switch (currentMode) {
|
||||
case MODE_LAST_HEARD:
|
||||
drawEntryLastHeard(display, node, x, y, columnWidth);
|
||||
break;
|
||||
case MODE_HOP_SIGNAL:
|
||||
drawEntryHopSignal(display, node, x, y, columnWidth);
|
||||
break;
|
||||
case MODE_DISTANCE:
|
||||
drawNodeDistance(display, node, x, y, columnWidth);
|
||||
break;
|
||||
default:
|
||||
break; // Silences warning for MODE_COUNT or unexpected values
|
||||
case MODE_LAST_HEARD:
|
||||
drawEntryLastHeard(display, node, x, y, columnWidth);
|
||||
break;
|
||||
case MODE_HOP_SIGNAL:
|
||||
drawEntryHopSignal(display, node, x, y, columnWidth);
|
||||
break;
|
||||
case MODE_DISTANCE:
|
||||
drawNodeDistance(display, node, x, y, columnWidth);
|
||||
break;
|
||||
default:
|
||||
break; // Silences warning for MODE_COUNT or unexpected values
|
||||
}
|
||||
}
|
||||
|
||||
const char* getCurrentModeTitle(int screenWidth)
|
||||
const char *getCurrentModeTitle(int screenWidth)
|
||||
{
|
||||
switch (currentMode) {
|
||||
case MODE_LAST_HEARD:
|
||||
return "Node List";
|
||||
case MODE_HOP_SIGNAL:
|
||||
return (screenWidth > 128) ? "Hops|Signals" : "Hop|Sig";
|
||||
case MODE_DISTANCE:
|
||||
return "Distances";
|
||||
default:
|
||||
return "Nodes";
|
||||
case MODE_LAST_HEARD:
|
||||
return "Node List";
|
||||
case MODE_HOP_SIGNAL:
|
||||
return (screenWidth > 128) ? "Hops|Signals" : "Hop|Sig";
|
||||
case MODE_DISTANCE:
|
||||
return "Distances";
|
||||
default:
|
||||
return "Nodes";
|
||||
}
|
||||
}
|
||||
|
||||
@ -2299,7 +2316,7 @@ static void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *
|
||||
}
|
||||
|
||||
// Render screen based on currentMode
|
||||
const char* title = getCurrentModeTitle(display->getWidth());
|
||||
const char *title = getCurrentModeTitle(display->getWidth());
|
||||
drawNodeListScreen(display, state, x, y, title, drawEntryDynamic);
|
||||
|
||||
// Track the last mode to avoid reinitializing modeStartTime
|
||||
@ -2316,12 +2333,11 @@ static void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *
|
||||
if (state->ticksSinceLastStateSwitch == 0) {
|
||||
currentMode = MODE_LAST_HEARD;
|
||||
}
|
||||
const char* title = getCurrentModeTitle();
|
||||
const char *title = getCurrentModeTitle();
|
||||
drawNodeListScreen(display, state, x, y, title, drawEntryDynamic);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
@ -2432,32 +2448,30 @@ static void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
// Display Region and Channel Utilization
|
||||
config.display.heading_bold = false;
|
||||
|
||||
drawNodes(display, x + 1, compactFirstLine + 3, nodeStatus);
|
||||
drawNodes(display, x + 1, compactFirstLine + 3, nodeStatus, -1, false);
|
||||
|
||||
#if HAS_GPS
|
||||
auto number_of_satellites = gpsStatus->getNumSatellites();
|
||||
int gps_rightchar_offset = (SCREEN_WIDTH > 128) ? -52 : -46;
|
||||
int gps_rightchar_offset = (SCREEN_WIDTH > 128) ? -30 : -46;
|
||||
if (number_of_satellites < 10) {
|
||||
gps_rightchar_offset += (SCREEN_WIDTH > 128) ? 14 : 6;
|
||||
gps_rightchar_offset -= (SCREEN_WIDTH > 128) ? 14 : 6;
|
||||
}
|
||||
if (!gpsStatus || !gpsStatus->getIsConnected()) {
|
||||
gps_rightchar_offset = (SCREEN_WIDTH > 128) ? -20 : 2;
|
||||
}
|
||||
|
||||
if (config.position.fixed_position) {
|
||||
if (SCREEN_WIDTH > 128) {
|
||||
drawGPS(display, SCREEN_WIDTH + gps_rightchar_offset, compactFirstLine + 3, gpsStatus);
|
||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
String displayLine = "";
|
||||
if (config.position.fixed_position) {
|
||||
gps_rightchar_offset = (SCREEN_WIDTH > 128) ? -80 : -50;
|
||||
displayLine = "Fixed GPS";
|
||||
} else {
|
||||
drawGPS(display, SCREEN_WIDTH + gps_rightchar_offset, compactFirstLine + 3, gpsStatus);
|
||||
gps_rightchar_offset = (SCREEN_WIDTH > 128) ? -58 : -38;
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||
}
|
||||
} 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, displayLine);
|
||||
display->drawString(SCREEN_WIDTH + gps_rightchar_offset, compactFirstLine, displayLine);
|
||||
} else {
|
||||
if (SCREEN_WIDTH > 128) {
|
||||
drawGPS(display, SCREEN_WIDTH + gps_rightchar_offset, compactFirstLine + 3, gpsStatus);
|
||||
} else {
|
||||
drawGPS(display, SCREEN_WIDTH + gps_rightchar_offset, compactFirstLine + 3, gpsStatus);
|
||||
}
|
||||
drawGPS(display, SCREEN_WIDTH + gps_rightchar_offset, compactFirstLine + 3, gpsStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2524,7 +2538,7 @@ static void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int
|
||||
|
||||
// === Draw title (aligned with header baseline) ===
|
||||
const int highlightHeight = FONT_HEIGHT_SMALL - 1;
|
||||
const int textY = y + 2 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const int textY = y + 1 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const char *titleStr = (SCREEN_WIDTH > 128) ? "LoRa Info" : "LoRa";
|
||||
const int centerX = x + SCREEN_WIDTH / 2;
|
||||
|
||||
@ -2541,6 +2555,8 @@ static void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
// === First Row: Region / Radio Preset ===
|
||||
drawNodes(display, x, compactFirstLine + 3, nodeStatus, 0, true);
|
||||
|
||||
auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false);
|
||||
|
||||
// Display Region and Radio Preset
|
||||
@ -2549,7 +2565,7 @@ static void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int
|
||||
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s/%s", region, mode);
|
||||
int textWidth = display->getStringWidth(regionradiopreset);
|
||||
int nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||
display->drawString(nameX, compactFirstLine, regionradiopreset);
|
||||
display->drawString(SCREEN_WIDTH - textWidth, compactFirstLine, regionradiopreset);
|
||||
|
||||
// === Second Row: Channel Utilization ===
|
||||
// Get our hardware ID
|
||||
@ -2612,7 +2628,7 @@ static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
|
||||
// === Draw title ===
|
||||
const int highlightHeight = FONT_HEIGHT_SMALL - 1;
|
||||
const int textY = y + 2 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const int textY = y + 1 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const char *titleStr = "GPS";
|
||||
const int centerX = x + SCREEN_WIDTH / 2;
|
||||
|
||||
@ -2742,7 +2758,7 @@ static void drawMemoryScreen(OLEDDisplay *display, OLEDDisplayUiState *state, in
|
||||
|
||||
// === Draw title ===
|
||||
const int highlightHeight = FONT_HEIGHT_SMALL - 1;
|
||||
const int textY = y + 2 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const int textY = y + 1 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const char *titleStr = (SCREEN_WIDTH > 128) ? "Memory" : "Mem";
|
||||
const int centerX = x + SCREEN_WIDTH / 2;
|
||||
|
||||
@ -3518,7 +3534,6 @@ void Screen::setFrames(FrameFocus focus)
|
||||
normalFrames[numframes++] = drawTextMessageFrame;
|
||||
}
|
||||
|
||||
|
||||
normalFrames[numframes++] = drawDeviceFocused;
|
||||
normalFrames[numframes++] = drawDynamicNodeListScreen;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user