diff --git a/boards/nrf52840_s140_v6_extrafs.ld b/boards/nrf52840_s140_v6_extrafs.ld
new file mode 100644
index 00000000..35261067
--- /dev/null
+++ b/boards/nrf52840_s140_v6_extrafs.ld
@@ -0,0 +1,38 @@
+/* Linker script to configure memory regions. */
+
+SEARCH_DIR(.)
+GROUP(-lgcc -lc -lnosys)
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xD4000 - 0x26000
+
+ /* SRAM required by Softdevice depend on
+ * - Attribute Table Size (Number of Services and Characteristics)
+ * - Vendor UUID count
+ * - Max ATT MTU
+ * - Concurrent connection peripheral + central + secure links
+ * - Event Len, HVN queue, Write CMD queue
+ */
+ RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20040000 - 0x20006000
+}
+
+SECTIONS
+{
+ . = ALIGN(4);
+ .svc_data :
+ {
+ PROVIDE(__start_svc_data = .);
+ KEEP(*(.svc_data))
+ PROVIDE(__stop_svc_data = .);
+ } > RAM
+
+ .fs_data :
+ {
+ PROVIDE(__start_fs_data = .);
+ KEEP(*(.fs_data))
+ PROVIDE(__stop_fs_data = .);
+ } > RAM
+} INSERT AFTER .data;
+
+INCLUDE "nrf52_common.ld"
diff --git a/boards/nrf52840_s140_v7_extrafs.ld b/boards/nrf52840_s140_v7_extrafs.ld
new file mode 100644
index 00000000..5956183a
--- /dev/null
+++ b/boards/nrf52840_s140_v7_extrafs.ld
@@ -0,0 +1,38 @@
+/* Linker script to configure memory regions. */
+
+SEARCH_DIR(.)
+GROUP(-lgcc -lc -lnosys)
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xD4000 - 0x27000
+
+ /* SRAM required by Softdevice depend on
+ * - Attribute Table Size (Number of Services and Characteristics)
+ * - Vendor UUID count
+ * - Max ATT MTU
+ * - Concurrent connection peripheral + central + secure links
+ * - Event Len, HVN queue, Write CMD queue
+ */
+ RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20040000 - 0x20006000
+}
+
+SECTIONS
+{
+ . = ALIGN(4);
+ .svc_data :
+ {
+ PROVIDE(__start_svc_data = .);
+ KEEP(*(.svc_data))
+ PROVIDE(__stop_svc_data = .);
+ } > RAM
+
+ .fs_data :
+ {
+ PROVIDE(__start_fs_data = .);
+ KEEP(*(.fs_data))
+ PROVIDE(__stop_fs_data = .);
+ } > RAM
+} INSERT AFTER .data;
+
+INCLUDE "nrf52_common.ld"
diff --git a/docs/faq.md b/docs/faq.md
index 6dc8fe9e..391ceb5b 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -63,10 +63,11 @@ author: https://github.com/LitBomb
- [6.1. Q: My client says another client or a repeater or a room server was last seen many, many days ago.](#61-q-my-client-says-another-client-or-a-repeater-or-a-room-server-was-last-seen-many-many-days-ago)
- [6.2. Q: A repeater or a client or a room server I expect to see on my discover list (on T-Deck) or contact list (on a smart device client) are not listed.](#62-q-a-repeater-or-a-client-or-a-room-server-i-expect-to-see-on-my-discover-list-on-t-deck-or-contact-list-on-a-smart-device-client-are-not-listed)
- [6.3. Q: How to connect to a repeater via BLE (Bluetooth)?](#63-q-how-to-connect-to-a-repeater-via-ble-bluetooth)
- - [6.4. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?](#64-q-i-cant-connect-via-bluetooth-what-is-the-bluetooth-pairing-code)
- - [6.5. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.](#65-q-my-heltec-v3-keeps-disconnecting-from-my-smartphone--it-cant-hold-a-solid-bluetooth-connection)
- - [6.6. Q: My RAK/T1000-E/xiao\_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?](#66-q-my-rakt1000-exiao_nrf52-device-seems-to-be-corrupted-how-do-i-wipe-it-clean-to-start-fresh)
- - [6.7. Q: WebFlasher fails on Linux with failed to open](#67-q-webflasher-fails-on-linux-with-failed-to-open)
+ - [6.4. Q: My companion isn't showing up over Bluetooth?](#64-q-my-companion-isnt-showing-up-over-bluetooth)
+ - [6.5. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?](#64-q-i-cant-connect-via-bluetooth-what-is-the-bluetooth-pairing-code)
+ - [6.6. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.](#65-q-my-heltec-v3-keeps-disconnecting-from-my-smartphone--it-cant-hold-a-solid-bluetooth-connection)
+ - [6.7. Q: My RAK/T1000-E/xiao\_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?](#66-q-my-rakt1000-exiao_nrf52-device-seems-to-be-corrupted-how-do-i-wipe-it-clean-to-start-fresh)
+ - [6.8. Q: WebFlasher fails on Linux with failed to open](#67-q-webflasher-fails-on-linux-with-failed-to-open)
- [7. Other Questions:](#7-other-questions)
- [7.1 Q: How to update nRF (RAK, T114, Seed XIAO) repeater and room server firmware over the air using the new simpler DFU app?](#71-q-how-to-update-nrf-rak-t114-seed-xiao-repeater-and-room-server-firmware-over-the-air-using-the-new-simpler-dfu-app)
- [7.2 Q: How to update ESP32-based devices over the air?](#72-q-how-to-update-esp32-based-devices-over-the-air)
@@ -563,15 +564,19 @@ You can get the epoch time on and use it to se
### 6.3. Q: How to connect to a repeater via BLE (Bluetooth)?
**A:** You can't connect to a device running repeater firmware via Bluetooth. Devices running the BLE companion firmware you can connect to it via Bluetooth using the android app
-### 6.4. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?
+### 6.4. Q: My companion isn't showing up over Bluetooth?
+
+**A:** make sure that you flashed the Bluetooth companion firmware and not the USB-only companion firmware.
+
+### 6.5. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?
**A:** the default Bluetooth pairing code is `123456`
-### 6.5. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.
+### 6.6. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.
**A:** Heltec V3 has a very small coil antenna on its PCB for Wi-Fi and Bluetooth connectivity. It has a very short range, only a few feet. It is possible to remove the coil antenna and replace it with a 31mm wire. The BT range is much improved with the modification.
-### 6.6. Q: My RAK/T1000-E/xiao_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?
+### 6.7. Q: My RAK/T1000-E/xiao_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?
**A:**
1. Connect USB-C cable to your device, per your device's instruction, get it to flash mode:
@@ -591,8 +596,7 @@ You can get the epoch time on and use it to se
Separately, starting in firmware version 1.7.0, there is a CLI Rescue mode. If your device has a user button (e.g. some RAK, T114), you can activate the rescue mode by hold down the user button of the device within 8 seconds of boot. Then you can use the 'Console' on flasher.meshcore.co.uk
-
-### 6.7. Q: WebFlasher fails on Linux with failed to open
+### 6.8. Q: WebFlasher fails on Linux with failed to open
**A:** If the usb port doesn't have the right ownership for this task, the process fails with the following error:
`NetworkError: Failed to execute 'open' on 'SerialPort': Failed to open serial port.`
diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp
index 0f540878..1e03f086 100644
--- a/examples/companion_radio/ui-new/UITask.cpp
+++ b/examples/companion_radio/ui-new/UITask.cpp
@@ -75,6 +75,9 @@ class HomeScreen : public UIScreen {
RADIO,
BLUETOOTH,
ADVERT,
+#if UI_SENSORS_PAGE == 1
+ SENSORS,
+#endif
SHUTDOWN,
Count // keep as last
};
@@ -113,9 +116,37 @@ class HomeScreen : public UIScreen {
display.fillRect(iconX + 2, iconY + 2, fillWidth, iconHeight - 4);
}
+ CayenneLPP sensors_lpp;
+ int sensors_nb = 0;
+ bool sensors_scroll = false;
+ int sensors_scroll_offset = 0;
+ int next_sensors_refresh = 0;
+
+ void refresh_sensors() {
+ if (millis() > next_sensors_refresh) {
+ sensors_lpp.reset();
+ sensors_nb = 0;
+ sensors_lpp.addVoltage(TELEM_CHANNEL_SELF, (float)board.getBattMilliVolts() / 1000.0f);
+ sensors.querySensors(0xFF, sensors_lpp);
+ LPPReader reader (sensors_lpp.getBuffer(), sensors_lpp.getSize());
+ uint8_t channel, type;
+ while(reader.readHeader(channel, type)) {
+ reader.skipData(type);
+ sensors_nb ++;
+ }
+ sensors_scroll = sensors_nb > UI_RECENT_LIST_SIZE;
+#if AUTO_OFF_MILLIS > 0
+ next_sensors_refresh = millis() + 5000; // refresh sensor values every 5 sec
+#else
+ next_sensors_refresh = millis() + 60000; // refresh sensor values every 1 min
+#endif
+ }
+ }
+
public:
HomeScreen(UITask* task, mesh::RTCClock* rtc, SensorManager* sensors, NodePrefs* node_prefs)
- : _task(task), _rtc(rtc), _sensors(sensors), _node_prefs(node_prefs), _page(0), _shutdown_init(false) { }
+ : _task(task), _rtc(rtc), _sensors(sensors), _node_prefs(node_prefs), _page(0),
+ _shutdown_init(false), sensors_lpp(200) { }
void poll() override {
if (_shutdown_init && !_task->isButtonPressed()) { // must wait for USR button to be released
@@ -211,6 +242,78 @@ public:
display.setColor(DisplayDriver::GREEN);
display.drawXbm((display.width() - 32) / 2, 18, advert_icon, 32, 32);
display.drawTextCentered(display.width() / 2, 64 - 11, "advert: " PRESS_LABEL);
+#if UI_SENSORS_PAGE == 1
+ } else if (_page == HomePage::SENSORS) {
+ int y = 18;
+ refresh_sensors();
+ char buf[30];
+ char name[30];
+ LPPReader r(sensors_lpp.getBuffer(), sensors_lpp.getSize());
+
+ for (int i = 0; i < sensors_scroll_offset; i++) {
+ uint8_t channel, type;
+ r.readHeader(channel, type);
+ r.skipData(type);
+ }
+
+ for (int i = 0; i < (sensors_scroll?UI_RECENT_LIST_SIZE:sensors_nb); i++) {
+ uint8_t channel, type;
+ if (!r.readHeader(channel, type)) { // reached end, reset
+ r.reset();
+ r.readHeader(channel, type);
+ }
+
+ display.setCursor(0, y);
+ float v;
+ switch (type) {
+ case LPP_GPS: // GPS
+ float lat, lon, alt;
+ r.readGPS(lat, lon, alt);
+ strcpy(name, "gps"); sprintf(buf, "%.4f %.4f", lat, lon);
+ break;
+ case LPP_VOLTAGE:
+ r.readVoltage(v);
+ strcpy(name, "voltage"); sprintf(buf, "%6.2f", v);
+ break;
+ case LPP_CURRENT:
+ r.readCurrent(v);
+ strcpy(name, "current"); sprintf(buf, "%.3f", v);
+ break;
+ case LPP_TEMPERATURE:
+ r.readTemperature(v);
+ strcpy(name, "temperature"); sprintf(buf, "%.2f", v);
+ break;
+ case LPP_RELATIVE_HUMIDITY:
+ r.readRelativeHumidity(v);
+ strcpy(name, "humidity"); sprintf(buf, "%.2f", v);
+ break;
+ case LPP_BAROMETRIC_PRESSURE:
+ r.readPressure(v);
+ strcpy(name, "pressure"); sprintf(buf, "%.2f", v);
+ break;
+ case LPP_ALTITUDE:
+ r.readAltitude(v);
+ strcpy(name, "altitude"); sprintf(buf, "%.0f", v);
+ break;
+ case LPP_POWER:
+ r.readPower(v);
+ strcpy(name, "power"); sprintf(buf, "%6.2f", v);
+ break;
+ default:
+ r.skipData(type);
+ strcpy(name, "unk"); sprintf(buf, "");
+ }
+ display.setCursor(0, y);
+ display.print(name);
+ display.setCursor(
+ display.width()-display.getTextWidth(buf)-1, y
+ );
+ display.print(buf);
+ y = y + 12;
+ }
+ if (sensors_scroll) sensors_scroll_offset = (sensors_scroll_offset+1)%sensors_nb;
+ else sensors_scroll_offset = 0;
+#endif
} else if (_page == HomePage::SHUTDOWN) {
display.setColor(DisplayDriver::GREEN);
display.setTextSize(1);
@@ -255,6 +358,13 @@ public:
}
return true;
}
+#if UI_SENSORS_PAGE == 1
+ if (c == KEY_ENTER && _page == HomePage::SENSORS) {
+ _task->toggleGPS();
+ next_sensors_refresh=0;
+ return true;
+ }
+#endif
if (c == KEY_ENTER && _page == HomePage::SHUTDOWN) {
_shutdown_init = true; // need to wait for button to be released
return true;
diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h
index 46024b1f..769b2c64 100644
--- a/examples/companion_radio/ui-new/UITask.h
+++ b/examples/companion_radio/ui-new/UITask.h
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#ifdef PIN_BUZZER
#include
diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp
index df08ed78..6b1b9e47 100644
--- a/src/helpers/sensors/EnvironmentSensorManager.cpp
+++ b/src/helpers/sensors/EnvironmentSensorManager.cpp
@@ -252,7 +252,7 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen
next_available_channel = TELEM_CHANNEL_SELF + 1;
if (requester_permissions & TELEM_PERM_LOCATION && gps_active) {
- telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, 0.0f); // allow lat/lon via telemetry even if no GPS is detected
+ telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude); // allow lat/lon via telemetry even if no GPS is detected
}
if (requester_permissions & TELEM_PERM_ENVIRONMENT) {
@@ -577,17 +577,23 @@ void EnvironmentSensorManager::loop() {
node_lat = ((double)ublox_GNSS.getLatitude())/10000000.;
node_lon = ((double)ublox_GNSS.getLongitude())/10000000.;
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
+ node_altitude = ((double)ublox_GNSS.getAltitude()) / 1000.0;
+ MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude);
}
else if (serialGPSFlag && _location->isValid()) {
node_lat = ((double)_location->getLatitude())/1000000.;
node_lon = ((double)_location->getLongitude())/1000000.;
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
+ node_altitude = ((double)_location->getAltitude()) / 1000.0;
+ MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude);
}
#else
if (_location->isValid()) {
node_lat = ((double)_location->getLatitude())/1000000.;
node_lon = ((double)_location->getLongitude())/1000000.;
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
+ node_altitude = ((double)_location->getAltitude()) / 1000.0;
+ MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude);
}
#endif
}
diff --git a/src/helpers/sensors/LPPDataHelpers.h b/src/helpers/sensors/LPPDataHelpers.h
new file mode 100644
index 00000000..b9025de4
--- /dev/null
+++ b/src/helpers/sensors/LPPDataHelpers.h
@@ -0,0 +1,223 @@
+#pragma once
+
+#include
+
+#define LPP_DIGITAL_INPUT 0 // 1 byte
+#define LPP_DIGITAL_OUTPUT 1 // 1 byte
+#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed
+#define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed
+#define LPP_GENERIC_SENSOR 100 // 4 bytes, unsigned
+#define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned
+#define LPP_PRESENCE 102 // 1 byte, bool
+#define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed
+#define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned
+#define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G
+#define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1hPa unsigned
+#define LPP_VOLTAGE 116 // 2 bytes 0.01V unsigned
+#define LPP_CURRENT 117 // 2 bytes 0.001A unsigned
+#define LPP_FREQUENCY 118 // 4 bytes 1Hz unsigned
+#define LPP_PERCENTAGE 120 // 1 byte 1-100% unsigned
+#define LPP_ALTITUDE 121 // 2 byte 1m signed
+#define LPP_CONCENTRATION 125 // 2 bytes, 1 ppm unsigned
+#define LPP_POWER 128 // 2 byte, 1W, unsigned
+#define LPP_DISTANCE 130 // 4 byte, 0.001m, unsigned
+#define LPP_ENERGY 131 // 4 byte, 0.001kWh, unsigned
+#define LPP_DIRECTION 132 // 2 bytes, 1deg, unsigned
+#define LPP_UNIXTIME 133 // 4 bytes, unsigned
+#define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 °/s
+#define LPP_COLOUR 135 // 1 byte per RGB Color
+#define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter
+#define LPP_SWITCH 142 // 1 byte, 0/1
+#define LPP_POLYLINE 240 // 1 byte size, 1 byte delta factor, 3 byte lon/lat 0.0001° * factor, n (size-8) bytes deltas
+
+// Multipliers
+#define LPP_DIGITAL_INPUT_MULT 1
+#define LPP_DIGITAL_OUTPUT_MULT 1
+#define LPP_ANALOG_INPUT_MULT 100
+#define LPP_ANALOG_OUTPUT_MULT 100
+#define LPP_GENERIC_SENSOR_MULT 1
+#define LPP_LUMINOSITY_MULT 1
+#define LPP_PRESENCE_MULT 1
+#define LPP_TEMPERATURE_MULT 10
+#define LPP_RELATIVE_HUMIDITY_MULT 2
+#define LPP_ACCELEROMETER_MULT 1000
+#define LPP_BAROMETRIC_PRESSURE_MULT 10
+#define LPP_VOLTAGE_MULT 100
+#define LPP_CURRENT_MULT 1000
+#define LPP_FREQUENCY_MULT 1
+#define LPP_PERCENTAGE_MULT 1
+#define LPP_ALTITUDE_MULT 1
+#define LPP_POWER_MULT 1
+#define LPP_DISTANCE_MULT 1000
+#define LPP_ENERGY_MULT 1000
+#define LPP_DIRECTION_MULT 1
+#define LPP_UNIXTIME_MULT 1
+#define LPP_GYROMETER_MULT 100
+#define LPP_GPS_LAT_LON_MULT 10000
+#define LPP_GPS_ALT_MULT 100
+#define LPP_SWITCH_MULT 1
+#define LPP_CONCENTRATION_MULT 1
+#define LPP_COLOUR_MULT 1
+
+#define LPP_ERROR_OK 0
+#define LPP_ERROR_OVERFLOW 1
+#define LPP_ERROR_UNKOWN_TYPE 2
+
+class LPPReader {
+ const uint8_t* _buf;
+ uint8_t _len;
+ uint8_t _pos;
+
+ float getFloat(const uint8_t * buffer, uint8_t size, uint32_t multiplier, bool is_signed) {
+ uint32_t value = 0;
+ for (uint8_t i = 0; i < size; i++) {
+ value = (value << 8) + buffer[i];
+ }
+
+ int sign = 1;
+ if (is_signed) {
+ uint32_t bit = 1ul << ((size * 8) - 1);
+ if ((value & bit) == bit) {
+ value = (bit << 1) - value;
+ sign = -1;
+ }
+ }
+ return sign * ((float) value / multiplier);
+ }
+
+public:
+ LPPReader(const uint8_t buf[], uint8_t len) : _buf(buf), _len(len), _pos(0) { }
+
+ void reset() {
+ _pos = 0;
+ }
+
+ bool readHeader(uint8_t& channel, uint8_t& type) {
+ if (_pos + 2 < _len) {
+ channel = _buf[_pos++];
+ type = _buf[_pos++];
+
+ return channel != 0; // channel 0 is End-of-data
+ }
+ return false; // end-of-buffer
+ }
+
+ bool readGPS(float& lat, float& lon, float& alt) {
+ lat = getFloat(&_buf[_pos], 3, 10000, true); _pos += 3;
+ lon = getFloat(&_buf[_pos], 3, 10000, true); _pos += 3;
+ alt = getFloat(&_buf[_pos], 3, 100, true); _pos += 3;
+ return _pos <= _len;
+ }
+ bool readVoltage(float& voltage) {
+ voltage = getFloat(&_buf[_pos], 2, 100, false); _pos += 2;
+ return _pos <= _len;
+ }
+ bool readCurrent(float& amps) {
+ amps = getFloat(&_buf[_pos], 2, 1000, false); _pos += 2;
+ return _pos <= _len;
+ }
+ bool readPower(float& watts) {
+ watts = getFloat(&_buf[_pos], 2, 1, false); _pos += 2;
+ return _pos <= _len;
+ }
+ bool readTemperature(float& degrees_c) {
+ degrees_c = getFloat(&_buf[_pos], 2, 10, true); _pos += 2;
+ return _pos <= _len;
+ }
+ bool readPressure(float& pa) {
+ pa = getFloat(&_buf[_pos], 2, 10, false); _pos += 2;
+ return _pos <= _len;
+ }
+ bool readRelativeHumidity(float& pct) {
+ pct = getFloat(&_buf[_pos], 1, 2, false); _pos += 1;
+ return _pos <= _len;
+ }
+ bool readAltitude(float& m) {
+ m = getFloat(&_buf[_pos], 2, 1, true); _pos += 2;
+ return _pos <= _len;
+ }
+
+ void skipData(uint8_t type) {
+ switch (type) {
+ case LPP_GPS:
+ _pos += 9; break;
+ case LPP_POLYLINE:
+ _pos += 8; break; // TODO: this is MINIMIUM
+ case LPP_GYROMETER:
+ case LPP_ACCELEROMETER:
+ _pos += 6; break;
+ case LPP_GENERIC_SENSOR:
+ case LPP_FREQUENCY:
+ case LPP_DISTANCE:
+ case LPP_ENERGY:
+ case LPP_UNIXTIME:
+ _pos += 4; break;
+ case LPP_COLOUR:
+ _pos += 3; break;
+ case LPP_ANALOG_INPUT:
+ case LPP_ANALOG_OUTPUT:
+ case LPP_LUMINOSITY:
+ case LPP_TEMPERATURE:
+ case LPP_CONCENTRATION:
+ case LPP_BAROMETRIC_PRESSURE:
+ case LPP_ALTITUDE:
+ case LPP_VOLTAGE:
+ case LPP_CURRENT:
+ case LPP_DIRECTION:
+ case LPP_POWER:
+ _pos += 2; break;
+ default:
+ _pos++;
+ }
+ }
+};
+
+class LPPWriter {
+ uint8_t* _buf;
+ uint8_t _max_len;
+ uint8_t _len;
+
+ void write(uint16_t value) {
+ _buf[_len++] = (value >> 8) & 0xFF; // MSB
+ _buf[_len++] = value & 0xFF; // LSB
+ }
+
+public:
+ LPPWriter(uint8_t buf[], uint8_t max_len): _buf(buf), _max_len(max_len), _len(0) { }
+
+ bool writeVoltage(uint8_t channel, float voltage) {
+ if (_len + 4 <= _max_len) {
+ _buf[_len++] = channel;
+ _buf[_len++] = LPP_VOLTAGE;
+ uint16_t value = voltage * 100;
+ write(value);
+ return true;
+ }
+ return false;
+ }
+
+ bool writeGPS(uint8_t channel, float lat, float lon, float alt) {
+ if (_len + 11 <= _max_len) {
+ _buf[_len++] = channel;
+ _buf[_len++] = LPP_GPS;
+
+ int32_t lati = lat * 10000; // we lose some precision :-(
+ int32_t loni = lon * 10000;
+ int32_t alti = alt * 100;
+
+ _buf[_len++] = lati >> 16;
+ _buf[_len++] = lati >> 8;
+ _buf[_len++] = lati;
+ _buf[_len++] = loni >> 16;
+ _buf[_len++] = loni >> 8;
+ _buf[_len++] = loni;
+ _buf[_len++] = alti >> 16;
+ _buf[_len++] = alti >> 8;
+ _buf[_len++] = alti;
+ return true;
+ }
+ return false;
+ }
+
+ uint8_t length() { return _len; }
+};
diff --git a/variants/heltec_mesh_solar/platformio.ini b/variants/heltec_mesh_solar/platformio.ini
index 18c4ac73..c5d8c3e8 100644
--- a/variants/heltec_mesh_solar/platformio.ini
+++ b/variants/heltec_mesh_solar/platformio.ini
@@ -57,6 +57,8 @@ build_flags =
[env:Heltec_mesh_solar_companion_radio_ble]
extends = Heltec_mesh_solar
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Heltec_mesh_solar.build_flags}
-D MAX_CONTACTS=350
@@ -75,6 +77,8 @@ lib_deps =
[env:Heltec_mesh_solar_companion_radio_usb]
extends = Heltec_mesh_solar
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Heltec_mesh_solar.build_flags}
-D MAX_CONTACTS=350
diff --git a/variants/heltec_t114/platformio.ini b/variants/heltec_t114/platformio.ini
index dec3282d..4bbc05b1 100644
--- a/variants/heltec_t114/platformio.ini
+++ b/variants/heltec_t114/platformio.ini
@@ -70,6 +70,8 @@ build_flags =
[env:Heltec_t114_without_display_companion_radio_ble]
extends = Heltec_t114
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Heltec_t114.build_flags}
-I examples/companion_radio/ui-new
@@ -90,6 +92,8 @@ lib_deps =
[env:Heltec_t114_without_display_companion_radio_usb]
extends = Heltec_t114
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Heltec_t114.build_flags}
-I examples/companion_radio/ui-new
@@ -158,6 +162,8 @@ build_flags =
[env:Heltec_t114_companion_radio_ble]
extends = Heltec_t114_with_display
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Heltec_t114_with_display.build_flags}
-I examples/companion_radio/ui-new
@@ -178,6 +184,8 @@ lib_deps =
[env:Heltec_t114_companion_radio_usb]
extends = Heltec_t114_with_display
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Heltec_t114_with_display.build_flags}
-I examples/companion_radio/ui-new
diff --git a/variants/ikoka_stick_nrf/platformio.ini b/variants/ikoka_stick_nrf/platformio.ini
index 1f2bbfe9..071d2d4f 100644
--- a/variants/ikoka_stick_nrf/platformio.ini
+++ b/variants/ikoka_stick_nrf/platformio.ini
@@ -101,6 +101,8 @@ build_src_filter = ${nrf52840_xiao.build_src_filter}
[ikoka_stick_nrf_companion_radio_ble]
extends = ikoka_stick_nrf_baseboard
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags =
${ikoka_stick_nrf_baseboard.build_flags}
-D MAX_CONTACTS=350
@@ -121,6 +123,8 @@ lib_deps =
[ikoka_stick_nrf_companion_radio_usb]
extends = ikoka_stick_nrf_baseboard
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags =
${ikoka_stick_nrf_baseboard.build_flags}
-D MAX_CONTACTS=350
diff --git a/variants/lilygo_techo/platformio.ini b/variants/lilygo_techo/platformio.ini
index 7d64fad7..e814ea54 100644
--- a/variants/lilygo_techo/platformio.ini
+++ b/variants/lilygo_techo/platformio.ini
@@ -78,6 +78,8 @@ build_flags =
[env:LilyGo_T-Echo_companion_radio_ble]
extends = LilyGo_T-Echo
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${LilyGo_T-Echo.build_flags}
-I src/helpers/ui
@@ -88,6 +90,8 @@ build_flags =
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
+ -D UI_RECENT_LIST_SIZE=9
+ -D UI_SENSORS_PAGE=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
@@ -101,6 +105,8 @@ lib_deps =
[env:LilyGo_T-Echo_companion_radio_usb]
extends = LilyGo_T-Echo
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${LilyGo_T-Echo.build_flags}
-I src/helpers/ui
@@ -109,7 +115,9 @@ build_flags =
-D MAX_GROUP_CHANNELS=40
-D OFFLINE_QUEUE_SIZE=256
-D UI_RECENT_LIST_SIZE=9
+ -D UI_SENSORS_PAGE=1
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
+ -D QSPIFLASH=1
build_src_filter = ${LilyGo_T-Echo.build_src_filter}
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
diff --git a/variants/mesh_pocket/platformio.ini b/variants/mesh_pocket/platformio.ini
index 7c996157..1ed0d1ec 100644
--- a/variants/mesh_pocket/platformio.ini
+++ b/variants/mesh_pocket/platformio.ini
@@ -67,6 +67,8 @@ build_flags =
[env:Mesh_pocket_companion_radio_ble]
extends = Mesh_pocket
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Mesh_pocket.build_flags}
-I examples/companion_radio/ui-new
@@ -89,6 +91,8 @@ lib_deps =
[env:Mesh_pocket_companion_radio_usb]
extends = Mesh_pocket
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Mesh_pocket.build_flags}
-I examples/companion_radio/ui-new
diff --git a/variants/minewsemi_me25ls01/platformio.ini b/variants/minewsemi_me25ls01/platformio.ini
index 71887002..da234dd2 100644
--- a/variants/minewsemi_me25ls01/platformio.ini
+++ b/variants/minewsemi_me25ls01/platformio.ini
@@ -50,6 +50,8 @@ lib_deps = ${nrf52840_me25ls01.lib_deps}
[env:Minewsemi_me25ls01_companion_radio_ble]
extends = me25ls01
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags = ${me25ls01.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350
@@ -147,6 +149,8 @@ lib_deps = ${me25ls01.lib_deps}
[env:Minewsemi_me25ls01_companion_radio_usb]
extends = me25ls01
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags = ${me25ls01.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350
diff --git a/variants/nano_g2_ultra/nano-g2.h b/variants/nano_g2_ultra/nano-g2.h
index 69df0c65..5cedb0f9 100644
--- a/variants/nano_g2_ultra/nano-g2.h
+++ b/variants/nano_g2_ultra/nano-g2.h
@@ -52,8 +52,8 @@ public:
void powerOff() override {
// put GPS chip to sleep
digitalWrite(PIN_GPS_STANDBY, LOW);
-// unset buzzer to prevent notification circuit activating on hibernate
-#undef PIN_BUZZER
+ // TODO: unset buzzer to prevent notification circuit activating on hibernate
+ // needs to be set as silent or somehow stop using macros for pins
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(PIN_USER_BTN), NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_SENSE_LOW);
diff --git a/variants/nano_g2_ultra/platformio.ini b/variants/nano_g2_ultra/platformio.ini
index 163f4311..116a1f25 100644
--- a/variants/nano_g2_ultra/platformio.ini
+++ b/variants/nano_g2_ultra/platformio.ini
@@ -31,6 +31,8 @@ upload_protocol = nrfutil
[env:Nano_G2_Ultra_companion_radio_ble]
extends = Nano_G2_Ultra
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Nano_G2_Ultra.build_flags}
-I src/helpers/ui
@@ -62,12 +64,15 @@ lib_deps =
[env:Nano_G2_Ultra_companion_radio_usb]
extends = Nano_G2_Ultra
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${Nano_G2_Ultra.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
+ -D QSPIFLASH=1
-D OFFLINE_QUEUE_SIZE=256
-D DISPLAY_CLASS=SH1106Display
-D PIN_BUZZER=4
diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini
index 5a70f7ba..a65d3c69 100644
--- a/variants/promicro/platformio.ini
+++ b/variants/promicro/platformio.ini
@@ -86,6 +86,8 @@ lib_deps = ${Faketec.lib_deps}
[env:Faketec_companion_radio_usb]
extends = Faketec
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags = ${Faketec.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
@@ -104,6 +106,8 @@ lib_deps = ${Faketec.lib_deps}
[env:Faketec_companion_radio_ble]
extends = Faketec
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags = ${Faketec.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini
index 7e7d2234..01f4d088 100644
--- a/variants/rak4631/platformio.ini
+++ b/variants/rak4631/platformio.ini
@@ -64,6 +64,8 @@ build_src_filter = ${rak4631.build_src_filter}
[env:RAK_4631_companion_radio_usb]
extends = rak4631
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${rak4631.build_flags}
-I examples/companion_radio/ui-new
@@ -83,6 +85,8 @@ lib_deps =
[env:RAK_4631_companion_radio_ble]
extends = rak4631
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${rak4631.build_flags}
-I examples/companion_radio/ui-new
diff --git a/variants/rak_wismesh_tag/RAKWismeshTagBoard.h b/variants/rak_wismesh_tag/RAKWismeshTagBoard.h
index 22af6f74..e5104a58 100644
--- a/variants/rak_wismesh_tag/RAKWismeshTagBoard.h
+++ b/variants/rak_wismesh_tag/RAKWismeshTagBoard.h
@@ -62,7 +62,8 @@ public:
digitalWrite(LED_PIN, HIGH);
#endif
#ifdef BUTTON_PIN
- while(digitalRead(BUTTON_PIN));
+ // wismesh tag uses LOW to indicate button is pressed, wait until it goes HIGH to indicate it was released
+ while(digitalRead(BUTTON_PIN) == LOW);
#endif
#ifdef LED_GREEN
digitalWrite(LED_GREEN, LOW);
@@ -72,7 +73,8 @@ public:
#endif
#ifdef BUTTON_PIN
- nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
+ // configure button press to wake up when in powered off state
+ nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
#endif
sd_power_system_off();
diff --git a/variants/rak_wismesh_tag/platformio.ini b/variants/rak_wismesh_tag/platformio.ini
index 6b505073..59d55175 100644
--- a/variants/rak_wismesh_tag/platformio.ini
+++ b/variants/rak_wismesh_tag/platformio.ini
@@ -67,6 +67,8 @@ build_src_filter = ${rak_wismesh_tag.build_src_filter}
[env:RAK_WisMesh_Tag_companion_radio_usb]
extends = rak_wismesh_tag
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${rak_wismesh_tag.build_flags}
-I examples/companion_radio/ui-orig
@@ -83,6 +85,8 @@ lib_deps =
[env:RAK_WisMesh_Tag_companion_radio_ble]
extends = rak_wismesh_tag
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${rak_wismesh_tag.build_flags}
-I examples/companion_radio/ui-orig
diff --git a/variants/sensecap_solar/platformio.ini b/variants/sensecap_solar/platformio.ini
index ee9acf0d..31364ffe 100644
--- a/variants/sensecap_solar/platformio.ini
+++ b/variants/sensecap_solar/platformio.ini
@@ -74,6 +74,8 @@ build_src_filter = ${SenseCap_Solar.build_src_filter}
[env:SenseCap_Solar_companion_radio_ble]
extends = SenseCap_Solar
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags =
${SenseCap_Solar.build_flags}
-D MAX_CONTACTS=350
@@ -92,6 +94,8 @@ lib_deps =
[env:SenseCap_Solar_companion_radio_usb]
extends = SenseCap_Solar
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags =
${SenseCap_Solar.build_flags}
-D MAX_CONTACTS=350
diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini
index 1f7d60dd..69d9dccf 100644
--- a/variants/t1000-e/platformio.ini
+++ b/variants/t1000-e/platformio.ini
@@ -68,10 +68,12 @@ lib_deps = ${t1000-e.lib_deps}
[env:t1000e_companion_radio_usb]
extends = t1000-e
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags = ${t1000-e.build_flags}
-I examples/companion_radio/ui-orig
- -D MAX_CONTACTS=100
- -D MAX_GROUP_CHANNELS=8
+ -D MAX_CONTACTS=350
+ -D MAX_GROUP_CHANNELS=40
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D OFFLINE_QUEUE_SIZE=256
@@ -89,6 +91,8 @@ lib_deps = ${t1000-e.lib_deps}
[env:t1000e_companion_radio_ble]
extends = t1000-e
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags = ${t1000-e.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350
diff --git a/variants/thinknode_m1/platformio.ini b/variants/thinknode_m1/platformio.ini
index 7a8f5a3c..a0273ce2 100644
--- a/variants/thinknode_m1/platformio.ini
+++ b/variants/thinknode_m1/platformio.ini
@@ -67,6 +67,8 @@ lib_deps =
[env:ThinkNode_M1_companion_radio_ble]
extends = ThinkNode_M1
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${ThinkNode_M1.build_flags}
-I src/helpers/ui
@@ -99,6 +101,8 @@ lib_deps =
[env:ThinkNode_M1_companion_radio_usb]
extends = ThinkNode_M1
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
build_flags =
${ThinkNode_M1.build_flags}
-I src/helpers/ui
diff --git a/variants/wio-tracker-l1/platformio.ini b/variants/wio-tracker-l1/platformio.ini
index 87670bd0..585e0ba7 100644
--- a/variants/wio-tracker-l1/platformio.ini
+++ b/variants/wio-tracker-l1/platformio.ini
@@ -55,13 +55,16 @@ lib_deps = ${WioTrackerL1.lib_deps}
[env:WioTrackerL1_companion_radio_usb]
extends = WioTrackerL1
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags = ${WioTrackerL1.build_flags}
-I examples/companion_radio/ui-new
- -D MAX_CONTACTS=100
- -D MAX_GROUP_CHANNELS=8
+ -D MAX_CONTACTS=350
+ -D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SH1106Display
-D OFFLINE_QUEUE_SIZE=256
-D PIN_BUZZER=12
+ -D QSPIFLASH=1
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${WioTrackerL1.build_src_filter}
@@ -77,6 +80,8 @@ lib_deps = ${WioTrackerL1.lib_deps}
[env:WioTrackerL1_companion_radio_ble]
extends = WioTrackerL1
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags = ${WioTrackerL1.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini
index ea1cdd3d..212a55ea 100644
--- a/variants/xiao_nrf52/platformio.ini
+++ b/variants/xiao_nrf52/platformio.ini
@@ -57,6 +57,8 @@ upload_protocol = nrfutil
[env:Xiao_nrf52_companion_radio_ble]
extends = Xiao_nrf52
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags =
${Xiao_nrf52.build_flags}
-D MAX_CONTACTS=350
@@ -76,10 +78,13 @@ lib_deps =
[env:Xiao_nrf52_companion_radio_usb]
extends = Xiao_nrf52
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
build_flags =
${Xiao_nrf52.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
+ -D QSPIFLASH=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Xiao_nrf52.build_src_filter}