diff --git a/bin/build-all.sh b/bin/build-all.sh index 63dfc01c..9f0888f0 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -9,11 +9,10 @@ COUNTRIES="US EU433 EU865 CN JP ANZ KR" #COUNTRIES=CN BOARDS_ESP32="tlora-v2 tlora-v1 tlora-v2-1-1.6 tbeam heltec tbeam0.7" +# BOARDS_ESP32=tbeam # FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine BOARDS_NRF52="lora-relay-v1" -BOARDS="$BOARDS_ESP32 $BOARDS_NRF52" -#BOARDS=tbeam OUTDIR=release/latest @@ -22,22 +21,61 @@ ARCHIVEDIR=release/archive rm -f $OUTDIR/firmware* -mkdir -p $OUTDIR/bins $OUTDIR/elfs -rm -f $OUTDIR/bins/* +mkdir -p $OUTDIR/bins +rm -r $OUTDIR/bins/* +mkdir -p $OUTDIR/bins/universal $OUTDIR/elfs/universal # build the named environment and copy the bins to the release directory -function do_build { - echo "Building for $BOARD with $PLATFORMIO_BUILD_FLAGS" +function do_build() { + BOARD=$1 + COUNTRY=$2 + isNrf=$3 + + echo "Building $COUNTRY for $BOARD with $PLATFORMIO_BUILD_FLAGS" rm -f .pio/build/$BOARD/firmware.* # The shell vars the build tool expects to find - export HW_VERSION="1.0-$COUNTRY" export APP_VERSION=$VERSION - export COUNTRY + + # Are we building a universal/regionless rom? + if [ "x$COUNTRY" != "x" ] + then + export HW_VERSION="1.0-$COUNTRY" + export COUNTRY + basename=firmware-$BOARD-$COUNTRY-$VERSION + else + export HW_VERSION="1.0" + unset COUNTRY + basename=universal/firmware-$BOARD-$VERSION + fi pio run --jobs 4 --environment $BOARD # -v SRCELF=.pio/build/$BOARD/firmware.elf - cp $SRCELF $OUTDIR/elfs/firmware-$BOARD-$COUNTRY-$VERSION.elf + cp $SRCELF $OUTDIR/elfs/$basename.elf + + if [ "$isNrf" = "false" ] + then + echo "Copying ESP32 bin file" + SRCBIN=.pio/build/$BOARD/firmware.bin + cp $SRCBIN $OUTDIR/bins/$basename.bin + else + echo "Generating NRF52 uf2 file" + SRCHEX=.pio/build/$BOARD/firmware.hex + bin/uf2conv.py $SRCHEX -c -o $OUTDIR/bins/$basename.uf2 -f 0xADA52840 + fi +} + +function do_boards() { + declare boards=$1 + declare isNrf=$2 + for board in $boards; do + for country in $COUNTRIES; do + do_build $board $country "$isNrf" + done + + # Build universal + do_build $board "" "$isNrf" + done } # Make sure our submodules are current @@ -46,26 +84,16 @@ git submodule update # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale platformio lib update -for COUNTRY in $COUNTRIES; do - for BOARD in $BOARDS; do - do_build $BOARD - done - - echo "Copying ESP32 bin files" - for BOARD in $BOARDS_ESP32; do - SRCBIN=.pio/build/$BOARD/firmware.bin - cp $SRCBIN $OUTDIR/bins/firmware-$BOARD-$COUNTRY-$VERSION.bin - done - - echo "Generating NRF52 uf2 files" - for BOARD in $BOARDS_NRF52; do - SRCHEX=.pio/build/$BOARD/firmware.hex - bin/uf2conv.py $SRCHEX -c -o $OUTDIR/bins/firmware-$BOARD-$COUNTRY-$VERSION.uf2 -f 0xADA52840 - done -done +do_boards "$BOARDS_ESP32" "false" +do_boards "$BOARDS_NRF52" "true" # keep the bins in archive also -cp $OUTDIR/bins/firmware* $OUTDIR/elfs/firmware* $ARCHIVEDIR +cp $OUTDIR/bins/firmware* $OUTDIR/elfs/firmware* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR + +echo Updating android bins $OUTDIR/forandroid +rm -rf $OUTDIR/forandroid +mkdir -p $OUTDIR/forandroid +cp -a $OUTDIR/bins/universal/*.bin $OUTDIR/forandroid/ cat >$OUTDIR/curfirmwareversion.xml < @@ -79,6 +107,7 @@ Generated by bin/buildall.sh --> XML +echo Generating $ARCHIVEDIR/firmware-$VERSION.zip rm -f $ARCHIVEDIR/firmware-$VERSION.zip zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh diff --git a/bin/version.sh b/bin/version.sh index ecc6ad74..4e8e08ae 100644 --- a/bin/version.sh +++ b/bin/version.sh @@ -1,3 +1,3 @@ -export VERSION=1.1.5 \ No newline at end of file +export VERSION=1.1.6 \ No newline at end of file diff --git a/src/Power.cpp b/src/Power.cpp index 12a63811..ae51e803 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -18,6 +18,21 @@ Power *power; using namespace meshtastic; +#if defined(NRF52_SERIES) +/* + * Internal Reference is +/-0.6V, with an adjustable gain of 1/6, 1/5, 1/4, + * 1/3, 1/2 or 1, meaning 3.6, 3.0, 2.4, 1.8, 1.2 or 0.6V for the ADC levels. + * + * External Reference is VDD/4, with an adjustable gain of 1, 2 or 4, meaning + * VDD/4, VDD/2 or VDD for the ADC levels. + * + * Default settings are internal reference with 1/6 gain (GND..3.6V ADC range) + */ +#define AREF_VOLTAGE 3.6 +#else +#define AREF_VOLTAGE 3.3 +#endif + /** * If this board has a battery level sensor, set this to a valid implementation */ @@ -37,10 +52,13 @@ class AnalogBatteryLevel : public HasBatteryLevel { float v = getBattVoltage() / 1000; - if (v < 2.1) + if (v < noBatVolt) return -1; // If voltage is super low assume no battery installed - return 100 * (v - 3.27) / (4.2 - 3.27); + if (v > chargingVolt) + return 0; // While charging we can't report % full on the battery + + return 100 * (v - emptyVolt) / (fullVolt - emptyVolt); } /** @@ -48,9 +66,11 @@ class AnalogBatteryLevel : public HasBatteryLevel */ virtual float getBattVoltage() { + // Tested ttgo eink nrf52 board and the reported value is perfect + // DEBUG_MSG("raw val %u", raw); return #ifdef BATTERY_PIN - 1000.0 * analogRead(BATTERY_PIN) * 2.0 * (3.3 / 1024.0); + 1000.0 * 2.0 * (AREF_VOLTAGE / 1024.0) * analogRead(BATTERY_PIN); #else NAN; #endif @@ -59,7 +79,20 @@ class AnalogBatteryLevel : public HasBatteryLevel /** * return true if there is a battery installed in this unit */ - virtual bool isBatteryConnect() { return getBattVoltage() != -1; } + virtual bool isBatteryConnect() { return getBattPercentage() != -1; } + + /// If we see a battery voltage higher than physics allows - assume charger is pumping + /// in power + virtual bool isVBUSPlug() { return getBattVoltage() > chargingVolt; } + + /// Assume charging if we have a battery and external power is connected. + /// we can't be smart enough to say 'full'? + virtual bool isChargeing() { return isBatteryConnect() && isVBUSPlug(); } + + private: + /// If we see a battery voltage higher than physics allows - assume charger is pumping + /// in power + const float fullVolt = 4.2, emptyVolt = 3.27, chargingVolt = 4.3, noBatVolt = 2.1; } analogLevel; Power::Power() : OSThread("Power") {} @@ -68,10 +101,18 @@ bool Power::analogInit() { #ifdef BATTERY_PIN DEBUG_MSG("Using analog input for battery level\n"); + + // disable any internal pullups + pinMode(BATTERY_PIN, INPUT); + #ifndef NO_ESP32 // ESP32 needs special analog stuff adcAttachPin(BATTERY_PIN); #endif +#ifdef NRF52_SERIES + analogReference(AR_INTERNAL); // 3.6V +#endif + // adcStart(BATTERY_PIN); analogReadResolution(10); // Default of 12 is not very linear. Recommended to use 10 or 11 depending on needed resolution. batteryLevel = &analogLevel; @@ -121,7 +162,8 @@ void Power::readPowerStatus() const PowerStatus powerStatus = PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVBUSPlug() ? OptTrue : OptFalse, batteryLevel->isChargeing() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent); - DEBUG_MSG("Read power stat %d\n", powerStatus.getHasUSB()); + DEBUG_MSG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus.getHasUSB(), + powerStatus.getIsCharging(), powerStatus.getBatteryVoltageMv(), powerStatus.getBatteryChargePercent()); newStatus.notifyObservers(&powerStatus); // If we have a battery at all and it is less than 10% full, force deep sleep diff --git a/src/PowerStatus.h b/src/PowerStatus.h index c9bb89a0..e9c192fb 100644 --- a/src/PowerStatus.h +++ b/src/PowerStatus.h @@ -82,7 +82,7 @@ class PowerStatus : public Status isCharging = newStatus->isCharging; } if (isDirty) { - DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent); + // DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent); onNewStatus.notifyObservers(this); } return 0; diff --git a/src/esp32/BluetoothSoftwareUpdate.cpp b/src/esp32/BluetoothSoftwareUpdate.cpp index 4fa518cc..12e30d1c 100644 --- a/src/esp32/BluetoothSoftwareUpdate.cpp +++ b/src/esp32/BluetoothSoftwareUpdate.cpp @@ -72,7 +72,7 @@ int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_ 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 + powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); return 0; } diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 350b27d4..7773cdc3 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -92,21 +92,23 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1 // needs to be drawn relative to x and y // draw centered left to right and centered above the one line of app text - display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2, icon_width, - icon_height, (const uint8_t *)icon_bits); + display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2, + icon_width, icon_height, (const uint8_t *)icon_bits); display->setFont(FONT_MEDIUM); display->setTextAlignment(TEXT_ALIGN_LEFT); const char *title = "meshtastic.org"; display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title); display->setFont(FONT_SMALL); - const char *region = xstr(HW_VERSION); - if (*region && region[3] == '-') // Skip past 1.0- in the 1.0-EU865 string - region += 4; + + const char *region = myRegion ? myRegion->name : NULL; + if (region) + display->drawString(x + 0, y + 0, region); + 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); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf); screen->forceDisplay(); } @@ -1139,7 +1141,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg) // DEBUG_MSG("Screen got status update %d\n", arg->getStatusType()); switch (arg->getStatusType()) { case STATUS_TYPE_NODE: - if (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) { + if (showingNormalScreen && (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal())) { setFrames(); // Regen the list of screens } nodeDB.updateGUI = false; diff --git a/src/main.cpp b/src/main.cpp index e258ec52..2781b770 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -290,14 +290,6 @@ void setup() // Initialize the screen first so we can show the logo while we start up everything else. screen = new graphics::Screen(SSD1306_ADDRESS); -#if defined(ST7735_CS) || defined(HAS_EINK) - screen->setup(); -#else - if (ssd1306_found) - screen->setup(); -#endif - - screen->print("Started...\n"); readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time) @@ -338,6 +330,17 @@ void setup() service.init(); + // Don't call screen setup until after nodedb is setup (because we need + // the current region name) +#if defined(ST7735_CS) || defined(HAS_EINK) + screen->setup(); +#else + if (ssd1306_found) + screen->setup(); +#endif + + screen->print("Started...\n"); + // We have now loaded our saved preferences from flash // ONCE we will factory reset the GPS for bug #327 diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 2cee8f89..be99032f 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -16,4 +16,7 @@ struct RegionInfo { const char *name; // EU433 etc }; -extern const RegionInfo regions[]; \ No newline at end of file +extern const RegionInfo regions[]; +extern const RegionInfo *myRegion; + +extern void initRegion(); \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index cf47cfd1..1febc0ae 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -245,6 +245,9 @@ void NodeDB::init() } } + // Update the global myRegion + initRegion(); + strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version)); strncpy(myNodeInfo.hw_model, HW_VENDOR, sizeof(myNodeInfo.hw_model)); diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 8fefd80f..c35075c6 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -26,7 +26,20 @@ const RegionInfo regions[] = { RDEF(Unset, 903.08f, 2.16f, 13, 0) // Assume US freqs if unset, Must be last }; -static const RegionInfo *myRegion; +const RegionInfo *myRegion; + +void initRegion() +{ + if (!myRegion) { + const RegionInfo *r = regions; + for (; r->code != RegionCode_Unset && r->code != radioConfig.preferences.region; r++) + ; + myRegion = r; + DEBUG_MSG("Wanted region %d, using %s\n", radioConfig.preferences.region, r->name); + + myNodeInfo.num_channels = myRegion->numChannels; // Tell our android app how many channels we have + } +} /** * ## LoRaWAN for North America @@ -91,20 +104,10 @@ void printPacket(const char *prefix, const MeshPacket *p) DEBUG_MSG(")\n"); } -RadioInterface::RadioInterface() +RadioInterface::RadioInterface() { assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected - if (!myRegion) { - const RegionInfo *r = regions; - for (; r->code != RegionCode_Unset && r->code != radioConfig.preferences.region; r++) - ; - myRegion = r; - DEBUG_MSG("Wanted region %d, using %s\n", radioConfig.preferences.region, r->name); - - myNodeInfo.num_channels = myRegion->numChannels; // Tell our android app how many channels we have - } - // Can't print strings this early - serial not setup yet // DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name); } @@ -120,7 +123,7 @@ bool RadioInterface::init() // we now expect interfaces to operate in promiscous mode // radioIf.setThisAddress(nodeDB.getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at constructor // time. - + return true; }