diff --git a/README.md b/README.md index 273560e2d..c5bce39cd 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ We currently support three models of radios. - TTGO T-Beam - - [T-Beam V1.0 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (Recommended) - - [T-Beam V1.0 w/ NEO-6M](https://www.aliexpress.com/item/33050391850.html) + - [T-Beam V1.0 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (Recommended - slightly better GPS) + - [T-Beam V1.0 w/ NEO-6M](https://www.aliexpress.com/item/33050391850.html) (Includes built-in OLED display) - 3D printable cases - [T-Beam V0](https://www.thingiverse.com/thing:3773717) - [T-Beam V1](https://www.thingiverse.com/thing:3830711) diff --git a/bin/version.sh b/bin/version.sh index 7cc716c14..58db3c516 100644 --- a/bin/version.sh +++ b/bin/version.sh @@ -1,3 +1,3 @@ -export VERSION=0.7.8 \ No newline at end of file +export VERSION=0.7.9 \ No newline at end of file diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 1e42fa306..2c29b000a 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -2,6 +2,7 @@ You probably don't care about this section - skip to the next one. +- check BLE handle stability across sleep - stress test sleep/wake - btu_init_core calls gatt_init - which assigns handles global - test BLE software update again - @feh123 Sony Xperia Z1 C6903 running Android 5.1.1 - first message sent is still doubled for some people diff --git a/platformio.ini b/platformio.ini index ab23d99dc..bad647bfa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,7 +67,7 @@ debug_tool = jlink lib_deps = https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 SPI - ; 1260 ; OneButton - not used yet + 1260 ; OneButton library for non-blocking button debounce 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 @@ -98,6 +98,7 @@ board = ttgo-t-beam lib_deps = ${env.lib_deps} https://github.com/meshtastic/AXP202X_Library.git + build_flags = ${esp32_base.build_flags} -D TBEAM_V10 diff --git a/src/configuration.h b/src/configuration.h index 09132fd41..8ce140c8a 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -144,7 +144,8 @@ along with this program. If not, see . #define I2C_SDA 21 #define I2C_SCL 22 -#define BUTTON_PIN 38 +#define BUTTON_PIN 38 // The middle button GPIO on the T-Beam +#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed #ifndef USE_JTAG #define RESET_GPIO 14 @@ -213,6 +214,10 @@ along with this program. If not, see . #elif defined(TTGO_LORA_V1) // This string must exactly match the case used in release file names or the android updater won't work #define HW_VENDOR "ttgo-lora32-v1" +#undef GPS_RX_PIN +#undef GPS_TX_PIN +#define GPS_RX_PIN 36 +#define GPS_TX_PIN 37 #define I2C_SDA 4 // I2C pins for this board #define I2C_SCL 15 diff --git a/src/esp32/BluetoothSoftwareUpdate.cpp b/src/esp32/BluetoothSoftwareUpdate.cpp index f5f98a47f..fd4c06155 100644 --- a/src/esp32/BluetoothSoftwareUpdate.cpp +++ b/src/esp32/BluetoothSoftwareUpdate.cpp @@ -76,6 +76,7 @@ class DataCharacteristic : public CallbackCharacteristic crc.update(data, len); Update.write(data, len); updateActualSize += len; + powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG); // Not exactly correct, but we want to force the device to not sleep now } }; @@ -123,8 +124,10 @@ class CRC32Characteristic : public CallbackCharacteristic void bluetoothRebootCheck() { - if (rebootAtMsec && millis() > rebootAtMsec) + if (rebootAtMsec && millis() > rebootAtMsec) { + DEBUG_MSG("Rebooting for update\n"); ESP.restart(); + } } /* diff --git a/src/esp32/main-esp32.cpp b/src/esp32/main-esp32.cpp index 8b08118cb..e0d53eab1 100644 --- a/src/esp32/main-esp32.cpp +++ b/src/esp32/main-esp32.cpp @@ -5,6 +5,7 @@ #include "main.h" #include "power.h" #include "sleep.h" +#include "utils.h" #include "target_specific.h" bool bluetoothOn; @@ -81,8 +82,7 @@ void readPowerStatus() } else { // If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error // In that case, we compute an estimate of the charge percent based on maximum and minimum voltages defined in power.h - int calculatedPercentage = ((powerStatus.batteryVoltageMv - BAT_MILLIVOLTS_EMPTY) * 1e2) / (BAT_MILLIVOLTS_FULL - BAT_MILLIVOLTS_EMPTY); - powerStatus.batteryChargePercent = (calculatedPercentage < 0) ? 0 : (calculatedPercentage > 100) ? 100 : calculatedPercentage; + powerStatus.batteryChargePercent = clamp((int)(((powerStatus.batteryVoltageMv - BAT_MILLIVOLTS_EMPTY) * 1e2) / (BAT_MILLIVOLTS_FULL - BAT_MILLIVOLTS_EMPTY)), 0, 100); } DEBUG_MSG("Battery %dmV %d%%\n", powerStatus.batteryVoltageMv, powerStatus.batteryChargePercent); } diff --git a/src/main.cpp b/src/main.cpp index 5a501a464..fde93df02 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,6 +38,7 @@ #include "screen.h" #include "sleep.h" #include +#include // #include #ifndef NO_ESP32 @@ -125,6 +126,17 @@ static uint32_t ledBlinker() Periodic ledPeriodic(ledBlinker); +// Prepare for button presses +#ifdef BUTTON_PIN + OneButton userButton; +#endif +#ifdef BUTTON_PIN_ALT + OneButton userButtonAlt; +#endif +void userButtonPressed() { + powerFSM.trigger(EVENT_PRESS); +} + #ifndef NO_ESP32 void initWifi() { @@ -183,8 +195,12 @@ void setup() // Buttons & LED #ifdef BUTTON_PIN - pinMode(BUTTON_PIN, INPUT_PULLUP); - digitalWrite(BUTTON_PIN, 1); + userButton = OneButton(BUTTON_PIN, true, true); + userButton.attachClick(userButtonPressed); +#endif +#ifdef BUTTON_PIN_ALT + userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); + userButtonAlt.attachClick(userButtonPressed); #endif #ifdef LED_PIN pinMode(LED_PIN, OUTPUT); @@ -322,24 +338,10 @@ void loop() #endif #ifdef BUTTON_PIN - // if user presses button for more than 3 secs, discard our network prefs and reboot (FIXME, use a debounce lib instead of - // this boilerplate) - static bool wasPressed = false; - - if (!digitalRead(BUTTON_PIN)) { - if (!wasPressed) { // just started a new press - DEBUG_MSG("pressing\n"); - - // doLightSleep(); - // esp_pm_dump_locks(stdout); // FIXME, do this someplace better - wasPressed = true; - - powerFSM.trigger(EVENT_PRESS); - } - } else if (wasPressed) { - // we just did a release - wasPressed = false; - } + userButton.tick(); +#endif +#ifdef BUTTON_PIN_ALT + userButtonAlt.tick(); #endif // Show boot screen for first 3 seconds, then switch to normal operation. diff --git a/src/screen.cpp b/src/screen.cpp index 8cc0b6510..d0fb8f469 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -31,6 +31,7 @@ along with this program. If not, see . #include "main.h" #include "mesh-pb-constants.h" #include "screen.h" +#include "utils.h" #define FONT_HEIGHT 14 // actually 13 for "ariel 10" but want a little extra space #define FONT_HEIGHT_16 (ArialMT_Plain_16[1] + 1) @@ -79,14 +80,20 @@ static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, { display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_16); - display->drawString(64 + x, 2 + y, "Bluetooth"); + display->drawString(64 + x, y, "Bluetooth"); display->setFont(ArialMT_Plain_10); - display->drawString(64 + x, SCREEN_HEIGHT - FONT_HEIGHT + y, "Enter this code"); + display->drawString(64 + x, FONT_HEIGHT + y + 2, "Enter this code"); - display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_24); - display->drawString(64 + x, 22 + y, btPIN); + display->drawString(64 + x, 26 + y, btPIN); + + display->setFont(ArialMT_Plain_10); + char buf[30]; + const char *name = "Name: "; + strcpy(buf,name); + strcat(buf,getDeviceName()); + display->drawString(64 + x, 48 + y, buf); } /// Draw the last text message we received @@ -402,7 +409,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ const char *username = node->has_user ? node->user.long_name : "Unknown Name"; static char signalStr[20]; - snprintf(signalStr, sizeof(signalStr), "Signal: %.0f", node->snr); + snprintf(signalStr, sizeof(signalStr), "Signal: %d%%", clamp((int)((node->snr + 10) * 5), 0, 100)); uint32_t agoSecs = sinceLastSeen(node); static char lastStr[20]; @@ -511,6 +518,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]); @@ -717,7 +727,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 302c8e339..95ca0a60c 100644 --- a/src/screen.h +++ b/src/screen.h @@ -149,6 +149,37 @@ 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; + 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; + } + + uint8_t last = LASTCHAR; // get last char + LASTCHAR = ch; + + 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); } + } + + // 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) 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. // // Use this handle to set things like battery status, user count, GPS status, etc. diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 000000000..36f719ca7 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,7 @@ +#pragma once + +/// C++ v17+ clamp function, limits a given value to a range defined by lo and hi +template +constexpr const T& clamp( const T& v, const T& lo, const T& hi ) { + return (v < lo) ? lo : (hi < v) ? hi : v; +} \ No newline at end of file