From d48e803b7b2b3e0c326561b0e2c18c9d2b5745d9 Mon Sep 17 00:00:00 2001 From: Professr Date: Mon, 22 Jun 2020 12:03:26 -0700 Subject: [PATCH 1/5] Custom utf8 conversion replaces unconvertable chars with ? instead of blanks, #154 --- src/screen.cpp | 3 +++ src/screen.h | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/screen.cpp b/src/screen.cpp index 9085dc0e..5d7d5579 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -499,6 +499,9 @@ void Screen::setup() // Store a pointer to Screen so we can get to it from static functions. ui.getUiState()->userData = this; + // Set the utf8 conversion function + dispdev.setFontTableLookupFunction(customFontTableLookup); + // Add frames. static FrameCallback bootFrames[] = {drawBootScreen}; static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]); diff --git a/src/screen.h b/src/screen.h index 302c8e33..f5f4b3c9 100644 --- a/src/screen.h +++ b/src/screen.h @@ -149,6 +149,29 @@ class Screen : public PeriodicTask } } + /// Overrides the default utf8 character conversion, to replace empty space with question marks + static char customFontTableLookup(const uint8_t ch) { + // UTF-8 to font table index converter + // Code form http://playground.arduino.cc/Main/Utf8ascii + static uint8_t LASTCHAR; + + if (ch < 128) { // Standard ASCII-set 0..0x7F handling + LASTCHAR = 0; + return ch; + } + + uint8_t last = LASTCHAR; // get last char + LASTCHAR = ch; + + switch (last) { // conversion depnding on first UTF8-character + case 0xC2: return (uint8_t) ch; + case 0xC3: return (uint8_t) (ch | 0xC0); + case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol + } + + return (uint8_t) '?'; // otherwise: return ?, if character can't be converted + } + /// Returns a handle to the DebugInfo screen. // // Use this handle to set things like battery status, user count, GPS status, etc. From 2530dc44c782ceab537acc1a333108d04999052d Mon Sep 17 00:00:00 2001 From: Professr Date: Tue, 23 Jun 2020 16:46:41 -0700 Subject: [PATCH 2/5] =?UTF-8?q?Changed=20unconvertable-character=20symbol?= =?UTF-8?q?=20to=20=C2=BF=20and=20made=20it=20return=20only=20one=20per=20?= =?UTF-8?q?unconvertable=20sequence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screen.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/screen.h b/src/screen.h index f5f4b3c9..47860275 100644 --- a/src/screen.h +++ b/src/screen.h @@ -154,9 +154,11 @@ class Screen : public PeriodicTask // UTF-8 to font table index converter // Code form http://playground.arduino.cc/Main/Utf8ascii static uint8_t LASTCHAR; + static bool SKIPREST; // Only display a single unconvertable-character symbol per sequence of unconvertable characters if (ch < 128) { // Standard ASCII-set 0..0x7F handling LASTCHAR = 0; + SKIPREST = false; return ch; } @@ -164,12 +166,15 @@ class Screen : public PeriodicTask LASTCHAR = ch; switch (last) { // conversion depnding on first UTF8-character - case 0xC2: return (uint8_t) ch; - case 0xC3: return (uint8_t) (ch | 0xC0); - case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol + case 0xC2: { SKIPREST = false; return (uint8_t) ch; } + case 0xC3: { SKIPREST = false; return (uint8_t) (ch | 0xC0); } + case 0x82: { SKIPREST = false; if (ch == 0xAC) return (uint8_t) 0x80; } // special case Euro-symbol } + // If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the rest of it + if (SKIPREST) return (uint8_t) 0; + SKIPREST = true; - return (uint8_t) '?'; // otherwise: return ?, if character can't be converted + return (uint8_t) 0xA8; // otherwise: return ¿ if character can't be converted } /// Returns a handle to the DebugInfo screen. From e3bcb87cf0f54c0785a41ac6591ac7dea81bf204 Mon Sep 17 00:00:00 2001 From: Professr Date: Tue, 23 Jun 2020 18:02:41 -0700 Subject: [PATCH 3/5] Removed prefix chars, fixed issues related to custom font mappings --- src/screen.cpp | 2 +- src/screen.h | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/screen.cpp b/src/screen.cpp index 18e5cb1d..1200e5a4 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -717,7 +717,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 } const char *fields[] = {channelStr, nullptr}; - uint32_t yo = drawRows(display, x, y + 12, fields); + uint32_t yo = drawRows(display, x, y + FONT_HEIGHT, fields); display->drawLogBuffer(x, yo); } diff --git a/src/screen.h b/src/screen.h index 47860275..95ca0a60 100644 --- a/src/screen.h +++ b/src/screen.h @@ -168,13 +168,16 @@ class Screen : public PeriodicTask switch (last) { // conversion depnding on first UTF8-character case 0xC2: { SKIPREST = false; return (uint8_t) ch; } case 0xC3: { SKIPREST = false; return (uint8_t) (ch | 0xC0); } - case 0x82: { SKIPREST = false; if (ch == 0xAC) return (uint8_t) 0x80; } // special case Euro-symbol } + + // We want to strip out prefix chars for two-byte char formats + if (ch == 0xC2 || ch == 0xC3 || ch == 0x82) return (uint8_t) 0; + // If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the rest of it if (SKIPREST) return (uint8_t) 0; SKIPREST = true; - return (uint8_t) 0xA8; // otherwise: return ¿ if character can't be converted + return (uint8_t) 191; // otherwise: return ¿ if character can't be converted (note that the font map we're using doesn't stick to standard EASCII codes) } /// Returns a handle to the DebugInfo screen. From 3df05cd5c1442f15a33d4ea8df7b4761e36c612e Mon Sep 17 00:00:00 2001 From: Zach Whitehead Date: Mon, 22 Jun 2020 19:27:13 -0400 Subject: [PATCH 4/5] break out compass display Show question mark if unknown location --- platformio.ini | 34 ++++++++++++------------ src/screen.cpp | 72 ++++++++++++++++++++++++++------------------------ 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/platformio.ini b/platformio.ini index ab23d99d..9f1453d2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,21 +65,21 @@ debug_tool = jlink ; monitor adapter_khz 10000 lib_deps = - https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 + https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 SPI ; 1260 ; OneButton - not used yet 1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib Wire ; explicitly needed here because the AXP202 library forgets to add it - https://github.com/meshtastic/arduino-fsm.git + https://github.com/meshtastic/arduino-fsm.git https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git https://github.com/meshtastic/RadioLib.git - https://github.com/meshtastic/TinyGPSPlus.git - + https://github.com/meshtastic/TinyGPSPlus.git + ; Common settings for ESP targes, mixin with extends = esp32_base [esp32_base] platform = espressif32 framework = arduino -src_filter = +src_filter = ${env.src_filter} - upload_speed = 921600 debug_init_break = tbreak setup @@ -98,7 +98,7 @@ board = ttgo-t-beam lib_deps = ${env.lib_deps} https://github.com/meshtastic/AXP202X_Library.git -build_flags = +build_flags = ${esp32_base.build_flags} -D TBEAM_V10 ; The original TBEAM board without the AXP power chip and a few other changes @@ -106,28 +106,28 @@ build_flags = ;[env:tbeam0.7] ;extends = esp32_base ;board = ttgo-t-beam -;build_flags = +;build_flags = ; ${esp32_base.build_flags} -D TBEAM_V07 [env:heltec] -;build_type = debug ; to make it possible to step through our jtag debugger +;build_type = debug ; to make it possible to step through our jtag debugger extends = esp32_base board = heltec_wifi_lora_32_V2 [env:ttgo-lora32-v1] extends = esp32_base board = ttgo-lora32-v1 -build_flags = +build_flags = ${esp32_base.build_flags} -D TTGO_LORA_V1 ; note: the platformio definition for lora32-v2 seems stale, it is missing a pins_arduino.h file, therefore I don't think it works [env:ttgo-lora32-v2] extends = esp32_base board = ttgo-lora32-v1 -build_flags = +build_flags = ${esp32_base.build_flags} -D TTGO_LORA_V2 -; The Heltec Cubecell plus +; The Heltec Cubecell plus ; IMPORTANT NOTE: This target doesn't yet work and probably won't ever work. I'm keeping it around for now. ; For more details see my post in the forum. [env:cubecellplus] @@ -136,9 +136,9 @@ framework = arduino board = cubecell_board_plus ; FIXME, bug in cubecell arduino - they are supposed to set ARDUINO build_flags = ${env.build_flags} -DARDUINO=100 -Isrc/cubecell -src_filter = +src_filter = ${env.src_filter} - - - + ; Common settings for NRF52 based targets [nrf52_base] platform = nordicnrf52 @@ -146,10 +146,10 @@ framework = arduino debug_tool = jlink build_type = debug ; I'm debugging with ICE a lot now ; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME) -build_flags = - ${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3 +build_flags = + ${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3 ;-DCFG_DEBUG=3 -src_filter = +src_filter = ${env.src_filter} - lib_ignore = BluetoothOTA @@ -178,7 +178,7 @@ board = nrf52840_dk_modified [env:ppr] extends = nrf52_base board = ppr -lib_deps = +lib_deps = ${env.lib_deps} UC1701 diff --git a/src/screen.cpp b/src/screen.cpp index 9d43eda8..8cc0b651 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -52,7 +52,7 @@ namespace meshtastic // A text message frame + debug frame + all the node infos static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES]; static uint32_t targetFramerate = IDLE_FRAMERATE; -static char btPIN[16] = "888888"; +static char btPIN[16] = "888888"; uint8_t imgBattery[16] = { 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C }; @@ -73,7 +73,6 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1 char buf[16]; snprintf(buf, sizeof(buf), "%s", xstr(APP_VERSION)); // Note: we don't bother printing region or now, it makes the string too long display->drawString(SCREEN_WIDTH - 20, 0, buf); - } static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) @@ -346,6 +345,30 @@ static bool hasPosition(NodeInfo *n) static size_t nodeIndex; static int8_t prevFrame = -1; +// Draw the compass and arrow pointing to location +static void drawCompass(OLEDDisplay *display, int16_t compassX, int16_t compassY, float headingRadian) +{ + // display->drawXbm(compassX, compassY, compass_width, compass_height, + // (const uint8_t *)compass_bits); + + Point tip(0.0f, 0.5f), tail(0.0f, -0.5f); // pointing up initially + float arrowOffsetX = 0.2f, arrowOffsetY = 0.2f; + Point leftArrow(tip.x - arrowOffsetX, tip.y - arrowOffsetY), rightArrow(tip.x + arrowOffsetX, tip.y - arrowOffsetY); + + Point *points[] = {&tip, &tail, &leftArrow, &rightArrow}; + + for (int i = 0; i < 4; i++) { + points[i]->rotate(headingRadian); + points[i]->scale(COMPASS_DIAM * 0.6); + points[i]->translate(compassX, compassY); + } + drawLine(display, tip, tail); + drawLine(display, leftArrow, tip); + drawLine(display, rightArrow, tip); + + display->drawCircle(compassX, compassY, COMPASS_DIAM / 2); +} + /// Convert an integer GPS coords to a floating point #define DegD(i) (i * 1e-7) @@ -390,15 +413,17 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ else snprintf(lastStr, sizeof(lastStr), "%u hours ago", agoSecs / 60 / 60); - static float simRadian; - simRadian += 0.1; // For testing, have the compass spin unless both - // locations are valid - static char distStr[20]; *distStr = 0; // might not have location data - float headingRadian = simRadian; + float headingRadian; NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum()); - if (ourNode && hasPosition(ourNode) && hasPosition(node)) { + const char *fields[] = {username, distStr, signalStr, lastStr, NULL}; + drawColumns(display, x, y, fields); + + // coordinates for the center of the compass/circle + int16_t compassX = x + SCREEN_WIDTH - COMPASS_DIAM / 2 - 1, compassY = y + SCREEN_HEIGHT / 2; + + if (ourNode && hasPosition(ourNode) && hasPosition(node)) { // display direction toward node Position &op = ourNode->position, &p = node->position; float d = latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); if (d < 2000) @@ -411,35 +436,14 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ float bearingToOther = bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); float myHeading = estimatedHeading(DegD(p.latitude_i), DegD(p.longitude_i)); headingRadian = bearingToOther - myHeading; - } else { + drawCompass(display, compassX, compassY, headingRadian); + } else { // direction to node is unknown so display question mark // Debug info for gps lock errors // DEBUG_MSG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node)); + + display->drawString(compassX - FONT_HEIGHT/4, compassY - FONT_HEIGHT/2, "?"); + display->drawCircle(compassX, compassY, COMPASS_DIAM / 2); } - - const char *fields[] = {username, distStr, signalStr, lastStr, NULL}; - drawColumns(display, x, y, fields); - - // coordinates for the center of the compass - int16_t compassX = x + SCREEN_WIDTH - COMPASS_DIAM / 2 - 1, compassY = y + SCREEN_HEIGHT / 2; - // display->drawXbm(compassX, compassY, compass_width, compass_height, - // (const uint8_t *)compass_bits); - - Point tip(0.0f, 0.5f), tail(0.0f, -0.5f); // pointing up initially - float arrowOffsetX = 0.2f, arrowOffsetY = 0.2f; - Point leftArrow(tip.x - arrowOffsetX, tip.y - arrowOffsetY), rightArrow(tip.x + arrowOffsetX, tip.y - arrowOffsetY); - - Point *points[] = {&tip, &tail, &leftArrow, &rightArrow}; - - for (int i = 0; i < 4; i++) { - points[i]->rotate(headingRadian); - points[i]->scale(COMPASS_DIAM * 0.6); - points[i]->translate(compassX, compassY); - } - drawLine(display, tip, tail); - drawLine(display, leftArrow, tip); - drawLine(display, rightArrow, tip); - - display->drawCircle(compassX, compassY, COMPASS_DIAM / 2); } #if 0 From 2e172b019e416452ca4204262341e2154a6175c9 Mon Sep 17 00:00:00 2001 From: geeksville Date: Wed, 24 Jun 2020 13:29:56 -0700 Subject: [PATCH 5/5] Undo @zjwhitehead changes to platformio.ini --- platformio.ini | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/platformio.ini b/platformio.ini index 9f1453d2..ab23d99d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,21 +65,21 @@ debug_tool = jlink ; monitor adapter_khz 10000 lib_deps = - https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 + https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 SPI ; 1260 ; OneButton - not used yet 1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib Wire ; explicitly needed here because the AXP202 library forgets to add it - https://github.com/meshtastic/arduino-fsm.git + https://github.com/meshtastic/arduino-fsm.git https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git https://github.com/meshtastic/RadioLib.git - https://github.com/meshtastic/TinyGPSPlus.git - + https://github.com/meshtastic/TinyGPSPlus.git + ; Common settings for ESP targes, mixin with extends = esp32_base [esp32_base] platform = espressif32 framework = arduino -src_filter = +src_filter = ${env.src_filter} - upload_speed = 921600 debug_init_break = tbreak setup @@ -98,7 +98,7 @@ board = ttgo-t-beam lib_deps = ${env.lib_deps} https://github.com/meshtastic/AXP202X_Library.git -build_flags = +build_flags = ${esp32_base.build_flags} -D TBEAM_V10 ; The original TBEAM board without the AXP power chip and a few other changes @@ -106,28 +106,28 @@ build_flags = ;[env:tbeam0.7] ;extends = esp32_base ;board = ttgo-t-beam -;build_flags = +;build_flags = ; ${esp32_base.build_flags} -D TBEAM_V07 [env:heltec] -;build_type = debug ; to make it possible to step through our jtag debugger +;build_type = debug ; to make it possible to step through our jtag debugger extends = esp32_base board = heltec_wifi_lora_32_V2 [env:ttgo-lora32-v1] extends = esp32_base board = ttgo-lora32-v1 -build_flags = +build_flags = ${esp32_base.build_flags} -D TTGO_LORA_V1 ; note: the platformio definition for lora32-v2 seems stale, it is missing a pins_arduino.h file, therefore I don't think it works [env:ttgo-lora32-v2] extends = esp32_base board = ttgo-lora32-v1 -build_flags = +build_flags = ${esp32_base.build_flags} -D TTGO_LORA_V2 -; The Heltec Cubecell plus +; The Heltec Cubecell plus ; IMPORTANT NOTE: This target doesn't yet work and probably won't ever work. I'm keeping it around for now. ; For more details see my post in the forum. [env:cubecellplus] @@ -136,9 +136,9 @@ framework = arduino board = cubecell_board_plus ; FIXME, bug in cubecell arduino - they are supposed to set ARDUINO build_flags = ${env.build_flags} -DARDUINO=100 -Isrc/cubecell -src_filter = +src_filter = ${env.src_filter} - - - + ; Common settings for NRF52 based targets [nrf52_base] platform = nordicnrf52 @@ -146,10 +146,10 @@ framework = arduino debug_tool = jlink build_type = debug ; I'm debugging with ICE a lot now ; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME) -build_flags = - ${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3 +build_flags = + ${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3 ;-DCFG_DEBUG=3 -src_filter = +src_filter = ${env.src_filter} - lib_ignore = BluetoothOTA @@ -178,7 +178,7 @@ board = nrf52840_dk_modified [env:ppr] extends = nrf52_base board = ppr -lib_deps = +lib_deps = ${env.lib_deps} UC1701