diff --git a/build.sh b/build.sh index 095a1633..47fec4a3 100755 --- a/build.sh +++ b/build.sh @@ -3,6 +3,7 @@ # usage # sh build.sh build-firmware RAK_4631_Repeater # sh build.sh build-firmwares +# sh build.sh build-matching-firmwares RAK_4631 # sh build.sh build-companion-firmwares # sh build.sh build-repeater-firmwares # sh build.sh build-room-server-firmwares @@ -144,6 +145,16 @@ mkdir -p out if [[ $1 == "build-firmware" ]]; then if [ "$2" ]; then build_firmware $2 + else + echo "usage: $0 build-firmware " + exit 1 + fi +elif [[ $1 == "build-matching-firmwares" ]]; then + if [ "$2" ]; then + build_all_firmwares_matching $2 + else + echo "usage: $0 build-matching-firmwares " + exit 1 fi elif [[ $1 == "build-firmwares" ]]; then build_firmwares diff --git a/build_as_lib.py b/build_as_lib.py new file mode 100644 index 00000000..d8e95378 --- /dev/null +++ b/build_as_lib.py @@ -0,0 +1,64 @@ +from os.path import realpath + +Import("env") # type: ignore +menv=env # type: ignore + +src_filter = [ + '+<*.cpp>', + '+', + '+', + '+', + '+', + '+', +] + +# add build and include dirs according to CPPDEFINES +for item in menv.get("CPPDEFINES", []): + + # PLATFORM HANDLING + if item == "STM32_PLATFORM": + src_filter.append("+") + elif item == "ESP32": + src_filter.append("+") + elif item == "NRF52_PLATFORM": + src_filter.append("+") + elif item == "RP2040_PLATFORM": + src_filter.append("+") + + # DISPLAY HANDLING + elif isinstance(item, tuple) and item[0] == "DISPLAY_CLASS": + display_class = item[1] + src_filter.append(f"+") + if (display_class == "ST7789Display") : + src_filter.append(f"+") + src_filter.append(f"+") + + # VARIANTS HANDLING + elif isinstance(item, tuple) and item[0] == "MC_VARIANT": + variant_name = item[1] + src_filter.append(f"+<../variants/{variant_name}>") + + # INCLUDE EXAMPLE CODE IN BUILD (to provide your own support files without touching the tree) + elif isinstance(item, tuple) and item[0] == "BUILD_EXAMPLE": + example_name = item[1] + src_filter.append(f"+<../examples/{example_name}/*.cpp>") + + # EXCLUDE A SOURCE FILE FROM AN EXAMPLE (must be placed after example name or boom) + elif isinstance(item, tuple) and item[0] == "EXCLUDE_FROM_EXAMPLE": + exclude_name = item[1] + if example_name is None: + print("***** PLEASE DEFINE EXAMPLE FIRST *****") + break + src_filter.append(f"-<../examples/{example_name}/{exclude_name}>") + + # DEAL WITH UI VARIANT FOR AN EXAMPLE + elif isinstance(item, tuple) and item[0] == "MC_UI_FLAVOR": + ui_flavor = item[1] + if example_name is None: + print("***** PLEASE DEFINE EXAMPLE FIRST *****") + break + src_filter.append(f"+<../examples/{example_name}/{ui_flavor}/*.cpp>") + +menv.Replace(SRC_FILTER=src_filter) + +#print (menv.Dump()) diff --git a/examples/companion_radio/AbstractUITask.h b/examples/companion_radio/AbstractUITask.h new file mode 100644 index 00000000..1277bba9 --- /dev/null +++ b/examples/companion_radio/AbstractUITask.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#ifdef PIN_BUZZER + #include +#endif + +#include "NodePrefs.h" + +enum class UIEventType { + none, + contactMessage, + channelMessage, + roomMessage, + newContactMessage, + ack +}; + +class AbstractUITask { +protected: + mesh::MainBoard* _board; + BaseSerialInterface* _serial; + bool _connected; + + AbstractUITask(mesh::MainBoard* board, BaseSerialInterface* serial) : _board(board), _serial(serial) { + _connected = false; + } + +public: + void setHasConnection(bool connected) { _connected = connected; } + bool hasConnection() const { return _connected; } + uint16_t getBattMilliVolts() const { return _board->getBattMilliVolts(); } + bool isSerialEnabled() const { return _serial->isEnabled(); } + void enableSerial() { _serial->enable(); } + void disableSerial() { _serial->disable(); } + virtual void msgRead(int msgcount) = 0; + virtual void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) = 0; + virtual void soundBuzzer(UIEventType bet = UIEventType::none) = 0; + virtual void loop() = 0; +}; diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 901e3db5..1fa5478b 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -109,10 +109,6 @@ #define MAX_SIGN_DATA_LEN (8 * 1024) // 8K -#ifdef DISPLAY_CLASS -#include "UITask.h" -#endif - void MyMesh::writeOKFrame() { uint8_t buf[1]; buf[0] = RESP_CODE_OK; @@ -247,7 +243,7 @@ void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path } } else { #ifdef DISPLAY_CLASS - ui_task.soundBuzzer(UIEventType::newContactMessage); + if (_ui) _ui->soundBuzzer(UIEventType::newContactMessage); #endif } @@ -267,6 +263,7 @@ void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path } memcpy(p->pubkey_prefix, contact.id.pub_key, sizeof(p->pubkey_prefix)); + strcpy(p->name, contact.name); p->recv_timestamp = getRTCClock()->getCurrentTime(); p->path_len = path_len; memcpy(p->path, path, p->path_len); @@ -275,6 +272,20 @@ void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); } +static int sort_by_recent(const void *a, const void *b) { + return ((AdvertPath *) b)->recv_timestamp - ((AdvertPath *) a)->recv_timestamp; +} + +int MyMesh::getRecentlyHeard(AdvertPath dest[], int max_num) { + if (max_num > ADVERT_PATH_TABLE_SIZE) max_num = ADVERT_PATH_TABLE_SIZE; + qsort(advert_paths, ADVERT_PATH_TABLE_SIZE, sizeof(advert_paths[0]), sort_by_recent); + + for (int i = 0; i < max_num; i++) { + dest[i] = advert_paths[i]; + } + return max_num; +} + void MyMesh::onContactPathUpdated(const ContactInfo &contact) { out_frame[0] = PUSH_CODE_PATH_UPDATED; memcpy(&out_frame[1], contact.id.pub_key, PUB_KEY_SIZE); @@ -339,10 +350,10 @@ void MyMesh::queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packe #ifdef DISPLAY_CLASS // we only want to show text messages on display, not cli data bool should_display = txt_type == TXT_TYPE_PLAIN || txt_type == TXT_TYPE_SIGNED_PLAIN; - if (should_display) { - ui_task.newMsg(path_len, from.name, text, offline_queue_len); + if (should_display && _ui) { + _ui->newMsg(path_len, from.name, text, offline_queue_len); if (!_serial->isConnected()) { - ui_task.soundBuzzer(UIEventType::contactMessage); + _ui->soundBuzzer(UIEventType::contactMessage); } } #endif @@ -401,7 +412,7 @@ void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packe _serial->writeFrame(frame, 1); } else { #ifdef DISPLAY_CLASS - ui_task.soundBuzzer(UIEventType::channelMessage); + if (_ui) _ui->soundBuzzer(UIEventType::channelMessage); #endif } #ifdef DISPLAY_CLASS @@ -411,7 +422,7 @@ void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packe if (getChannel(channel_idx, channel_details)) { channel_name = channel_details.name; } - ui_task.newMsg(path_len, channel_name, text, offline_queue_len); + if (_ui) _ui->newMsg(path_len, channel_name, text, offline_queue_len); #endif } @@ -620,9 +631,9 @@ uint32_t MyMesh::calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t void MyMesh::onSendTimeout() {} -MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store) +MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store, AbstractUITask* ui) : BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables), - _serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store) { + _serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store), _ui(ui) { _iter_started = false; _cli_rescue = false; offline_queue_len = 0; @@ -1026,7 +1037,7 @@ void MyMesh::handleCmdFrame(size_t len) { if ((out_len = getFromOfflineQueue(out_frame)) > 0) { _serial->writeFrame(out_frame, out_len); #ifdef DISPLAY_CLASS - ui_task.msgRead(offline_queue_len); + if (_ui) _ui->msgRead(offline_queue_len); #endif } else { out_frame[0] = RESP_CODE_NO_MORE_MESSAGES; @@ -1628,7 +1639,7 @@ void MyMesh::loop() { } #ifdef DISPLAY_CLASS - ui_task.setHasConnection(_serial->isConnected()); + if (_ui) _ui->setHasConnection(_serial->isConnected()); #endif } diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index 01889223..0a5057ea 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -2,9 +2,7 @@ #include #include -#ifdef DISPLAY_CLASS -#include "UITask.h" -#endif +#include "AbstractUITask.h" /*------------ Frame Protocol --------------*/ #define FIRMWARE_VER_CODE 7 @@ -77,9 +75,17 @@ #define REQ_TYPE_KEEP_ALIVE 0x02 #define REQ_TYPE_GET_TELEMETRY_DATA 0x03 +struct AdvertPath { + uint8_t pubkey_prefix[7]; + uint8_t path_len; + char name[32]; + uint32_t recv_timestamp; + uint8_t path[MAX_PATH_SIZE]; +}; + class MyMesh : public BaseChatMesh, public DataStoreHost { public: - MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store); + MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store, AbstractUITask* ui=NULL); void begin(bool has_display); void startInterface(BaseSerialInterface &serial); @@ -93,6 +99,8 @@ public: bool advert(); void enterCLIRescue(); + int getRecentlyHeard(AdvertPath dest[], int max_num); + protected: float getAirtimeBudgetFactor() const override; int getInterferenceThreshold() const override; @@ -169,6 +177,7 @@ private: uint32_t pending_telemetry, pending_discovery; // pending _TELEMETRY_REQ uint32_t pending_req; // pending _BINARY_REQ BaseSerialInterface *_serial; + AbstractUITask* _ui; ContactsIterator _iter; uint32_t _iter_filter_since; @@ -201,17 +210,8 @@ private: AckTableEntry expected_ack_table[EXPECTED_ACK_TABLE_SIZE]; // circular table int next_ack_idx; - struct AdvertPath { - uint8_t pubkey_prefix[7]; - uint8_t path_len; - uint32_t recv_timestamp; - uint8_t path[MAX_PATH_SIZE]; - }; #define ADVERT_PATH_TABLE_SIZE 16 AdvertPath advert_paths[ADVERT_PATH_TABLE_SIZE]; // circular table }; extern MyMesh the_mesh; -#ifdef DISPLAY_CLASS -extern UITask ui_task; -#endif \ No newline at end of file diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 34c30498..1d5ec564 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -75,14 +75,19 @@ static uint32_t _atoi(const char* sp) { #endif /* GLOBAL OBJECTS */ -StdRNG fast_rng; -SimpleMeshTables tables; -MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables, store); - #ifdef DISPLAY_CLASS #include "UITask.h" - UITask ui_task(&board); + UITask ui_task(&board, &serial_interface); #endif + +StdRNG fast_rng; +SimpleMeshTables tables; +MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables, store + #ifdef DISPLAY_CLASS + , &ui_task + #endif +); + /* END GLOBAL OBJECTS */ void halt() { @@ -99,7 +104,10 @@ void setup() { if (display.begin()) { disp = &display; disp->startFrame(); - disp->print("Please wait..."); + #ifdef ST7789 + disp->setTextSize(2); + #endif + disp->drawTextCentered(disp->width() / 2, 28, "Loading..."); disp->endFrame(); } #endif diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp new file mode 100644 index 00000000..1920dd26 --- /dev/null +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -0,0 +1,597 @@ +#include "UITask.h" +#include +#include "../MyMesh.h" +#include "target.h" + +#define AUTO_OFF_MILLIS 15000 // 15 seconds +#define BOOT_SCREEN_MILLIS 3000 // 3 seconds + +#ifdef PIN_STATUS_LED +#define LED_ON_MILLIS 20 +#define LED_ON_MSG_MILLIS 200 +#define LED_CYCLE_MILLIS 4000 +#endif + +#define LONG_PRESS_MILLIS 1200 + +#ifndef UI_RECENT_LIST_SIZE + #define UI_RECENT_LIST_SIZE 4 +#endif + +#define PRESS_LABEL "long press" + +#include "icons.h" + +class SplashScreen : public UIScreen { + UITask* _task; + unsigned long dismiss_after; + char _version_info[12]; + +public: + SplashScreen(UITask* task) : _task(task) { + // strip off dash and commit hash by changing dash to null terminator + // e.g: v1.2.3-abcdef -> v1.2.3 + const char *ver = FIRMWARE_VERSION; + const char *dash = strchr(ver, '-'); + + int len = dash ? dash - ver : strlen(ver); + if (len >= sizeof(_version_info)) len = sizeof(_version_info) - 1; + memcpy(_version_info, ver, len); + _version_info[len] = 0; + + dismiss_after = millis() + BOOT_SCREEN_MILLIS; + } + + int render(DisplayDriver& display) override { + // meshcore logo + display.setColor(DisplayDriver::BLUE); + int logoWidth = 128; + display.drawXbm((display.width() - logoWidth) / 2, 3, meshcore_logo, logoWidth, 13); + + // version info + display.setColor(DisplayDriver::LIGHT); + display.setTextSize(2); + display.drawTextCentered(display.width()/2, 22, _version_info); + + display.setTextSize(1); + display.drawTextCentered(display.width()/2, 42, FIRMWARE_BUILD_DATE); + + return 1000; + } + + void poll() override { + if (millis() >= dismiss_after) { + _task->gotoHomeScreen(); + } + } +}; + +class HomeScreen : public UIScreen { + enum HomePage { + FIRST, + RECENT, + RADIO, + BLUETOOTH, + ADVERT, + SHUTDOWN, + Count // keep as last + }; + + UITask* _task; + mesh::RTCClock* _rtc; + SensorManager* _sensors; + NodePrefs* _node_prefs; + uint8_t _page; + bool _shutdown_init; + AdvertPath recent[UI_RECENT_LIST_SIZE]; + + void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts) { + // Convert millivolts to percentage + const int minMilliVolts = 3000; // Minimum voltage (e.g., 3.0V) + const int maxMilliVolts = 4200; // Maximum voltage (e.g., 4.2V) + int batteryPercentage = ((batteryMilliVolts - minMilliVolts) * 100) / (maxMilliVolts - minMilliVolts); + if (batteryPercentage < 0) batteryPercentage = 0; // Clamp to 0% + if (batteryPercentage > 100) batteryPercentage = 100; // Clamp to 100% + + // battery icon + int iconWidth = 24; + int iconHeight = 10; + int iconX = display.width() - iconWidth - 5; // Position the icon near the top-right corner + int iconY = 0; + display.setColor(DisplayDriver::GREEN); + + // battery outline + display.drawRect(iconX, iconY, iconWidth, iconHeight); + + // battery "cap" + display.fillRect(iconX + iconWidth, iconY + (iconHeight / 4), 3, iconHeight / 2); + + // fill the battery based on the percentage + int fillWidth = (batteryPercentage * (iconWidth - 4)) / 100; + display.fillRect(iconX + 2, iconY + 2, fillWidth, iconHeight - 4); + } + +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) { } + + void poll() override { + if (_shutdown_init && !_task->isButtonPressed()) { // must wait for USR button to be released + _task->shutdown(); + } + } + + int render(DisplayDriver& display) override { + char tmp[80]; + // node name + display.setCursor(0, 0); + display.setTextSize(1); + display.setColor(DisplayDriver::GREEN); + display.print(_node_prefs->node_name); + + // battery voltage + renderBatteryIndicator(display, _task->getBattMilliVolts()); + + // curr page indicator + int y = 14; + int x = display.width() / 2 - 25; + for (uint8_t i = 0; i < HomePage::Count; i++, x += 10) { + if (i == _page) { + display.fillRect(x-1, y-1, 3, 3); + } else { + display.fillRect(x, y, 1, 1); + } + } + + if (_page == HomePage::FIRST) { + display.setColor(DisplayDriver::YELLOW); + display.setTextSize(2); + sprintf(tmp, "MSG: %d", _task->getMsgCount()); + display.drawTextCentered(display.width() / 2, 20, tmp); + + if (_task->hasConnection()) { + display.setColor(DisplayDriver::GREEN); + display.setTextSize(1); + display.drawTextCentered(display.width() / 2, 43, "< Connected >"); + } else if (the_mesh.getBLEPin() != 0) { // BT pin + display.setColor(DisplayDriver::RED); + display.setTextSize(2); + sprintf(tmp, "Pin:%d", the_mesh.getBLEPin()); + display.drawTextCentered(display.width() / 2, 43, tmp); + } + } else if (_page == HomePage::RECENT) { + the_mesh.getRecentlyHeard(recent, UI_RECENT_LIST_SIZE); + display.setColor(DisplayDriver::GREEN); + int y = 20; + for (int i = 0; i < UI_RECENT_LIST_SIZE; i++, y += 11) { + auto a = &recent[i]; + if (a->name[0] == 0) continue; // empty slot + display.setCursor(0, y); + display.print(a->name); + int secs = _rtc->getCurrentTime() - a->recv_timestamp; + if (secs < 60) { + sprintf(tmp, "%ds", secs); + } else if (secs < 60*60) { + sprintf(tmp, "%dm", secs / 60); + } else { + sprintf(tmp, "%dh", secs / (60*60)); + } + display.setCursor(display.width() - display.getTextWidth(tmp) - 1, y); + display.print(tmp); + } + } else if (_page == HomePage::RADIO) { + display.setColor(DisplayDriver::YELLOW); + display.setTextSize(1); + // freq / sf + display.setCursor(0, 20); + sprintf(tmp, "FQ: %06.3f SF: %d", _node_prefs->freq, _node_prefs->sf); + display.print(tmp); + + display.setCursor(0, 31); + sprintf(tmp, "BW: %03.2f CR: %d", _node_prefs->bw, _node_prefs->cr); + display.print(tmp); + + // tx power, noise floor + display.setCursor(0, 42); + sprintf(tmp, "TX: %ddBm", _node_prefs->tx_power_dbm); + display.print(tmp); + display.setCursor(0, 53); + sprintf(tmp, "Noise floor: %d", radio_driver.getNoiseFloor()); + display.print(tmp); + } else if (_page == HomePage::BLUETOOTH) { + display.setColor(DisplayDriver::GREEN); + display.drawXbm((display.width() - 32) / 2, 18, + _task->isSerialEnabled() ? bluetooth_on : bluetooth_off, + 32, 32); + display.setTextSize(1); + display.drawTextCentered(display.width() / 2, 64 - 11, "toggle: " PRESS_LABEL); + } else if (_page == HomePage::ADVERT) { + 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); + } else if (_page == HomePage::SHUTDOWN) { + display.setColor(DisplayDriver::GREEN); + display.setTextSize(1); + if (_shutdown_init) { + display.drawTextCentered(display.width() / 2, 34, "hibernating..."); + } else { + display.drawXbm((display.width() - 32) / 2, 18, power_icon, 32, 32); + display.drawTextCentered(display.width() / 2, 64 - 11, "hibernate: " PRESS_LABEL); + } + } + return 5000; // next render after 5000 ms + } + + bool handleInput(char c) override { + if (c == KEY_LEFT) { + _page = (_page + HomePage::Count - 1) % HomePage::Count; + return true; + } + if (c == KEY_RIGHT || c == KEY_SELECT) { + _page = (_page + 1) % HomePage::Count; + if (_page == HomePage::RECENT) { + _task->showAlert("Recent adverts", 800); + } + return true; + } + if (c == KEY_ENTER && _page == HomePage::BLUETOOTH) { + if (_task->isSerialEnabled()) { // toggle Bluetooth on/off + _task->disableSerial(); + } else { + _task->enableSerial(); + } + return true; + } + if (c == KEY_ENTER && _page == HomePage::ADVERT) { + #ifdef PIN_BUZZER + _task->soundBuzzer(UIEventType::ack); + #endif + if (the_mesh.advert()) { + _task->showAlert("Advert sent!", 1000); + } else { + _task->showAlert("Advert failed..", 1000); + } + return true; + } + if (c == KEY_ENTER && _page == HomePage::SHUTDOWN) { + _shutdown_init = true; // need to wait for button to be released + return true; + } + return false; + } +}; + +class MsgPreviewScreen : public UIScreen { + UITask* _task; + mesh::RTCClock* _rtc; + + struct MsgEntry { + uint32_t timestamp; + char origin[62]; + char msg[78]; + }; + #define MAX_UNREAD_MSGS 32 + int num_unread; + MsgEntry unread[MAX_UNREAD_MSGS]; + +public: + MsgPreviewScreen(UITask* task, mesh::RTCClock* rtc) : _task(task), _rtc(rtc) { num_unread = 0; } + + void addPreview(uint8_t path_len, const char* from_name, const char* msg) { + if (num_unread >= MAX_UNREAD_MSGS) return; // full + + auto p = &unread[num_unread++]; + p->timestamp = _rtc->getCurrentTime(); + if (path_len == 0xFF) { + sprintf(p->origin, "(D) %s:", from_name); + } else { + sprintf(p->origin, "(%d) %s:", (uint32_t) path_len, from_name); + } + StrHelper::strncpy(p->msg, msg, sizeof(p->msg)); + } + + int render(DisplayDriver& display) override { + char tmp[16]; + display.setCursor(0, 0); + display.setTextSize(1); + display.setColor(DisplayDriver::GREEN); + sprintf(tmp, "Unread: %d", num_unread); + display.print(tmp); + + auto p = &unread[0]; + + int secs = _rtc->getCurrentTime() - p->timestamp; + if (secs < 60) { + sprintf(tmp, "%ds", secs); + } else if (secs < 60*60) { + sprintf(tmp, "%dm", secs / 60); + } else { + sprintf(tmp, "%dh", secs / (60*60)); + } + display.setCursor(display.width() - display.getTextWidth(tmp) - 2, 0); + display.print(tmp); + + display.drawRect(0, 11, display.width(), 1); // horiz line + + display.setCursor(0, 14); + display.setColor(DisplayDriver::YELLOW); + display.print(p->origin); + + display.setCursor(0, 25); + display.setColor(DisplayDriver::LIGHT); + display.printWordWrap(p->msg, display.width()); + + return 1000; // next render after 1000 ms + } + + bool handleInput(char c) override { + if (c == KEY_SELECT || c == KEY_RIGHT) { + num_unread--; + if (num_unread == 0) { + _task->gotoHomeScreen(); + } else { + // delete first/curr item from unread queue + for (int i = 0; i < num_unread; i++) { + unread[i] = unread[i + 1]; + } + } + return true; + } + if (c == KEY_ENTER) { + num_unread = 0; // clear unread queue + _task->gotoHomeScreen(); + return true; + } + return false; + } +}; + +void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* node_prefs) { + _display = display; + _sensors = sensors; + _auto_off = millis() + AUTO_OFF_MILLIS; + +#if defined(PIN_USER_BTN) + user_btn.begin(); +#endif + + _node_prefs = node_prefs; + if (_display != NULL) { + _display->turnOn(); + } + +#ifdef PIN_BUZZER + buzzer.begin(); +#endif + + ui_started_at = millis(); + _alert_expiry = 0; + + splash = new SplashScreen(this); + home = new HomeScreen(this, &rtc_clock, sensors, node_prefs); + msg_preview = new MsgPreviewScreen(this, &rtc_clock); + setCurrScreen(splash); +} + +void UITask::showAlert(const char* text, int duration_millis) { + strcpy(_alert, text); + _alert_expiry = millis() + duration_millis; +} + +void UITask::soundBuzzer(UIEventType bet) { +#if defined(PIN_BUZZER) +switch(bet){ + case UIEventType::contactMessage: + // gemini's pick + buzzer.play("MsgRcv3:d=4,o=6,b=200:32e,32g,32b,16c7"); + break; + case UIEventType::channelMessage: + buzzer.play("kerplop:d=16,o=6,b=120:32g#,32c#"); + break; + case UIEventType::ack: + buzzer.play("ack:d=32,o=8,b=120:c"); + break; + case UIEventType::roomMessage: + case UIEventType::newContactMessage: + case UIEventType::none: + default: + break; +} +#endif +} + +void UITask::msgRead(int msgcount) { + _msgcount = msgcount; + if (msgcount == 0) { + gotoHomeScreen(); + } +} + +void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) { + _msgcount = msgcount; + + ((MsgPreviewScreen *) msg_preview)->addPreview(path_len, from_name, text); + setCurrScreen(msg_preview); + + if (_display != NULL) { + if (!_display->isOn()) _display->turnOn(); + _auto_off = millis() + AUTO_OFF_MILLIS; // extend the auto-off timer + _next_refresh = 0; // trigger refresh + } +} + +void UITask::userLedHandler() { +#ifdef PIN_STATUS_LED + static int state = 0; + static int next_change = 0; + static int last_increment = 0; + + int cur_time = millis(); + if (cur_time > next_change) { + if (state == 0) { + state = 1; + if (_msgcount > 0) { + last_increment = LED_ON_MSG_MILLIS; + } else { + last_increment = LED_ON_MILLIS; + } + next_change = cur_time + last_increment; + } else { + state = 0; + next_change = cur_time + LED_CYCLE_MILLIS - last_increment; + } + digitalWrite(PIN_STATUS_LED, state); + } +#endif +} + +void UITask::setCurrScreen(UIScreen* c) { + curr = c; + _next_refresh = 0; +} + +/* + hardware-agnostic pre-shutdown activity should be done here +*/ +void UITask::shutdown(bool restart){ + + #ifdef PIN_BUZZER + /* note: we have a choice here - + we can do a blocking buzzer.loop() with non-deterministic consequences + or we can set a flag and delay the shutdown for a couple of seconds + while a non-blocking buzzer.loop() plays out in UITask::loop() + */ + buzzer.shutdown(); + uint32_t buzzer_timer = millis(); // fail-safe shutdown + while (buzzer.isPlaying() && (millis() - 2500) < buzzer_timer) + buzzer.loop(); + + #endif // PIN_BUZZER + + if (restart) { + _board->reboot(); + } else { + _display->turnOff(); + _board->powerOff(); + } +} + +bool UITask::isButtonPressed() const { +#ifdef PIN_USER_BTN + return user_btn.isPressed(); +#else + return false; +#endif +} + +void UITask::loop() { + char c = 0; +#if defined(PIN_USER_BTN) + int ev = user_btn.check(); + if (ev == BUTTON_EVENT_CLICK) { + c = checkDisplayOn(KEY_SELECT); + } else if (ev == BUTTON_EVENT_LONG_PRESS) { + c = handleLongPress(KEY_ENTER); + } +#endif +#if defined(WIO_TRACKER_L1) + ev = joystick_left.check(); + if (ev == BUTTON_EVENT_CLICK) { + c = checkDisplayOn(KEY_LEFT); + } else if (ev == BUTTON_EVENT_LONG_PRESS) { + c = handleLongPress(KEY_LEFT); + } + ev = joystick_right.check(); + if (ev == BUTTON_EVENT_CLICK) { + c = checkDisplayOn(KEY_RIGHT); + } else if (ev == BUTTON_EVENT_LONG_PRESS) { + c = handleLongPress(KEY_RIGHT); + } +#endif + + if (c != 0 && curr) { + curr->handleInput(c); + _auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer + _next_refresh = 0; // trigger refresh + } + + userLedHandler(); + +#ifdef PIN_BUZZER + if (buzzer.isPlaying()) buzzer.loop(); +#endif + + if (curr) curr->poll(); + + if (_display != NULL && _display->isOn()) { + if (millis() >= _next_refresh && curr) { + _display->startFrame(); + int delay_millis = curr->render(*_display); + if (millis() < _alert_expiry) { // render alert popup + _display->setTextSize(1); + int y = _display->height() / 3; + int p = _display->height() / 32; + _display->setColor(DisplayDriver::DARK); + _display->fillRect(p, y, _display->width() - p*2, y); + _display->setColor(DisplayDriver::LIGHT); // draw box border + _display->drawRect(p, y, _display->width() - p*2, y); + _display->drawTextCentered(_display->width() / 2, y + p*3, _alert); + _next_refresh = _alert_expiry; // will need refresh when alert is dismissed + } else { + _next_refresh = millis() + delay_millis; + } + _display->endFrame(); + } + if (millis() > _auto_off) { + _display->turnOff(); + } + } + +#ifdef AUTO_SHUTDOWN_MILLIVOLTS + if (millis() > next_batt_chck) { + uint16_t milliVolts = getBattMilliVolts(); + if (milliVolts > 0 && milliVolts < AUTO_SHUTDOWN_MILLIVOLTS) { + shutdown(); + } + next_batt_chck = millis() + 8000; + } +#endif +} + +char UITask::checkDisplayOn(char c) { + if (_display != NULL) { + if (!_display->isOn()) { + _display->turnOn(); // turn display on and consume event + c = 0; + } + _auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer + _next_refresh = 0; // trigger refresh + } + return c; +} + +char UITask::handleLongPress(char c) { + if (millis() - ui_started_at < 8000) { // long press in first 8 seconds since startup -> CLI/rescue + the_mesh.enterCLIRescue(); + c = 0; // consume event + } + return c; +} + +/* +void UITask::handleButtonTriplePress() { + MESH_DEBUG_PRINTLN("UITask: triple press triggered"); + // Toggle buzzer quiet mode + #ifdef PIN_BUZZER + if (buzzer.isQuiet()) { + buzzer.quiet(false); + soundBuzzer(UIEventType::ack); + showAlert("Buzzer: ON", 600); + } else { + buzzer.quiet(true); + showAlert("Buzzer: OFF", 600); + } + _next_refresh = 0; // trigger refresh + #endif +} +*/ diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h new file mode 100644 index 00000000..f9e01550 --- /dev/null +++ b/examples/companion_radio/ui-new/UITask.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#ifdef PIN_BUZZER + #include +#endif + +#include "../AbstractUITask.h" +#include "../NodePrefs.h" + +class UITask : public AbstractUITask { + DisplayDriver* _display; + SensorManager* _sensors; +#ifdef PIN_BUZZER + genericBuzzer buzzer; +#endif + unsigned long _next_refresh, _auto_off; + NodePrefs* _node_prefs; + char _alert[80]; + unsigned long _alert_expiry; + int _msgcount; + unsigned long ui_started_at, next_batt_chck; + + UIScreen* splash; + UIScreen* home; + UIScreen* msg_preview; + UIScreen* curr; + + void userLedHandler(); + + // Button action handlers + char checkDisplayOn(char c); + char handleLongPress(char c); + + void setCurrScreen(UIScreen* c); + +public: + + UITask(mesh::MainBoard* board, BaseSerialInterface* serial) : AbstractUITask(board, serial), _display(NULL), _sensors(NULL) { + next_batt_chck = _next_refresh = 0; + ui_started_at = 0; + curr = NULL; + } + void begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* node_prefs); + + void gotoHomeScreen() { setCurrScreen(home); } + void showAlert(const char* text, int duration_millis); + int getMsgCount() const { return _msgcount; } + bool hasDisplay() const { return _display != NULL; } + bool isButtonPressed() const; + + // from AbstractUITask + void msgRead(int msgcount) override; + void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) override; + void soundBuzzer(UIEventType bet = UIEventType::none) override; + void loop() override; + + void shutdown(bool restart = false); +}; diff --git a/examples/companion_radio/ui-new/icons.h b/examples/companion_radio/ui-new/icons.h new file mode 100644 index 00000000..5220f409 --- /dev/null +++ b/examples/companion_radio/ui-new/icons.h @@ -0,0 +1,118 @@ +#pragma once + +#include + +// 'meshcore', 128x13px +static const uint8_t meshcore_logo [] = { + 0x3c, 0x01, 0xe3, 0xff, 0xc7, 0xff, 0x8f, 0x03, 0x87, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, + 0x3c, 0x03, 0xe3, 0xff, 0xc7, 0xff, 0x8e, 0x03, 0x8f, 0xfe, 0x3f, 0xfe, 0x1f, 0xff, 0x1f, 0xfe, + 0x3e, 0x03, 0xc3, 0xff, 0x8f, 0xff, 0x0e, 0x07, 0x8f, 0xfe, 0x7f, 0xfe, 0x1f, 0xff, 0x1f, 0xfc, + 0x3e, 0x07, 0xc7, 0x80, 0x0e, 0x00, 0x0e, 0x07, 0x9e, 0x00, 0x78, 0x0e, 0x3c, 0x0f, 0x1c, 0x00, + 0x3e, 0x0f, 0xc7, 0x80, 0x1e, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x70, 0x0e, 0x38, 0x0f, 0x3c, 0x00, + 0x7f, 0x0f, 0xc7, 0xfe, 0x1f, 0xfc, 0x1f, 0xff, 0x1c, 0x00, 0x70, 0x0e, 0x38, 0x0e, 0x3f, 0xf8, + 0x7f, 0x1f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x0e, 0x38, 0x0e, 0x3f, 0xf8, + 0x7f, 0x3f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x1e, 0x3f, 0xfe, 0x3f, 0xf0, + 0x77, 0x3b, 0x87, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xfc, 0x38, 0x00, + 0x77, 0xfb, 0x8f, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xf8, 0x38, 0x00, + 0x73, 0xf3, 0x8f, 0xff, 0x0f, 0xff, 0x1c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x78, 0x7f, 0xf8, + 0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfe, 0x3c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x3c, 0x7f, 0xf8, + 0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfc, 0x3c, 0x0e, 0x1f, 0xf8, 0xff, 0xf8, 0x70, 0x3c, 0x7f, 0xf8, +}; + +static const uint8_t bluetooth_on[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x3B, 0xE0, 0x00, + 0x30, 0x38, 0xF8, 0x00, + 0x3C, 0x38, 0x7C, 0x00, + 0x3E, 0x38, 0x7C, 0x00, + 0x1F, 0xB8, 0xF8, 0x70, + 0x07, 0xF9, 0xF0, 0x78, + 0x03, 0xFF, 0xC0, 0x78, + 0x00, 0xFF, 0x80, 0x3C, + 0x00, 0x7F, 0x07, 0x1C, + 0x00, 0x7E, 0x07, 0x1C, + 0x03, 0xFF, 0x82, 0x1C, + 0x03, 0xFF, 0xC0, 0x78, + 0x07, 0xFB, 0xE0, 0x78, + 0x0F, 0xB8, 0xF8, 0x70, + 0x3E, 0x38, 0x7C, 0x00, + 0x3C, 0x38, 0x7C, 0x00, + 0x38, 0x38, 0xF8, 0x00, + 0x00, 0x39, 0xF0, 0x00, + 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const uint8_t bluetooth_off[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xE0, 0x00, + 0x38, 0x03, 0xF8, 0x00, + 0x3C, 0x03, 0xFC, 0x00, + 0x3E, 0x03, 0xBF, 0x00, + 0x0F, 0x83, 0x8F, 0x80, + 0x07, 0xC3, 0x87, 0xC0, + 0x03, 0xF0, 0x03, 0xC0, + 0x00, 0xF8, 0x0F, 0x80, + 0x00, 0x7C, 0x0F, 0x00, + 0x00, 0x1F, 0x0E, 0x00, + 0x00, 0x0F, 0x80, 0x00, + 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x3F, 0xBE, 0x00, + 0x00, 0x7F, 0x9F, 0x00, + 0x00, 0xFB, 0x8F, 0xC0, + 0x03, 0xE3, 0x83, 0xE0, + 0x03, 0xC3, 0x87, 0xF0, + 0x03, 0x83, 0x8F, 0xFC, + 0x00, 0x03, 0xBF, 0x3C, + 0x00, 0x03, 0xFC, 0x1C, + 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const uint8_t power_icon[] = { + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x33, 0xCC, 0x00, 0x00, 0xF3, 0xCF, 0x00, 0x01, 0xF3, 0xCF, 0x80, + 0x03, 0xF3, 0xCF, 0xC0, 0x07, 0xF3, 0xCF, 0xE0, 0x0F, 0xE3, 0xC7, 0xF0, + 0x1F, 0xC3, 0xC3, 0xF8, 0x1F, 0x83, 0xC1, 0xF8, 0x3F, 0x03, 0xC0, 0xFC, + 0x3E, 0x03, 0xC0, 0x7C, 0x3E, 0x03, 0xC0, 0x7C, 0x7E, 0x01, 0x80, 0x7E, + 0x7C, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0x3E, + 0x7C, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0x3E, 0x3E, 0x00, 0x00, 0x7C, + 0x3E, 0x00, 0x00, 0x7C, 0x3F, 0x00, 0x00, 0xFC, 0x1F, 0x80, 0x01, 0xF8, + 0x1F, 0xC0, 0x03, 0xF8, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0xF0, + 0x07, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, +}; + +static const uint8_t advert_icon[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x30, +0x1C, 0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0x18, 0x30, 0x00, 0x00, 0x0C, +0x30, 0x60, 0x06, 0x0C, 0x60, 0xE0, 0x07, 0x06, 0x61, 0xC0, 0x03, 0x86, +0xE1, 0x81, 0x81, 0x87, 0xC3, 0x07, 0xE0, 0xC3, 0xC3, 0x0F, 0xF0, 0xC3, +0xC3, 0x0F, 0xF0, 0xC3, 0xC3, 0x0F, 0xF0, 0xC3, 0xC3, 0x0F, 0xF0, 0xC3, +0xC3, 0x07, 0xE0, 0xC3, 0xC1, 0x83, 0xC1, 0x83, 0x61, 0x80, 0x01, 0x86, +0x60, 0xC0, 0x03, 0x06, 0x70, 0xE0, 0x07, 0x0E, 0x30, 0x40, 0x02, 0x0C, +0x38, 0x00, 0x00, 0x1C, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x30, +0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; \ No newline at end of file diff --git a/examples/companion_radio/Button.cpp b/examples/companion_radio/ui-orig/Button.cpp similarity index 100% rename from examples/companion_radio/Button.cpp rename to examples/companion_radio/ui-orig/Button.cpp diff --git a/examples/companion_radio/Button.h b/examples/companion_radio/ui-orig/Button.h similarity index 100% rename from examples/companion_radio/Button.h rename to examples/companion_radio/ui-orig/Button.h diff --git a/examples/companion_radio/UITask.cpp b/examples/companion_radio/ui-orig/UITask.cpp similarity index 99% rename from examples/companion_radio/UITask.cpp rename to examples/companion_radio/ui-orig/UITask.cpp index a7f03a26..29d995a7 100644 --- a/examples/companion_radio/UITask.cpp +++ b/examples/companion_radio/ui-orig/UITask.cpp @@ -1,8 +1,7 @@ #include "UITask.h" #include #include -#include "NodePrefs.h" -#include "MyMesh.h" +#include "../MyMesh.h" #define AUTO_OFF_MILLIS 15000 // 15 seconds #define BOOT_SCREEN_MILLIS 3000 // 3 seconds diff --git a/examples/companion_radio/UITask.h b/examples/companion_radio/ui-orig/UITask.h similarity index 73% rename from examples/companion_radio/UITask.h rename to examples/companion_radio/ui-orig/UITask.h index 77ef875f..a59ddc41 100644 --- a/examples/companion_radio/UITask.h +++ b/examples/companion_radio/ui-orig/UITask.h @@ -9,28 +9,18 @@ #include #endif -#include "NodePrefs.h" +#include "../AbstractUITask.h" +#include "../NodePrefs.h" + #include "Button.h" - enum class UIEventType -{ - none, - contactMessage, - channelMessage, - roomMessage, - newContactMessage, - ack -}; - -class UITask { +class UITask : public AbstractUITask { DisplayDriver* _display; - mesh::MainBoard* _board; SensorManager* _sensors; #ifdef PIN_BUZZER genericBuzzer buzzer; #endif unsigned long _next_refresh, _auto_off; - bool _connected; NodePrefs* _node_prefs; char _version_info[32]; char _origin[62]; @@ -64,19 +54,20 @@ class UITask { public: - UITask(mesh::MainBoard* board) : _board(board), _display(NULL), _sensors(NULL) { + UITask(mesh::MainBoard* board, BaseSerialInterface* serial) : AbstractUITask(board, serial), _display(NULL), _sensors(NULL) { _next_refresh = 0; ui_started_at = 0; - _connected = false; } void begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* node_prefs); - void setHasConnection(bool connected) { _connected = connected; } bool hasDisplay() const { return _display != NULL; } void clearMsgPreview(); - void msgRead(int msgcount); - void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount); - void soundBuzzer(UIEventType bet = UIEventType::none); + + // from AbstractUITask + void msgRead(int msgcount) override; + void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) override; + void soundBuzzer(UIEventType bet = UIEventType::none) override; + void loop() override; + void shutdown(bool restart = false); - void loop(); }; diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 7ad0e64a..622a0554 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -159,7 +159,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { } void putNeighbour(const mesh::Identity& id, uint32_t timestamp, float snr) { - #if MAX_NEIGHBOURS // check if neighbours enabled + #if MAX_NEIGHBOURS // check if neighbours enabled // find existing neighbour, else use least recently updated uint32_t oldest_timestamp = 0xFFFFFFFF; NeighbourInfo* neighbour = &neighbours[0]; @@ -589,7 +589,7 @@ public: _prefs.cr = LORA_CR; _prefs.tx_power_dbm = LORA_TX_POWER; _prefs.advert_interval = 1; // default to 2 minutes for NEW installs - _prefs.flood_advert_interval = 3; // 3 hours + _prefs.flood_advert_interval = 12; // 12 hours _prefs.flood_max = 64; _prefs.interference_threshold = 0; // disabled } @@ -611,8 +611,8 @@ public: const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; } const char* getRole() override { return FIRMWARE_ROLE; } const char* getNodeName() { return _prefs.node_name; } - NodePrefs* getNodePrefs() { - return &_prefs; + NodePrefs* getNodePrefs() { + return &_prefs; } void savePrefs() override { diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 34b94ad2..712d02a5 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -298,7 +298,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { // uint32_t now = getRTCClock()->getCurrentTimeUnique(); // memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp memcpy(reply_data, &sender_timestamp, 4); // reflect sender_timestamp back in response packet (kind of like a 'tag') - + switch (payload[0]) { case REQ_TYPE_GET_STATUS: { ServerStats stats; @@ -746,9 +746,9 @@ public: _prefs.tx_power_dbm = LORA_TX_POWER; _prefs.disable_fwd = 1; _prefs.advert_interval = 1; // default to 2 minutes for NEW installs - _prefs.flood_advert_interval = 3; // 3 hours + _prefs.flood_advert_interval = 12; // 12 hours _prefs.flood_max = 64; - _prefs.interference_threshold = 0; // disabled + _prefs.interference_threshold = 0; // disabled #ifdef ROOM_PASSWORD StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password)); #endif @@ -778,8 +778,8 @@ public: const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; } const char* getRole() override { return FIRMWARE_ROLE; } const char* getNodeName() { return _prefs.node_name; } - NodePrefs* getNodePrefs() { - return &_prefs; + NodePrefs* getNodePrefs() { + return &_prefs; } void savePrefs() override { diff --git a/examples/simple_sensor/SensorMesh.cpp b/examples/simple_sensor/SensorMesh.cpp index ce36e0c2..ad295501 100644 --- a/examples/simple_sensor/SensorMesh.cpp +++ b/examples/simple_sensor/SensorMesh.cpp @@ -613,6 +613,23 @@ void SensorMesh::getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) { } } +void SensorMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) { + if (dest.out_path_len < 0) { + mesh::Packet* ack = createAck(ack_hash); + if (ack) sendFlood(ack, TXT_ACK_DELAY); + } else { + uint32_t d = TXT_ACK_DELAY; + if (getExtraAckTransmitCount() > 0) { + mesh::Packet* a1 = createMultiAck(ack_hash, 1); + if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, d); + d += 300; + } + + mesh::Packet* a2 = createAck(ack_hash); + if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d); + } +} + void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { @@ -656,38 +673,55 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong) uint flags = (data[4] >> 2); // message attempt number, and other flags - if (!(flags == TXT_TYPE_CLI_DATA)) { - MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags); - } else if (sender_timestamp > from.last_timestamp) { // prevent replay attacks - from.last_timestamp = sender_timestamp; - from.last_activity = getRTCClock()->getCurrentTime(); + if (sender_timestamp > from.last_timestamp) { // prevent replay attacks + if (flags == TXT_TYPE_PLAIN) { + bool handled = handleIncomingMsg(from, sender_timestamp, &data[5], flags, len - 5); + if (handled) { // if msg was handled then send an ack + uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it + mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE); - // len can be > original length, but 'text' will be padded with zeroes - data[len] = 0; // need to make a C string again, with null terminator - - uint8_t temp[166]; - char *command = (char *) &data[5]; - char *reply = (char *) &temp[5]; - handleCommand(sender_timestamp, command, reply); - - int text_len = strlen(reply); - if (text_len > 0) { - uint32_t timestamp = getRTCClock()->getCurrentTimeUnique(); - if (timestamp == sender_timestamp) { - // WORKAROUND: the two timestamps need to be different, in the CLI view - timestamp++; - } - memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique - temp[4] = (TXT_TYPE_CLI_DATA << 2); - - auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len); - if (reply) { - if (from.out_path_len < 0) { - sendFlood(reply, CLI_REPLY_DELAY_MILLIS); + if (packet->isRouteFlood()) { + // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK + mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len, + PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4); + if (path) sendFlood(path, TXT_ACK_DELAY); } else { - sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS); + sendAckTo(from, ack_hash); + } + } + } else if (flags == TXT_TYPE_CLI_DATA) { + from.last_timestamp = sender_timestamp; + from.last_activity = getRTCClock()->getCurrentTime(); + + // len can be > original length, but 'text' will be padded with zeroes + data[len] = 0; // need to make a C string again, with null terminator + + uint8_t temp[166]; + char *command = (char *) &data[5]; + char *reply = (char *) &temp[5]; + handleCommand(sender_timestamp, command, reply); + + int text_len = strlen(reply); + if (text_len > 0) { + uint32_t timestamp = getRTCClock()->getCurrentTimeUnique(); + if (timestamp == sender_timestamp) { + // WORKAROUND: the two timestamps need to be different, in the CLI view + timestamp++; + } + memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique + temp[4] = (TXT_TYPE_CLI_DATA << 2); + + auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len); + if (reply) { + if (from.out_path_len < 0) { + sendFlood(reply, CLI_REPLY_DELAY_MILLIS); + } else { + sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS); + } } } + } else { + MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags); } } else { MESH_DEBUG_PRINTLN("onPeerDataRecv: possible replay attack detected"); @@ -695,6 +729,15 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i } } +bool SensorMesh::handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len) { + MESH_DEBUG_PRINT("handleIncomingMsg: unhandled msg from "); + #ifdef MESH_DEBUG + mesh::Utils::printHex(Serial, from.id.pub_key, PUB_KEY_SIZE); + Serial.printf(": %s\n", data); + #endif + return false; +} + bool SensorMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { diff --git a/examples/simple_sensor/SensorMesh.h b/examples/simple_sensor/SensorMesh.h index 0d87617b..62c1867e 100644 --- a/examples/simple_sensor/SensorMesh.h +++ b/examples/simple_sensor/SensorMesh.h @@ -140,7 +140,8 @@ protected: void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override; bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override; void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override; - + virtual bool handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len); + void sendAckTo(const ContactInfo& dest, uint32_t ack_hash); private: FILESYSTEM* _fs; unsigned long next_local_advert, next_flood_advert; diff --git a/library.json b/library.json new file mode 100644 index 00000000..982983a3 --- /dev/null +++ b/library.json @@ -0,0 +1,16 @@ +{ + "name": "MeshCore", + "version" : "1.7.4", + "dependencies": { + "SPI": "*", + "Wire": "*", + "jgromes/RadioLib": "^7.1.2", + "rweather/Crypto": "^0.4.0", + "adafruit/RTClib": "^2.1.3", + "melopero/Melopero RV3028": "^1.1.0", + "electroniccats/CayenneLPP": "1.4.0" + }, + "build": { + "extraScript": "build_as_lib.py" + } +} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 02190102..e935d77e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -47,6 +47,7 @@ build_src_filter = +<*.cpp> + + + + ; ----------------- ESP32 --------------------- @@ -114,12 +115,14 @@ build_flags = -D ENV_INCLUDE_LPS22HB=1 -D ENV_INCLUDE_INA3221=1 -D ENV_INCLUDE_INA219=1 + -D ENV_INCLUDE_INA226=1 -D ENV_INCLUDE_INA260=1 -D ENV_INCLUDE_MLX90614=1 -D ENV_INCLUDE_VL53L0X=1 lib_deps = adafruit/Adafruit INA3221 Library @ ^1.0.1 adafruit/Adafruit INA219 @ ^1.2.3 + robtillaart/INA226 @ ^0.6.4 adafruit/Adafruit INA260 Library @ ^1.5.3 adafruit/Adafruit AHTX0 @ ^2.0.5 adafruit/Adafruit BME280 Library @ ^2.3.0 diff --git a/src/helpers/esp32/SerialBLEInterface.cpp b/src/helpers/esp32/SerialBLEInterface.cpp index 8a8710a7..1be703a8 100644 --- a/src/helpers/esp32/SerialBLEInterface.cpp +++ b/src/helpers/esp32/SerialBLEInterface.cpp @@ -83,6 +83,7 @@ void SerialBLEInterface::onConnect(BLEServer* pServer) { void SerialBLEInterface::onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param) { BLE_DEBUG_PRINTLN("onConnect(), conn_id=%d, mtu=%d", param->connect.conn_id, pServer->getPeerMTU(param->connect.conn_id)); + last_conn_id = param->connect.conn_id; } void SerialBLEInterface::onMtuChanged(BLEServer* pServer, esp_ble_gatts_cb_param_t* param) { @@ -143,6 +144,7 @@ void SerialBLEInterface::disable() { BLE_DEBUG_PRINTLN("SerialBLEInterface::disable"); pServer->getAdvertising()->stop(); + pServer->disconnect(last_conn_id); pService->stop(); oldDeviceConnected = deviceConnected = false; adv_restart_time = 0; diff --git a/src/helpers/esp32/SerialBLEInterface.h b/src/helpers/esp32/SerialBLEInterface.h index bf1eee09..29ad897a 100644 --- a/src/helpers/esp32/SerialBLEInterface.h +++ b/src/helpers/esp32/SerialBLEInterface.h @@ -13,6 +13,7 @@ class SerialBLEInterface : public BaseSerialInterface, BLESecurityCallbacks, BLE bool deviceConnected; bool oldDeviceConnected; bool _isEnabled; + uint16_t last_conn_id; uint32_t _pin_code; unsigned long _last_write; unsigned long adv_restart_time; @@ -56,6 +57,7 @@ public: adv_restart_time = 0; _isEnabled = false; _last_write = 0; + last_conn_id = 0; send_queue_len = recv_queue_len = 0; } diff --git a/src/helpers/nrf52/SerialBLEInterface.cpp b/src/helpers/nrf52/SerialBLEInterface.cpp index a8c11d97..170a7331 100644 --- a/src/helpers/nrf52/SerialBLEInterface.cpp +++ b/src/helpers/nrf52/SerialBLEInterface.cpp @@ -115,6 +115,20 @@ void SerialBLEInterface::enable() { void SerialBLEInterface::disable() { _isEnabled = false; BLE_DEBUG_PRINTLN("SerialBLEInterface::disable"); + +#ifdef RAK_BOARD + Bluefruit.disconnect(Bluefruit.connHandle()); +#else + uint16_t conn_id; + if (Bluefruit.getConnectedHandles(&conn_id, 1) > 0) { + Bluefruit.disconnect(conn_id); + } +#endif + + Bluefruit.Advertising.restartOnDisconnect(false); + Bluefruit.Advertising.stop(); + Bluefruit.Advertising.clearData(); + stopAdv(); } diff --git a/src/helpers/nrf52/T114Board.h b/src/helpers/nrf52/T114Board.h index 154ccb22..cd58134d 100644 --- a/src/helpers/nrf52/T114Board.h +++ b/src/helpers/nrf52/T114Board.h @@ -60,5 +60,9 @@ public: NVIC_SystemReset(); } + void powerOff() override { + sd_power_system_off(); + } + bool startOTAUpdate(const char* id, char reply[]) override; }; diff --git a/src/helpers/nrf52/TechoBoard.h b/src/helpers/nrf52/TechoBoard.h index c8ef7006..2c05c4ed 100644 --- a/src/helpers/nrf52/TechoBoard.h +++ b/src/helpers/nrf52/TechoBoard.h @@ -43,6 +43,25 @@ public: return "LilyGo T-Echo"; } + void powerOff() override { + #ifdef LED_RED + digitalWrite(LED_RED, LOW); + #endif + #ifdef LED_GREEN + digitalWrite(LED_GREEN, LOW); + #endif + #ifdef LED_BLUE + digitalWrite(LED_BLUE, LOW); + #endif + #ifdef DISP_BACKLIGHT + digitalWrite(DISP_BACKLIGHT, LOW); + #endif + #ifdef PIN_PWR_EN + digitalWrite(PIN_PWR_EN, LOW); + #endif + sd_power_system_off(); + } + void reboot() override { NVIC_SystemReset(); } diff --git a/src/helpers/nrf52/ThinkNodeM1Board.h b/src/helpers/nrf52/ThinkNodeM1Board.h index 97334bd3..c1ffcbbf 100644 --- a/src/helpers/nrf52/ThinkNodeM1Board.h +++ b/src/helpers/nrf52/ThinkNodeM1Board.h @@ -55,4 +55,8 @@ public: void reboot() override { NVIC_SystemReset(); } + + void powerOff() override { + sd_power_system_off(); + } }; diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 0f3289b8..f444b67b 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -65,6 +65,14 @@ static Adafruit_INA219 INA219(TELEM_INA219_ADDRESS); static Adafruit_INA260 INA260; #endif +#if ENV_INCLUDE_INA226 +#define TELEM_INA226_ADDRESS 0x44 +#define TELEM_INA226_SHUNT_VALUE 0.100 +#define TELEM_INA226_MAX_AMP 0.8 +#include +static INA226 INA226(TELEM_INA226_ADDRESS); +#endif + #if ENV_INCLUDE_MLX90614 #define TELEM_MLX90614_ADDRESS 0x5A // MLX90614 IR temperature sensor I2C address #include @@ -202,6 +210,17 @@ bool EnvironmentSensorManager::begin() { } #endif + #if ENV_INCLUDE_INA226 + if (INA226.begin()) { + MESH_DEBUG_PRINTLN("Found INA226 at address: %02X", TELEM_INA226_ADDRESS); + INA226.setMaxCurrentShunt(TELEM_INA226_MAX_AMP, TELEM_INA226_SHUNT_VALUE); + INA226_initialized = true; + } else { + INA226_initialized = false; + MESH_DEBUG_PRINTLN("INA226 was not found at I2C address %02X", TELEM_INA226_ADDRESS); + } + #endif + #if ENV_INCLUDE_MLX90614 if (MLX90614.begin(TELEM_MLX90614_ADDRESS, TELEM_WIRE)) { MESH_DEBUG_PRINTLN("Found MLX90614 at address: %02X", TELEM_MLX90614_ADDRESS); @@ -323,6 +342,15 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen } #endif + #if ENV_INCLUDE_INA226 + if (INA226_initialized) { + telemetry.addVoltage(next_available_channel, INA226.getBusVoltage()); + telemetry.addCurrent(next_available_channel, INA226.getCurrent_mA() / 1000.0); + telemetry.addPower(next_available_channel, INA226.getPower_mW() / 1000.0); + next_available_channel++; + } + #endif + #if ENV_INCLUDE_MLX90614 if (MLX90614_initialized) { telemetry.addTemperature(TELEM_CHANNEL_SELF, MLX90614.readObjectTempC()); diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index bb0fd2b9..3302d6f6 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -14,6 +14,7 @@ protected: bool INA3221_initialized = false; bool INA219_initialized = false; bool INA260_initialized = false; + bool INA226_initialized = false; bool SHTC3_initialized = false; bool LPS22HB_initialized = false; bool MLX90614_initialized = false; diff --git a/src/helpers/ui/DisplayDriver.h b/src/helpers/ui/DisplayDriver.h index 2d8b69c1..d81d99fb 100644 --- a/src/helpers/ui/DisplayDriver.h +++ b/src/helpers/ui/DisplayDriver.h @@ -21,9 +21,15 @@ public: virtual void setColor(Color c) = 0; virtual void setCursor(int x, int y) = 0; virtual void print(const char* str) = 0; + virtual void printWordWrap(const char* str, int max_width) { print(str); } // fallback to basic print() if no override virtual void fillRect(int x, int y, int w, int h) = 0; virtual void drawRect(int x, int y, int w, int h) = 0; virtual void drawXbm(int x, int y, const uint8_t* bits, int w, int h) = 0; virtual uint16_t getTextWidth(const char* str) = 0; + virtual void drawTextCentered(int mid_x, int y, const char* str) { // helper method (override to optimise) + int w = getTextWidth(str); + setCursor(mid_x - w/2, y); + print(str); + } virtual void endFrame() = 0; }; diff --git a/src/helpers/ui/GxEPDDisplay.cpp b/src/helpers/ui/GxEPDDisplay.cpp index 875e29ac..ace25460 100644 --- a/src/helpers/ui/GxEPDDisplay.cpp +++ b/src/helpers/ui/GxEPDDisplay.cpp @@ -29,8 +29,8 @@ void GxEPDDisplay::turnOn() { if (!_init) begin(); #if DISP_BACKLIGHT digitalWrite(DISP_BACKLIGHT, HIGH); - _isOn = true; #endif + _isOn = true; } void GxEPDDisplay::turnOff() { @@ -47,6 +47,7 @@ void GxEPDDisplay::clear() { void GxEPDDisplay::startFrame(Color bkg) { display.fillScreen(GxEPD_WHITE); + display.setTextColor(_curr_color = GxEPD_BLACK); } void GxEPDDisplay::setTextSize(int sz) { @@ -67,7 +68,12 @@ void GxEPDDisplay::setTextSize(int sz) { } void GxEPDDisplay::setColor(Color c) { - display.setTextColor(GxEPD_BLACK); + // colours need to be inverted for epaper displays + if (c == DARK) { + display.setTextColor(_curr_color = GxEPD_WHITE); + } else { + display.setTextColor(_curr_color = GxEPD_BLACK); + } } void GxEPDDisplay::setCursor(int x, int y) { @@ -79,11 +85,11 @@ void GxEPDDisplay::print(const char* str) { } void GxEPDDisplay::fillRect(int x, int y, int w, int h) { - display.fillRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, GxEPD_BLACK); + display.fillRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color); } void GxEPDDisplay::drawRect(int x, int y, int w, int h) { - display.drawRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, GxEPD_BLACK); + display.drawRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color); } void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) { @@ -116,7 +122,7 @@ void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) { // If the bit is set, draw a block of pixels if (bitSet) { // Draw the block as a filled rectangle - display.fillRect(x1, y1, block_w, block_h, GxEPD_BLACK); + display.fillRect(x1, y1, block_w, block_h, _curr_color); } } } @@ -126,7 +132,7 @@ uint16_t GxEPDDisplay::getTextWidth(const char* str) { int16_t x1, y1; uint16_t w, h; display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h); - return w / SCALE_X; + return ceil((w + 1) / SCALE_X); } void GxEPDDisplay::endFrame() { diff --git a/src/helpers/ui/GxEPDDisplay.h b/src/helpers/ui/GxEPDDisplay.h index ec2bcec0..49746dee 100644 --- a/src/helpers/ui/GxEPDDisplay.h +++ b/src/helpers/ui/GxEPDDisplay.h @@ -28,6 +28,7 @@ class GxEPDDisplay : public DisplayDriver { GxEPD2_BW display; bool _init = false; bool _isOn = false; + uint16_t _curr_color; public: // there is a margin in y... diff --git a/src/helpers/ui/MomentaryButton.cpp b/src/helpers/ui/MomentaryButton.cpp new file mode 100644 index 00000000..9ddf1327 --- /dev/null +++ b/src/helpers/ui/MomentaryButton.cpp @@ -0,0 +1,75 @@ +#include "MomentaryButton.h" + +MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse, bool pulldownup) { + _pin = pin; + _reverse = reverse; + _pull = pulldownup; + down_at = 0; + prev = _reverse ? HIGH : LOW; + cancel = 0; + _long_millis = long_press_millis; +} + +void MomentaryButton::begin() { + if (_pin >= 0) { + pinMode(_pin, _pull ? (_reverse ? INPUT_PULLUP : INPUT_PULLDOWN) : INPUT); + } +} + +bool MomentaryButton::isPressed() const { + return isPressed(digitalRead(_pin)); +} + +void MomentaryButton::cancelClick() { + cancel = 1; +} + +bool MomentaryButton::isPressed(int level) const { + if (_reverse) { + return level == LOW; + } else { + return level != LOW; + } +} + +int MomentaryButton::check(bool repeat_click) { + if (_pin < 0) return BUTTON_EVENT_NONE; + + int event = BUTTON_EVENT_NONE; + int btn = digitalRead(_pin); + if (btn != prev) { + if (isPressed(btn)) { + down_at = millis(); + } else { + // button UP + if (_long_millis > 0) { + if (down_at > 0 && (unsigned long)(millis() - down_at) < _long_millis) { // only a CLICK if still within the long_press millis + event = BUTTON_EVENT_CLICK; + } + } else { + event = BUTTON_EVENT_CLICK; // any UP results in CLICK event when NOT using long_press feature + } + if (event == BUTTON_EVENT_CLICK && cancel) { + event = BUTTON_EVENT_NONE; + } + down_at = 0; + } + prev = btn; + } + if (!isPressed(btn) && cancel) { // always clear the pending 'cancel' once button is back in UP state + cancel = 0; + } + + if (_long_millis > 0 && down_at > 0 && (unsigned long)(millis() - down_at) >= _long_millis) { + event = BUTTON_EVENT_LONG_PRESS; + down_at = 0; + } + if (down_at > 0 && repeat_click) { + unsigned long diff = (unsigned long)(millis() - down_at); + if (diff >= 700) { + event = BUTTON_EVENT_CLICK; // wait 700 millis before repeating the click events + } + } + + return event; +} \ No newline at end of file diff --git a/src/helpers/ui/MomentaryButton.h b/src/helpers/ui/MomentaryButton.h new file mode 100644 index 00000000..0bcc776c --- /dev/null +++ b/src/helpers/ui/MomentaryButton.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +#define BUTTON_EVENT_NONE 0 +#define BUTTON_EVENT_CLICK 1 +#define BUTTON_EVENT_LONG_PRESS 2 + +class MomentaryButton { + int8_t _pin; + int8_t prev, cancel; + bool _reverse, _pull; + int _long_millis; + unsigned long down_at; + + bool isPressed(int level) const; + +public: + MomentaryButton(int8_t pin, int long_press_mills=0, bool reverse=false, bool pulldownup=false); + void begin(); + int check(bool repeat_click=false); // returns one of BUTTON_EVENT_* + void cancelClick(); // suppress next BUTTON_EVENT_CLICK (if already in DOWN state) + uint8_t getPin() { return _pin; } + bool isPressed() const; +}; diff --git a/src/helpers/ui/ST7789Display.cpp b/src/helpers/ui/ST7789Display.cpp index 6a91457a..7ea35187 100644 --- a/src/helpers/ui/ST7789Display.cpp +++ b/src/helpers/ui/ST7789Display.cpp @@ -73,6 +73,9 @@ void ST7789Display::clear() { void ST7789Display::startFrame(Color bkg) { display.clear(); + _color = ST77XX_WHITE; + display.setRGB(_color); + display.setFont(ArialMT_Plain_16); } void ST7789Display::setTextSize(int sz) { @@ -92,7 +95,9 @@ void ST7789Display::setColor(Color c) { switch (c) { case DisplayDriver::DARK : _color = ST77XX_BLACK; + display.setColor(OLEDDISPLAY_COLOR::BLACK); break; +#if 0 case DisplayDriver::LIGHT : _color = ST77XX_WHITE; break; @@ -111,8 +116,10 @@ void ST7789Display::setColor(Color c) { case DisplayDriver::ORANGE : _color = ST77XX_ORANGE; break; +#endif default: _color = ST77XX_WHITE; + display.setColor(OLEDDISPLAY_COLOR::WHITE); break; } display.setRGB(_color); @@ -127,6 +134,10 @@ void ST7789Display::print(const char* str) { display.drawString(_x, _y, str); } +void ST7789Display::printWordWrap(const char* str, int max_width) { + display.drawStringMaxWidth(_x, _y, max_width*SCALE_X, str); +} + void ST7789Display::fillRect(int x, int y, int w, int h) { display.fillRect(x*SCALE_X + X_OFFSET, y*SCALE_Y + Y_OFFSET, w*SCALE_X, h*SCALE_Y); } diff --git a/src/helpers/ui/ST7789Display.h b/src/helpers/ui/ST7789Display.h index 0f7ff71b..cb56ff8a 100644 --- a/src/helpers/ui/ST7789Display.h +++ b/src/helpers/ui/ST7789Display.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include "ST7789Spi.h" class ST7789Display : public DisplayDriver { ST7789Spi display; @@ -30,6 +30,7 @@ public: void setColor(Color c) override; void setCursor(int x, int y) override; void print(const char* str) override; + void printWordWrap(const char* str, int max_width) override; void fillRect(int x, int y, int w, int h) override; void drawRect(int x, int y, int w, int h) override; void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override; diff --git a/src/helpers/ui/UIScreen.h b/src/helpers/ui/UIScreen.h new file mode 100644 index 00000000..6faa591a --- /dev/null +++ b/src/helpers/ui/UIScreen.h @@ -0,0 +1,21 @@ +#pragma once + +#include "DisplayDriver.h" + +#define KEY_LEFT 0xB4 +#define KEY_UP 0xB5 +#define KEY_DOWN 0xB6 +#define KEY_RIGHT 0xB7 +#define KEY_SELECT 10 +#define KEY_ENTER 13 +#define KEY_BACK 27 // Esc + +class UIScreen { +protected: + UIScreen() { } +public: + virtual int render(DisplayDriver& display) =0; // return value is number of millis until next render + virtual bool handleInput(char c) { return false; } + virtual void poll() { } +}; + diff --git a/variants/generic_espnow/platformio.ini b/variants/generic_espnow/platformio.ini index dbc902f0..cf3e4c94 100644 --- a/variants/generic_espnow/platformio.ini +++ b/variants/generic_espnow/platformio.ini @@ -60,7 +60,7 @@ build_flags = ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 ; NOTE: DO NOT ENABLE --> -D ESPNOW_DEBUG_LOGGING=1 build_src_filter = ${Generic_ESPNOW.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Generic_ESPNOW.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_ct62/platformio.ini b/variants/heltec_ct62/platformio.ini index ec24cdcd..9721d037 100644 --- a/variants/heltec_ct62/platformio.ini +++ b/variants/heltec_ct62/platformio.ini @@ -61,7 +61,7 @@ build_flags = ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_ct62.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Heltec_ct62.lib_deps} ${esp32_ota.lib_deps} @@ -80,7 +80,7 @@ build_flags = ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_ct62.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + lib_deps = ${Heltec_ct62.lib_deps} diff --git a/variants/heltec_mesh_solar/platformio.ini b/variants/heltec_mesh_solar/platformio.ini index 5cd8af86..9fd3edd5 100644 --- a/variants/heltec_mesh_solar/platformio.ini +++ b/variants/heltec_mesh_solar/platformio.ini @@ -68,7 +68,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_mesh_solar.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Heltec_mesh_solar.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -85,7 +85,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_mesh_solar.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Heltec_mesh_solar.lib_deps} densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/variants/heltec_tracker/platformio.ini b/variants/heltec_tracker/platformio.ini index 8d9013a5..357ab854 100644 --- a/variants/heltec_tracker/platformio.ini +++ b/variants/heltec_tracker/platformio.ini @@ -39,6 +39,7 @@ extends = Heltec_tracker_base build_flags = ${Heltec_tracker_base.build_flags} -I src/helpers/ui + -I examples/companion_radio/ui-new -D ARDUINO_USB_CDC_ON_BOOT=1 ; need for Serial -D DISPLAY_ROTATION=1 -D DISPLAY_CLASS=ST7735Display @@ -51,7 +52,9 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_tracker_base.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> + lib_deps = ${Heltec_tracker_base.lib_deps} diff --git a/variants/heltec_tracker/target.cpp b/variants/heltec_tracker/target.cpp index f41702c5..5ba9a8fb 100644 --- a/variants/heltec_tracker/target.cpp +++ b/variants/heltec_tracker/target.cpp @@ -21,6 +21,7 @@ HWTSensorManager sensors = HWTSensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display(&board.periph_power); // peripheral power pin is shared + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/heltec_tracker/target.h b/variants/heltec_tracker/target.h index c08be80a..8ac5eb72 100644 --- a/variants/heltec_tracker/target.h +++ b/variants/heltec_tracker/target.h @@ -10,6 +10,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif class HWTSensorManager : public SensorManager { @@ -36,6 +37,7 @@ extern HWTSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/heltec_v2/platformio.ini b/variants/heltec_v2/platformio.ini index 43bc43ad..ea41f845 100644 --- a/variants/heltec_v2/platformio.ini +++ b/variants/heltec_v2/platformio.ini @@ -35,6 +35,7 @@ build_flags = build_src_filter = ${Heltec_lora32_v2.build_src_filter} +<../examples/simple_repeater> + + + lib_deps = ${Heltec_lora32_v2.lib_deps} ${esp32_ota.lib_deps} @@ -53,6 +54,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + + +<../examples/simple_room_server> lib_deps = ${Heltec_lora32_v2.lib_deps} @@ -76,6 +78,7 @@ lib_deps = extends = Heltec_lora32_v2 build_flags = ${Heltec_lora32_v2.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SSD1306Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 @@ -84,7 +87,9 @@ build_flags = build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_lora32_v2.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -93,6 +98,7 @@ lib_deps = extends = Heltec_lora32_v2 build_flags = ${Heltec_lora32_v2.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SSD1306Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 @@ -104,7 +110,9 @@ build_flags = build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_lora32_v2.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_v2/target.cpp b/variants/heltec_v2/target.cpp index 418f1f7f..df71d3f4 100644 --- a/variants/heltec_v2/target.cpp +++ b/variants/heltec_v2/target.cpp @@ -18,6 +18,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/heltec_v2/target.h b/variants/heltec_v2/target.h index 0c330316..2e5b17de 100644 --- a/variants/heltec_v2/target.h +++ b/variants/heltec_v2/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern HeltecV2Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 08eb500e..24bc0bf0 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -6,6 +6,7 @@ build_flags = ${sensor_base.build_flags} -I variants/heltec_v3 -D HELTEC_LORA_V3 + -D ESP32_CPU_FREQ=80 -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 @@ -16,7 +17,7 @@ build_flags = -D PIN_VEXT_EN=36 -D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO3_TCXO_VOLTAGE=1.8 - -D SX126X_CURRENT_LIMIT=140 + -D SX126X_CURRENT_LIMIT=160 -D SX126X_RX_BOOSTED_GAIN=1 -D PIN_GPS_RX=47 -D PIN_GPS_TX=48 @@ -46,6 +47,7 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter} lib_deps = ${Heltec_lora32_v3.lib_deps} ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 [env:Heltec_v3_room_server] extends = Heltec_lora32_v3 @@ -84,6 +86,7 @@ lib_deps = extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display @@ -91,7 +94,9 @@ build_flags = ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_lora32_v3.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -100,18 +105,22 @@ lib_deps = extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} - -D MAX_CONTACTS=100 + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=160 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display -D BLE_PIN_CODE=123456 ; dynamic, random PIN + -D AUTO_SHUTDOWN_MILLIVOLTS=3400 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_lora32_v3.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -130,6 +139,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + +<../examples/companion_radio> lib_deps = @@ -172,6 +182,7 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter} lib_deps = ${Heltec_lora32_v3.lib_deps} ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 [env:Heltec_WSL3_room_server] extends = Heltec_lora32_v3 @@ -203,7 +214,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Heltec_lora32_v3.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -217,7 +228,7 @@ build_flags = ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Heltec_lora32_v3.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_v3/target.cpp b/variants/heltec_v3/target.cpp index 4cbc78fb..78b88197 100644 --- a/variants/heltec_v3/target.cpp +++ b/variants/heltec_v3/target.cpp @@ -25,6 +25,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/heltec_v3/target.h b/variants/heltec_v3/target.h index 992a3d2c..b2125664 100644 --- a/variants/heltec_v3/target.h +++ b/variants/heltec_v3/target.h @@ -10,6 +10,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern HeltecV3Board board; @@ -19,6 +20,7 @@ extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/ikoka_stick_nrf/ikoka_stick_nrf_board.h b/variants/ikoka_stick_nrf/ikoka_stick_nrf_board.h index a5f33b01..c66f4827 100644 --- a/variants/ikoka_stick_nrf/ikoka_stick_nrf_board.h +++ b/variants/ikoka_stick_nrf/ikoka_stick_nrf_board.h @@ -5,20 +5,6 @@ #ifdef XIAO_NRF52 -// redefine lora pins if using the S3 variant of SX1262 board -#ifdef SX1262_XIAO_S3_VARIANT - #undef P_LORA_DIO_1 - #undef P_LORA_BUSY - #undef P_LORA_RESET - #undef P_LORA_NSS - #undef SX126X_RXEN - #define P_LORA_DIO_1 D0 - #define P_LORA_BUSY D1 - #define P_LORA_RESET D2 - #define P_LORA_NSS D3 - #define SX126X_RXEN D4 -#endif - class ikoka_stick_nrf_board : public mesh::MainBoard { protected: uint8_t startup_reason; diff --git a/variants/ikoka_stick_nrf/platformio.ini b/variants/ikoka_stick_nrf/platformio.ini index 3e62b5e7..6e6ae101 100644 --- a/variants/ikoka_stick_nrf/platformio.ini +++ b/variants/ikoka_stick_nrf/platformio.ini @@ -19,11 +19,10 @@ lib_deps = adafruit/Adafruit INA3221 Library @ ^1.0.1 adafruit/Adafruit INA219 @ ^1.2.3 adafruit/Adafruit AHTX0 @ ^2.0.5 - adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BME280 Library @ ^2.3.0 adafruit/Adafruit SSD1306 @ ^2.5.13 - -[ikoka_stick_nrf] +[ikoka_stick_nrf_baseboard] extends = nrf52840_xiao ;board_build.ldscript = boards/nrf52840_s140_v7.ld build_flags = ${nrf52840_xiao.build_flags} @@ -34,7 +33,6 @@ build_flags = ${nrf52840_xiao.build_flags} -D DISPLAY_ROTATION=2 -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=9 -D P_LORA_DIO_1=D1 -D P_LORA_RESET=D2 -D P_LORA_BUSY=D3 @@ -52,57 +50,96 @@ build_flags = ${nrf52840_xiao.build_flags} -D ENV_INCLUDE_BME280=1 -D ENV_INCLUDE_INA3221=1 -D ENV_INCLUDE_INA219=1 -build_src_filter = ${nrf52840_xiao.build_src_filter} - + - + - + - +<../variants/ikoka_stick_nrf> debug_tool = jlink upload_protocol = nrfutil -[env:ikoka_stick_nrf_companion_radio_ble] -extends = ikoka_stick_nrf + +;;; abstracted hardware variants + +[ikoka_stick_nrf_e22_22dbm] +extends = ikoka_stick_nrf_baseboard +; No PA in this model, full 22dBm build_flags = - ${ikoka_stick_nrf.build_flags} + ${ikoka_stick_nrf_baseboard.build_flags} + -D LORA_TX_POWER=22 +build_src_filter = ${nrf52840_xiao.build_src_filter} + + + + + + + + + +<../variants/ikoka_stick_nrf> + +[ikoka_stick_nrf_e22_30dbm] +extends = ikoka_stick_nrf_baseboard +; limit txpower to 20dBm on E22-900M30S. Anything higher will +; cause distortion in the PA output. 20dBm in -> 30dBm out +build_flags = + ${ikoka_stick_nrf_baseboard.build_flags} + -D LORA_TX_POWER=20 +build_src_filter = ${nrf52840_xiao.build_src_filter} + + + + + + + + + +<../variants/ikoka_stick_nrf> + +[ikoka_stick_nrf_e22_33dbm] +extends = ikoka_stick_nrf_baseboard +; limit txpower to 9dBm on E22-900M33S to avoid hardware damage +; to the rf amplifier frontend. 9dBm in -> 33dBm out +build_flags = + ${ikoka_stick_nrf_baseboard.build_flags} + -D LORA_TX_POWER=9 +build_src_filter = ${nrf52840_xiao.build_src_filter} + + + + + + + + + +<../variants/ikoka_stick_nrf> + +;;; abstracted firmware roles + +[ikoka_stick_nrf_companion_radio_ble] +extends = ikoka_stick_nrf_baseboard +build_flags = + ${ikoka_stick_nrf_baseboard.build_flags} -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D OFFLINE_QUEUE_SIZE=256 + -I examples/companion_radio/ui-new ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 -build_src_filter = ${ikoka_stick_nrf.build_src_filter} +build_src_filter = ${ikoka_stick_nrf_baseboard.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = - ${ikoka_stick_nrf.lib_deps} + ${ikoka_stick_nrf_baseboard.lib_deps} densaugeo/base64 @ ~1.4.0 -[env:ikoka_stick_nrf_companion_radio_usb] -extends = ikoka_stick_nrf +[ikoka_stick_nrf_companion_radio_usb] +extends = ikoka_stick_nrf_baseboard build_flags = - ${ikoka_stick_nrf.build_flags} + ${ikoka_stick_nrf_baseboard.build_flags} -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 + -I examples/companion_radio/ui-new ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 -build_src_filter = ${ikoka_stick_nrf.build_src_filter} +build_src_filter = ${ikoka_stick_nrf_baseboard.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = - ${ikoka_stick_nrf.lib_deps} + ${ikoka_stick_nrf_baseboard.lib_deps} densaugeo/base64 @ ~1.4.0 -[env:ikoka_stick_nrf_alt_pinout_companion_radio_ble] -extends = env:ikoka_stick_nrf_companion_radio_ble +[ikoka_stick_nrf_repeater] +extends = ikoka_stick_nrf_baseboard build_flags = - ${env:ikoka_stick_nrf_companion_radio_ble.build_flags} - -D SX1262_XIAO_S3_VARIANT - -[env:ikoka_stick_nrf_repeater] -extends = ikoka_stick_nrf -build_flags = - ${ikoka_stick_nrf.build_flags} + ${ikoka_stick_nrf_baseboard.build_flags} -D ADVERT_NAME='"Ikoka Stick Repeater"' -D ADVERT_LAT=0.0 -D ADVERT_LON=0.0 @@ -110,24 +147,161 @@ build_flags = -D MAX_NEIGHBOURS=8 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 -build_src_filter = ${ikoka_stick_nrf.build_src_filter} - +<../examples/simple_repeater/main.cpp> +build_src_filter = ${ikoka_stick_nrf_baseboard.build_src_filter} + + + +<../examples/simple_repeater/*.cpp> -[env:ikoka_stick_nrf_alt_pinout_repeater] -extends = env:ikoka_stick_nrf_repeater +[ikoka_stick_nrf_room_server] +extends = ikoka_stick_nrf_baseboard build_flags = - ${env:ikoka_stick_nrf_repeater.build_flags} - -D SX1262_XIAO_S3_VARIANT - -[env:ikoka_stick_nrf_room_server] -extends = ikoka_stick_nrf -build_flags = - ${ikoka_stick_nrf.build_flags} + ${ikoka_stick_nrf_baseboard.build_flags} -D ADVERT_NAME='"Ikoka Stick Room"' -D ADVERT_LAT=0.0 -D ADVERT_LON=0.0 -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 -build_src_filter = ${ikoka_stick_nrf.build_src_filter} - +<../examples/simple_room_server/main.cpp> +build_src_filter = ${ikoka_stick_nrf_baseboard.build_src_filter} + +<../examples/simple_room_server/*.cpp> + +;;; hardware + firmware variants + +;;; 22dBm EBYTE E22-900M22 variants + +[env:ikoka_stick_nrf_22dbm_companion_radio_usb] +extends = + ikoka_stick_nrf_e22_22dbm + ikoka_stick_nrf_companion_radio_usb +build_flags = + ${ikoka_stick_nrf_companion_radio_usb.build_flags} + ${ikoka_stick_nrf_e22_22dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_companion_radio_usb.build_src_filter} + ${ikoka_stick_nrf_e22_22dbm.build_src_filter} + +[env:ikoka_stick_nrf_22dbm_companion_radio_ble] +extends = + ikoka_stick_nrf_e22_22dbm + ikoka_stick_nrf_companion_radio_ble +build_flags = + ${ikoka_stick_nrf_companion_radio_ble.build_flags} + ${ikoka_stick_nrf_e22_22dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_companion_radio_ble.build_src_filter} + ${ikoka_stick_nrf_e22_22dbm.build_src_filter} + +[env:ikoka_stick_nrf_22dbm_repeater] +extends = + ikoka_stick_nrf_e22_22dbm + ikoka_stick_nrf_repeater +build_flags = + ${ikoka_stick_nrf_repeater.build_flags} + ${ikoka_stick_nrf_e22_22dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_repeater.build_src_filter} + ${ikoka_stick_nrf_e22_22dbm.build_src_filter} + +[env:ikoka_stick_nrf_22dbm_room_server] +extends = + ikoka_stick_nrf_e22_22dbm + ikoka_stick_nrf_room_server +build_flags = + ${ikoka_stick_nrf_room_server.build_flags} + ${ikoka_stick_nrf_e22_22dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_room_server.build_src_filter} + ${ikoka_stick_nrf_e22_22dbm.build_src_filter} + + +;;; 30dBm EBYTE E22-900M30 variants + +[env:ikoka_stick_nrf_30dbm_companion_radio_usb] +extends = + ikoka_stick_nrf_e22_30dbm + ikoka_stick_nrf_companion_radio_usb +build_flags = + ${ikoka_stick_nrf_companion_radio_usb.build_flags} + ${ikoka_stick_nrf_e22_30dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_companion_radio_usb.build_src_filter} + ${ikoka_stick_nrf_e22_30dbm.build_src_filter} + +[env:ikoka_stick_nrf_30dbm_companion_radio_ble] +extends = + ikoka_stick_nrf_e22_30dbm + ikoka_stick_nrf_companion_radio_ble +build_flags = + ${ikoka_stick_nrf_companion_radio_ble.build_flags} + ${ikoka_stick_nrf_e22_30dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_companion_radio_ble.build_src_filter} + ${ikoka_stick_nrf_e22_30dbm.build_src_filter} + +[env:ikoka_stick_nrf_30dbm_repeater] +extends = + ikoka_stick_nrf_e22_30dbm + ikoka_stick_nrf_repeater +build_flags = + ${ikoka_stick_nrf_repeater.build_flags} + ${ikoka_stick_nrf_e22_30dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_repeater.build_src_filter} + ${ikoka_stick_nrf_e22_30dbm.build_src_filter} + +[env:ikoka_stick_nrf_30dbm_room_server] +extends = + ikoka_stick_nrf_e22_30dbm + ikoka_stick_nrf_room_server +build_flags = + ${ikoka_stick_nrf_room_server.build_flags} + ${ikoka_stick_nrf_e22_30dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_room_server.build_src_filter} + ${ikoka_stick_nrf_e22_30dbm.build_src_filter} + + +;;; 33dBm EBYTE E22-900M33 variants + +[env:ikoka_stick_nrf_33dbm_companion_radio_usb] +extends = + ikoka_stick_nrf_e22_33dbm + ikoka_stick_nrf_companion_radio_usb +build_flags = + ${ikoka_stick_nrf_companion_radio_usb.build_flags} + ${ikoka_stick_nrf_e22_33dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_companion_radio_usb.build_src_filter} + ${ikoka_stick_nrf_e22_33dbm.build_src_filter} + +[env:ikoka_stick_nrf_33dbm_companion_radio_ble] +extends = + ikoka_stick_nrf_e22_33dbm + ikoka_stick_nrf_companion_radio_ble +build_flags = + ${ikoka_stick_nrf_companion_radio_ble.build_flags} + ${ikoka_stick_nrf_e22_33dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_companion_radio_ble.build_src_filter} + ${ikoka_stick_nrf_e22_33dbm.build_src_filter} + +[env:ikoka_stick_nrf_33dbm_repeater] +extends = + ikoka_stick_nrf_e22_33dbm + ikoka_stick_nrf_repeater +build_flags = + ${ikoka_stick_nrf_repeater.build_flags} + ${ikoka_stick_nrf_e22_33dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_repeater.build_src_filter} + ${ikoka_stick_nrf_e22_33dbm.build_src_filter} + +[env:ikoka_stick_nrf_33dbm_room_server] +extends = + ikoka_stick_nrf_e22_33dbm + ikoka_stick_nrf_room_server +build_flags = + ${ikoka_stick_nrf_room_server.build_flags} + ${ikoka_stick_nrf_e22_33dbm.build_flags} +build_src_filter = + ${ikoka_stick_nrf_room_server.build_src_filter} + ${ikoka_stick_nrf_e22_33dbm.build_src_filter} diff --git a/variants/ikoka_stick_nrf/target.cpp b/variants/ikoka_stick_nrf/target.cpp index e50150eb..c2712761 100644 --- a/variants/ikoka_stick_nrf/target.cpp +++ b/variants/ikoka_stick_nrf/target.cpp @@ -6,6 +6,7 @@ ikoka_stick_nrf_board board; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); diff --git a/variants/ikoka_stick_nrf/target.h b/variants/ikoka_stick_nrf/target.h index 758cd019..8311503a 100644 --- a/variants/ikoka_stick_nrf/target.h +++ b/variants/ikoka_stick_nrf/target.h @@ -11,7 +11,9 @@ #ifdef DISPLAY_CLASS #include + #include extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif extern ikoka_stick_nrf_board board; diff --git a/variants/lilygo_t3s3/platformio.ini b/variants/lilygo_t3s3/platformio.ini index f3a95e96..722a3243 100644 --- a/variants/lilygo_t3s3/platformio.ini +++ b/variants/lilygo_t3s3/platformio.ini @@ -89,6 +89,7 @@ lib_deps = extends = LilyGo_T3S3_sx1262 build_flags = ${LilyGo_T3S3_sx1262.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SSD1306Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 @@ -96,7 +97,9 @@ build_flags = ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_T3S3_sx1262.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -105,6 +108,7 @@ lib_deps = extends = LilyGo_T3S3_sx1262 build_flags = ${LilyGo_T3S3_sx1262.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SSD1306Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 @@ -116,7 +120,9 @@ build_flags = build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_T3S3_sx1262.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_t3s3/target.cpp b/variants/lilygo_t3s3/target.cpp index b7c4542c..1c7b3b09 100644 --- a/variants/lilygo_t3s3/target.cpp +++ b/variants/lilygo_t3s3/target.cpp @@ -13,6 +13,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif #ifndef LORA_CR diff --git a/variants/lilygo_t3s3/target.h b/variants/lilygo_t3s3/target.h index b768b2b0..f184c757 100644 --- a/variants/lilygo_t3s3/target.h +++ b/variants/lilygo_t3s3/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern ESP32Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/lilygo_t3s3_sx1276/platformio.ini b/variants/lilygo_t3s3_sx1276/platformio.ini index 74eced9c..8f1c00e4 100644 --- a/variants/lilygo_t3s3_sx1276/platformio.ini +++ b/variants/lilygo_t3s3_sx1276/platformio.ini @@ -88,6 +88,7 @@ extends = LilyGo_T3S3_sx1276 upload_speed = 115200 build_flags = ${LilyGo_T3S3_sx1276.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SSD1306Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 @@ -95,7 +96,9 @@ build_flags = -D MESH_DEBUG=1 build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_T3S3_sx1276.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -104,6 +107,7 @@ lib_deps = extends = LilyGo_T3S3_sx1276 build_flags = ${LilyGo_T3S3_sx1276.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SSD1306Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 @@ -115,7 +119,9 @@ build_flags = build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_T3S3_sx1276.lib_deps} densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/variants/lilygo_t3s3_sx1276/target.cpp b/variants/lilygo_t3s3_sx1276/target.cpp index b2ee4455..042ff206 100644 --- a/variants/lilygo_t3s3_sx1276/target.cpp +++ b/variants/lilygo_t3s3_sx1276/target.cpp @@ -18,6 +18,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/lilygo_t3s3_sx1276/target.h b/variants/lilygo_t3s3_sx1276/target.h index 52ecf867..98a0fe35 100644 --- a/variants/lilygo_t3s3_sx1276/target.h +++ b/variants/lilygo_t3s3_sx1276/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern ESP32Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/lilygo_tbeam_SX1262/platformio.ini b/variants/lilygo_tbeam_SX1262/platformio.ini index eac899f0..7bb008ac 100644 --- a/variants/lilygo_tbeam_SX1262/platformio.ini +++ b/variants/lilygo_tbeam_SX1262/platformio.ini @@ -37,6 +37,7 @@ extends = LilyGo_TBeam_SX1262 board_build.upload.maximum_ram_size=2000000 build_flags = ${LilyGo_TBeam_SX1262.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -49,7 +50,9 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_TBeam_SX1262.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_tbeam_SX1262/target.cpp b/variants/lilygo_tbeam_SX1262/target.cpp index fb05958b..a8caecb3 100644 --- a/variants/lilygo_tbeam_SX1262/target.cpp +++ b/variants/lilygo_tbeam_SX1262/target.cpp @@ -25,6 +25,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/lilygo_tbeam_SX1262/target.h b/variants/lilygo_tbeam_SX1262/target.h index cb9b28df..5f33abb8 100644 --- a/variants/lilygo_tbeam_SX1262/target.h +++ b/variants/lilygo_tbeam_SX1262/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern TBeamBoard board; @@ -18,6 +19,7 @@ extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/lilygo_tbeam_SX1276/platformio.ini b/variants/lilygo_tbeam_SX1276/platformio.ini index 8febe7b3..e0391f1d 100644 --- a/variants/lilygo_tbeam_SX1276/platformio.ini +++ b/variants/lilygo_tbeam_SX1276/platformio.ini @@ -36,6 +36,7 @@ extends = LilyGo_TBeam_SX1276 board_build.upload.maximum_ram_size=2000000 build_flags = ${LilyGo_TBeam_SX1276.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -46,7 +47,9 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_TBeam_SX1276.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_tbeam_SX1276/target.cpp b/variants/lilygo_tbeam_SX1276/target.cpp index 7e2537bb..0a7517a2 100644 --- a/variants/lilygo_tbeam_SX1276/target.cpp +++ b/variants/lilygo_tbeam_SX1276/target.cpp @@ -25,6 +25,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/lilygo_tbeam_SX1276/target.h b/variants/lilygo_tbeam_SX1276/target.h index bcd8cb0b..b382b652 100644 --- a/variants/lilygo_tbeam_SX1276/target.h +++ b/variants/lilygo_tbeam_SX1276/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern TBeamBoard board; @@ -18,6 +19,7 @@ extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini index 5c2d6e86..9b10f459 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini +++ b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini @@ -73,6 +73,7 @@ lib_deps = extends = T_Beam_S3_Supreme_SX1262 build_flags = ${T_Beam_S3_Supreme_SX1262.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -82,7 +83,9 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${T_Beam_S3_Supreme_SX1262.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_tbeam_supreme_SX1262/target.cpp b/variants/lilygo_tbeam_supreme_SX1262/target.cpp index 68d54396..8ad306f1 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/target.cpp +++ b/variants/lilygo_tbeam_supreme_SX1262/target.cpp @@ -5,6 +5,7 @@ TBeamBoard board; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif static SPIClass spi; diff --git a/variants/lilygo_tbeam_supreme_SX1262/target.h b/variants/lilygo_tbeam_supreme_SX1262/target.h index 62a92329..c6ffa0a6 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/target.h +++ b/variants/lilygo_tbeam_supreme_SX1262/target.h @@ -11,6 +11,8 @@ #ifdef DISPLAY_CLASS #include extern DISPLAY_CLASS display; + #include + extern MomentaryButton user_btn; #endif extern TBeamBoard board; diff --git a/variants/lilygo_tlora_c6/platformio.ini b/variants/lilygo_tlora_c6/platformio.ini index 7f89c3da..5aab2213 100644 --- a/variants/lilygo_tlora_c6/platformio.ini +++ b/variants/lilygo_tlora_c6/platformio.ini @@ -79,7 +79,7 @@ build_flags = ${tlora_c6.build_flags} build_src_filter = ${tlora_c6.build_src_filter} + - - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${tlora_c6.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_tlora_v2_1/platformio.ini b/variants/lilygo_tlora_v2_1/platformio.ini index 71b49aab..0ed06856 100644 --- a/variants/lilygo_tlora_v2_1/platformio.ini +++ b/variants/lilygo_tlora_v2_1/platformio.ini @@ -83,13 +83,16 @@ lib_deps = extends = LilyGo_TLora_V2_1_1_6 build_flags = ${LilyGo_TLora_V2_1_1_6.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_TLora_V2_1_1_6.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -98,6 +101,7 @@ lib_deps = extends = LilyGo_TLora_V2_1_1_6 build_flags = ${LilyGo_TLora_V2_1_1_6.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -108,7 +112,9 @@ build_flags = build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_TLora_V2_1_1_6.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_tlora_v2_1/target.cpp b/variants/lilygo_tlora_v2_1/target.cpp index 5e8f15b2..65a78c19 100644 --- a/variants/lilygo_tlora_v2_1/target.cpp +++ b/variants/lilygo_tlora_v2_1/target.cpp @@ -14,6 +14,7 @@ EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/lilygo_tlora_v2_1/target.h b/variants/lilygo_tlora_v2_1/target.h index f05b8055..380d733b 100644 --- a/variants/lilygo_tlora_v2_1/target.h +++ b/variants/lilygo_tlora_v2_1/target.h @@ -10,6 +10,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern LilyGoTLoraBoard board; @@ -19,6 +20,7 @@ extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/meshadventurer/platformio.ini b/variants/meshadventurer/platformio.ini index f8995e18..60cc55eb 100644 --- a/variants/meshadventurer/platformio.ini +++ b/variants/meshadventurer/platformio.ini @@ -78,7 +78,7 @@ lib_deps = [env:Meshadventurer_sx1262_companion_radio_usb] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + build_flags = ${Meshadventurer.build_flags} @@ -96,7 +96,7 @@ lib_deps = [env:Meshadventurer_sx1262_companion_radio_ble] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + + build_flags = @@ -157,7 +157,7 @@ lib_deps = [env:Meshadventurer_sx1268_companion_radio_usb] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + build_flags = ${Meshadventurer.build_flags} @@ -175,7 +175,7 @@ lib_deps = [env:Meshadventurer_sx1268_companion_radio_ble] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + + build_flags = diff --git a/variants/minewsemi_me25ls01/platformio.ini b/variants/minewsemi_me25ls01/platformio.ini index f7265af4..3436062f 100644 --- a/variants/minewsemi_me25ls01/platformio.ini +++ b/variants/minewsemi_me25ls01/platformio.ini @@ -51,6 +51,7 @@ lib_deps = ${nrf52840_me25ls01.lib_deps} [env:Minewsemi_me25ls01_companion_radio_ble] extends = me25ls01 build_flags = ${me25ls01.build_flags} + -I examples/companion_radio/ui-orig -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -66,6 +67,7 @@ build_flags = ${me25ls01.build_flags} build_src_filter = ${me25ls01.build_src_filter} + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> lib_deps = ${me25ls01.lib_deps} adafruit/RTClib @ ^2.1.3 @@ -146,6 +148,7 @@ lib_deps = ${me25ls01.lib_deps} [env:Minewsemi_me25ls01_companion_radio_usb] extends = me25ls01 build_flags = ${me25ls01.build_flags} + -I examples/companion_radio/ui-orig -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 ;-D BLE_PIN_CODE=123456 @@ -158,7 +161,8 @@ build_flags = ${me25ls01.build_flags} -D DISPLAY_CLASS=NullDisplayDriver build_src_filter = ${me25ls01.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> lib_deps = ${me25ls01.lib_deps} adafruit/RTClib @ ^2.1.3 diff --git a/variants/nano_g2_ultra/platformio.ini b/variants/nano_g2_ultra/platformio.ini index 25871fc9..7fb2de28 100644 --- a/variants/nano_g2_ultra/platformio.ini +++ b/variants/nano_g2_ultra/platformio.ini @@ -34,6 +34,7 @@ extends = Nano_G2_Ultra build_flags = ${Nano_G2_Ultra.build_flags} -I src/helpers/ui + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -47,7 +48,9 @@ build_src_filter = ${Nano_G2_Ultra.build_src_filter} + + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Nano_G2_Ultra.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -61,6 +64,7 @@ extends = Nano_G2_Ultra build_flags = ${Nano_G2_Ultra.build_flags} -I src/helpers/ui + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D OFFLINE_QUEUE_SIZE=256 @@ -71,7 +75,9 @@ build_flags = build_src_filter = ${Nano_G2_Ultra.build_src_filter} + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Nano_G2_Ultra.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/nano_g2_ultra/target.cpp b/variants/nano_g2_ultra/target.cpp index b6084236..81e7744f 100644 --- a/variants/nano_g2_ultra/target.cpp +++ b/variants/nano_g2_ultra/target.cpp @@ -1,5 +1,6 @@ -#include #include "target.h" + +#include #include #include @@ -16,29 +17,26 @@ NanoG2UltraSensorManager sensors = NanoG2UltraSensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; +MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif -bool radio_init() -{ +bool radio_init() { rtc_clock.begin(Wire); return radio.std_init(&SPI); } -uint32_t radio_get_rng_seed() -{ +uint32_t radio_get_rng_seed() { return radio.random(0x7FFFFFFF); } -void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) -{ +void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { radio.setFrequency(freq); radio.setSpreadingFactor(sf); radio.setBandwidth(bw); radio.setCodingRate(cr); } -void radio_set_tx_power(uint8_t dbm) -{ +void radio_set_tx_power(uint8_t dbm) { radio.setOutputPower(dbm); } @@ -64,8 +62,7 @@ void NanoG2UltraSensorManager::stop_gps() { _location->stop(); } -bool NanoG2UltraSensorManager::begin() -{ +bool NanoG2UltraSensorManager::begin() { digitalWrite(PIN_GPS_STANDBY, HIGH); // Wake GPS from standby Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX); Serial1.begin(9600); @@ -83,29 +80,26 @@ bool NanoG2UltraSensorManager::begin() return true; } -bool NanoG2UltraSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP &telemetry) -{ - if (requester_permissions & TELEM_PERM_LOCATION) - { // does requester have permission? +bool NanoG2UltraSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP &telemetry) { + if (requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission? telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude); } return true; } -void NanoG2UltraSensorManager::loop() -{ +void NanoG2UltraSensorManager::loop() { static long next_gps_update = 0; if (!gps_active) { - return; // GPS is not active, skip further processing + return; // GPS is not active, skip further processing } _location->loop(); if (millis() > next_gps_update) { if (_location->isValid()) { - node_lat = ((double)_location->getLatitude())/1000000.; - node_lon = ((double)_location->getLongitude())/1000000.; + node_lat = ((double)_location->getLatitude()) / 1000000.; + node_lon = ((double)_location->getLongitude()) / 1000000.; node_altitude = ((double)_location->getAltitude()) / 1000.0; MESH_DEBUG_PRINTLN("VALID location: lat %f lon %f", node_lat, node_lon); } else { @@ -116,24 +110,22 @@ void NanoG2UltraSensorManager::loop() } } -int NanoG2UltraSensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch) +int NanoG2UltraSensorManager::getNumSettings() const { + return 1; +} // just one supported: "gps" (power switch) -const char *NanoG2UltraSensorManager::getSettingName(int i) const -{ +const char *NanoG2UltraSensorManager::getSettingName(int i) const { return i == 0 ? "gps" : NULL; } -const char *NanoG2UltraSensorManager::getSettingValue(int i) const -{ - if (i == 0) - { +const char *NanoG2UltraSensorManager::getSettingValue(int i) const { + if (i == 0) { return gps_active ? "1" : "0"; } return NULL; } -bool NanoG2UltraSensorManager::setSettingValue(const char *name, const char *value) -{ +bool NanoG2UltraSensorManager::setSettingValue(const char *name, const char *value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { stop_gps(); @@ -145,8 +137,7 @@ bool NanoG2UltraSensorManager::setSettingValue(const char *name, const char *val return false; // not supported } -mesh::LocalIdentity radio_new_identity() -{ +mesh::LocalIdentity radio_new_identity() { RadioNoiseListener rng(radio); return mesh::LocalIdentity(&rng); // create new random identity } diff --git a/variants/nano_g2_ultra/target.h b/variants/nano_g2_ultra/target.h index 5cde6405..3e58b900 100644 --- a/variants/nano_g2_ultra/target.h +++ b/variants/nano_g2_ultra/target.h @@ -1,13 +1,15 @@ #pragma once #define RADIOLIB_STATIC_ONLY 1 -#include #include "nano-g2.h" -#include -#include + +#include #include #include +#include +#include #ifdef DISPLAY_CLASS +#include #include #endif #include @@ -37,6 +39,7 @@ extern NanoG2UltraSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; +extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/picow/platformio.ini b/variants/picow/platformio.ini index 8b6c2506..7b75c224 100644 --- a/variants/picow/platformio.ini +++ b/variants/picow/platformio.ini @@ -52,7 +52,7 @@ build_flags = ${picow.build_flags} ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${picow.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${picow.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -66,7 +66,7 @@ lib_deps = ${picow.lib_deps} ; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_DEBUG=1 ; build_src_filter = ${picow.build_src_filter} -; +<../examples/companion_radio> +; +<../examples/companion_radio/*.cpp> ; lib_deps = ${picow.lib_deps} ; densaugeo/base64 @ ~1.4.0 @@ -81,7 +81,7 @@ lib_deps = ${picow.lib_deps} ; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_DEBUG=1 ; build_src_filter = ${picow.build_src_filter} -; +<../examples/companion_radio> +; +<../examples/companion_radio/*.cpp> ; lib_deps = ${picow.lib_deps} ; densaugeo/base64 @ ~1.4.0 diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 78b25aa7..6b77bdcf 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -39,6 +39,7 @@ extends = Faketec build_src_filter = ${Faketec.build_src_filter} +<../examples/simple_repeater> + + + build_flags = ${Faketec.build_flags} -D ADVERT_NAME='"Faketec Repeater"' @@ -57,6 +58,7 @@ extends = Faketec build_src_filter = ${Faketec.build_src_filter} +<../examples/simple_room_server> + + + build_flags = ${Faketec.build_flags} -D ADVERT_NAME='"Faketec Room"' -D ADVERT_LAT=0.0 @@ -85,14 +87,17 @@ lib_deps = ${Faketec.lib_deps} [env:Faketec_companion_radio_usb] extends = Faketec build_flags = ${Faketec.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${Faketec.build_src_filter} - +<../examples/companion_radio> + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Faketec.lib_deps} adafruit/RTClib @ ^2.1.3 densaugeo/base64 @ ~1.4.0 @@ -100,6 +105,7 @@ lib_deps = ${Faketec.lib_deps} [env:Faketec_companion_radio_ble] extends = Faketec build_flags = ${Faketec.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -110,8 +116,10 @@ build_flags = ${Faketec.build_flags} -D MESH_DEBUG=1 build_src_filter = ${Faketec.build_src_filter} + - +<../examples/companion_radio> + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Faketec.lib_deps} adafruit/RTClib @ ^2.1.3 densaugeo/base64 @ ~1.4.0 @@ -129,6 +137,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Faketec.build_src_filter} + + + +<../examples/simple_sensor> lib_deps = ${Faketec.lib_deps} diff --git a/variants/promicro/target.cpp b/variants/promicro/target.cpp index 03a5a16a..b26320e4 100644 --- a/variants/promicro/target.cpp +++ b/variants/promicro/target.cpp @@ -20,6 +20,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true); #endif bool radio_init() { diff --git a/variants/promicro/target.h b/variants/promicro/target.h index de2719e6..38c4b4e8 100644 --- a/variants/promicro/target.h +++ b/variants/promicro/target.h @@ -8,6 +8,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif #include @@ -19,6 +20,7 @@ extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 8fb4d1bb..c9091878 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -22,6 +22,8 @@ build_flags = ${nrf52_base.build_flags} build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> + + + + + lib_deps = ${nrf52_base.lib_deps} ${sensor_base.lib_deps} @@ -64,6 +66,7 @@ build_src_filter = ${rak4631.build_src_filter} extends = rak4631 build_flags = ${rak4631.build_flags} + -I examples/companion_radio/ui-new -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 -D DISPLAY_CLASS=SSD1306Display @@ -72,8 +75,8 @@ build_flags = ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${rak4631.build_src_filter} - + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${rak4631.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -82,6 +85,7 @@ lib_deps = extends = rak4631 build_flags = ${rak4631.build_flags} + -I examples/companion_radio/ui-new -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 -D DISPLAY_CLASS=SSD1306Display @@ -93,9 +97,9 @@ build_flags = ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${rak4631.build_src_filter} - + + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${rak4631.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/rak4631/target.cpp b/variants/rak4631/target.cpp index 4e9d3cce..618c9fc5 100644 --- a/variants/rak4631/target.cpp +++ b/variants/rak4631/target.cpp @@ -4,8 +4,13 @@ RAK4631Board board; +#ifndef PIN_USER_BTN + #define PIN_USER_BTN (-1) +#endif + #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); diff --git a/variants/rak4631/target.h b/variants/rak4631/target.h index c4c88183..5e93b7fc 100644 --- a/variants/rak4631/target.h +++ b/variants/rak4631/target.h @@ -11,6 +11,8 @@ #ifdef DISPLAY_CLASS #include extern DISPLAY_CLASS display; + #include + extern MomentaryButton user_btn; #endif extern RAK4631Board board; diff --git a/variants/sensecap_solar/platformio.ini b/variants/sensecap_solar/platformio.ini index 9626e9cd..bbac5d99 100644 --- a/variants/sensecap_solar/platformio.ini +++ b/variants/sensecap_solar/platformio.ini @@ -85,7 +85,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${SenseCap_Solar.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${SenseCap_Solar.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -100,7 +100,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${SenseCap_Solar.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${SenseCap_Solar.lib_deps} densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/variants/station_g2/platformio.ini b/variants/station_g2/platformio.ini index 5d9a6823..756ff5f3 100644 --- a/variants/station_g2/platformio.ini +++ b/variants/station_g2/platformio.ini @@ -22,6 +22,7 @@ build_flags = build_src_filter = ${esp32_base.build_src_filter} +<../variants/station_g2> + + + lib_deps = ${esp32_base.lib_deps} adafruit/Adafruit SH110X @ ~2.1.13 @@ -44,6 +45,25 @@ lib_deps = ${Station_G2.lib_deps} ${esp32_ota.lib_deps} +[env:Station_G2_logging_repeater] +extends = Station_G2 +build_flags = + ${Station_G2.build_flags} + -D ADVERT_NAME='"Station G2 Logging Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D MESH_PACKET_LOGGING=1 + -D SX126X_RX_BOOSTED_GAIN=1 +; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance +; -D MESH_DEBUG=1 +build_src_filter = ${Station_G2.build_src_filter} + +<../examples/simple_repeater> +lib_deps = + ${Station_G2.lib_deps} + ${esp32_ota.lib_deps} + [env:Station_G2_room_server] extends = Station_G2 build_src_filter = ${Station_G2.build_src_filter} @@ -65,14 +85,16 @@ lib_deps = extends = Station_G2 build_flags = ${Station_G2.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SH1106Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${Station_G2.build_src_filter} - + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Station_G2.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -81,6 +103,7 @@ lib_deps = extends = Station_G2 build_flags = ${Station_G2.build_flags} + -I examples/companion_radio/ui-new -D DISPLAY_CLASS=SH1106Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 @@ -91,8 +114,8 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Station_G2.build_src_filter} + - + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Station_G2.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/station_g2/target.cpp b/variants/station_g2/target.cpp index 2b19f5f0..5423af68 100644 --- a/variants/station_g2/target.cpp +++ b/variants/station_g2/target.cpp @@ -18,10 +18,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; -#endif - -#ifndef LORA_CR - #define LORA_CR 5 + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/station_g2/target.h b/variants/station_g2/target.h index 6d80f098..3f67af3a 100644 --- a/variants/station_g2/target.h +++ b/variants/station_g2/target.h @@ -10,6 +10,7 @@ #ifdef DISPLAY_CLASS #include + #include #endif extern StationG2Board board; @@ -19,6 +20,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/t1000-e/T1000eBoard.h b/variants/t1000-e/T1000eBoard.h index 24584757..f87d71e0 100644 --- a/variants/t1000-e/T1000eBoard.h +++ b/variants/t1000-e/T1000eBoard.h @@ -84,12 +84,21 @@ public: digitalWrite(PIN_3V3_EN, LOW); #endif + // set led on and wait for button release before poweroff + #ifdef LED_PIN + digitalWrite(LED_PIN, HIGH); + #endif + #ifdef BUTTON_PIN + while(digitalRead(BUTTON_PIN)); + #endif #ifdef LED_PIN digitalWrite(LED_PIN, LOW); #endif + #ifdef BUTTON_PIN nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); #endif + sd_power_system_off(); } diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini index 00974208..2811e243 100644 --- a/variants/t1000-e/platformio.ini +++ b/variants/t1000-e/platformio.ini @@ -37,6 +37,7 @@ upload_protocol = nrfutil [env:t1000e_companion_radio_ble] extends = t1000-e build_flags = ${t1000-e.build_flags} + -I examples/companion_radio/ui-orig -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -53,6 +54,7 @@ build_src_filter = ${t1000-e.build_src_filter} + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> lib_deps = ${t1000-e.lib_deps} densaugeo/base64 @ ~1.4.0 stevemarple/MicroNMEA @ ^2.0.6 diff --git a/variants/t114/platformio.ini b/variants/t114/platformio.ini index dac12da9..e48ee121 100644 --- a/variants/t114/platformio.ini +++ b/variants/t114/platformio.ini @@ -30,6 +30,7 @@ build_src_filter = ${nrf52840_t114.build_src_filter} + +<../variants/t114> + + + + + lib_deps = @@ -72,6 +73,7 @@ build_flags = extends = Heltec_t114 build_flags = ${Heltec_t114.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -81,7 +83,8 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_t114.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_t114.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -90,6 +93,7 @@ lib_deps = extends = Heltec_t114 build_flags = ${Heltec_t114.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 ; -D BLE_PIN_CODE=123456 @@ -98,7 +102,8 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_t114.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_t114.lib_deps} densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/variants/t114/target.cpp b/variants/t114/target.cpp index d97c03f6..d2fa6c4c 100644 --- a/variants/t114/target.cpp +++ b/variants/t114/target.cpp @@ -16,6 +16,7 @@ T114SensorManager sensors = T114SensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/t114/target.h b/variants/t114/target.h index 8831d9f7..35e86f60 100644 --- a/variants/t114/target.h +++ b/variants/t114/target.h @@ -10,6 +10,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif class T114SensorManager : public SensorManager { @@ -37,6 +38,7 @@ extern T114SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/techo/platformio.ini b/variants/techo/platformio.ini index 8ad5ca03..76712178 100644 --- a/variants/techo/platformio.ini +++ b/variants/techo/platformio.ini @@ -21,6 +21,7 @@ build_flags = ${nrf52840_techo.build_flags} -D LORA_TX_POWER=22 -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 + -D P_LORA_TX_LED=LED_GREEN build_src_filter = ${nrf52840_techo.build_src_filter} + + @@ -61,19 +62,23 @@ extends = LilyGo_Techo build_flags = ${LilyGo_Techo.build_flags} -I src/helpers/ui + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D DISPLAY_CLASS=GxEPDDisplay -D OFFLINE_QUEUE_SIZE=256 + -D UI_RECENT_LIST_SIZE=9 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${LilyGo_Techo.build_src_filter} + + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${LilyGo_Techo.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/techo/target.cpp b/variants/techo/target.cpp index 1e413531..9a10491d 100644 --- a/variants/techo/target.cpp +++ b/variants/techo/target.cpp @@ -16,6 +16,7 @@ TechoSensorManager sensors = TechoSensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/techo/target.h b/variants/techo/target.h index 7c05e742..58fba687 100644 --- a/variants/techo/target.h +++ b/variants/techo/target.h @@ -10,6 +10,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif class TechoSensorManager : public SensorManager { @@ -36,6 +37,7 @@ extern TechoSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/techo/variant.cpp b/variants/techo/variant.cpp index ad1fd560..0bad7829 100644 --- a/variants/techo/variant.cpp +++ b/variants/techo/variant.cpp @@ -24,6 +24,8 @@ void initVariant() { pinMode(LED_GREEN, OUTPUT); pinMode(LED_BLUE, OUTPUT); digitalWrite(LED_BLUE, HIGH); + digitalWrite(LED_GREEN, HIGH); + digitalWrite(LED_RED, HIGH); pinMode(PIN_TXCO, OUTPUT); digitalWrite(PIN_TXCO, HIGH); diff --git a/variants/techo/variant.h b/variants/techo/variant.h index 6aebf82f..da8d81d4 100644 --- a/variants/techo/variant.h +++ b/variants/techo/variant.h @@ -61,19 +61,15 @@ //////////////////////////////////////////////////////////////////////////////// // Builtin LEDs -#define LED_RED (34) -#define LED_GREEN (33) +#define LED_RED (13) #define LED_BLUE (14) +#define LED_GREEN (15) -#define PIN_STATUS_LED LED_GREEN -#define LED_BUILTIN LED_GREEN -#define PIN_LED LED_BUILTIN +//#define PIN_STATUS_LED LED_BLUE +#define LED_BUILTIN (-1) #define LED_PIN LED_BUILTIN #define LED_STATE_ON LOW -#define PIN_NEOPIXEL (14) -#define NEOPIXEL_NUM (2) - //////////////////////////////////////////////////////////////////////////////// // Builtin buttons diff --git a/variants/thinknode_m1/platformio.ini b/variants/thinknode_m1/platformio.ini index 2104a080..fa8cd55b 100644 --- a/variants/thinknode_m1/platformio.ini +++ b/variants/thinknode_m1/platformio.ini @@ -68,6 +68,7 @@ extends = ThinkNode_M1 build_flags = ${ThinkNode_M1.build_flags} -I src/helpers/ui + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -83,7 +84,9 @@ build_src_filter = ${ThinkNode_M1.build_src_filter} + + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${ThinkNode_M1.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/thinknode_m1/target.cpp b/variants/thinknode_m1/target.cpp index 19230232..2b04d7c6 100644 --- a/variants/thinknode_m1/target.cpp +++ b/variants/thinknode_m1/target.cpp @@ -16,6 +16,7 @@ ThinkNodeM1SensorManager sensors = ThinkNodeM1SensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/thinknode_m1/target.h b/variants/thinknode_m1/target.h index c938d422..eac221c3 100644 --- a/variants/thinknode_m1/target.h +++ b/variants/thinknode_m1/target.h @@ -10,6 +10,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif class ThinkNodeM1SensorManager : public SensorManager { @@ -37,6 +38,7 @@ extern ThinkNodeM1SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init(); diff --git a/variants/waveshare_rp2040_lora/platformio.ini b/variants/waveshare_rp2040_lora/platformio.ini index 2730734d..933c7661 100644 --- a/variants/waveshare_rp2040_lora/platformio.ini +++ b/variants/waveshare_rp2040_lora/platformio.ini @@ -61,7 +61,7 @@ build_flags = ${waveshare_rp2040_lora.build_flags} ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${waveshare_rp2040_lora.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${waveshare_rp2040_lora.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -75,7 +75,7 @@ lib_deps = ${waveshare_rp2040_lora.lib_deps} ; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_DEBUG=1 ; build_src_filter = ${waveshare_rp2040_lora.build_src_filter} -; +<../examples/companion_radio> +; +<../examples/companion_radio/*.cpp> ; lib_deps = ${waveshare_rp2040_lora.lib_deps} ; densaugeo/base64 @ ~1.4.0 @@ -90,7 +90,7 @@ lib_deps = ${waveshare_rp2040_lora.lib_deps} ; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_DEBUG=1 ; build_src_filter = ${waveshare_rp2040_lora.build_src_filter} -; +<../examples/companion_radio> +; +<../examples/companion_radio/*.cpp> ; lib_deps = ${waveshare_rp2040_lora.lib_deps} ; densaugeo/base64 @ ~1.4.0 diff --git a/variants/wio-e5-mini/platformio.ini b/variants/wio-e5-mini/platformio.ini index 93508d8e..3d98d93e 100644 --- a/variants/wio-e5-mini/platformio.ini +++ b/variants/wio-e5-mini/platformio.ini @@ -37,11 +37,13 @@ build_src_filter = ${lora_e5_mini.build_src_filter} [env:wio-e5-mini_companion_radio_usb] extends = lora_e5_mini build_flags = ${lora_e5_mini.build_flags} + -I examples/companion_radio/ui-orig -D LORA_TX_POWER=22 -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=NullDisplayDriver build_src_filter = ${lora_e5_mini.build_src_filter} +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> lib_deps = ${lora_e5_mini.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/wio-tracker-l1/WioTrackerL1Board.h b/variants/wio-tracker-l1/WioTrackerL1Board.h index 03aef79c..f04b673f 100644 --- a/variants/wio-tracker-l1/WioTrackerL1Board.h +++ b/variants/wio-tracker-l1/WioTrackerL1Board.h @@ -38,5 +38,9 @@ public: NVIC_SystemReset(); } + void powerOff() override { + sd_power_system_off(); + } + bool startOTAUpdate(const char* id, char reply[]) override; }; diff --git a/variants/wio-tracker-l1/platformio.ini b/variants/wio-tracker-l1/platformio.ini index 380ff90f..ddf7cf47 100644 --- a/variants/wio-tracker-l1/platformio.ini +++ b/variants/wio-tracker-l1/platformio.ini @@ -56,13 +56,16 @@ lib_deps = ${WioTrackerL1.lib_deps} [env:WioTrackerL1_companion_radio_usb] extends = WioTrackerL1 build_flags = ${WioTrackerL1.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SH1106Display ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${WioTrackerL1.build_src_filter} - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> + + lib_deps = ${WioTrackerL1.lib_deps} @@ -73,6 +76,7 @@ lib_deps = ${WioTrackerL1.lib_deps} [env:WioTrackerL1_companion_radio_ble] extends = WioTrackerL1 build_flags = ${WioTrackerL1.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -84,8 +88,10 @@ build_flags = ${WioTrackerL1.build_flags} -D PIN_BUZZER=12 build_src_filter = ${WioTrackerL1.build_src_filter} + - +<../examples/companion_radio> + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${WioTrackerL1.lib_deps} adafruit/RTClib @ ^2.1.3 densaugeo/base64 @ ~1.4.0 diff --git a/variants/wio-tracker-l1/target.cpp b/variants/wio-tracker-l1/target.cpp index 0809e19e..349d73b4 100644 --- a/variants/wio-tracker-l1/target.cpp +++ b/variants/wio-tracker-l1/target.cpp @@ -16,6 +16,9 @@ WioTrackerL1SensorManager sensors = WioTrackerL1SensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); + MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true); + MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true); #endif bool radio_init() { diff --git a/variants/wio-tracker-l1/target.h b/variants/wio-tracker-l1/target.h index ab42b7b5..6f5da7c6 100644 --- a/variants/wio-tracker-l1/target.h +++ b/variants/wio-tracker-l1/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif #include @@ -38,6 +39,9 @@ extern AutoDiscoverRTCClock rtc_clock; extern WioTrackerL1SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; + extern MomentaryButton joystick_left; + extern MomentaryButton joystick_right; #endif bool radio_init(); diff --git a/variants/xiao_c3/platformio.ini b/variants/xiao_c3/platformio.ini index 3e4bfdb4..659313db 100644 --- a/variants/xiao_c3/platformio.ini +++ b/variants/xiao_c3/platformio.ini @@ -61,11 +61,12 @@ build_flags = lib_deps = ${Xiao_esp32_C3.lib_deps} ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 [env:Xiao_C3_companion_radio_ble] extends = Xiao_esp32_C3 build_src_filter = ${Xiao_esp32_C3.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + build_flags = ${Xiao_esp32_C3.build_flags} @@ -88,7 +89,7 @@ lib_deps = [env:Xiao_C3_companion_radio_usb] extends = Xiao_esp32_C3 build_src_filter = ${Xiao_esp32_C3.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + build_flags = ${Xiao_esp32_C3.build_flags} @@ -127,6 +128,7 @@ build_flags = lib_deps = ${Xiao_esp32_C3_custom.lib_deps} ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 [env:Xiao_C3_Repeater_sx1268_custom] extends = Xiao_esp32_C3_custom @@ -146,4 +148,5 @@ build_flags = ; -D MESH_DEBUG=1 lib_deps = ${Xiao_esp32_C3_custom.lib_deps} - ${esp32_ota.lib_deps} \ No newline at end of file + ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 diff --git a/variants/xiao_c6/platformio.ini b/variants/xiao_c6/platformio.ini index 95dede08..602bd6ae 100644 --- a/variants/xiao_c6/platformio.ini +++ b/variants/xiao_c6/platformio.ini @@ -62,7 +62,7 @@ build_flags = ${Xiao_C6.build_flags} build_src_filter = ${Xiao_C6.build_src_filter} + - - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Xiao_C6.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -117,7 +117,69 @@ build_flags = ${Meshimi.build_flags} build_src_filter = ${Meshimi.build_src_filter} + - - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Meshimi.lib_deps} densaugeo/base64 @ ~1.4.0 + +; WHY2025 badge variant +; requires soldering 2 pins between the esp32-C6 and the lora chip as shown here: https://wiki.why2025.org/Project:Meshtastic_on_the_WHY2025_badge +; also requires wiping the esp32-P4 +[WHY2025_badge] +extends = Xiao_C6 +board_build.partitions = default_8MB.csv +board_upload.flash_size = 8MB +board_upload.maximum_size = 8388608 +build_flags = + ${Xiao_C6.build_flags} + -D P_LORA_SCLK=6 + -D P_LORA_MISO=2 + -D P_LORA_MOSI=7 + -D P_LORA_NSS=4 + -D P_LORA_DIO_1=5 + -D P_LORA_BUSY=11 + -D P_LORA_RESET=1 + -D SX126X_TXEN=3 + -UPIN_BOARD_SDA + -UPIN_BOARD_SCL + -UP_LORA_TX_LED + -USX126X_RXEN + -USX126X_DIO2_AS_RF_SWITCH + -USX126X_DIO3_TCXO_VOLTAGE + +[env:WHY2025_badge_Repeater] +extends = WHY2025_badge +build_src_filter = ${WHY2025_badge.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${WHY2025_badge.build_flags} + -D ADVERT_NAME='"WHY2025 Badge Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${WHY2025_badge.lib_deps} +; ${esp32_ota.lib_deps} + +[env:WHY2025_badge_companion_radio_ble] +extends = WHY2025_badge +build_flags = ${WHY2025_badge.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_PRIVATE_KEY_IMPORT=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${WHY2025_badge.build_src_filter} + + + - + +<../examples/companion_radio/*.cpp> +lib_deps = + ${WHY2025_badge.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index bba3e632..fd4c362b 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -68,7 +68,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Xiao_nrf52.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Xiao_nrf52.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -83,7 +83,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Xiao_nrf52.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Xiao_nrf52.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/xiao_rp2040/platformio.ini b/variants/xiao_rp2040/platformio.ini index 960fdbba..619350ec 100644 --- a/variants/xiao_rp2040/platformio.ini +++ b/variants/xiao_rp2040/platformio.ini @@ -58,7 +58,7 @@ build_flags = ${Xiao_rp2040.build_flags} ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${Xiao_rp2040.build_src_filter} - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Xiao_rp2040.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -72,7 +72,7 @@ lib_deps = ${Xiao_rp2040.lib_deps} ; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_DEBUG=1 ; build_src_filter = ${Xiao_rp2040.build_src_filter} -; +<../examples/companion_radio> +; +<../examples/companion_radio/*.cpp> ; lib_deps = ${Xiao_rp2040.lib_deps} ; densaugeo/base64 @ ~1.4.0 @@ -87,7 +87,7 @@ lib_deps = ${Xiao_rp2040.lib_deps} ; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_DEBUG=1 ; build_src_filter = ${Xiao_rp2040.build_src_filter} -; +<../examples/companion_radio> +; +<../examples/companion_radio/*.cpp> ; lib_deps = ${Xiao_rp2040.lib_deps} ; densaugeo/base64 @ ~1.4.0 diff --git a/variants/xiao_s3_wio/platformio.ini b/variants/xiao_s3_wio/platformio.ini index 4d6fed88..fe4670b5 100644 --- a/variants/xiao_s3_wio/platformio.ini +++ b/variants/xiao_s3_wio/platformio.ini @@ -79,6 +79,7 @@ lib_deps = extends = Xiao_S3_WIO build_flags = ${Xiao_S3_WIO.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 @@ -90,7 +91,9 @@ build_flags = build_src_filter = ${Xiao_S3_WIO.build_src_filter} + + - +<../examples/companion_radio> + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Xiao_S3_WIO.lib_deps} densaugeo/base64 @ ~1.4.0 @@ -108,7 +111,7 @@ build_flags = ; -D MESH_DEBUG=1 build_src_filter = ${Xiao_S3_WIO.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> lib_deps = ${Xiao_S3_WIO.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/xiao_s3_wio/target.cpp b/variants/xiao_s3_wio/target.cpp index 4b2b059f..ed8584ff 100644 --- a/variants/xiao_s3_wio/target.cpp +++ b/variants/xiao_s3_wio/target.cpp @@ -18,6 +18,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/xiao_s3_wio/target.h b/variants/xiao_s3_wio/target.h index b768b2b0..f184c757 100644 --- a/variants/xiao_s3_wio/target.h +++ b/variants/xiao_s3_wio/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include + #include #endif extern ESP32Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; #endif bool radio_init();