├── .envrc ├── .github ├── actions │ └── setup-build-environment │ │ └── action.yml └── workflows │ ├── build-companion-firmwares.yml │ ├── build-repeater-firmwares.yml │ └── build-room-server-firmwares.yml ├── .gitignore ├── .vscode └── extensions.json ├── README.md ├── RELEASE.md ├── arch ├── esp32 │ └── AsyncElegantOTA │ │ ├── LICENSE │ │ ├── keywords.txt │ │ ├── library.properties │ │ └── src │ │ ├── AsyncElegantOTA.cpp │ │ ├── AsyncElegantOTA.h │ │ ├── Hash.h │ │ └── elegantWebpage.h └── stm32 │ ├── Adafruit_LittleFS_stm32 │ ├── README.md │ ├── library.properties │ └── src │ │ ├── Adafruit_LittleFS.cpp │ │ ├── Adafruit_LittleFS.h │ │ ├── Adafruit_LittleFS_File.cpp │ │ ├── Adafruit_LittleFS_File.h │ │ └── littlefs │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── lfs.c │ │ ├── lfs.h │ │ ├── lfs_util.c │ │ └── lfs_util.h │ └── build_hex.py ├── bin └── uf2conv │ ├── uf2conv.py │ └── uf2families.json ├── boards ├── heltec_t114.json ├── nano-g2-ultra.json ├── nrf52840_s140_v6.ld ├── nrf52840_s140_v7.ld ├── promicro_nrf52840.json ├── rak3172.json ├── seeed-xiao-afruitnrf52-nrf52840.json ├── station-g2.json ├── t-echo.json ├── t3_s3_v1_x.json ├── t_beams3_supreme.json ├── thinknode_m1.json └── tracker-t1000-e.json ├── build.sh ├── default.nix ├── docs ├── faq.md ├── packet_structure.md └── payloads.md ├── examples ├── companion_radio │ ├── NodePrefs.h │ ├── UITask.cpp │ ├── UITask.h │ └── main.cpp ├── simple_repeater │ ├── UITask.cpp │ ├── UITask.h │ └── main.cpp ├── simple_room_server │ ├── UITask.cpp │ ├── UITask.h │ └── main.cpp └── simple_secure_chat │ └── main.cpp ├── include └── README ├── lib ├── README ├── ed25519 │ ├── add_scalar.c │ ├── ed_25519.h │ ├── fe.c │ ├── fe.h │ ├── fixedint.h │ ├── ge.c │ ├── ge.h │ ├── key_exchange.c │ ├── keypair.c │ ├── license.txt │ ├── precomp_data.h │ ├── sc.c │ ├── sc.h │ ├── seed.c │ ├── sha512.c │ ├── sha512.h │ ├── sign.c │ └── verify.c └── nrf52 │ ├── include │ ├── ble.h │ ├── ble_err.h │ ├── ble_gap.h │ ├── ble_gatt.h │ ├── ble_gattc.h │ ├── ble_gatts.h │ ├── ble_hci.h │ ├── ble_l2cap.h │ ├── ble_ranges.h │ ├── ble_types.h │ ├── nrf52 │ │ └── nrf_mbr.h │ ├── nrf_error.h │ ├── nrf_error_sdm.h │ ├── nrf_error_soc.h │ ├── nrf_nvic.h │ ├── nrf_sdm.h │ ├── nrf_soc.h │ └── nrf_svc.h │ └── s140_nrf52_7.3.0_API │ └── include │ ├── ble.h │ ├── ble_err.h │ ├── ble_gap.h │ ├── ble_gatt.h │ ├── ble_gattc.h │ ├── ble_gatts.h │ ├── ble_hci.h │ ├── ble_l2cap.h │ ├── ble_ranges.h │ ├── ble_types.h │ ├── nrf52 │ └── nrf_mbr.h │ ├── nrf_error.h │ ├── nrf_error_sdm.h │ ├── nrf_error_soc.h │ ├── nrf_nvic.h │ ├── nrf_sdm.h │ ├── nrf_soc.h │ └── nrf_svc.h ├── license.txt ├── logo ├── meshcore.afdesign ├── meshcore.png ├── meshcore.svg └── meshcore_tm.svg ├── merge-bin.py ├── platformio.ini ├── src ├── Dispatcher.cpp ├── Dispatcher.h ├── Identity.cpp ├── Identity.h ├── Mesh.cpp ├── Mesh.h ├── MeshCore.h ├── Packet.cpp ├── Packet.h ├── Utils.cpp ├── Utils.h └── helpers │ ├── AdvertDataHelpers.cpp │ ├── AdvertDataHelpers.h │ ├── ArduinoHelpers.h │ ├── ArduinoSerialInterface.cpp │ ├── ArduinoSerialInterface.h │ ├── AutoDiscoverRTCClock.cpp │ ├── AutoDiscoverRTCClock.h │ ├── BaseChatMesh.cpp │ ├── BaseChatMesh.h │ ├── BaseSerialInterface.h │ ├── CommonCLI.cpp │ ├── CommonCLI.h │ ├── CustomLLCC68.h │ ├── CustomLLCC68Wrapper.h │ ├── CustomLR1110.h │ ├── CustomLR1110Wrapper.h │ ├── CustomSTM32WLx.h │ ├── CustomSTM32WLxWrapper.h │ ├── CustomSX1262.h │ ├── CustomSX1262Wrapper.h │ ├── CustomSX1268.h │ ├── CustomSX1268Wrapper.h │ ├── CustomSX1276.h │ ├── CustomSX1276Wrapper.h │ ├── ESP32Board.cpp │ ├── ESP32Board.h │ ├── HeltecV2Board.h │ ├── HeltecV3Board.h │ ├── IdentityStore.cpp │ ├── IdentityStore.h │ ├── LilyGoTLoraBoard.h │ ├── RadioLibWrappers.cpp │ ├── RadioLibWrappers.h │ ├── RefCountedDigitalPin.h │ ├── SensorManager.h │ ├── SimpleMeshTables.h │ ├── StaticPoolPacketManager.cpp │ ├── StaticPoolPacketManager.h │ ├── StationG2Board.h │ ├── TBeamBoard.h │ ├── TBeamBoardSX1262.h │ ├── TBeamS3SupremeBoard.h │ ├── TxtDataHelpers.cpp │ ├── TxtDataHelpers.h │ ├── XiaoC3Board.h │ ├── esp32 │ ├── ESPNOWRadio.cpp │ ├── ESPNOWRadio.h │ ├── SerialBLEInterface.cpp │ ├── SerialBLEInterface.h │ ├── SerialWifiInterface.cpp │ └── SerialWifiInterface.h │ ├── nrf52 │ ├── PromicroBoard.cpp │ ├── PromicroBoard.h │ ├── RAK4631Board.cpp │ ├── RAK4631Board.h │ ├── SerialBLEInterface.cpp │ ├── SerialBLEInterface.h │ ├── T1000eBoard.cpp │ ├── T1000eBoard.h │ ├── T114Board.cpp │ ├── T114Board.h │ ├── TechoBoard.cpp │ ├── TechoBoard.h │ ├── ThinkNodeM1Board.cpp │ ├── ThinkNodeM1Board.h │ ├── XiaoNrf52Board.cpp │ └── XiaoNrf52Board.h │ ├── rp2040 │ ├── PicoWBoard.cpp │ └── PicoWBoard.h │ ├── sensors │ ├── EnvironmentSensorManager.cpp │ ├── EnvironmentSensorManager.h │ ├── LocationProvider.h │ └── MicroNMEALocationProvider.h │ ├── stm32 │ ├── InternalFileSystem.cpp │ ├── InternalFileSystem.h │ └── STM32Board.h │ └── ui │ ├── DisplayDriver.h │ ├── GxEPDDisplay.cpp │ ├── GxEPDDisplay.h │ ├── OLEDDisplay.cpp │ ├── OLEDDisplay.h │ ├── OLEDDisplayFonts.cpp │ ├── OLEDDisplayFonts.h │ ├── SH1106Display.cpp │ ├── SH1106Display.h │ ├── SSD1306Display.cpp │ ├── SSD1306Display.h │ ├── ST7735Display.cpp │ ├── ST7735Display.h │ ├── ST7789Display.cpp │ ├── ST7789Display.h │ ├── ST7789Spi.h │ ├── buzzer.cpp │ └── buzzer.h └── variants ├── generic-e22 ├── platformio.ini ├── target.cpp ├── target.h └── variant.h ├── generic_espnow ├── platformio.ini ├── target.cpp └── target.h ├── heltec_tracker ├── platformio.ini ├── target.cpp └── target.h ├── heltec_v2 ├── platformio.ini ├── target.cpp └── target.h ├── heltec_v3 ├── platformio.ini ├── target.cpp └── target.h ├── lilygo_t3s3 ├── platformio.ini ├── target.cpp └── target.h ├── lilygo_tbeam ├── platformio.ini ├── target.cpp └── target.h ├── lilygo_tbeam_SX1262 ├── platformio.ini ├── target.cpp └── target.h ├── lilygo_tbeam_supreme_SX1262 ├── platformio.ini ├── target.cpp └── target.h ├── lilygo_tlora_v2_1 ├── platformio.ini ├── target.cpp └── target.h ├── nano_g2_ultra ├── nano-g2.cpp ├── nano-g2.h ├── platformio.ini ├── target.cpp ├── target.h ├── variant.cpp └── variant.h ├── picow ├── platformio.ini ├── target.cpp └── target.h ├── promicro ├── platformio.ini ├── target.cpp ├── target.h ├── variant.cpp └── variant.h ├── rak3x72 ├── platformio.ini ├── target.cpp ├── target.h └── variant.h ├── rak4631 ├── platformio.ini ├── target.cpp └── target.h ├── station_g2 ├── platformio.ini ├── target.cpp └── target.h ├── t1000-e ├── NullDisplayDriver.h ├── platformio.ini ├── target.cpp ├── target.h ├── variant.cpp └── variant.h ├── t114 ├── platformio.ini ├── target.cpp ├── target.h ├── variant.cpp └── variant.h ├── techo ├── platformio.ini ├── target.cpp ├── target.h ├── variant.cpp └── variant.h ├── thinknode_m1 ├── platformio.ini ├── target.cpp ├── target.h ├── variant.cpp └── variant.h ├── wio-e5 ├── platformio.ini ├── target.cpp ├── target.h └── variant.h ├── xiao_c3 ├── platformio.ini ├── target.cpp └── target.h ├── xiao_nrf52 ├── platformio.ini ├── target.cpp ├── target.h ├── variant.cpp └── variant.h └── xiao_s3_wio ├── platformio.ini ├── target.cpp └── target.h /.envrc: -------------------------------------------------------------------------------- 1 | use nix 2 | -------------------------------------------------------------------------------- /.github/actions/setup-build-environment/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup Build Environment 2 | runs: 3 | using: "composite" 4 | steps: 5 | 6 | - name: Init Cache 7 | uses: actions/cache@v4 8 | with: 9 | path: | 10 | ~/.cache/pip 11 | ~/.platformio/.cache 12 | key: ${{ runner.os }}-pio 13 | 14 | - name: Install Python 15 | uses: actions/setup-python@v5 16 | with: 17 | python-version: '3.11' 18 | 19 | - name: Install PlatformIO 20 | shell: bash 21 | run: | 22 | pip install --upgrade platformio 23 | 24 | # a git tag of "room-server-v1.2.3" should set "v1.2.3" as GIT_TAG_VERSION 25 | - name: Extract Version from Git Tag 26 | shell: bash 27 | run: | 28 | GIT_TAG_NAME="${GITHUB_REF#refs/tags/}" 29 | echo "GIT_TAG_VERSION=${GIT_TAG_NAME##*-}" >> $GITHUB_ENV 30 | -------------------------------------------------------------------------------- /.github/workflows/build-companion-firmwares.yml: -------------------------------------------------------------------------------- 1 | name: Build Companion Firmwares 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | tags: 10 | - 'companion-*' 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | 18 | - name: Clone Repo 19 | uses: actions/checkout@v4 20 | 21 | - name: Setup Build Environment 22 | uses: ./.github/actions/setup-build-environment 23 | 24 | - name: Build Firmwares 25 | env: 26 | FIRMWARE_VERSION: ${{ env.GIT_TAG_VERSION }} 27 | run: /usr/bin/env bash build.sh build-companion-firmwares 28 | 29 | - name: Upload Workflow Artifacts 30 | uses: actions/upload-artifact@v4 31 | with: 32 | name: companion-firmwares 33 | path: out 34 | 35 | - name: Create Release 36 | uses: softprops/action-gh-release@v2 37 | if: startsWith(github.ref, 'refs/tags/') 38 | with: 39 | name: Companion Firmware ${{ env.GIT_TAG_VERSION }} 40 | body: "" 41 | draft: true 42 | files: out/* -------------------------------------------------------------------------------- /.github/workflows/build-repeater-firmwares.yml: -------------------------------------------------------------------------------- 1 | name: Build Repeater Firmwares 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | tags: 10 | - 'repeater-*' 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | 18 | - name: Clone Repo 19 | uses: actions/checkout@v4 20 | 21 | - name: Setup Build Environment 22 | uses: ./.github/actions/setup-build-environment 23 | 24 | - name: Build Firmwares 25 | env: 26 | FIRMWARE_VERSION: ${{ env.GIT_TAG_VERSION }} 27 | run: /usr/bin/env bash build.sh build-repeater-firmwares 28 | 29 | - name: Upload Workflow Artifacts 30 | uses: actions/upload-artifact@v4 31 | with: 32 | name: repeater-firmwares 33 | path: out 34 | 35 | - name: Create Release 36 | uses: softprops/action-gh-release@v2 37 | if: startsWith(github.ref, 'refs/tags/') 38 | with: 39 | name: Repeater Firmware ${{ env.GIT_TAG_VERSION }} 40 | body: "" 41 | draft: true 42 | files: out/* -------------------------------------------------------------------------------- /.github/workflows/build-room-server-firmwares.yml: -------------------------------------------------------------------------------- 1 | name: Build Room Server Firmwares 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | tags: 10 | - 'room-server-*' 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | 18 | - name: Clone Repo 19 | uses: actions/checkout@v4 20 | 21 | - name: Setup Build Environment 22 | uses: ./.github/actions/setup-build-environment 23 | 24 | - name: Build Firmwares 25 | env: 26 | FIRMWARE_VERSION: ${{ env.GIT_TAG_VERSION }} 27 | run: /usr/bin/env bash build.sh build-room-server-firmwares 28 | 29 | - name: Upload Workflow Artifacts 30 | uses: actions/upload-artifact@v4 31 | with: 32 | name: room-server-firmwares 33 | path: out 34 | 35 | - name: Create Release 36 | uses: softprops/action-gh-release@v2 37 | if: startsWith(github.ref, 'refs/tags/') 38 | with: 39 | name: Room Server Firmware ${{ env.GIT_TAG_VERSION }} 40 | body: "" 41 | draft: true 42 | files: out/* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .direnv 2 | .pio 3 | .vscode/.browse.c_cpp.db* 4 | .vscode/c_cpp_properties.json 5 | .vscode/launch.json 6 | .vscode/ipch 7 | out/ 8 | .direnv/ 9 | .DS_Store 10 | .vscode/settings.json 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ], 7 | "unwantedRecommendations": [ 8 | "ms-vscode.cpptools-extension-pack" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Releasing Firmware 2 | 3 | GitHub Actions is set up to automatically build and release firmware. 4 | 5 | It will automatically build firmware when one of the following tag formats are pushed. 6 | 7 | - `companion-v1.0.0` 8 | - `repeater-v1.0.0` 9 | - `room-server-v1.0.0` 10 | 11 | > NOTE: replace `v1.0.0` with the version you want to release as. 12 | 13 | - You can push one, or more tags on the same commit, and they will all build separately. 14 | - Once the firmware has been built, a new (draft) GitHub Release will be created. 15 | - You will need to update the release notes, and publish it. 16 | -------------------------------------------------------------------------------- /arch/esp32/AsyncElegantOTA/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ayush Sharma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /arch/esp32/AsyncElegantOTA/keywords.txt: -------------------------------------------------------------------------------- 1 | AsyncElegantOTA KEYWORD1 2 | begin KEYWORD2 -------------------------------------------------------------------------------- /arch/esp32/AsyncElegantOTA/library.properties: -------------------------------------------------------------------------------- 1 | name=AsyncElegantOTA 2 | version=2.2.8 3 | author=Ayush Sharma 4 | category=Communication 5 | maintainer=Ayush Sharma 6 | sentence=Perform OTAs for ESP8266 & ESP32 Asynchronously. 7 | paragraph=A User Interface Library which provides interactive elements for your Over the Air Updates on ESP8266/ESP32. 8 | url=https://github.com/ayushsharma82/AsyncElegantOTA 9 | architectures=esp8266,esp32 10 | -------------------------------------------------------------------------------- /arch/esp32/AsyncElegantOTA/src/AsyncElegantOTA.h: -------------------------------------------------------------------------------- 1 | #ifndef AsyncElegantOTA_h 2 | #define AsyncElegantOTA_h 3 | 4 | #warning AsyncElegantOTA library is deprecated, Please consider moving to newer ElegantOTA library which now comes with an Async Mode. Learn More: https://docs.elegantota.pro/async-mode/ 5 | 6 | #include "Arduino.h" 7 | #include "stdlib_noniso.h" 8 | 9 | #if defined(ESP8266) 10 | #include "ESP8266WiFi.h" 11 | #include "ESPAsyncTCP.h" 12 | #include "flash_hal.h" 13 | #include "FS.h" 14 | #elif defined(ESP32) 15 | #include "WiFi.h" 16 | #include "AsyncTCP.h" 17 | #include "Update.h" 18 | #include "esp_int_wdt.h" 19 | #include "esp_task_wdt.h" 20 | #endif 21 | 22 | #include "Hash.h" 23 | #include "ESPAsyncWebServer.h" 24 | #include "FS.h" 25 | 26 | #include "elegantWebpage.h" 27 | 28 | 29 | class AsyncElegantOtaClass{ 30 | 31 | public: 32 | void 33 | setID(const char* id), 34 | begin(AsyncWebServer *server, const char* username = "", const char* password = ""), 35 | loop(), 36 | restart(); 37 | 38 | private: 39 | AsyncWebServer *_server; 40 | 41 | String getID(); 42 | 43 | String _id = getID(); 44 | String _username = ""; 45 | String _password = ""; 46 | bool _authRequired = false; 47 | 48 | }; 49 | 50 | extern AsyncElegantOtaClass AsyncElegantOTA; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /arch/esp32/AsyncElegantOTA/src/Hash.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hash.h 3 | * @date 20.05.2015 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the esp8266 core for Arduino environment. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef HASH_H_ 26 | #define HASH_H_ 27 | 28 | //#define DEBUG_SHA1 29 | 30 | void sha1(const uint8_t* data, uint32_t size, uint8_t hash[20]); 31 | void sha1(const char* data, uint32_t size, uint8_t hash[20]); 32 | void sha1(const String& data, uint8_t hash[20]); 33 | 34 | String sha1(const uint8_t* data, uint32_t size); 35 | String sha1(const char* data, uint32_t size); 36 | String sha1(const String& data); 37 | 38 | #endif /* HASH_H_ */ -------------------------------------------------------------------------------- /arch/stm32/Adafruit_LittleFS_stm32/README.md: -------------------------------------------------------------------------------- 1 | This is LittleFS from Adafruit, stripped from things that makes it not compile with stm32 (refs to TinyUSB and free_rtos, mostly) -------------------------------------------------------------------------------- /arch/stm32/Adafruit_LittleFS_stm32/library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit Little File System Libraries 2 | version=0.11.0 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Arduino library for ARM Little File System 6 | paragraph=Arduino library for ARM Little File System 7 | category=Data Storage 8 | url=https://github.com/adafruit/Adafruit_nRF52_Arduino 9 | architectures=* 10 | includes=Adafruit_LittleFS.h 11 | -------------------------------------------------------------------------------- /arch/stm32/Adafruit_LittleFS_stm32/src/littlefs/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Arm Limited. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | - Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | - Redistributions in binary form must reproduce the above copyright notice, this 9 | list of conditions and the following disclaimer in the documentation and/or 10 | other materials provided with the distribution. 11 | - Neither the name of ARM nor the names of its contributors may be used to 12 | endorse or promote products derived from this software without specific prior 13 | written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /arch/stm32/Adafruit_LittleFS_stm32/src/littlefs/lfs_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * lfs util functions 3 | * 4 | * Copyright (c) 2017, Arm Limited. All rights reserved. 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | #include "lfs_util.h" 8 | 9 | // Only compile if user does not provide custom config 10 | #ifndef LFS_CONFIG 11 | 12 | 13 | // Software CRC implementation with small lookup table 14 | void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { 15 | static const uint32_t rtable[16] = { 16 | 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 17 | 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 18 | 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 19 | 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c, 20 | }; 21 | 22 | const uint8_t *data = buffer; 23 | 24 | for (size_t i = 0; i < size; i++) { 25 | *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf]; 26 | *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf]; 27 | } 28 | } 29 | 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /arch/stm32/build_hex.py: -------------------------------------------------------------------------------- 1 | Import("env") 2 | 3 | # Make custom HEX from ELF 4 | env.AddPostAction( 5 | "$BUILD_DIR/${PROGNAME}.elf", 6 | env.VerboseAction(" ".join([ 7 | "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", 8 | '"$BUILD_DIR/${PROGNAME}.elf"', '"$BUILD_DIR/${PROGNAME}.hex"' 9 | ]), "Building $BUILD_DIR/${PROGNAME}.hex") 10 | ) -------------------------------------------------------------------------------- /boards/heltec_t114.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "nrf52840_s140_v6.ld" 5 | }, 6 | "core": "nRF5", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA", 9 | "f_cpu": "64000000L", 10 | "hwids": [ 11 | ["0x239A","0x8029"], 12 | ["0x239A","0x0029"], 13 | ["0x239A","0x002A"], 14 | ["0x239A","0x802A"] 15 | ], 16 | "usb_product": "HT-n5262", 17 | "mcu": "nrf52840", 18 | "variant": "Heltec_T114_Board", 19 | "bsp": { 20 | "name": "adafruit" 21 | }, 22 | "softdevice": { 23 | "sd_flags": "-DS140", 24 | "sd_name": "s140", 25 | "sd_version": "6.1.1", 26 | "sd_fwid": "0x00B6" 27 | }, 28 | "bootloader": { 29 | "settings_addr": "0xFF000" 30 | } 31 | }, 32 | "connectivity": [ 33 | "bluetooth" 34 | ], 35 | "debug": { 36 | "jlink_device": "nRF52840_xxAA", 37 | "svd_path": "nrf52840.svd", 38 | "openocd_target": "nrf52.cfg" 39 | }, 40 | "frameworks": [ 41 | "arduino" 42 | ], 43 | "name": "Heltec T114 Board", 44 | "upload": { 45 | "maximum_ram_size": 248832, 46 | "maximum_size": 815104, 47 | "speed": 115200, 48 | "protocol": "nrfutil", 49 | "protocols": [ 50 | "jlink", 51 | "nrfjprog", 52 | "nrfutil", 53 | "stlink" 54 | ], 55 | "use_1200bps_touch": true, 56 | "require_upload_port": true, 57 | "wait_for_upload_port": true 58 | }, 59 | "url": "https://heltec.org/", 60 | "vendor": "Heltec" 61 | } -------------------------------------------------------------------------------- /boards/nano-g2-ultra.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "nrf52840_s140_v6.ld" 5 | }, 6 | "core": "nRF5", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA", 9 | "f_cpu": "64000000L", 10 | "hwids": [ 11 | [ 12 | "0x239A", 13 | "0x8029" 14 | ], 15 | [ 16 | "0x239A", 17 | "0x0029" 18 | ], 19 | [ 20 | "0x239A", 21 | "0x002A" 22 | ], 23 | [ 24 | "0x239A", 25 | "0x802A" 26 | ] 27 | ], 28 | "usb_product": "BQ nRF52840", 29 | "mcu": "nrf52840", 30 | "variant": "nano-g2-ultra", 31 | "bsp": { 32 | "name": "adafruit" 33 | }, 34 | "softdevice": { 35 | "sd_flags": "-DS140", 36 | "sd_name": "s140", 37 | "sd_version": "6.1.1", 38 | "sd_fwid": "0x00B6" 39 | }, 40 | "bootloader": { 41 | "settings_addr": "0xFF000" 42 | } 43 | }, 44 | "connectivity": [ 45 | "bluetooth" 46 | ], 47 | "debug": { 48 | "jlink_device": "nRF52840_xxAA", 49 | "svd_path": "nrf52840.svd" 50 | }, 51 | "frameworks": [ 52 | "arduino" 53 | ], 54 | "name": "BQ nRF52840", 55 | "upload": { 56 | "maximum_ram_size": 248832, 57 | "maximum_size": 815104, 58 | "speed": 115200, 59 | "protocol": "nrfutil", 60 | "protocols": [ 61 | "jlink", 62 | "nrfjprog", 63 | "nrfutil", 64 | "stlink" 65 | ], 66 | "use_1200bps_touch": true, 67 | "require_upload_port": true, 68 | "wait_for_upload_port": true 69 | }, 70 | "url": "https://wiki.uniteng.com/en/meshtastic/nano-g2-ultra", 71 | "vendor": "BQ Consulting" 72 | } -------------------------------------------------------------------------------- /boards/nrf52840_s140_v6.ld: -------------------------------------------------------------------------------- 1 | /* Linker script to configure memory regions. */ 2 | 3 | SEARCH_DIR(.) 4 | GROUP(-lgcc -lc -lnosys) 5 | 6 | MEMORY 7 | { 8 | FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xED000 - 0x26000 9 | 10 | /* SRAM required by Softdevice depend on 11 | * - Attribute Table Size (Number of Services and Characteristics) 12 | * - Vendor UUID count 13 | * - Max ATT MTU 14 | * - Concurrent connection peripheral + central + secure links 15 | * - Event Len, HVN queue, Write CMD queue 16 | */ 17 | RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20040000 - 0x20006000 18 | } 19 | 20 | SECTIONS 21 | { 22 | . = ALIGN(4); 23 | .svc_data : 24 | { 25 | PROVIDE(__start_svc_data = .); 26 | KEEP(*(.svc_data)) 27 | PROVIDE(__stop_svc_data = .); 28 | } > RAM 29 | 30 | .fs_data : 31 | { 32 | PROVIDE(__start_fs_data = .); 33 | KEEP(*(.fs_data)) 34 | PROVIDE(__stop_fs_data = .); 35 | } > RAM 36 | } INSERT AFTER .data; 37 | 38 | INCLUDE "nrf52_common.ld" 39 | -------------------------------------------------------------------------------- /boards/nrf52840_s140_v7.ld: -------------------------------------------------------------------------------- 1 | /* Linker script to configure memory regions. */ 2 | 3 | SEARCH_DIR(.) 4 | GROUP(-lgcc -lc -lnosys) 5 | 6 | MEMORY 7 | { 8 | FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xED000 - 0x27000 9 | 10 | /* SRAM required by Softdevice depend on 11 | * - Attribute Table Size (Number of Services and Characteristics) 12 | * - Vendor UUID count 13 | * - Max ATT MTU 14 | * - Concurrent connection peripheral + central + secure links 15 | * - Event Len, HVN queue, Write CMD queue 16 | */ 17 | RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20040000 - 0x20006000 18 | } 19 | 20 | SECTIONS 21 | { 22 | . = ALIGN(4); 23 | .svc_data : 24 | { 25 | PROVIDE(__start_svc_data = .); 26 | KEEP(*(.svc_data)) 27 | PROVIDE(__stop_svc_data = .); 28 | } > RAM 29 | 30 | .fs_data : 31 | { 32 | PROVIDE(__start_fs_data = .); 33 | KEEP(*(.fs_data)) 34 | PROVIDE(__stop_fs_data = .); 35 | } > RAM 36 | } INSERT AFTER .data; 37 | 38 | INCLUDE "nrf52_common.ld" 39 | -------------------------------------------------------------------------------- /boards/promicro_nrf52840.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino":{ 4 | "ldscript": "nrf52840_s140_v6.ld" 5 | }, 6 | "core": "nRF5", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA", 9 | "f_cpu": "64000000L", 10 | "hwids": [ 11 | [ 12 | "0x239A", 13 | "0x00B3" 14 | ], 15 | [ 16 | "0x239A", 17 | "0x8029" 18 | ], 19 | [ 20 | "0x239A", 21 | "0x0029" 22 | ], 23 | [ 24 | "0x239A", 25 | "0x002A" 26 | ], 27 | [ 28 | "0x239A", 29 | "0x802A" 30 | ] 31 | ], 32 | "usb_product": "ProMicro NRF52840", 33 | "mcu": "nrf52840", 34 | "variant": "promicro_nrf52840", 35 | "variants_dir": "variants", 36 | "bsp": { 37 | "name": "adafruit" 38 | }, 39 | "softdevice": { 40 | "sd_flags": "-DS140", 41 | "sd_name": "s140", 42 | "sd_version": "6.1.1", 43 | "sd_fwid": "0x00B6" 44 | }, 45 | "bootloader": { 46 | "settings_addr": "0xFF000" 47 | } 48 | }, 49 | "connectivity": [ 50 | "bluetooth" 51 | ], 52 | "debug": { 53 | "jlink_device": "nRF52840_xxAA", 54 | "svd_path": "nrf52840.svd", 55 | "openocd_target": "nrf52.cfg" 56 | }, 57 | "frameworks": [ 58 | "arduino", 59 | "zephyr" 60 | ], 61 | "name": "ProMicro NRF52840", 62 | "upload": { 63 | "maximum_ram_size": 248832, 64 | "maximum_size": 815104, 65 | "speed": 115200, 66 | "protocol": "nrfutil", 67 | "protocols": [ 68 | "jlink", 69 | "nrfjprog", 70 | "nrfutil", 71 | "stlink" 72 | ], 73 | "use_1200bps_touch": true, 74 | "require_upload_port": true, 75 | "wait_for_upload_port": true 76 | }, 77 | "url": "https://www.nologo.tech/en/product/otherboard/NRF52840.html", 78 | "vendor": "Nologo" 79 | } -------------------------------------------------------------------------------- /boards/rak3172.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "variant_h": "variant_RAK3172_MODULE.h" 5 | }, 6 | "core": "stm32", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DSTM32WL -DSTM32WLxx -DSTM32WLE5xx", 9 | "framework_extra_flags": { 10 | "arduino": "-DUSE_CM4_STARTUP_FILE -DARDUINO_RAK3172_MODULE" 11 | }, 12 | "f_cpu": "48000000L", 13 | "mcu": "stm32wle5ccu", 14 | "product_line": "STM32WLE5xx", 15 | "variant": "STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U" 16 | }, 17 | "debug": { 18 | "default_tools": ["stlink"], 19 | "jlink_device": "STM32WLE5CC", 20 | "openocd_target": "stm32wlx", 21 | "svd_path": "STM32WLE5_CM4.svd" 22 | }, 23 | "frameworks": ["arduino"], 24 | "name": "BB-STM32WL", 25 | "upload": { 26 | "maximum_ram_size": 65536, 27 | "maximum_size": 262144, 28 | "protocol": "stlink", 29 | "protocols": ["stlink", "jlink"] 30 | }, 31 | "url": "https://store.rakwireless.com/products/wisduo-lpwan-module-rak3172", 32 | "vendor": "RAK" 33 | } 34 | -------------------------------------------------------------------------------- /boards/seeed-xiao-afruitnrf52-nrf52840.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "nrf52840_s140_v7.ld" 5 | }, 6 | "core": "nRF5", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DARDUINO_Seeed_XIAO_nRF52840 -DNRF52840_XXAA -DSEEED_XIAO_NRF52840 ", 9 | "f_cpu": "64000000L", 10 | "hwids": [ 11 | [ "0x2886", "0x8044" ], 12 | [ "0x2886", "0x0044" ] 13 | ], 14 | "mcu": "nrf52840", 15 | "variant": "Seeed_XIAO_nRF52840", 16 | "softdevice": { 17 | "sd_flags": "-DS140", 18 | "sd_name": "s140", 19 | "sd_version": "7.3.0", 20 | "sd_fwid": "0x0123" 21 | }, 22 | "bsp": { 23 | "name": "adafruit" 24 | }, 25 | "bootloader": { 26 | "settings_addr": "0xFF000" 27 | }, 28 | "usb_product": "XIAO nRF52840" 29 | }, 30 | "connectivity": [ 31 | "bluetooth" 32 | ], 33 | "debug": { 34 | "jlink_device": "nRF52840_xxAA", 35 | "openocd_target": "nrf52.cfg", 36 | "svd_path": "nrf52840.svd" 37 | }, 38 | "frameworks": [ 39 | "arduino" 40 | ], 41 | "name": "Seeed Studio XIAO nRF52840", 42 | "upload": { 43 | "maximum_ram_size": 237568, 44 | "maximum_size": 811008, 45 | "protocol": "nrfutil", 46 | "speed": 115200, 47 | "protocols": [ 48 | "jlink", 49 | "nrfjprog", 50 | "nrfutil", 51 | "cmsis-dap", 52 | "sam-ba", 53 | "blackmagic" 54 | ], 55 | "use_1200bps_touch": true, 56 | "require_upload_port": true, 57 | "wait_for_upload_port": true 58 | }, 59 | "url": "https://wiki.seeedstudio.com/XIAO_BLE", 60 | "vendor": "Seeed Studio" 61 | } 62 | -------------------------------------------------------------------------------- /boards/station-g2.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "esp32s3_out.ld", 5 | "memory_type": "qio_opi" 6 | }, 7 | "core": "esp32", 8 | "extra_flags": [ 9 | "-DBOARD_HAS_PSRAM", 10 | "-DARDUINO_USB_CDC_ON_BOOT=1", 11 | "-DARDUINO_USB_MODE=0", 12 | "-DARDUINO_RUNNING_CORE=1", 13 | "-DARDUINO_EVENT_RUNNING_CORE=0" 14 | ], 15 | "f_cpu": "240000000L", 16 | "f_flash": "80000000L", 17 | "flash_mode": "qio", 18 | "hwids": [["0x303A", "0x1001"]], 19 | "mcu": "esp32s3", 20 | "variant": "esp32s3" 21 | }, 22 | "connectivity": [ 23 | "wifi" 24 | ], 25 | "debug": { 26 | "default_tool": "esp-builtin", 27 | "onboard_tools": ["esp-builtin"], 28 | "openocd_target": "esp32s3.cfg" 29 | }, 30 | "frameworks": ["arduino", "espidf"], 31 | "name": "BQ Station G2", 32 | "upload": { 33 | "flash_size": "16MB", 34 | "maximum_ram_size": 327680, 35 | "maximum_size": 16777216, 36 | "use_1200bps_touch": true, 37 | "wait_for_upload_port": true, 38 | "require_upload_port": true, 39 | "speed": 921600 40 | }, 41 | "url": "https://wiki.uniteng.com/en/meshtastic/station-g2", 42 | "vendor": "BQ Consulting" 43 | } 44 | -------------------------------------------------------------------------------- /boards/t-echo.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "nrf52840_s140_v6.ld" 5 | }, 6 | "core": "nRF5", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA", 9 | "f_cpu": "64000000L", 10 | "hwids": [ 11 | [ 12 | "0x239A", 13 | "0x8029" 14 | ] 15 | ], 16 | "usb_product": "NRF52 DK", 17 | "mcu": "nrf52840", 18 | "variant": "pca10056", 19 | "bsp": { 20 | "name": "adafruit" 21 | }, 22 | "softdevice": { 23 | "sd_flags": "-DS140", 24 | "sd_name": "s140", 25 | "sd_version": "6.1.1", 26 | "sd_fwid": "0x00B6" 27 | }, 28 | "bootloader": { 29 | "settings_addr": "0xFF000" 30 | } 31 | }, 32 | "connectivity": [ 33 | "bluetooth" 34 | ], 35 | "debug": { 36 | "jlink_device": "nRF52840_xxAA", 37 | "onboard_tools": [ 38 | "jlink" 39 | ], 40 | "svd_path": "nrf52840.svd", 41 | "openocd_target": "nrf52.cfg" 42 | }, 43 | "frameworks": [ 44 | "arduino" 45 | ], 46 | "name": "LilyGo T-ECHO", 47 | "upload": { 48 | "maximum_ram_size": 248832, 49 | "maximum_size": 815104, 50 | "require_upload_port": true, 51 | "speed": 115200, 52 | "protocol": "jlink", 53 | "protocols": [ 54 | "jlink", 55 | "nrfjprog", 56 | "stlink", 57 | "cmsis-dap", 58 | "blackmagic" 59 | ] 60 | }, 61 | "url": "https://os.mbed.com/platforms/Nordic-nRF52840-DK/", 62 | "vendor": "Nordic" 63 | } -------------------------------------------------------------------------------- /boards/t3_s3_v1_x.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "esp32s3_out.ld", 5 | "partitions": "default.csv", 6 | "memory_type": "qio_qspi" 7 | }, 8 | "core": "esp32", 9 | "extra_flags": [ 10 | "-DARDUINO_LILYGO_T3_S3_V1_X", 11 | "-DBOARD_HAS_PSRAM", 12 | "-DARDUINO_USB_CDC_ON_BOOT=1", 13 | "-DARDUINO_RUNNING_CORE=1", 14 | "-DARDUINO_EVENT_RUNNING_CORE=1", 15 | "-DARDUINO_USB_MODE=1" 16 | ], 17 | "f_cpu": "240000000L", 18 | "f_flash": "80000000L", 19 | "flash_mode": "qio", 20 | "mcu": "esp32s3", 21 | "variant": "esp32s3" 22 | }, 23 | "connectivity": [ 24 | "wifi" 25 | ], 26 | "debug": { 27 | "openocd_target": "esp32s3.cfg" 28 | }, 29 | "frameworks": [ 30 | "arduino", 31 | "espidf" 32 | ], 33 | "name": "LilyGo T3-S3 Radio", 34 | "upload": { 35 | "flash_size": "4MB", 36 | "maximum_ram_size": 327680, 37 | "maximum_size": 4194304, 38 | "use_1200bps_touch": true, 39 | "wait_for_upload_port": true, 40 | "require_upload_port": true, 41 | "speed": 460800 42 | }, 43 | "url": "https://www.lilygo.cc", 44 | "vendor": "LilyGo" 45 | } -------------------------------------------------------------------------------- /boards/t_beams3_supreme.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino":{ 4 | "ldscript": "esp32s3_out.ld", 5 | "partitions": "default.csv", 6 | "memory_type": "qio_qspi" 7 | }, 8 | "core": "esp32", 9 | "extra_flags": [ 10 | "-DARDUINO_USB_MODE=1", 11 | "-DARDUINO_USB_CDC_ON_BOOT=1", 12 | "-DARDUINO_RUNNING_CORE=1", 13 | "-DARDUINO_EVENT_RUNNING_CORE=1" 14 | ], 15 | "f_cpu": "240000000L", 16 | "f_flash": "80000000L", 17 | "flash_mode": "qio", 18 | "hwids": [ 19 | [ 20 | "0x303A", 21 | "0x1001" 22 | ] 23 | ], 24 | "mcu": "esp32s3", 25 | "variant": "esp32s3" 26 | }, 27 | "connectivity": [ 28 | "wifi" 29 | ], 30 | "debug": { 31 | "default_tool": "esp-builtin", 32 | "onboard_tools": [ 33 | "esp-builtin" 34 | ], 35 | "openocd_target": "esp32s3.cfg" 36 | }, 37 | "frameworks": [ 38 | "arduino", 39 | "espidf" 40 | ], 41 | "name": "LilyGo T-Beam supreme (8MB Flash 8MB PSRAM)", 42 | "upload": { 43 | "flash_size": "8MB", 44 | "maximum_ram_size": 327680, 45 | "maximum_size": 8388608, 46 | "require_upload_port": true, 47 | "speed": 460800 48 | }, 49 | "url": "https://www.lilygo.cc/products/t-beamsupreme-m", 50 | "vendor": "LilyGo" 51 | } -------------------------------------------------------------------------------- /boards/thinknode_m1.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "nrf52840_s140_v6.ld" 5 | }, 6 | "core": "nRF5", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA", 9 | "f_cpu": "64000000L", 10 | "hwids": [ 11 | [ 12 | "0x239A", 13 | "0x4405" 14 | ], 15 | [ 16 | "0x239A", 17 | "0x0029" 18 | ], 19 | [ 20 | "0x239A", 21 | "0x002A" 22 | ] 23 | ], 24 | "usb_product": "elecrow_eink", 25 | "mcu": "nrf52840", 26 | "variant": "ELECROW-ThinkNode-M1", 27 | "bsp": { 28 | "name": "adafruit" 29 | }, 30 | "softdevice": { 31 | "sd_flags": "-DS140", 32 | "sd_name": "s140", 33 | "sd_version": "6.1.1", 34 | "sd_fwid": "0x00B6" 35 | }, 36 | "bootloader": { 37 | "settings_addr": "0xFF000" 38 | } 39 | }, 40 | "connectivity": [ 41 | "bluetooth" 42 | ], 43 | "debug": { 44 | "jlink_device": "nRF52840_xxAA", 45 | "onboard_tools": [ 46 | "jlink" 47 | ], 48 | "svd_path": "nrf52840.svd", 49 | "openocd_target": "nrf52.cfg" 50 | }, 51 | "frameworks": [ 52 | "arduino" 53 | ], 54 | "name": "elecrow eink", 55 | "upload": { 56 | "maximum_ram_size": 248832, 57 | "maximum_size": 815104, 58 | "speed": 115200, 59 | "use_1200bps_touch": true, 60 | "require_upload_port": true, 61 | "wait_for_upload_port": true, 62 | "protocol": "nrfutil", 63 | "protocols": [ 64 | "jlink", 65 | "nrfjprog", 66 | "nrfutil", 67 | "stlink" 68 | ] 69 | }, 70 | "url": "https://github.com/Elecrow-RD", 71 | "vendor": "ELECROW" 72 | } -------------------------------------------------------------------------------- /boards/tracker-t1000-e.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "nrf52840_s140_v7.ld" 5 | }, 6 | "core": "nRF5", 7 | "cpu": "cortex-m4", 8 | "extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA", 9 | "f_cpu": "64000000L", 10 | "hwids": [ 11 | ["0x239A", "0x8029"], 12 | ["0x239A", "0x0029"], 13 | ["0x239A", "0x002A"], 14 | ["0x239A", "0x802A"] 15 | ], 16 | "usb_product": "T1000-E-BOOT", 17 | "mcu": "nrf52840", 18 | "variant": "Seeed_T1000-E", 19 | "bsp": { 20 | "name": "adafruit" 21 | }, 22 | "softdevice": { 23 | "sd_flags": "-DS140", 24 | "sd_name": "s140", 25 | "sd_version": "7.3.0", 26 | "sd_fwid": "0x0123" 27 | }, 28 | "bootloader": { 29 | "settings_addr": "0xFF000" 30 | } 31 | }, 32 | "connectivity": ["bluetooth"], 33 | "debug": { 34 | "jlink_device": "nRF52840_xxAA", 35 | "svd_path": "nrf52840.svd", 36 | "openocd_target": "nrf52.cfg" 37 | }, 38 | "frameworks": ["arduino"], 39 | "name": "Seeed T1000-E", 40 | "upload": { 41 | "maximum_ram_size": 248832, 42 | "maximum_size": 815104, 43 | "speed": 115200, 44 | "protocol": "nrfutil", 45 | "protocols": [ 46 | "jlink", 47 | "nrfjprog", 48 | "nrfutil", 49 | "stlink", 50 | "cmsis-dap", 51 | "blackmagic" 52 | ], 53 | "use_1200bps_touch": true, 54 | "require_upload_port": true, 55 | "wait_for_upload_port": true 56 | }, 57 | "url": "https://www.seeedstudio.com/SenseCAP-Card-Tracker-T1000-E-for-Meshtastic-p-5913.html", 58 | "vendor": "Seeed Studio" 59 | } 60 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | let 3 | in 4 | pkgs.mkShell { 5 | buildInputs = [ 6 | pkgs.platformio 7 | # optional: needed as a programmer i.e. for esp32 8 | pkgs.avrdude 9 | ]; 10 | } 11 | -------------------------------------------------------------------------------- /examples/companion_radio/NodePrefs.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_PREFS_H 2 | #define NODE_PREFS_H 3 | 4 | #include // For uint8_t, uint32_t 5 | 6 | #define TELEM_MODE_DENY 0 7 | #define TELEM_MODE_ALLOW_FLAGS 1 // use contact.flags 8 | #define TELEM_MODE_ALLOW_ALL 2 9 | 10 | struct NodePrefs { // persisted to file 11 | float airtime_factor; 12 | char node_name[32]; 13 | float freq; 14 | uint8_t sf; 15 | uint8_t cr; 16 | uint8_t reserved1; 17 | uint8_t manual_add_contacts; 18 | float bw; 19 | uint8_t tx_power_dbm; 20 | uint8_t telemetry_mode_base; 21 | uint8_t telemetry_mode_loc; 22 | uint8_t telemetry_mode_env; 23 | float rx_delay_base; 24 | uint32_t ble_pin; 25 | }; 26 | 27 | #endif // NODE_PREFS_H -------------------------------------------------------------------------------- /examples/companion_radio/UITask.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef PIN_BUZZER 8 | #include 9 | #endif 10 | 11 | #include "NodePrefs.h" 12 | 13 | enum class UIEventType 14 | { 15 | none, 16 | contactMessage, 17 | channelMessage, 18 | roomMessage, 19 | newContactMessage 20 | }; 21 | 22 | class UITask { 23 | DisplayDriver* _display; 24 | mesh::MainBoard* _board; 25 | #ifdef PIN_BUZZER 26 | genericBuzzer buzzer; 27 | #endif 28 | unsigned long _next_refresh, _auto_off; 29 | bool _connected; 30 | uint32_t _pin_code; 31 | NodePrefs* _node_prefs; 32 | char _version_info[32]; 33 | char _origin[62]; 34 | char _msg[80]; 35 | int _msgcount; 36 | bool _need_refresh = true; 37 | 38 | void renderCurrScreen(); 39 | void buttonHandler(); 40 | void userLedHandler(); 41 | void renderBatteryIndicator(uint16_t batteryMilliVolts); 42 | 43 | 44 | public: 45 | 46 | UITask(mesh::MainBoard* board) : _board(board), _display(NULL) { 47 | _next_refresh = 0; 48 | _connected = false; 49 | } 50 | void begin(DisplayDriver* display, NodePrefs* node_prefs, const char* build_date, const char* firmware_version, uint32_t pin_code); 51 | 52 | void setHasConnection(bool connected) { _connected = connected; } 53 | bool hasDisplay() const { return _display != NULL; } 54 | void clearMsgPreview(); 55 | void msgRead(int msgcount); 56 | void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount); 57 | void soundBuzzer(UIEventType bet = UIEventType::none); 58 | void loop(); 59 | }; 60 | -------------------------------------------------------------------------------- /examples/simple_repeater/UITask.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class UITask { 7 | DisplayDriver* _display; 8 | unsigned long _next_read, _next_refresh, _auto_off; 9 | int _prevBtnState; 10 | NodePrefs* _node_prefs; 11 | char _version_info[32]; 12 | 13 | void renderCurrScreen(); 14 | public: 15 | UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; } 16 | void begin(NodePrefs* node_prefs, const char* build_date, const char* firmware_version); 17 | 18 | void loop(); 19 | }; -------------------------------------------------------------------------------- /examples/simple_room_server/UITask.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class UITask { 7 | DisplayDriver* _display; 8 | unsigned long _next_read, _next_refresh, _auto_off; 9 | int _prevBtnState; 10 | NodePrefs* _node_prefs; 11 | char _version_info[32]; 12 | 13 | void renderCurrScreen(); 14 | public: 15 | UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; } 16 | void begin(NodePrefs* node_prefs, const char* build_date, const char* firmware_version); 17 | 18 | void loop(); 19 | }; -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /lib/ed25519/ed_25519.h: -------------------------------------------------------------------------------- 1 | #ifndef ED25519_H 2 | #define ED25519_H 3 | 4 | // Nightcracker's Ed25519 - https://github.com/orlp/ed25519 5 | 6 | #include 7 | 8 | #if defined(_WIN32) 9 | #if defined(ED25519_BUILD_DLL) 10 | #define ED25519_DECLSPEC __declspec(dllexport) 11 | #elif defined(ED25519_DLL) 12 | #define ED25519_DECLSPEC __declspec(dllimport) 13 | #else 14 | #define ED25519_DECLSPEC 15 | #endif 16 | #else 17 | #define ED25519_DECLSPEC 18 | #endif 19 | 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | #ifndef ED25519_NO_SEED 26 | int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); 27 | #endif 28 | 29 | void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); 30 | void ED25519_DECLSPEC ed25519_derive_pub(unsigned char *public_key, const unsigned char *private_key); 31 | void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); 32 | int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); 33 | void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); 34 | void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); 35 | 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /lib/ed25519/fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "fixedint.h" 5 | 6 | 7 | /* 8 | fe means field element. 9 | Here the field is \Z/(2^255-19). 10 | An element t, entries t[0]...t[9], represents the integer 11 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 12 | Bounds on each t[i] vary depending on context. 13 | */ 14 | 15 | 16 | typedef int32_t fe[10]; 17 | 18 | 19 | void fe_0(fe h); 20 | void fe_1(fe h); 21 | 22 | void fe_frombytes(fe h, const unsigned char *s); 23 | void fe_tobytes(unsigned char *s, const fe h); 24 | 25 | void fe_copy(fe h, const fe f); 26 | int fe_isnegative(const fe f); 27 | int fe_isnonzero(const fe f); 28 | void fe_cmov(fe f, const fe g, unsigned int b); 29 | void fe_cswap(fe f, fe g, unsigned int b); 30 | 31 | void fe_neg(fe h, const fe f); 32 | void fe_add(fe h, const fe f, const fe g); 33 | void fe_invert(fe out, const fe z); 34 | void fe_sq(fe h, const fe f); 35 | void fe_sq2(fe h, const fe f); 36 | void fe_mul(fe h, const fe f, const fe g); 37 | void fe_mul121666(fe h, fe f); 38 | void fe_pow22523(fe out, const fe z); 39 | void fe_sub(fe h, const fe f, const fe g); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /lib/ed25519/ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | #include "fe.h" 5 | 6 | 7 | /* 8 | ge means group element. 9 | 10 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 11 | satisfying -x^2 + y^2 = 1 + d x^2y^2 12 | where d = -121665/121666. 13 | 14 | Representations: 15 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 16 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 17 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 18 | ge_precomp (Duif): (y+x,y-x,2dxy) 19 | */ 20 | 21 | typedef struct { 22 | fe X; 23 | fe Y; 24 | fe Z; 25 | } ge_p2; 26 | 27 | typedef struct { 28 | fe X; 29 | fe Y; 30 | fe Z; 31 | fe T; 32 | } ge_p3; 33 | 34 | typedef struct { 35 | fe X; 36 | fe Y; 37 | fe Z; 38 | fe T; 39 | } ge_p1p1; 40 | 41 | typedef struct { 42 | fe yplusx; 43 | fe yminusx; 44 | fe xy2d; 45 | } ge_precomp; 46 | 47 | typedef struct { 48 | fe YplusX; 49 | fe YminusX; 50 | fe Z; 51 | fe T2d; 52 | } ge_cached; 53 | 54 | void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); 55 | void ge_tobytes(unsigned char *s, const ge_p2 *h); 56 | int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s); 57 | 58 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 59 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 60 | void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); 61 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 62 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 63 | void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); 64 | 65 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); 66 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); 67 | void ge_p2_0(ge_p2 *h); 68 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); 69 | void ge_p3_0(ge_p3 *h); 70 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); 71 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); 72 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /lib/ed25519/key_exchange.c: -------------------------------------------------------------------------------- 1 | #include "ed_25519.h" 2 | #include "fe.h" 3 | 4 | void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) { 5 | unsigned char e[32]; 6 | unsigned int i; 7 | 8 | fe x1; 9 | fe x2; 10 | fe z2; 11 | fe x3; 12 | fe z3; 13 | fe tmp0; 14 | fe tmp1; 15 | 16 | int pos; 17 | unsigned int swap; 18 | unsigned int b; 19 | 20 | /* copy the private key and make sure it's valid */ 21 | for (i = 0; i < 32; ++i) { 22 | e[i] = private_key[i]; 23 | } 24 | 25 | e[0] &= 248; 26 | e[31] &= 63; 27 | e[31] |= 64; 28 | 29 | /* unpack the public key and convert edwards to montgomery */ 30 | /* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */ 31 | fe_frombytes(x1, public_key); 32 | fe_1(tmp1); 33 | fe_add(tmp0, x1, tmp1); 34 | fe_sub(tmp1, tmp1, x1); 35 | fe_invert(tmp1, tmp1); 36 | fe_mul(x1, tmp0, tmp1); 37 | 38 | fe_1(x2); 39 | fe_0(z2); 40 | fe_copy(x3, x1); 41 | fe_1(z3); 42 | 43 | swap = 0; 44 | for (pos = 254; pos >= 0; --pos) { 45 | b = e[pos / 8] >> (pos & 7); 46 | b &= 1; 47 | swap ^= b; 48 | fe_cswap(x2, x3, swap); 49 | fe_cswap(z2, z3, swap); 50 | swap = b; 51 | 52 | /* from montgomery.h */ 53 | fe_sub(tmp0, x3, z3); 54 | fe_sub(tmp1, x2, z2); 55 | fe_add(x2, x2, z2); 56 | fe_add(z2, x3, z3); 57 | fe_mul(z3, tmp0, x2); 58 | fe_mul(z2, z2, tmp1); 59 | fe_sq(tmp0, tmp1); 60 | fe_sq(tmp1, x2); 61 | fe_add(x3, z3, z2); 62 | fe_sub(z2, z3, z2); 63 | fe_mul(x2, tmp1, tmp0); 64 | fe_sub(tmp1, tmp1, tmp0); 65 | fe_sq(z2, z2); 66 | fe_mul121666(z3, tmp1); 67 | fe_sq(x3, x3); 68 | fe_add(tmp0, tmp0, z3); 69 | fe_mul(z3, x1, z2); 70 | fe_mul(z2, tmp1, tmp0); 71 | } 72 | 73 | fe_cswap(x2, x3, swap); 74 | fe_cswap(z2, z3, swap); 75 | 76 | fe_invert(z2, z2); 77 | fe_mul(x2, x2, z2); 78 | fe_tobytes(shared_secret, x2); 79 | } 80 | -------------------------------------------------------------------------------- /lib/ed25519/keypair.c: -------------------------------------------------------------------------------- 1 | #include "ed_25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | 5 | 6 | void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) { 7 | ge_p3 A; 8 | 9 | sha512(seed, 32, private_key); 10 | private_key[0] &= 248; 11 | private_key[31] &= 63; 12 | private_key[31] |= 64; 13 | 14 | ge_scalarmult_base(&A, private_key); 15 | ge_p3_tobytes(public_key, &A); 16 | } 17 | 18 | void ed25519_derive_pub(unsigned char *public_key, const unsigned char *private_key) { 19 | ge_p3 A; 20 | 21 | ge_scalarmult_base(&A, private_key); 22 | ge_p3_tobytes(public_key, &A); 23 | } 24 | -------------------------------------------------------------------------------- /lib/ed25519/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Orson Peters 2 | 3 | This software is provided 'as-is', without any express or implied warranty. In no event will the 4 | authors be held liable for any damages arising from the use of this software. 5 | 6 | Permission is granted to anyone to use this software for any purpose, including commercial 7 | applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | original software. If you use this software in a product, an acknowledgment in the product 11 | documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 14 | being the original software. 15 | 16 | 3. This notice may not be removed or altered from any source distribution. 17 | -------------------------------------------------------------------------------- /lib/ed25519/sc.h: -------------------------------------------------------------------------------- 1 | #ifndef SC_H 2 | #define SC_H 3 | 4 | /* 5 | The set of scalars is \Z/l 6 | where l = 2^252 + 27742317777372353535851937790883648493. 7 | */ 8 | 9 | void sc_reduce(unsigned char *s); 10 | void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /lib/ed25519/seed.c: -------------------------------------------------------------------------------- 1 | #include "ed_25519.h" 2 | 3 | #ifndef ED25519_NO_SEED 4 | 5 | #ifdef _WIN32 6 | #include 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | int ed25519_create_seed(unsigned char *seed) { 13 | #ifdef _WIN32 14 | HCRYPTPROV prov; 15 | 16 | if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 17 | return 1; 18 | } 19 | 20 | if (!CryptGenRandom(prov, 32, seed)) { 21 | CryptReleaseContext(prov, 0); 22 | return 1; 23 | } 24 | 25 | CryptReleaseContext(prov, 0); 26 | #else 27 | FILE *f = fopen("/dev/urandom", "rb"); 28 | 29 | if (f == NULL) { 30 | return 1; 31 | } 32 | 33 | fread(seed, 1, 32, f); 34 | fclose(f); 35 | #endif 36 | 37 | return 0; 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /lib/ed25519/sha512.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA512_H 2 | #define SHA512_H 3 | 4 | #include 5 | 6 | #include "fixedint.h" 7 | 8 | /* state */ 9 | typedef struct sha512_context_ { 10 | uint64_t length, state[8]; 11 | size_t curlen; 12 | unsigned char buf[128]; 13 | } sha512_context; 14 | 15 | 16 | int sha512_init(sha512_context * md); 17 | int sha512_final(sha512_context * md, unsigned char *out); 18 | int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen); 19 | int sha512(const unsigned char *message, size_t message_len, unsigned char *out); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /lib/ed25519/sign.c: -------------------------------------------------------------------------------- 1 | #include "ed_25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | 7 | void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { 8 | sha512_context hash; 9 | unsigned char hram[64]; 10 | unsigned char r[64]; 11 | ge_p3 R; 12 | 13 | 14 | sha512_init(&hash); 15 | sha512_update(&hash, private_key + 32, 32); 16 | sha512_update(&hash, message, message_len); 17 | sha512_final(&hash, r); 18 | 19 | sc_reduce(r); 20 | ge_scalarmult_base(&R, r); 21 | ge_p3_tobytes(signature, &R); 22 | 23 | sha512_init(&hash); 24 | sha512_update(&hash, signature, 32); 25 | sha512_update(&hash, public_key, 32); 26 | sha512_update(&hash, message, message_len); 27 | sha512_final(&hash, hram); 28 | 29 | sc_reduce(hram); 30 | sc_muladd(signature + 32, hram, private_key, r); 31 | } 32 | -------------------------------------------------------------------------------- /lib/ed25519/verify.c: -------------------------------------------------------------------------------- 1 | #include "ed_25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | static int consttime_equal(const unsigned char *x, const unsigned char *y) { 7 | unsigned char r = 0; 8 | 9 | r = x[0] ^ y[0]; 10 | #define F(i) r |= x[i] ^ y[i] 11 | F(1); 12 | F(2); 13 | F(3); 14 | F(4); 15 | F(5); 16 | F(6); 17 | F(7); 18 | F(8); 19 | F(9); 20 | F(10); 21 | F(11); 22 | F(12); 23 | F(13); 24 | F(14); 25 | F(15); 26 | F(16); 27 | F(17); 28 | F(18); 29 | F(19); 30 | F(20); 31 | F(21); 32 | F(22); 33 | F(23); 34 | F(24); 35 | F(25); 36 | F(26); 37 | F(27); 38 | F(28); 39 | F(29); 40 | F(30); 41 | F(31); 42 | #undef F 43 | 44 | return !r; 45 | } 46 | 47 | int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { 48 | unsigned char h[64]; 49 | unsigned char checker[32]; 50 | sha512_context hash; 51 | ge_p3 A; 52 | ge_p2 R; 53 | 54 | if (signature[63] & 224) { 55 | return 0; 56 | } 57 | 58 | if (ge_frombytes_negate_vartime(&A, public_key) != 0) { 59 | return 0; 60 | } 61 | 62 | sha512_init(&hash); 63 | sha512_update(&hash, signature, 32); 64 | sha512_update(&hash, public_key, 32); 65 | sha512_update(&hash, message, message_len); 66 | sha512_final(&hash, h); 67 | 68 | sc_reduce(h); 69 | ge_double_scalarmult_vartime(&R, h, &A, signature + 32); 70 | ge_tobytes(checker, &R); 71 | 72 | if (!consttime_equal(checker, signature)) { 73 | return 0; 74 | } 75 | 76 | return 1; 77 | } 78 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Scott Powell / rippleradios.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /logo/meshcore.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ripplebiz/MeshCore/5be09ff570211b09ceb67de89269066af44c9d31/logo/meshcore.afdesign -------------------------------------------------------------------------------- /logo/meshcore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ripplebiz/MeshCore/5be09ff570211b09ceb67de89269066af44c9d31/logo/meshcore.png -------------------------------------------------------------------------------- /merge-bin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Adds PlatformIO post-processing to merge all the ESP flash images into a single image. 4 | 5 | import os 6 | 7 | Import("env", "projenv") 8 | 9 | board_config = env.BoardConfig() 10 | firmware_bin = "${BUILD_DIR}/${PROGNAME}.bin" 11 | merged_bin = os.environ.get("MERGED_BIN_PATH", "${BUILD_DIR}/${PROGNAME}-merged.bin") 12 | 13 | 14 | def merge_bin_action(source, target, env): 15 | flash_images = [ 16 | *env.Flatten(env.get("FLASH_EXTRA_IMAGES", [])), 17 | "$ESP32_APP_OFFSET", 18 | source[0].get_abspath(), 19 | ] 20 | merge_cmd = " ".join( 21 | [ 22 | '"$PYTHONEXE"', 23 | '"$OBJCOPY"', 24 | "--chip", 25 | board_config.get("build.mcu", "esp32"), 26 | "merge_bin", 27 | "-o", 28 | merged_bin, 29 | "--flash_mode", 30 | board_config.get("build.flash_mode", "dio"), 31 | "--flash_freq", 32 | "${__get_board_f_flash(__env__)}", 33 | "--flash_size", 34 | board_config.get("upload.flash_size", "4MB"), 35 | *flash_images, 36 | ] 37 | ) 38 | env.Execute(merge_cmd) 39 | 40 | 41 | env.AddCustomTarget( 42 | name="mergebin", 43 | dependencies=firmware_bin, 44 | actions=merge_bin_action, 45 | title="Merge binary", 46 | description="Build combined image", 47 | always_build=True, 48 | ) -------------------------------------------------------------------------------- /src/MeshCore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define MAX_HASH_SIZE 8 6 | #define PUB_KEY_SIZE 32 7 | #define PRV_KEY_SIZE 64 8 | #define SEED_SIZE 32 9 | #define SIGNATURE_SIZE 64 10 | #define MAX_ADVERT_DATA_SIZE 32 11 | #define CIPHER_KEY_SIZE 16 12 | #define CIPHER_BLOCK_SIZE 16 13 | 14 | // V1 15 | #define CIPHER_MAC_SIZE 2 16 | #define PATH_HASH_SIZE 1 17 | 18 | #define MAX_PACKET_PAYLOAD 184 19 | #define MAX_PATH_SIZE 64 20 | #define MAX_TRANS_UNIT 255 21 | 22 | #if MESH_DEBUG && ARDUINO 23 | #include 24 | #define MESH_DEBUG_PRINT(F, ...) Serial.printf("DEBUG: " F, ##__VA_ARGS__) 25 | #define MESH_DEBUG_PRINTLN(F, ...) Serial.printf("DEBUG: " F "\n", ##__VA_ARGS__) 26 | #else 27 | #define MESH_DEBUG_PRINT(...) {} 28 | #define MESH_DEBUG_PRINTLN(...) {} 29 | #endif 30 | 31 | namespace mesh { 32 | 33 | #define BD_STARTUP_NORMAL 0 // getStartupReason() codes 34 | #define BD_STARTUP_RX_PACKET 1 35 | 36 | class MainBoard { 37 | public: 38 | virtual uint16_t getBattMilliVolts() = 0; 39 | virtual const char* getManufacturerName() const = 0; 40 | virtual void onBeforeTransmit() { } 41 | virtual void onAfterTransmit() { } 42 | virtual void reboot() = 0; 43 | virtual void powerOff() { /* no op */ } 44 | virtual uint8_t getStartupReason() const = 0; 45 | virtual bool startOTAUpdate(const char* id, char reply[]) { return false; } // not supported 46 | }; 47 | 48 | /** 49 | * An abstraction of the device's Realtime Clock. 50 | */ 51 | class RTCClock { 52 | uint32_t last_unique; 53 | protected: 54 | RTCClock() { last_unique = 0; } 55 | 56 | public: 57 | /** 58 | * \returns the current time. in UNIX epoch seconds. 59 | */ 60 | virtual uint32_t getCurrentTime() = 0; 61 | 62 | /** 63 | * \param time current time in UNIX epoch seconds. 64 | */ 65 | virtual void setCurrentTime(uint32_t time) = 0; 66 | 67 | uint32_t getCurrentTimeUnique() { 68 | uint32_t t = getCurrentTime(); 69 | if (t <= last_unique) { 70 | return ++last_unique; 71 | } 72 | return last_unique = t; 73 | } 74 | }; 75 | 76 | } -------------------------------------------------------------------------------- /src/Packet.cpp: -------------------------------------------------------------------------------- 1 | #include "Packet.h" 2 | #include 3 | #include 4 | 5 | namespace mesh { 6 | 7 | Packet::Packet() { 8 | header = 0; 9 | path_len = 0; 10 | payload_len = 0; 11 | } 12 | 13 | int Packet::getRawLength() const { 14 | return 2 + path_len + payload_len + (hasTransportCodes() ? 4 : 0); 15 | } 16 | 17 | void Packet::calculatePacketHash(uint8_t* hash) const { 18 | SHA256 sha; 19 | uint8_t t = getPayloadType(); 20 | sha.update(&t, 1); 21 | if (t == PAYLOAD_TYPE_TRACE) { 22 | sha.update(&path_len, sizeof(path_len)); // CAVEAT: TRACE packets can revisit same node on return path 23 | } 24 | sha.update(payload, payload_len); 25 | sha.finalize(hash, MAX_HASH_SIZE); 26 | } 27 | 28 | uint8_t Packet::writeTo(uint8_t dest[]) const { 29 | uint8_t i = 0; 30 | dest[i++] = header; 31 | if (hasTransportCodes()) { 32 | memcpy(&dest[i], &transport_codes[0], 2); i += 2; 33 | memcpy(&dest[i], &transport_codes[1], 2); i += 2; 34 | } 35 | dest[i++] = path_len; 36 | memcpy(&dest[i], path, path_len); i += path_len; 37 | memcpy(&dest[i], payload, payload_len); i += payload_len; 38 | return i; 39 | } 40 | 41 | bool Packet::readFrom(const uint8_t src[], uint8_t len) { 42 | uint8_t i = 0; 43 | header = src[i++]; 44 | if (hasTransportCodes()) { 45 | memcpy(&transport_codes[0], &src[i], 2); i += 2; 46 | memcpy(&transport_codes[1], &src[i], 2); i += 2; 47 | } else { 48 | transport_codes[0] = transport_codes[1] = 0; 49 | } 50 | path_len = src[i++]; 51 | if (path_len > sizeof(path)) return false; // bad encoding 52 | memcpy(path, &src[i], path_len); i += path_len; 53 | if (i >= len) return false; // bad encoding 54 | payload_len = len - i; 55 | if (payload_len > sizeof(payload)) return false; // bad encoding 56 | memcpy(payload, &src[i], payload_len); //i += payload_len; 57 | return true; // success 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /src/helpers/AdvertDataHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define ADV_TYPE_NONE 0 8 | #define ADV_TYPE_CHAT 1 9 | #define ADV_TYPE_REPEATER 2 10 | #define ADV_TYPE_ROOM 3 11 | //FUTURE: 4..15 12 | 13 | #define ADV_LATLON_MASK 0x10 14 | #define ADV_FEAT1_MASK 0x20 // FUTURE 15 | #define ADV_FEAT2_MASK 0x40 // FUTURE 16 | #define ADV_NAME_MASK 0x80 17 | 18 | class AdvertDataBuilder { 19 | uint8_t _type; 20 | const char* _name; 21 | int32_t _lat, _lon; 22 | uint16_t _extra1 = 0; 23 | uint16_t _extra2 = 0; 24 | public: 25 | AdvertDataBuilder(uint8_t adv_type) : _type(adv_type), _name(NULL), _lat(0), _lon(0) { } 26 | AdvertDataBuilder(uint8_t adv_type, const char* name) : _type(adv_type), _name(name), _lat(0), _lon(0) { } 27 | AdvertDataBuilder(uint8_t adv_type, const char* name, double lat, double lon) : 28 | _type(adv_type), _name(name), _lat(lat * 1E6), _lon(lon * 1E6) { } 29 | 30 | void setFeat1(uint16_t extra) { _extra1 = extra; } 31 | void setFeat2(uint16_t extra) { _extra2 = extra; } 32 | 33 | /** 34 | * \brief encode the given advertisement data. 35 | * \param app_data dest array, must be MAX_ADVERT_DATA_SIZE 36 | * \returns the encoded length in bytes 37 | */ 38 | uint8_t encodeTo(uint8_t app_data[]); 39 | }; 40 | 41 | class AdvertDataParser { 42 | uint8_t _flags; 43 | bool _valid; 44 | char _name[MAX_ADVERT_DATA_SIZE]; 45 | int32_t _lat, _lon; 46 | uint16_t _extra1; 47 | uint16_t _extra2; 48 | public: 49 | AdvertDataParser(const uint8_t app_data[], uint8_t app_data_len); 50 | 51 | bool isValid() const { return _valid; } 52 | uint8_t getType() const { return _flags & 0x0F; } 53 | uint16_t getFeat1() const { return _extra1; } 54 | uint16_t getFeat2() const { return _extra2; } 55 | 56 | bool hasName() const { return _name[0] != 0; } 57 | const char* getName() const { return _name; } 58 | 59 | bool hasLatLon() const { return !(_lat == 0 && _lon == 0); } 60 | int32_t getIntLat() const { return _lat; } 61 | int32_t getIntLon() const { return _lon; } 62 | double getLat() const { return ((double)_lat) / 1000000.0; } 63 | double getLon() const { return ((double)_lon) / 1000000.0; } 64 | }; 65 | 66 | class AdvertTimeHelper { 67 | public: 68 | static void formatRelativeTimeDiff(char dest[], int32_t seconds_from_now, bool short_fmt); 69 | }; 70 | -------------------------------------------------------------------------------- /src/helpers/ArduinoHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class VolatileRTCClock : public mesh::RTCClock { 7 | long millis_offset; 8 | public: 9 | VolatileRTCClock() { millis_offset = 1715770351; } // 15 May 2024, 8:50pm 10 | uint32_t getCurrentTime() override { return (millis()/1000 + millis_offset); } 11 | void setCurrentTime(uint32_t time) override { millis_offset = time - millis()/1000; } 12 | }; 13 | 14 | class ArduinoMillis : public mesh::MillisecondClock { 15 | public: 16 | unsigned long getMillis() override { return millis(); } 17 | }; 18 | 19 | class StdRNG : public mesh::RNG { 20 | public: 21 | void begin(long seed) { randomSeed(seed); } 22 | void random(uint8_t* dest, size_t sz) override { 23 | for (int i = 0; i < sz; i++) { 24 | dest[i] = (::random(0, 256) & 0xFF); 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/helpers/ArduinoSerialInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "ArduinoSerialInterface.h" 2 | 3 | #define RECV_STATE_IDLE 0 4 | #define RECV_STATE_HDR_FOUND 1 5 | #define RECV_STATE_LEN1_FOUND 2 6 | #define RECV_STATE_LEN2_FOUND 3 7 | 8 | void ArduinoSerialInterface::enable() { 9 | _isEnabled = true; 10 | _state = RECV_STATE_IDLE; 11 | } 12 | void ArduinoSerialInterface::disable() { 13 | _isEnabled = false; 14 | } 15 | 16 | bool ArduinoSerialInterface::isConnected() const { 17 | return true; // no way of knowing, so assume yes 18 | } 19 | 20 | bool ArduinoSerialInterface::isWriteBusy() const { 21 | return false; 22 | } 23 | 24 | size_t ArduinoSerialInterface::writeFrame(const uint8_t src[], size_t len) { 25 | if (len > MAX_FRAME_SIZE) { 26 | // frame is too big! 27 | return 0; 28 | } 29 | 30 | uint8_t hdr[3]; 31 | hdr[0] = '>'; 32 | hdr[1] = (len & 0xFF); // LSB 33 | hdr[2] = (len >> 8); // MSB 34 | 35 | _serial->write(hdr, 3); 36 | return _serial->write(src, len); 37 | } 38 | 39 | size_t ArduinoSerialInterface::checkRecvFrame(uint8_t dest[]) { 40 | while (_serial->available()) { 41 | int c = _serial->read(); 42 | if (c < 0) break; 43 | 44 | switch (_state) { 45 | case RECV_STATE_IDLE: 46 | if (c == '<') { 47 | _state = RECV_STATE_HDR_FOUND; 48 | } 49 | break; 50 | case RECV_STATE_HDR_FOUND: 51 | _frame_len = (uint8_t)c; // LSB 52 | _state = RECV_STATE_LEN1_FOUND; 53 | break; 54 | case RECV_STATE_LEN1_FOUND: 55 | _frame_len |= ((uint16_t)c) << 8; // MSB 56 | rx_len = 0; 57 | _state = _frame_len > 0 ? RECV_STATE_LEN2_FOUND : RECV_STATE_IDLE; 58 | break; 59 | default: 60 | if (rx_len < MAX_FRAME_SIZE) { 61 | rx_buf[rx_len] = (uint8_t)c; // rest of frame will be discarded if > MAX 62 | } 63 | rx_len++; 64 | if (rx_len >= _frame_len) { // received a complete frame? 65 | if (_frame_len > MAX_FRAME_SIZE) _frame_len = MAX_FRAME_SIZE; // truncate 66 | memcpy(dest, rx_buf, _frame_len); 67 | _state = RECV_STATE_IDLE; // reset state, for next frame 68 | return _frame_len; 69 | } 70 | } 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /src/helpers/ArduinoSerialInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseSerialInterface.h" 4 | #include 5 | 6 | class ArduinoSerialInterface : public BaseSerialInterface { 7 | bool _isEnabled; 8 | uint8_t _state; 9 | uint16_t _frame_len; 10 | uint16_t rx_len; 11 | Stream* _serial; 12 | uint8_t rx_buf[MAX_FRAME_SIZE]; 13 | 14 | public: 15 | ArduinoSerialInterface() { _isEnabled = false; _state = 0; } 16 | 17 | void begin(Stream& serial) { 18 | _serial = &serial; 19 | #ifdef RAK_4631 20 | pinMode(WB_IO2, OUTPUT); 21 | #endif 22 | } 23 | 24 | // BaseSerialInterface methods 25 | void enable() override; 26 | void disable() override; 27 | bool isEnabled() const override { return _isEnabled; } 28 | 29 | bool isConnected() const override; 30 | 31 | bool isWriteBusy() const override; 32 | size_t writeFrame(const uint8_t src[], size_t len) override; 33 | size_t checkRecvFrame(uint8_t dest[]) override; 34 | }; -------------------------------------------------------------------------------- /src/helpers/AutoDiscoverRTCClock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class AutoDiscoverRTCClock : public mesh::RTCClock { 8 | mesh::RTCClock* _fallback; 9 | 10 | bool i2c_probe(TwoWire& wire, uint8_t addr); 11 | public: 12 | AutoDiscoverRTCClock(mesh::RTCClock& fallback) : _fallback(&fallback) { } 13 | 14 | void begin(TwoWire& wire); 15 | uint32_t getCurrentTime() override; 16 | void setCurrentTime(uint32_t time) override; 17 | }; 18 | -------------------------------------------------------------------------------- /src/helpers/BaseSerialInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define MAX_FRAME_SIZE 172 6 | 7 | class BaseSerialInterface { 8 | protected: 9 | BaseSerialInterface() { } 10 | 11 | public: 12 | virtual void enable() = 0; 13 | virtual void disable() = 0; 14 | virtual bool isEnabled() const = 0; 15 | 16 | virtual bool isConnected() const = 0; 17 | 18 | virtual bool isWriteBusy() const = 0; 19 | virtual size_t writeFrame(const uint8_t src[], size_t len) = 0; 20 | virtual size_t checkRecvFrame(uint8_t dest[]) = 0; 21 | }; 22 | -------------------------------------------------------------------------------- /src/helpers/CommonCLI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Mesh.h" 4 | #include 5 | 6 | struct NodePrefs { // persisted to file 7 | float airtime_factor; 8 | char node_name[32]; 9 | double node_lat, node_lon; 10 | char password[16]; 11 | float freq; 12 | uint8_t tx_power_dbm; 13 | uint8_t disable_fwd; 14 | uint8_t advert_interval; // minutes / 2 15 | uint8_t flood_advert_interval; // hours 16 | float rx_delay_base; 17 | float tx_delay_factor; 18 | char guest_password[16]; 19 | float direct_tx_delay_factor; 20 | uint32_t guard; 21 | uint8_t sf; 22 | uint8_t cr; 23 | uint8_t allow_read_only; 24 | uint8_t reserved2; 25 | float bw; 26 | uint8_t flood_max; 27 | }; 28 | 29 | class CommonCLICallbacks { 30 | public: 31 | virtual void savePrefs() = 0; 32 | virtual const char* getFirmwareVer() = 0; 33 | virtual const char* getBuildDate() = 0; 34 | virtual const char* getRole() = 0; 35 | virtual bool formatFileSystem() = 0; 36 | virtual void sendSelfAdvertisement(int delay_millis) = 0; 37 | virtual void updateAdvertTimer() = 0; 38 | virtual void updateFloodAdvertTimer() = 0; 39 | virtual void setLoggingOn(bool enable) = 0; 40 | virtual void eraseLogFile() = 0; 41 | virtual void dumpLogFile() = 0; 42 | virtual void setTxPower(uint8_t power_dbm) = 0; 43 | virtual void formatNeighborsReply(char *reply) = 0; 44 | virtual const uint8_t* getSelfIdPubKey() = 0; 45 | virtual void clearStats() = 0; 46 | }; 47 | 48 | class CommonCLI { 49 | mesh::RTCClock* _rtc; 50 | NodePrefs* _prefs; 51 | CommonCLICallbacks* _callbacks; 52 | mesh::MainBoard* _board; 53 | char tmp[80]; 54 | 55 | mesh::RTCClock* getRTCClock() { return _rtc; } 56 | void savePrefs() { _callbacks->savePrefs(); } 57 | 58 | void checkAdvertInterval(); 59 | 60 | void loadPrefsInt(FILESYSTEM* _fs, const char* filename); 61 | 62 | public: 63 | CommonCLI(mesh::MainBoard& board, mesh::RTCClock& rtc, NodePrefs* prefs, CommonCLICallbacks* callbacks) 64 | : _board(&board), _rtc(&rtc), _prefs(prefs), _callbacks(callbacks) { } 65 | 66 | void loadPrefs(FILESYSTEM* _fs); 67 | void savePrefs(FILESYSTEM* _fs); 68 | void handleCommand(uint32_t sender_timestamp, const char* command, char* reply); 69 | }; 70 | -------------------------------------------------------------------------------- /src/helpers/CustomLLCC68.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received 6 | #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 7 | 8 | class CustomLLCC68 : public LLCC68 { 9 | public: 10 | CustomLLCC68(Module *mod) : LLCC68(mod) { } 11 | 12 | bool isReceiving() { 13 | uint16_t irq = getIrqFlags(); 14 | bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED); 15 | return detected; 16 | } 17 | }; -------------------------------------------------------------------------------- /src/helpers/CustomLLCC68Wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CustomLLCC68.h" 4 | #include "RadioLibWrappers.h" 5 | 6 | class CustomLLCC68Wrapper : public RadioLibWrapper { 7 | public: 8 | CustomLLCC68Wrapper(CustomLLCC68& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } 9 | bool isReceiving() override { 10 | if (((CustomLLCC68 *)_radio)->isReceiving()) return true; 11 | 12 | idle(); // put sx126x into standby 13 | // do some basic CAD (blocks for ~12780 micros (on SF 10)!) 14 | bool activity = (((CustomLLCC68 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED); 15 | if (activity) { 16 | startRecv(); 17 | } else { 18 | idle(); 19 | } 20 | return activity; 21 | } 22 | float getLastRSSI() const override { return ((CustomLLCC68 *)_radio)->getRSSI(); } 23 | float getLastSNR() const override { return ((CustomLLCC68 *)_radio)->getSNR(); } 24 | 25 | float packetScore(float snr, int packet_len) override { 26 | int sf = ((CustomLLCC68 *)_radio)->spreadingFactor; 27 | return packetScoreInt(snr, sf, packet_len); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/helpers/CustomLR1110.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define LR1110_IRQ_HAS_PREAMBLE 0b0000000100 // 4 4 valid LoRa header received 6 | #define LR1110_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received 7 | 8 | class CustomLR1110 : public LR1110 { 9 | public: 10 | CustomLR1110(Module *mod) : LR1110(mod) { } 11 | 12 | bool isReceiving() { 13 | uint16_t irq = getIrqStatus(); 14 | bool detected = ((irq & LR1110_IRQ_HEADER_VALID) || (irq & LR1110_IRQ_HAS_PREAMBLE)); 15 | return detected; 16 | } 17 | }; -------------------------------------------------------------------------------- /src/helpers/CustomLR1110Wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CustomLR1110.h" 4 | #include "RadioLibWrappers.h" 5 | 6 | class CustomLR1110Wrapper : public RadioLibWrapper { 7 | public: 8 | CustomLR1110Wrapper(CustomLR1110& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } 9 | bool isReceiving() override { 10 | if (((CustomLR1110 *)_radio)->isReceiving()) return true; 11 | 12 | idle(); // put sx126x into standby 13 | // do some basic CAD (blocks for ~12780 micros (on SF 10)!) 14 | bool activity = (((CustomLR1110 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED); 15 | if (activity) { 16 | startRecv(); 17 | } else { 18 | idle(); 19 | } 20 | return activity; 21 | } 22 | 23 | void onSendFinished() override { 24 | RadioLibWrapper::onSendFinished(); 25 | _radio->setPreambleLength(8); // overcomes weird issues with small and big pkts 26 | } 27 | 28 | float getLastRSSI() const override { return ((CustomLR1110 *)_radio)->getRSSI(); } 29 | float getLastSNR() const override { return ((CustomLR1110 *)_radio)->getSNR(); } 30 | int16_t setRxBoostedGainMode(bool en) { return ((CustomLR1110 *)_radio)->setRxBoostedGainMode(en); }; 31 | }; 32 | -------------------------------------------------------------------------------- /src/helpers/CustomSTM32WLx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received 6 | #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 7 | 8 | class CustomSTM32WLx : public STM32WLx { 9 | public: 10 | CustomSTM32WLx(STM32WLx_Module *mod) : STM32WLx(mod) { } 11 | 12 | bool isReceiving() { 13 | uint16_t irq = getIrqFlags(); 14 | bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED); 15 | return detected; 16 | } 17 | }; -------------------------------------------------------------------------------- /src/helpers/CustomSTM32WLxWrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CustomSTM32WLx.h" 4 | #include "RadioLibWrappers.h" 5 | #include 6 | 7 | class CustomSTM32WLxWrapper : public RadioLibWrapper { 8 | public: 9 | CustomSTM32WLxWrapper(CustomSTM32WLx& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } 10 | bool isReceiving() override { 11 | if (((CustomSTM32WLx *)_radio)->isReceiving()) return true; 12 | 13 | idle(); // put sx126x into standby 14 | // do some basic CAD (blocks for ~12780 micros (on SF 10)!) 15 | bool activity = (((CustomSTM32WLx *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED); 16 | if (activity) { 17 | startRecv(); 18 | } else { 19 | idle(); 20 | } 21 | return activity; 22 | } 23 | float getLastRSSI() const override { return ((CustomSTM32WLx *)_radio)->getRSSI(); } 24 | float getLastSNR() const override { return ((CustomSTM32WLx *)_radio)->getSNR(); } 25 | 26 | float packetScore(float snr, int packet_len) override { 27 | int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor; 28 | return packetScoreInt(snr, sf, packet_len); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/helpers/CustomSX1262.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received 6 | #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 7 | 8 | class CustomSX1262 : public SX1262 { 9 | public: 10 | CustomSX1262(Module *mod) : SX1262(mod) { } 11 | 12 | bool isReceiving() { 13 | uint16_t irq = getIrqFlags(); 14 | bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED); 15 | return detected; 16 | } 17 | }; -------------------------------------------------------------------------------- /src/helpers/CustomSX1262Wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CustomSX1262.h" 4 | #include "RadioLibWrappers.h" 5 | #include 6 | 7 | class CustomSX1262Wrapper : public RadioLibWrapper { 8 | public: 9 | CustomSX1262Wrapper(CustomSX1262& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } 10 | bool isReceiving() override { 11 | if (((CustomSX1262 *)_radio)->isReceiving()) return true; 12 | 13 | idle(); // put sx126x into standby 14 | // do some basic CAD (blocks for ~12780 micros (on SF 10)!) 15 | bool activity = (((CustomSX1262 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED); 16 | if (activity) { 17 | startRecv(); 18 | } else { 19 | idle(); 20 | } 21 | return activity; 22 | } 23 | float getLastRSSI() const override { return ((CustomSX1262 *)_radio)->getRSSI(); } 24 | float getLastSNR() const override { return ((CustomSX1262 *)_radio)->getSNR(); } 25 | 26 | float packetScore(float snr, int packet_len) override { 27 | int sf = ((CustomSX1262 *)_radio)->spreadingFactor; 28 | return packetScoreInt(snr, sf, packet_len); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/helpers/CustomSX1268.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received 6 | #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 7 | 8 | class CustomSX1268 : public SX1268 { 9 | public: 10 | CustomSX1268(Module *mod) : SX1268(mod) { } 11 | 12 | bool isReceiving() { 13 | uint16_t irq = getIrqFlags(); 14 | bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED); 15 | return detected; 16 | } 17 | }; -------------------------------------------------------------------------------- /src/helpers/CustomSX1268Wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CustomSX1268.h" 4 | #include "RadioLibWrappers.h" 5 | 6 | class CustomSX1268Wrapper : public RadioLibWrapper { 7 | public: 8 | CustomSX1268Wrapper(CustomSX1268& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } 9 | bool isReceiving() override { 10 | if (((CustomSX1268 *)_radio)->isReceiving()) return true; 11 | 12 | idle(); // put sx126x into standby 13 | // do some basic CAD (blocks for ~12780 micros (on SF 10)!) 14 | bool activity = (((CustomSX1268 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED); 15 | if (activity) { 16 | startRecv(); 17 | } else { 18 | idle(); 19 | } 20 | return activity; 21 | } 22 | float getLastRSSI() const override { return ((CustomSX1268 *)_radio)->getRSSI(); } 23 | float getLastSNR() const override { return ((CustomSX1268 *)_radio)->getSNR(); } 24 | 25 | float packetScore(float snr, int packet_len) override { 26 | int sf = ((CustomSX1268 *)_radio)->spreadingFactor; 27 | return packetScoreInt(snr, sf, packet_len); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/helpers/CustomSX1276.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define RH_RF95_MODEM_STATUS_CLEAR 0x10 6 | #define RH_RF95_MODEM_STATUS_HEADER_INFO_VALID 0x08 7 | #define RH_RF95_MODEM_STATUS_RX_ONGOING 0x04 8 | #define RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED 0x02 9 | #define RH_RF95_MODEM_STATUS_SIGNAL_DETECTED 0x01 10 | 11 | class CustomSX1276 : public SX1276 { 12 | public: 13 | CustomSX1276(Module *mod) : SX1276(mod) { } 14 | 15 | bool isReceiving() { 16 | return (getModemStatus() & 17 | (RH_RF95_MODEM_STATUS_SIGNAL_DETECTED 18 | | RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED 19 | | RH_RF95_MODEM_STATUS_HEADER_INFO_VALID)) != 0; 20 | } 21 | 22 | int tryScanChannel() { 23 | // start CAD 24 | int16_t state = startChannelScan(); 25 | RADIOLIB_ASSERT(state); 26 | 27 | // wait for channel activity detected or timeout 28 | unsigned long timeout = millis() + 16; 29 | while(!this->mod->hal->digitalRead(this->mod->getIrq()) && millis() < timeout) { 30 | this->mod->hal->yield(); 31 | if(this->mod->hal->digitalRead(this->mod->getGpio())) { 32 | return(RADIOLIB_PREAMBLE_DETECTED); 33 | } 34 | } 35 | return 0; // timed out 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /src/helpers/CustomSX1276Wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CustomSX1276.h" 4 | #include "RadioLibWrappers.h" 5 | 6 | class CustomSX1276Wrapper : public RadioLibWrapper { 7 | public: 8 | CustomSX1276Wrapper(CustomSX1276& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } 9 | bool isReceiving() override { 10 | if (((CustomSX1276 *)_radio)->isReceiving()) return true; 11 | 12 | idle(); // put into standby 13 | // do some basic CAD (blocks for ~12780 micros (on SF 10)!) 14 | bool activity = (((CustomSX1276 *)_radio)->tryScanChannel() == RADIOLIB_PREAMBLE_DETECTED); 15 | if (activity) { 16 | startRecv(); 17 | } else { 18 | idle(); 19 | } 20 | return activity; 21 | } 22 | float getLastRSSI() const override { return ((CustomSX1276 *)_radio)->getRSSI(); } 23 | float getLastSNR() const override { return ((CustomSX1276 *)_radio)->getSNR(); } 24 | 25 | float packetScore(float snr, int packet_len) override { 26 | int sf = ((CustomSX1276 *)_radio)->spreadingFactor; 27 | return packetScoreInt(snr, sf, packet_len); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/helpers/ESP32Board.cpp: -------------------------------------------------------------------------------- 1 | #ifdef ESP_PLATFORM 2 | 3 | #include "ESP32Board.h" 4 | 5 | #if defined(ADMIN_PASSWORD) // Repeater or Room Server only 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | bool ESP32Board::startOTAUpdate(const char* id, char reply[]) { 14 | WiFi.softAP("MeshCore-OTA", NULL); 15 | 16 | sprintf(reply, "Started: http://%s/update", WiFi.softAPIP().toString().c_str()); 17 | MESH_DEBUG_PRINTLN("startOTAUpdate: %s", reply); 18 | 19 | static char id_buf[60]; 20 | sprintf(id_buf, "%s (%s)", id, getManufacturerName()); 21 | static char home_buf[90]; 22 | sprintf(home_buf, "

Hi! I am a MeshCore Repeater. ID: %s

", id); 23 | 24 | AsyncWebServer* server = new AsyncWebServer(80); 25 | 26 | server->on("/", HTTP_GET, [](AsyncWebServerRequest *request) { 27 | request->send(200, "text/html", home_buf); 28 | }); 29 | server->on("/log", HTTP_GET, [](AsyncWebServerRequest *request) { 30 | request->send(SPIFFS, "/packet_log", "text/plain"); 31 | }); 32 | 33 | AsyncElegantOTA.setID(id_buf); 34 | AsyncElegantOTA.begin(server); // Start ElegantOTA 35 | server->begin(); 36 | 37 | return true; 38 | } 39 | 40 | #else 41 | bool ESP32Board::startOTAUpdate(const char* id, char reply[]) { 42 | return false; // not supported 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/helpers/IdentityStore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(ESP32) || defined(RP2040_PLATFORM) 4 | #include 5 | #define FILESYSTEM fs::FS 6 | #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) 7 | #include 8 | #define FILESYSTEM Adafruit_LittleFS 9 | 10 | using namespace Adafruit_LittleFS_Namespace; 11 | #endif 12 | 13 | #include 14 | 15 | class IdentityStore { 16 | FILESYSTEM* _fs; 17 | const char* _dir; 18 | public: 19 | IdentityStore(FILESYSTEM& fs, const char* dir): _fs(&fs), _dir(dir) { } 20 | 21 | void begin() { if (_dir && _dir[0] == '/') { _fs->mkdir(_dir); } } 22 | bool load(const char *name, mesh::LocalIdentity& id); 23 | bool load(const char *name, mesh::LocalIdentity& id, char display_name[], int max_name_sz); 24 | bool save(const char *name, const mesh::LocalIdentity& id); 25 | bool save(const char *name, const mesh::LocalIdentity& id, const char display_name[]); 26 | }; 27 | -------------------------------------------------------------------------------- /src/helpers/LilyGoTLoraBoard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "ESP32Board.h" 5 | 6 | // LILYGO T-LoRa V2.1-1.6 board with SX1276 7 | class LilyGoTLoraBoard : public ESP32Board { 8 | public: 9 | const char* getManufacturerName() const override { 10 | return "LILYGO T-LoRa V2.1-1.6"; 11 | } 12 | 13 | uint16_t getBattMilliVolts() override { 14 | analogReadResolution(12); 15 | 16 | uint32_t raw = 0; 17 | for (int i = 0; i < 8; i++) { 18 | raw += analogReadMilliVolts(PIN_VBAT_READ); 19 | } 20 | raw = raw / 8; 21 | 22 | return (2 * raw); 23 | } 24 | }; -------------------------------------------------------------------------------- /src/helpers/RadioLibWrappers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class RadioLibWrapper : public mesh::Radio { 7 | protected: 8 | PhysicalLayer* _radio; 9 | mesh::MainBoard* _board; 10 | uint32_t n_recv, n_sent; 11 | 12 | void idle(); 13 | void startRecv(); 14 | float packetScoreInt(float snr, int sf, int packet_len); 15 | 16 | public: 17 | RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; } 18 | 19 | void begin() override; 20 | int recvRaw(uint8_t* bytes, int sz) override; 21 | uint32_t getEstAirtimeFor(int len_bytes) override; 22 | bool startSendRaw(const uint8_t* bytes, int len) override; 23 | bool isSendComplete() override; 24 | void onSendFinished() override; 25 | bool isInRecvMode() const override; 26 | 27 | uint32_t getPacketsRecv() const { return n_recv; } 28 | uint32_t getPacketsSent() const { return n_sent; } 29 | void resetStats() { n_recv = n_sent = 0; } 30 | 31 | virtual float getLastRSSI() const override; 32 | virtual float getLastSNR() const override; 33 | 34 | float packetScore(float snr, int packet_len) override { return packetScoreInt(snr, 10, packet_len); } // assume sf=10 35 | }; 36 | 37 | /** 38 | * \brief an RNG impl using the noise from the LoRa radio as entropy. 39 | * NOTE: this is VERY SLOW! Use only for things like creating new LocalIdentity 40 | */ 41 | class RadioNoiseListener : public mesh::RNG { 42 | PhysicalLayer* _radio; 43 | public: 44 | RadioNoiseListener(PhysicalLayer& radio): _radio(&radio) { } 45 | 46 | void random(uint8_t* dest, size_t sz) override { 47 | for (int i = 0; i < sz; i++) { 48 | dest[i] = _radio->randomByte() ^ (::random(0, 256) & 0xFF); 49 | } 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /src/helpers/RefCountedDigitalPin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class RefCountedDigitalPin { 6 | uint8_t _pin; 7 | int8_t _claims = 0; 8 | 9 | public: 10 | RefCountedDigitalPin(uint8_t pin): _pin(pin) { } 11 | 12 | void begin() { 13 | pinMode(_pin, OUTPUT); 14 | digitalWrite(_pin, LOW); // initial state 15 | } 16 | 17 | void claim() { 18 | _claims++; 19 | if (_claims > 0) { 20 | digitalWrite(_pin, HIGH); 21 | } 22 | } 23 | void release() { 24 | _claims--; 25 | if (_claims == 0) { 26 | digitalWrite(_pin, LOW); 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/helpers/SensorManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define TELEM_PERM_BASE 0x01 // 'base' permission includes battery 6 | #define TELEM_PERM_LOCATION 0x02 7 | #define TELEM_PERM_ENVIRONMENT 0x04 // permission to access environment sensors 8 | 9 | #define TELEM_CHANNEL_SELF 1 // LPP data channel for 'self' device 10 | 11 | class SensorManager { 12 | public: 13 | double node_lat, node_lon; // modify these, if you want to affect Advert location 14 | double node_altitude; // altitude in meters 15 | 16 | SensorManager() { node_lat = 0; node_lon = 0; node_altitude = 0; } 17 | virtual bool begin() { return false; } 18 | virtual bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { return false; } 19 | virtual void loop() { } 20 | virtual int getNumSettings() const { return 0; } 21 | virtual const char* getSettingName(int i) const { return NULL; } 22 | virtual const char* getSettingValue(int i) const { return NULL; } 23 | virtual bool setSettingValue(const char* name, const char* value) { return false; } 24 | }; 25 | -------------------------------------------------------------------------------- /src/helpers/StaticPoolPacketManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class PacketQueue { 6 | mesh::Packet** _table; 7 | uint8_t* _pri_table; 8 | uint32_t* _schedule_table; 9 | int _size, _num; 10 | 11 | public: 12 | PacketQueue(int max_entries); 13 | mesh::Packet* get(uint32_t now); 14 | void add(mesh::Packet* packet, uint8_t priority, uint32_t scheduled_for); 15 | int count() const { return _num; } 16 | int countBefore(uint32_t now) const; 17 | mesh::Packet* itemAt(int i) const { return _table[i]; } 18 | mesh::Packet* removeByIdx(int i); 19 | }; 20 | 21 | class StaticPoolPacketManager : public mesh::PacketManager { 22 | PacketQueue unused, send_queue, rx_queue; 23 | 24 | public: 25 | StaticPoolPacketManager(int pool_size); 26 | 27 | mesh::Packet* allocNew() override; 28 | void free(mesh::Packet* packet) override; 29 | void queueOutbound(mesh::Packet* packet, uint8_t priority, uint32_t scheduled_for) override; 30 | mesh::Packet* getNextOutbound(uint32_t now) override; 31 | int getOutboundCount(uint32_t now) const override; 32 | int getFreeCount() const override; 33 | mesh::Packet* getOutboundByIdx(int i) override; 34 | mesh::Packet* removeOutboundByIdx(int i) override; 35 | void queueInbound(mesh::Packet* packet, uint32_t scheduled_for) override; 36 | mesh::Packet* getNextInbound(uint32_t now) override; 37 | }; -------------------------------------------------------------------------------- /src/helpers/StationG2Board.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // LoRa radio module pins for Station G2 6 | #define P_LORA_DIO_1 48 7 | #define P_LORA_NSS 11 8 | #define P_LORA_RESET 21 9 | #define P_LORA_BUSY 47 10 | #define P_LORA_SCLK 12 11 | #define P_LORA_MISO 14 12 | #define P_LORA_MOSI 13 13 | 14 | // built-ins 15 | //#define PIN_LED_BUILTIN 35 16 | //#define PIN_VEXT_EN 36 17 | 18 | #include "ESP32Board.h" 19 | 20 | #include 21 | 22 | class StationG2Board : public ESP32Board { 23 | public: 24 | void begin() { 25 | ESP32Board::begin(); 26 | 27 | esp_reset_reason_t reason = esp_reset_reason(); 28 | if (reason == ESP_RST_DEEPSLEEP) { 29 | long wakeup_source = esp_sleep_get_ext1_wakeup_status(); 30 | if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep) 31 | startup_reason = BD_STARTUP_RX_PACKET; 32 | } 33 | 34 | rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS); 35 | rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1); 36 | } 37 | } 38 | 39 | void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) { 40 | esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); 41 | 42 | // Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep 43 | rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY); 44 | rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1); 45 | 46 | rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS); 47 | 48 | if (pin_wake_btn < 0) { 49 | esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet 50 | } else { 51 | esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet OR wake btn 52 | } 53 | 54 | if (secs > 0) { 55 | esp_sleep_enable_timer_wakeup(secs * 1000000); 56 | } 57 | 58 | // Finally set ESP32 into sleep 59 | esp_deep_sleep_start(); // CPU halts here and never returns! 60 | } 61 | 62 | uint16_t getBattMilliVolts() override { 63 | return 0; 64 | } 65 | 66 | const char* getManufacturerName() const override { 67 | return "Station G2"; 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /src/helpers/TxtDataHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define TXT_TYPE_PLAIN 0 // a plain text message 7 | #define TXT_TYPE_CLI_DATA 1 // a CLI command 8 | #define TXT_TYPE_SIGNED_PLAIN 2 // plain text, signed by sender 9 | 10 | class StrHelper { 11 | public: 12 | static void strncpy(char* dest, const char* src, size_t buf_sz); 13 | static void strzcpy(char* dest, const char* src, size_t buf_sz); // pads with trailing nulls 14 | static const char* ftoa(float f); 15 | }; 16 | -------------------------------------------------------------------------------- /src/helpers/esp32/ESPNOWRadio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class ESPNOWRadio : public mesh::Radio { 6 | protected: 7 | uint32_t n_recv, n_sent; 8 | 9 | public: 10 | ESPNOWRadio() { n_recv = n_sent = 0; } 11 | 12 | void init(); 13 | int recvRaw(uint8_t* bytes, int sz) override; 14 | uint32_t getEstAirtimeFor(int len_bytes) override; 15 | bool startSendRaw(const uint8_t* bytes, int len) override; 16 | bool isSendComplete() override; 17 | void onSendFinished() override; 18 | bool isInRecvMode() const override; 19 | 20 | uint32_t getPacketsRecv() const { return n_recv; } 21 | uint32_t getPacketsSent() const { return n_sent; } 22 | void resetStats() { n_recv = n_sent = 0; } 23 | 24 | virtual float getLastRSSI() const override; 25 | virtual float getLastSNR() const override; 26 | 27 | float packetScore(float snr, int packet_len) override { return 0; } 28 | uint32_t intID(); 29 | void setTxPower(uint8_t dbm); 30 | }; 31 | 32 | #if ESPNOW_DEBUG_LOGGING && ARDUINO 33 | #include 34 | #define ESPNOW_DEBUG_PRINT(F, ...) Serial.printf("ESP-Now: " F, ##__VA_ARGS__) 35 | #define ESPNOW_DEBUG_PRINTLN(F, ...) Serial.printf("ESP-Now: " F "\n", ##__VA_ARGS__) 36 | #else 37 | #define ESPNOW_DEBUG_PRINT(...) {} 38 | #define ESPNOW_DEBUG_PRINTLN(...) {} 39 | #endif 40 | -------------------------------------------------------------------------------- /src/helpers/esp32/SerialWifiInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../BaseSerialInterface.h" 4 | #include 5 | 6 | class SerialWifiInterface : public BaseSerialInterface { 7 | bool deviceConnected; 8 | bool _isEnabled; 9 | unsigned long _last_write; 10 | unsigned long adv_restart_time; 11 | 12 | WiFiServer server; 13 | WiFiClient client; 14 | 15 | struct Frame { 16 | uint8_t len; 17 | uint8_t buf[MAX_FRAME_SIZE]; 18 | }; 19 | 20 | #define FRAME_QUEUE_SIZE 4 21 | int recv_queue_len; 22 | Frame recv_queue[FRAME_QUEUE_SIZE]; 23 | int send_queue_len; 24 | Frame send_queue[FRAME_QUEUE_SIZE]; 25 | 26 | void clearBuffers() { recv_queue_len = 0; send_queue_len = 0; } 27 | 28 | protected: 29 | 30 | public: 31 | SerialWifiInterface() : server(WiFiServer()), client(WiFiClient()) { 32 | deviceConnected = false; 33 | _isEnabled = false; 34 | _last_write = 0; 35 | send_queue_len = recv_queue_len = 0; 36 | } 37 | 38 | void begin(int port); 39 | 40 | // BaseSerialInterface methods 41 | void enable() override; 42 | void disable() override; 43 | bool isEnabled() const override { return _isEnabled; } 44 | 45 | bool isConnected() const override; 46 | bool isWriteBusy() const override; 47 | 48 | size_t writeFrame(const uint8_t src[], size_t len) override; 49 | size_t checkRecvFrame(uint8_t dest[]) override; 50 | }; 51 | 52 | #if WIFI_DEBUG_LOGGING && ARDUINO 53 | #include 54 | #define WIFI_DEBUG_PRINT(F, ...) Serial.printf("WiFi: " F, ##__VA_ARGS__) 55 | #define WIFI_DEBUG_PRINTLN(F, ...) Serial.printf("WiFi: " F "\n", ##__VA_ARGS__) 56 | #else 57 | #define WIFI_DEBUG_PRINT(...) {} 58 | #define WIFI_DEBUG_PRINTLN(...) {} 59 | #endif 60 | -------------------------------------------------------------------------------- /src/helpers/nrf52/PromicroBoard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define P_LORA_NSS 13 //P1.13 45 7 | #define P_LORA_DIO_1 11 //P0.10 10 8 | #define P_LORA_RESET 10 //P0.09 9 9 | #define P_LORA_BUSY 16 //P0.29 29 10 | #define P_LORA_MISO 15 //P0.02 2 11 | #define P_LORA_SCLK 12 //P1.11 43 12 | #define P_LORA_MOSI 14 //P1.15 47 13 | #define SX126X_POWER_EN 21 //P0.13 13 14 | #define SX126X_RXEN 2 //P0.17 15 | #define SX126X_TXEN RADIOLIB_NC 16 | #define SX126X_DIO2_AS_RF_SWITCH true 17 | #define SX126X_DIO3_TCXO_VOLTAGE (1.8f) 18 | 19 | #define PIN_VBAT_READ 17 20 | #define ADC_MULTIPLIER (1.815f) // dependent on voltage divider resistors. TODO: more accurate battery tracking 21 | 22 | class PromicroBoard : public mesh::MainBoard { 23 | protected: 24 | uint8_t startup_reason; 25 | uint8_t btn_prev_state; 26 | 27 | public: 28 | void begin(); 29 | 30 | uint8_t getStartupReason() const override { return startup_reason; } 31 | 32 | #define BATTERY_SAMPLES 8 33 | 34 | uint16_t getBattMilliVolts() override { 35 | analogReadResolution(12); 36 | 37 | uint32_t raw = 0; 38 | for (int i = 0; i < BATTERY_SAMPLES; i++) { 39 | raw += analogRead(PIN_VBAT_READ); 40 | } 41 | raw = raw / BATTERY_SAMPLES; 42 | return (ADC_MULTIPLIER * raw); 43 | } 44 | 45 | const char* getManufacturerName() const override { 46 | return "ProMicro DIY"; 47 | } 48 | 49 | int buttonStateChanged() { 50 | #ifdef BUTTON_PIN 51 | uint8_t v = digitalRead(BUTTON_PIN); 52 | if (v != btn_prev_state) { 53 | btn_prev_state = v; 54 | return (v == LOW) ? 1 : -1; 55 | } 56 | #endif 57 | return 0; 58 | } 59 | 60 | void reboot() override { 61 | NVIC_SystemReset(); 62 | } 63 | 64 | bool startOTAUpdate(const char* id, char reply[]) override; 65 | }; 66 | -------------------------------------------------------------------------------- /src/helpers/nrf52/RAK4631Board.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // LoRa radio module pins for RAK4631 7 | #define P_LORA_DIO_1 47 8 | #define P_LORA_NSS 42 9 | #define P_LORA_RESET RADIOLIB_NC // 38 10 | #define P_LORA_BUSY 46 11 | #define P_LORA_SCLK 43 12 | #define P_LORA_MISO 45 13 | #define P_LORA_MOSI 44 14 | #define SX126X_POWER_EN 37 15 | 16 | #define SX126X_DIO2_AS_RF_SWITCH true 17 | #define SX126X_DIO3_TCXO_VOLTAGE 1.8 18 | 19 | // built-ins 20 | #define PIN_VBAT_READ 5 21 | #define ADC_MULTIPLIER (3 * 1.73 * 1.187 * 1000) 22 | 23 | class RAK4631Board : public mesh::MainBoard { 24 | protected: 25 | uint8_t startup_reason; 26 | 27 | public: 28 | void begin(); 29 | uint8_t getStartupReason() const override { return startup_reason; } 30 | 31 | #define BATTERY_SAMPLES 8 32 | 33 | uint16_t getBattMilliVolts() override { 34 | analogReadResolution(12); 35 | 36 | uint32_t raw = 0; 37 | for (int i = 0; i < BATTERY_SAMPLES; i++) { 38 | raw += analogRead(PIN_VBAT_READ); 39 | } 40 | raw = raw / BATTERY_SAMPLES; 41 | 42 | return (ADC_MULTIPLIER * raw) / 4096; 43 | } 44 | 45 | const char* getManufacturerName() const override { 46 | return "RAK 4631"; 47 | } 48 | 49 | void reboot() override { 50 | NVIC_SystemReset(); 51 | } 52 | 53 | bool startOTAUpdate(const char* id, char reply[]) override; 54 | }; 55 | -------------------------------------------------------------------------------- /src/helpers/nrf52/SerialBLEInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../BaseSerialInterface.h" 4 | #include 5 | 6 | class SerialBLEInterface : public BaseSerialInterface { 7 | BLEUart bleuart; 8 | bool deviceConnected; 9 | bool oldDeviceConnected; 10 | bool checkAdvRestart; 11 | bool _isEnabled; 12 | unsigned long _last_write; 13 | 14 | struct Frame { 15 | uint8_t len; 16 | uint8_t buf[MAX_FRAME_SIZE]; 17 | }; 18 | 19 | #define FRAME_QUEUE_SIZE 4 20 | int send_queue_len; 21 | Frame send_queue[FRAME_QUEUE_SIZE]; 22 | 23 | void clearBuffers() { send_queue_len = 0; } 24 | void startAdv(); 25 | 26 | public: 27 | SerialBLEInterface() { 28 | deviceConnected = false; 29 | oldDeviceConnected = false; 30 | checkAdvRestart = false; 31 | _isEnabled = false; 32 | _last_write = 0; 33 | send_queue_len = 0; 34 | } 35 | 36 | void begin(const char* device_name, uint32_t pin_code); 37 | 38 | // BaseSerialInterface methods 39 | void enable() override; 40 | void disable() override; 41 | bool isEnabled() const override { return _isEnabled; } 42 | 43 | bool isConnected() const override; 44 | 45 | bool isWriteBusy() const override; 46 | size_t writeFrame(const uint8_t src[], size_t len) override; 47 | size_t checkRecvFrame(uint8_t dest[]) override; 48 | }; 49 | 50 | #if BLE_DEBUG_LOGGING && ARDUINO 51 | #include 52 | #define BLE_DEBUG_PRINT(F, ...) Serial.printf("BLE: " F, ##__VA_ARGS__) 53 | #define BLE_DEBUG_PRINTLN(F, ...) Serial.printf("BLE: " F "\n", ##__VA_ARGS__) 54 | #else 55 | #define BLE_DEBUG_PRINT(...) {} 56 | #define BLE_DEBUG_PRINTLN(...) {} 57 | #endif 58 | -------------------------------------------------------------------------------- /src/helpers/nrf52/T114Board.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // LoRa radio module pins for Heltec T114 7 | #define P_LORA_DIO_1 20 8 | #define P_LORA_NSS 24 9 | #define P_LORA_RESET 25 10 | #define P_LORA_BUSY 17 11 | #define P_LORA_SCLK 19 12 | #define P_LORA_MISO 23 13 | #define P_LORA_MOSI 22 14 | #define SX126X_POWER_EN 37 15 | 16 | #define SX126X_DIO2_AS_RF_SWITCH true 17 | #define SX126X_DIO3_TCXO_VOLTAGE 1.8 18 | 19 | // built-ins 20 | #define PIN_VBAT_READ 4 21 | #define PIN_BAT_CTL 6 22 | #define MV_LSB (3000.0F / 4096.0F) // 12-bit ADC with 3.0V input range 23 | 24 | class T114Board : public mesh::MainBoard { 25 | protected: 26 | uint8_t startup_reason; 27 | 28 | public: 29 | void begin(); 30 | uint8_t getStartupReason() const override { return startup_reason; } 31 | 32 | #if defined(P_LORA_TX_LED) 33 | void onBeforeTransmit() override { 34 | digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED on 35 | } 36 | void onAfterTransmit() override { 37 | digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED off 38 | } 39 | #endif 40 | 41 | uint16_t getBattMilliVolts() override { 42 | int adcvalue = 0; 43 | analogReadResolution(12); 44 | analogReference(AR_INTERNAL_3_0); 45 | pinMode(PIN_BAT_CTL, OUTPUT); // battery adc can be read only ctrl pin 6 set to high 46 | digitalWrite(PIN_BAT_CTL, 1); 47 | 48 | delay(10); 49 | adcvalue = analogRead(PIN_VBAT_READ); 50 | digitalWrite(6, 0); 51 | 52 | return (uint16_t)((float)adcvalue * MV_LSB * 4.9); 53 | } 54 | 55 | const char* getManufacturerName() const override { 56 | return "Heltec T114"; 57 | } 58 | 59 | void reboot() override { 60 | NVIC_SystemReset(); 61 | } 62 | 63 | bool startOTAUpdate(const char* id, char reply[]) override; 64 | }; 65 | -------------------------------------------------------------------------------- /src/helpers/nrf52/TechoBoard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // LoRa radio module pins for LilyGo T-Echo 7 | #define P_LORA_DIO_1 20 8 | #define P_LORA_NSS 24 9 | #define P_LORA_RESET 25 10 | #define P_LORA_BUSY 17 11 | #define P_LORA_SCLK 19 12 | #define P_LORA_MISO 23 13 | #define P_LORA_MOSI 22 14 | #define SX126X_POWER_EN 37 15 | 16 | #define SX126X_DIO2_AS_RF_SWITCH true 17 | #define SX126X_DIO3_TCXO_VOLTAGE 1.8 18 | 19 | // built-ins 20 | #define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 21 | 22 | #define VBAT_DIVIDER (0.5F) // 150K + 150K voltage divider on VBAT 23 | #define VBAT_DIVIDER_COMP (2.0F) // Compensation factor for the VBAT divider 24 | 25 | #define PIN_VBAT_READ (4) 26 | #define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB) 27 | 28 | class TechoBoard : public mesh::MainBoard { 29 | protected: 30 | uint8_t startup_reason; 31 | 32 | public: 33 | 34 | void begin(); 35 | uint16_t getBattMilliVolts() override; 36 | bool startOTAUpdate(const char* id, char reply[]) override; 37 | 38 | uint8_t getStartupReason() const override { 39 | return startup_reason; 40 | } 41 | 42 | const char* getManufacturerName() const override { 43 | return "LilyGo T-Echo"; 44 | } 45 | 46 | void reboot() override { 47 | NVIC_SystemReset(); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /src/helpers/nrf52/ThinkNodeM1Board.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // LoRa radio module pins for Elecrow ThinkNode M1 7 | #define P_LORA_DIO_1 20 8 | #define P_LORA_NSS 24 9 | #define P_LORA_RESET 25 10 | #define P_LORA_BUSY 17 11 | #define P_LORA_SCLK 19 12 | #define P_LORA_MISO 23 13 | #define P_LORA_MOSI 22 14 | #define SX126X_POWER_EN 37 15 | 16 | #define SX126X_DIO2_AS_RF_SWITCH true 17 | #define SX126X_DIO3_TCXO_VOLTAGE 1.8 18 | 19 | // built-ins 20 | #define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 21 | 22 | #define VBAT_DIVIDER (0.5F) // 150K + 150K voltage divider on VBAT 23 | #define VBAT_DIVIDER_COMP (2.0F) // Compensation factor for the VBAT divider 24 | 25 | #define PIN_VBAT_READ (4) 26 | #define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB) 27 | 28 | class ThinkNodeM1Board : public mesh::MainBoard { 29 | protected: 30 | uint8_t startup_reason; 31 | 32 | public: 33 | 34 | void begin(); 35 | uint16_t getBattMilliVolts() override; 36 | bool startOTAUpdate(const char* id, char reply[]) override; 37 | 38 | uint8_t getStartupReason() const override { 39 | return startup_reason; 40 | } 41 | 42 | const char* getManufacturerName() const override { 43 | return "Elecrow ThinkNode-M1"; 44 | } 45 | 46 | void reboot() override { 47 | NVIC_SystemReset(); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /src/helpers/nrf52/XiaoNrf52Board.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef XIAO_NRF52 7 | 8 | // LoRa radio module pins for Seeed Xiao-nrf52 9 | #ifdef SX1262_XIAO_S3_VARIANT 10 | #undef P_LORA_DIO_1 11 | #undef P_LORA_BUSY 12 | #undef P_LORA_RESET 13 | #undef P_LORA_NSS 14 | #define P_LORA_DIO_1 D0 15 | #define P_LORA_BUSY D1 16 | #define P_LORA_RESET D2 17 | #define P_LORA_NSS D3 18 | #endif 19 | //#define SX126X_POWER_EN 37 20 | 21 | 22 | 23 | class XiaoNrf52Board : public mesh::MainBoard { 24 | protected: 25 | uint8_t startup_reason; 26 | 27 | public: 28 | void begin(); 29 | uint8_t getStartupReason() const override { return startup_reason; } 30 | 31 | #if defined(P_LORA_TX_LED) 32 | void onBeforeTransmit() override { 33 | digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED on 34 | } 35 | void onAfterTransmit() override { 36 | digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED off 37 | } 38 | #endif 39 | 40 | uint16_t getBattMilliVolts() override { 41 | // Please read befor going further ;) 42 | // https://wiki.seeedstudio.com/XIAO_BLE#q3-what-are-the-considerations-when-using-xiao-nrf52840-sense-for-battery-charging 43 | 44 | // We can't drive VBAT_ENABLE to HIGH as long 45 | // as we don't know wether we are charging or not ... 46 | // this is a 3mA loss (4/1500) 47 | digitalWrite(VBAT_ENABLE, LOW); 48 | int adcvalue = 0; 49 | analogReadResolution(12); 50 | analogReference(AR_INTERNAL_3_0); 51 | delay(10); 52 | adcvalue = analogRead(PIN_VBAT); 53 | return (adcvalue * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096; 54 | } 55 | 56 | const char* getManufacturerName() const override { 57 | return "Seeed Xiao-nrf52"; 58 | } 59 | 60 | void reboot() override { 61 | NVIC_SystemReset(); 62 | } 63 | 64 | bool startOTAUpdate(const char* id, char reply[]) override; 65 | }; 66 | 67 | #endif -------------------------------------------------------------------------------- /src/helpers/rp2040/PicoWBoard.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PicoWBoard.h" 3 | 4 | //#include 5 | #include 6 | 7 | //static BLEDfu bledfu; 8 | 9 | static void connect_callback(uint16_t conn_handle) { 10 | (void)conn_handle; 11 | MESH_DEBUG_PRINTLN("BLE client connected"); 12 | } 13 | 14 | static void disconnect_callback(uint16_t conn_handle, uint8_t reason) { 15 | (void)conn_handle; 16 | (void)reason; 17 | 18 | MESH_DEBUG_PRINTLN("BLE client disconnected"); 19 | } 20 | 21 | void PicoWBoard::begin() { 22 | // for future use, sub-classes SHOULD call this from their begin() 23 | startup_reason = BD_STARTUP_NORMAL; 24 | pinMode(PIN_VBAT_READ, INPUT); 25 | #ifdef PIN_USER_BTN 26 | pinMode(PIN_USER_BTN, INPUT_PULLUP); 27 | #endif 28 | 29 | #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) 30 | Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); 31 | #endif 32 | 33 | Wire.begin(); 34 | 35 | //pinMode(SX126X_POWER_EN, OUTPUT); 36 | //digitalWrite(SX126X_POWER_EN, HIGH); 37 | delay(10); // give sx1262 some time to power up 38 | } 39 | 40 | bool PicoWBoard::startOTAUpdate(const char* id, char reply[]) { 41 | return false; 42 | } 43 | -------------------------------------------------------------------------------- /src/helpers/rp2040/PicoWBoard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // LoRa radio module pins for PicoW 7 | #define P_LORA_DIO_1 20 8 | #define P_LORA_NSS 3 9 | #define P_LORA_RESET 15 10 | #define P_LORA_BUSY 2 11 | #define P_LORA_SCLK 10 12 | #define P_LORA_MISO 12 13 | #define P_LORA_MOSI 11 14 | //#define SX126X_POWER_EN ??? // Not Sure 15 | 16 | #define SX126X_DIO2_AS_RF_SWITCH true 17 | #define SX126X_DIO3_TCXO_VOLTAGE 1.8 18 | 19 | // built-ins 20 | #define PIN_VBAT_READ 26 21 | #define ADC_MULTIPLIER (3.1 * 3.3 * 1000) // MT Uses 3.1 22 | #define PIN_LED_BUILTIN LED_BUILTIN 23 | 24 | class PicoWBoard : public mesh::MainBoard { 25 | protected: 26 | uint8_t startup_reason; 27 | 28 | public: 29 | void begin(); 30 | uint8_t getStartupReason() const override { return startup_reason; } 31 | 32 | void onBeforeTransmit() override { 33 | digitalWrite(LED_BUILTIN, HIGH); // turn TX LED on 34 | } 35 | 36 | void onAfterTransmit() override { 37 | digitalWrite(LED_BUILTIN, LOW); // turn TX LED off 38 | } 39 | 40 | #define BATTERY_SAMPLES 8 41 | 42 | uint16_t getBattMilliVolts() override { 43 | analogReadResolution(12); 44 | 45 | uint32_t raw = 0; 46 | for (int i = 0; i < BATTERY_SAMPLES; i++) { 47 | raw += analogRead(PIN_VBAT_READ); 48 | } 49 | raw = raw / BATTERY_SAMPLES; 50 | 51 | return (ADC_MULTIPLIER * raw) / 4096; 52 | } 53 | 54 | const char* getManufacturerName() const override { 55 | return "Pico W"; 56 | } 57 | 58 | void reboot() override { 59 | //NVIC_SystemReset(); 60 | rp2040.reboot(); 61 | } 62 | 63 | bool startOTAUpdate(const char* id, char reply[]) override; 64 | }; 65 | -------------------------------------------------------------------------------- /src/helpers/sensors/EnvironmentSensorManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class EnvironmentSensorManager : public SensorManager { 8 | protected: 9 | int next_available_channel = TELEM_CHANNEL_SELF + 1; 10 | 11 | bool AHTX0_initialized = false; 12 | bool BME280_initialized = false; 13 | bool INA3221_initialized = false; 14 | bool INA219_initialized = false; 15 | 16 | bool gps_detected = false; 17 | bool gps_active = false; 18 | 19 | #if ENV_INCLUDE_GPS 20 | LocationProvider* _location; 21 | void start_gps(); 22 | void stop_gps(); 23 | void initBasicGPS(); 24 | #endif 25 | 26 | 27 | public: 28 | #if ENV_INCLUDE_GPS 29 | EnvironmentSensorManager(LocationProvider &location): _location(&location){}; 30 | #else 31 | EnvironmentSensorManager(){}; 32 | #endif 33 | bool begin() override; 34 | bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; 35 | #if ENV_INCLUDE_GPS 36 | void loop() override; 37 | #endif 38 | int getNumSettings() const override; 39 | const char* getSettingName(int i) const override; 40 | const char* getSettingValue(int i) const override; 41 | bool setSettingValue(const char* name, const char* value) override; 42 | }; 43 | -------------------------------------------------------------------------------- /src/helpers/sensors/LocationProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Mesh.h" 4 | 5 | 6 | class LocationProvider { 7 | 8 | public: 9 | virtual long getLatitude() = 0; 10 | virtual long getLongitude() = 0; 11 | virtual long getAltitude() = 0; 12 | virtual bool isValid() = 0; 13 | virtual long getTimestamp() = 0; 14 | virtual void reset(); 15 | virtual void begin(); 16 | virtual void stop(); 17 | virtual void loop(); 18 | }; 19 | -------------------------------------------------------------------------------- /src/helpers/stm32/InternalFileSystem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef INTERNALFILESYSTEM_H_ 26 | #define INTERNALFILESYSTEM_H_ 27 | 28 | #include "Adafruit_LittleFS.h" 29 | 30 | #ifndef LFS_FLASH_TOTAL_SIZE /* Flash size can be configured in platformio.ini */ 31 | #define LFS_FLASH_TOTAL_SIZE (16 * 2048) /* defaults to 32k flash */ 32 | #endif 33 | #define LFS_BLOCK_SIZE (2048) 34 | #define LFS_FLASH_ADDR_BASE (FLASH_END_ADDR - LFS_FLASH_TOTAL_SIZE + 1) 35 | 36 | class InternalFileSystem : public Adafruit_LittleFS 37 | { 38 | public: 39 | InternalFileSystem(void); 40 | 41 | // overwrite to also perform low level format (sector erase of whole flash region) 42 | bool begin(void); 43 | }; 44 | 45 | extern InternalFileSystem InternalFS; 46 | 47 | #endif /* INTERNALFILESYSTEM_H_ */ 48 | -------------------------------------------------------------------------------- /src/helpers/stm32/STM32Board.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class STM32Board : public mesh::MainBoard { 7 | protected: 8 | uint8_t startup_reason; 9 | 10 | public: 11 | void begin() { 12 | startup_reason = BD_STARTUP_NORMAL; 13 | } 14 | 15 | uint8_t getStartupReason() const override { return startup_reason; } 16 | 17 | uint16_t getBattMilliVolts() override { 18 | return 0; // not supported 19 | } 20 | 21 | const char* getManufacturerName() const override { 22 | return "Generic STM32"; 23 | } 24 | 25 | void reboot() override { 26 | } 27 | 28 | bool startOTAUpdate(const char* id, char reply[]) override { return false; }; 29 | }; -------------------------------------------------------------------------------- /src/helpers/ui/DisplayDriver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class DisplayDriver { 6 | int _w, _h; 7 | protected: 8 | DisplayDriver(int w, int h) { _w = w; _h = h; } 9 | public: 10 | enum Color { DARK=0, LIGHT, RED, GREEN, BLUE, YELLOW, ORANGE }; // on b/w screen, colors will be !=0 synonym of light 11 | 12 | int width() const { return _w; } 13 | int height() const { return _h; } 14 | 15 | virtual bool isOn() = 0; 16 | virtual void turnOn() = 0; 17 | virtual void turnOff() = 0; 18 | virtual void clear() = 0; 19 | virtual void startFrame(Color bkg = DARK) = 0; 20 | virtual void setTextSize(int sz) = 0; 21 | virtual void setColor(Color c) = 0; 22 | virtual void setCursor(int x, int y) = 0; 23 | virtual void print(const char* str) = 0; 24 | virtual void fillRect(int x, int y, int w, int h) = 0; 25 | virtual void drawRect(int x, int y, int w, int h) = 0; 26 | virtual void drawXbm(int x, int y, const uint8_t* bits, int w, int h) = 0; 27 | virtual uint16_t getTextWidth(const char* str) = 0; 28 | virtual void endFrame() = 0; 29 | }; 30 | -------------------------------------------------------------------------------- /src/helpers/ui/GxEPDDisplay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define ENABLE_GxEPD2_GFX 0 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define GxEPD2_DISPLAY_CLASS GxEPD2_BW 15 | #define GxEPD2_DRIVER_CLASS GxEPD2_150_BN // DEPG0150BN 200x200, SSD1681, (FPC8101), TTGO T5 V2.4.1 16 | 17 | #include // 1.54" b/w 18 | 19 | #include "DisplayDriver.h" 20 | 21 | //GxEPD2_BW display(GxEPD2_150_BN(DISP_CS, DISP_DC, DISP_RST, DISP_BUSY)); // DEPG0150BN 200x200, SSD1681, TTGO T5 V2.4.1 22 | 23 | 24 | class GxEPDDisplay : public DisplayDriver { 25 | 26 | GxEPD2_BW display; 27 | bool _init = false; 28 | bool _isOn = false; 29 | 30 | public: 31 | // there is a margin in y... 32 | GxEPDDisplay() : DisplayDriver(128, 128), display(GxEPD2_150_BN(DISP_CS, DISP_DC, DISP_RST, DISP_BUSY)) { 33 | } 34 | 35 | bool begin(); 36 | 37 | bool isOn() override {return _isOn;}; 38 | void turnOn() override; 39 | void turnOff() override; 40 | void clear() override; 41 | void startFrame(Color bkg = DARK) override; 42 | void setTextSize(int sz) override; 43 | void setColor(Color c) override; 44 | void setCursor(int x, int y) override; 45 | void print(const char* str) override; 46 | void fillRect(int x, int y, int w, int h) override; 47 | void drawRect(int x, int y, int w, int h) override; 48 | void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override; 49 | uint16_t getTextWidth(const char* str) override; 50 | void endFrame() override; 51 | }; 52 | -------------------------------------------------------------------------------- /src/helpers/ui/OLEDDisplayFonts.h: -------------------------------------------------------------------------------- 1 | #ifndef OLEDDISPLAYFONTS_h 2 | #define OLEDDISPLAYFONTS_h 3 | 4 | #ifdef ARDUINO 5 | #include 6 | #elif __MBED__ 7 | #define PROGMEM 8 | #endif 9 | 10 | extern const uint8_t ArialMT_Plain_10[] PROGMEM; 11 | extern const uint8_t ArialMT_Plain_16[] PROGMEM; 12 | extern const uint8_t ArialMT_Plain_24[] PROGMEM; 13 | #endif 14 | -------------------------------------------------------------------------------- /src/helpers/ui/SH1106Display.cpp: -------------------------------------------------------------------------------- 1 | #include "SH1106Display.h" 2 | #include 3 | #include "Adafruit_SH110X.h" 4 | 5 | bool SH1106Display::i2c_probe(TwoWire &wire, uint8_t addr) 6 | { 7 | wire.beginTransmission(addr); 8 | uint8_t error = wire.endTransmission(); 9 | return (error == 0); 10 | } 11 | 12 | bool SH1106Display::begin() 13 | { 14 | return display.begin(DISPLAY_ADDRESS, true) && i2c_probe(Wire, DISPLAY_ADDRESS); 15 | } 16 | 17 | void SH1106Display::turnOn() 18 | { 19 | display.oled_command(SH110X_DISPLAYON); 20 | _isOn = true; 21 | } 22 | 23 | void SH1106Display::turnOff() 24 | { 25 | display.oled_command(SH110X_DISPLAYOFF); 26 | _isOn = false; 27 | } 28 | 29 | void SH1106Display::clear() 30 | { 31 | display.clearDisplay(); 32 | display.display(); 33 | } 34 | 35 | void SH1106Display::startFrame(Color bkg) 36 | { 37 | display.clearDisplay(); // TODO: apply 'bkg' 38 | _color = SH110X_WHITE; 39 | display.setTextColor(_color); 40 | display.setTextSize(1); 41 | display.cp437(true); // Use full 256 char 'Code Page 437' font 42 | } 43 | 44 | void SH1106Display::setTextSize(int sz) 45 | { 46 | display.setTextSize(sz); 47 | } 48 | 49 | void SH1106Display::setColor(Color c) 50 | { 51 | _color = (c != 0) ? SH110X_WHITE : SH110X_BLACK; 52 | display.setTextColor(_color); 53 | } 54 | 55 | void SH1106Display::setCursor(int x, int y) 56 | { 57 | display.setCursor(x, y); 58 | } 59 | 60 | void SH1106Display::print(const char *str) 61 | { 62 | display.print(str); 63 | } 64 | 65 | void SH1106Display::fillRect(int x, int y, int w, int h) 66 | { 67 | display.fillRect(x, y, w, h, _color); 68 | } 69 | 70 | void SH1106Display::drawRect(int x, int y, int w, int h) 71 | { 72 | display.drawRect(x, y, w, h, _color); 73 | } 74 | 75 | void SH1106Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) 76 | { 77 | display.drawBitmap(x, y, bits, w, h, SH110X_WHITE); 78 | } 79 | 80 | uint16_t SH1106Display::getTextWidth(const char *str) 81 | { 82 | int16_t x1, y1; 83 | uint16_t w, h; 84 | display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h); 85 | return w; 86 | } 87 | 88 | void SH1106Display::endFrame() 89 | { 90 | display.display(); 91 | } 92 | -------------------------------------------------------------------------------- /src/helpers/ui/SH1106Display.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DisplayDriver.h" 4 | #include 5 | #include 6 | #define SH110X_NO_SPLASH 7 | #include 8 | 9 | #ifndef PIN_OLED_RESET 10 | #define PIN_OLED_RESET -1 11 | #endif 12 | 13 | #ifndef DISPLAY_ADDRESS 14 | #define DISPLAY_ADDRESS 0x3C 15 | #endif 16 | 17 | class SH1106Display : public DisplayDriver 18 | { 19 | Adafruit_SH1106G display; 20 | bool _isOn; 21 | uint8_t _color; 22 | 23 | bool i2c_probe(TwoWire &wire, uint8_t addr); 24 | 25 | public: 26 | SH1106Display() : DisplayDriver(128, 64), display(128, 64, &Wire, PIN_OLED_RESET) { _isOn = false; } 27 | bool begin(); 28 | 29 | bool isOn() override { return _isOn; } 30 | void turnOn() override; 31 | void turnOff() override; 32 | void clear() override; 33 | void startFrame(Color bkg = DARK) override; 34 | void setTextSize(int sz) override; 35 | void setColor(Color c) override; 36 | void setCursor(int x, int y) override; 37 | void print(const char *str) override; 38 | void fillRect(int x, int y, int w, int h) override; 39 | void drawRect(int x, int y, int w, int h) override; 40 | void drawXbm(int x, int y, const uint8_t *bits, int w, int h) override; 41 | uint16_t getTextWidth(const char *str) override; 42 | void endFrame() override; 43 | }; 44 | -------------------------------------------------------------------------------- /src/helpers/ui/SSD1306Display.cpp: -------------------------------------------------------------------------------- 1 | #include "SSD1306Display.h" 2 | 3 | bool SSD1306Display::i2c_probe(TwoWire& wire, uint8_t addr) { 4 | wire.beginTransmission(addr); 5 | uint8_t error = wire.endTransmission(); 6 | return (error == 0); 7 | } 8 | 9 | bool SSD1306Display::begin() { 10 | return display.begin(SSD1306_SWITCHCAPVCC, DISPLAY_ADDRESS, true, false) && i2c_probe(Wire, DISPLAY_ADDRESS); 11 | } 12 | 13 | void SSD1306Display::turnOn() { 14 | display.ssd1306_command(SSD1306_DISPLAYON); 15 | _isOn = true; 16 | } 17 | 18 | void SSD1306Display::turnOff() { 19 | display.ssd1306_command(SSD1306_DISPLAYOFF); 20 | _isOn = false; 21 | } 22 | 23 | void SSD1306Display::clear() { 24 | display.clearDisplay(); 25 | display.display(); 26 | } 27 | 28 | void SSD1306Display::startFrame(Color bkg) { 29 | display.clearDisplay(); // TODO: apply 'bkg' 30 | _color = SSD1306_WHITE; 31 | display.setTextColor(_color); 32 | display.setTextSize(1); 33 | display.cp437(true); // Use full 256 char 'Code Page 437' font 34 | } 35 | 36 | void SSD1306Display::setTextSize(int sz) { 37 | display.setTextSize(sz); 38 | } 39 | 40 | void SSD1306Display::setColor(Color c) { 41 | _color = (c != 0) ? SSD1306_WHITE : SSD1306_BLACK; 42 | display.setTextColor(_color); 43 | } 44 | 45 | void SSD1306Display::setCursor(int x, int y) { 46 | display.setCursor(x, y); 47 | } 48 | 49 | void SSD1306Display::print(const char* str) { 50 | display.print(str); 51 | } 52 | 53 | void SSD1306Display::fillRect(int x, int y, int w, int h) { 54 | display.fillRect(x, y, w, h, _color); 55 | } 56 | 57 | void SSD1306Display::drawRect(int x, int y, int w, int h) { 58 | display.drawRect(x, y, w, h, _color); 59 | } 60 | 61 | void SSD1306Display::drawXbm(int x, int y, const uint8_t* bits, int w, int h) { 62 | display.drawBitmap(x, y, bits, w, h, SSD1306_WHITE); 63 | } 64 | 65 | uint16_t SSD1306Display::getTextWidth(const char* str) { 66 | int16_t x1, y1; 67 | uint16_t w, h; 68 | display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h); 69 | return w; 70 | } 71 | 72 | void SSD1306Display::endFrame() { 73 | display.display(); 74 | } 75 | -------------------------------------------------------------------------------- /src/helpers/ui/SSD1306Display.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DisplayDriver.h" 4 | #include 5 | #include 6 | #define SSD1306_NO_SPLASH 7 | #include 8 | 9 | #ifndef PIN_OLED_RESET 10 | #define PIN_OLED_RESET 21 // Reset pin # (or -1 if sharing Arduino reset pin) 11 | #endif 12 | 13 | #ifndef DISPLAY_ADDRESS 14 | #define DISPLAY_ADDRESS 0x3C 15 | #endif 16 | 17 | class SSD1306Display : public DisplayDriver { 18 | Adafruit_SSD1306 display; 19 | bool _isOn; 20 | uint8_t _color; 21 | 22 | bool i2c_probe(TwoWire& wire, uint8_t addr); 23 | public: 24 | SSD1306Display() : DisplayDriver(128, 64), display(128, 64, &Wire, PIN_OLED_RESET) { _isOn = false; } 25 | bool begin(); 26 | 27 | bool isOn() override { return _isOn; } 28 | void turnOn() override; 29 | void turnOff() override; 30 | void clear() override; 31 | void startFrame(Color bkg = DARK) override; 32 | void setTextSize(int sz) override; 33 | void setColor(Color c) override; 34 | void setCursor(int x, int y) override; 35 | void print(const char* str) override; 36 | void fillRect(int x, int y, int w, int h) override; 37 | void drawRect(int x, int y, int w, int h) override; 38 | void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override; 39 | uint16_t getTextWidth(const char* str) override; 40 | void endFrame() override; 41 | }; 42 | -------------------------------------------------------------------------------- /src/helpers/ui/ST7735Display.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DisplayDriver.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class ST7735Display : public DisplayDriver { 11 | Adafruit_ST7735 display; 12 | bool _isOn; 13 | uint16_t _color; 14 | RefCountedDigitalPin* _peripher_power; 15 | 16 | bool i2c_probe(TwoWire& wire, uint8_t addr); 17 | public: 18 | #ifdef USE_PIN_TFT 19 | ST7735Display(RefCountedDigitalPin* peripher_power=NULL) : DisplayDriver(128, 64), 20 | display(PIN_TFT_CS, PIN_TFT_DC, PIN_TFT_SDA, PIN_TFT_SCL, PIN_TFT_RST), 21 | _peripher_power(peripher_power) 22 | { 23 | _isOn = false; 24 | } 25 | #else 26 | ST7735Display(RefCountedDigitalPin* peripher_power=NULL) : DisplayDriver(128, 64), 27 | display(&SPI1, PIN_TFT_CS, PIN_TFT_DC, PIN_TFT_RST), 28 | _peripher_power(peripher_power) 29 | { 30 | _isOn = false; 31 | } 32 | #endif 33 | bool begin(); 34 | 35 | bool isOn() override { return _isOn; } 36 | void turnOn() override; 37 | void turnOff() override; 38 | void clear() override; 39 | void startFrame(Color bkg = DARK) override; 40 | void setTextSize(int sz) override; 41 | void setColor(Color c) override; 42 | void setCursor(int x, int y) override; 43 | void print(const char* str) override; 44 | void fillRect(int x, int y, int w, int h) override; 45 | void drawRect(int x, int y, int w, int h) override; 46 | void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override; 47 | uint16_t getTextWidth(const char* str) override; 48 | void endFrame() override; 49 | }; 50 | -------------------------------------------------------------------------------- /src/helpers/ui/ST7789Display.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DisplayDriver.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class ST7789Display : public DisplayDriver { 10 | ST7789Spi display; 11 | bool _isOn; 12 | uint16_t _color; 13 | int _x=0, _y=0; 14 | 15 | bool i2c_probe(TwoWire& wire, uint8_t addr); 16 | public: 17 | ST7789Display() : DisplayDriver(128, 64), display(&SPI1, PIN_TFT_RST, PIN_TFT_DC, PIN_TFT_CS, GEOMETRY_RAWMODE, 240, 135) {_isOn = false;} 18 | 19 | bool begin(); 20 | 21 | bool isOn() override { return _isOn; } 22 | void turnOn() override; 23 | void turnOff() override; 24 | void clear() override; 25 | void startFrame(Color bkg = DARK) override; 26 | void setTextSize(int sz) override; 27 | void setColor(Color c) override; 28 | void setCursor(int x, int y) override; 29 | void print(const char* str) override; 30 | void fillRect(int x, int y, int w, int h) override; 31 | void drawRect(int x, int y, int w, int h) override; 32 | void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override; 33 | uint16_t getTextWidth(const char* str) override; 34 | void endFrame() override; 35 | }; 36 | -------------------------------------------------------------------------------- /src/helpers/ui/buzzer.cpp: -------------------------------------------------------------------------------- 1 | #ifdef PIN_BUZZER 2 | #include "buzzer.h" 3 | 4 | void genericBuzzer::begin() { 5 | // Serial.print("DBG: Setting up buzzer on pin "); 6 | // Serial.println(PIN_BUZZER); 7 | #ifdef PIN_BUZZER_EN 8 | pinMode(PIN_BUZZER_EN, OUTPUT); 9 | digitalWrite(PIN_BUZZER_EN, HIGH); 10 | #endif 11 | 12 | quiet(false); 13 | pinMode(PIN_BUZZER, OUTPUT); 14 | startup(); 15 | } 16 | 17 | void genericBuzzer::play(const char *melody) { 18 | if (isPlaying()) // interrupt existing 19 | { 20 | rtttl::stop(); 21 | } 22 | 23 | if (_is_quiet) return; 24 | 25 | rtttl::begin(PIN_BUZZER,melody); 26 | // Serial.print("DBG: Playing melody - isQuiet: "); 27 | // Serial.println(isQuiet()); 28 | } 29 | 30 | bool genericBuzzer::isPlaying() { 31 | return rtttl::isPlaying(); 32 | } 33 | 34 | void genericBuzzer::loop() { 35 | if (!rtttl::done()) rtttl::play(); 36 | } 37 | 38 | void genericBuzzer::startup() { 39 | play(startup_song); 40 | } 41 | 42 | void genericBuzzer::shutdown() { 43 | play(shutdown_song); 44 | } 45 | 46 | void genericBuzzer::quiet(bool buzzer_state) { 47 | _is_quiet = buzzer_state; 48 | } 49 | 50 | bool genericBuzzer::isQuiet() { 51 | return _is_quiet; 52 | } 53 | 54 | #endif // ifdef PIN_BUZZER -------------------------------------------------------------------------------- /src/helpers/ui/buzzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /* class abstracts underlying RTTTL library 7 | 8 | Just a simple imlementation to start. At the moment use same 9 | melody for message and discovery 10 | Suggest enum type for different sounds 11 | - on message 12 | - on discovery 13 | 14 | TODO 15 | - make message ring tone configurable 16 | 17 | */ 18 | 19 | class genericBuzzer 20 | { 21 | public: 22 | void begin(); // set up buzzer port 23 | void play(const char *melody); // Generic play function 24 | void loop(); // loop driven-nonblocking 25 | void startup(); // play startup sound 26 | void shutdown(); // play shutdown sound 27 | bool isPlaying(); // returns true if a sound is still playing else false 28 | void quiet(bool buzzer_state); // enables or disables the buzzer 29 | bool isQuiet(); // get buzzer state on/off 30 | 31 | private: 32 | // gemini's picks: 33 | const char *startup_song = "Startup:d=4,o=5,b=160:16c6,16e6,8g6"; 34 | const char *shutdown_song = "Shutdown:d=4,o=5,b=100:8g5,16e5,16c5"; 35 | 36 | bool _is_quiet = true; 37 | }; 38 | -------------------------------------------------------------------------------- /variants/generic-e22/platformio.ini: -------------------------------------------------------------------------------- 1 | [Generic_E22] 2 | extends = esp32_base 3 | board = esp32doit-devkit-v1 4 | build_flags = 5 | ${esp32_base.build_flags} 6 | -I variants/generic-e22 7 | -D GENERIC_E22 8 | -D P_LORA_TX_LED=2 9 | -D PIN_VBAT_READ=35 10 | -D P_LORA_DIO_1=33 11 | -D P_LORA_NSS=18 12 | -D P_LORA_RESET=RADIOLIB_NC 13 | -D P_LORA_BUSY=32 14 | -D P_LORA_SCLK=5 15 | -D P_LORA_MOSI=27 16 | -D P_LORA_MISO=19 17 | -D SX126X_TXEN=13 18 | -D SX126X_RXEN=14 19 | -D PIN_BOARD_SDA=21 20 | -D PIN_BOARD_SCL=22 21 | -D SX126X_DIO2_AS_RF_SWITCH=true 22 | -D SX126X_DIO3_TCXO_VOLTAGE=1.8 23 | -D SX126X_CURRENT_LIMIT=140 24 | build_src_filter = ${esp32_base.build_src_filter} 25 | +<../variants/generic-e22> 26 | lib_deps = 27 | ${esp32_base.lib_deps} 28 | adafruit/Adafruit SSD1306 @ ^2.5.13 29 | 30 | [env:Generic_E22_sx1262_repeater] 31 | extends = Generic_E22 32 | build_src_filter = ${Generic_E22.build_src_filter} 33 | +<../examples/simple_repeater/main.cpp> 34 | build_flags = 35 | ${Generic_E22.build_flags} 36 | -D RADIO_CLASS=CustomSX1262 37 | -D WRAPPER_CLASS=CustomSX1262Wrapper 38 | -D LORA_TX_POWER=22 39 | -D ADVERT_NAME='"E22 Repeater"' 40 | -D ADVERT_LAT=0.0 41 | -D ADVERT_LON=0.0 42 | -D ADMIN_PASSWORD='"password"' 43 | -D MAX_NEIGHBOURS=8 44 | ; -D MESH_PACKET_LOGGING=1 45 | ; -D MESH_DEBUG=1 46 | lib_deps = 47 | ${Generic_E22.lib_deps} 48 | ${esp32_ota.lib_deps} 49 | 50 | [env:Generic_E22_sx1268_repeater] 51 | extends = Generic_E22 52 | build_src_filter = ${Generic_E22.build_src_filter} 53 | +<../examples/simple_repeater/main.cpp> 54 | build_flags = 55 | ${Generic_E22.build_flags} 56 | -D RADIO_CLASS=CustomSX1268 57 | -D WRAPPER_CLASS=CustomSX1268Wrapper 58 | -D LORA_TX_POWER=22 59 | -D ADVERT_NAME='"E22 Repeater"' 60 | -D ADVERT_LAT=0.0 61 | -D ADVERT_LON=0.0 62 | -D ADMIN_PASSWORD='"password"' 63 | -D MAX_NEIGHBOURS=8 64 | ; -D MESH_PACKET_LOGGING=1 65 | ; -D MESH_DEBUG=1 66 | lib_deps = 67 | ${Generic_E22.lib_deps} 68 | ${esp32_ota.lib_deps} 69 | -------------------------------------------------------------------------------- /variants/generic-e22/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | ESP32Board board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifndef LORA_CR 20 | #define LORA_CR 5 21 | #endif 22 | 23 | bool radio_init() { 24 | fallback_clock.begin(); 25 | rtc_clock.begin(Wire); 26 | 27 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 28 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 29 | #else 30 | float tcxo = 1.6f; 31 | #endif 32 | 33 | #if defined(P_LORA_SCLK) 34 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 35 | #endif 36 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 37 | if (status != RADIOLIB_ERR_NONE) { 38 | Serial.print("ERROR: radio init failed: "); 39 | Serial.println(status); 40 | return false; // fail 41 | } 42 | 43 | radio.setCRC(1); 44 | 45 | #if defined(SX126X_RXEN) && defined(SX126X_TXEN) 46 | radio.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN); 47 | #endif 48 | 49 | #ifdef SX126X_CURRENT_LIMIT 50 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 51 | #endif 52 | #ifdef SX126X_DIO2_AS_RF_SWITCH 53 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 54 | #endif 55 | #ifdef SX126X_RX_BOOSTED_GAIN 56 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 57 | #endif 58 | 59 | return true; // success 60 | } 61 | 62 | uint32_t radio_get_rng_seed() { 63 | return radio.random(0x7FFFFFFF); 64 | } 65 | 66 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 67 | radio.setFrequency(freq); 68 | radio.setSpreadingFactor(sf); 69 | radio.setBandwidth(bw); 70 | radio.setCodingRate(cr); 71 | } 72 | 73 | void radio_set_tx_power(uint8_t dbm) { 74 | radio.setOutputPower(dbm); 75 | } 76 | 77 | mesh::LocalIdentity radio_new_identity() { 78 | RadioNoiseListener rng(radio); 79 | return mesh::LocalIdentity(&rng); // create new random identity 80 | } 81 | -------------------------------------------------------------------------------- /variants/generic-e22/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | extern ESP32Board board; 13 | extern WRAPPER_CLASS radio_driver; 14 | extern AutoDiscoverRTCClock rtc_clock; 15 | extern SensorManager sensors; 16 | 17 | bool radio_init(); 18 | uint32_t radio_get_rng_seed(); 19 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 20 | void radio_set_tx_power(uint8_t dbm); 21 | mesh::LocalIdentity radio_new_identity(); 22 | -------------------------------------------------------------------------------- /variants/generic_espnow/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | ESP32Board board; 6 | 7 | ESPNOWRadio radio_driver; 8 | 9 | ESP32RTCClock rtc_clock; 10 | SensorManager sensors; 11 | 12 | bool radio_init() { 13 | rtc_clock.begin(); 14 | 15 | radio_driver.init(); 16 | 17 | return true; // success 18 | } 19 | 20 | uint32_t radio_get_rng_seed() { 21 | return millis() + radio_driver.intID(); // TODO: where to get some entropy? 22 | } 23 | 24 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 25 | // no-op 26 | } 27 | 28 | void radio_set_tx_power(uint8_t dbm) { 29 | radio_driver.setTxPower(dbm); 30 | } 31 | 32 | // NOTE: as we are using the WiFi radio, the ESP_IDF will have enabled hardware RNG: 33 | // https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/random.html 34 | class ESP_RNG : public mesh::RNG { 35 | public: 36 | void random(uint8_t* dest, size_t sz) override { 37 | esp_fill_random(dest, sz); 38 | } 39 | }; 40 | 41 | mesh::LocalIdentity radio_new_identity() { 42 | ESP_RNG rng; 43 | return mesh::LocalIdentity(&rng); // create new random identity 44 | } 45 | -------------------------------------------------------------------------------- /variants/generic_espnow/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | extern ESP32Board board; 8 | extern ESPNOWRadio radio_driver; 9 | extern ESP32RTCClock rtc_clock; 10 | extern SensorManager sensors; 11 | 12 | bool radio_init(); 13 | uint32_t radio_get_rng_seed(); 14 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 15 | void radio_set_tx_power(uint8_t dbm); 16 | mesh::LocalIdentity radio_new_identity(); 17 | -------------------------------------------------------------------------------- /variants/heltec_tracker/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #ifdef DISPLAY_CLASS 12 | #include 13 | #endif 14 | 15 | class HWTSensorManager : public SensorManager { 16 | bool gps_active = false; 17 | LocationProvider * _location; 18 | 19 | void start_gps(); 20 | void stop_gps(); 21 | public: 22 | HWTSensorManager(LocationProvider &location): _location(&location) { } 23 | bool begin() override; 24 | bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; 25 | void loop() override; 26 | int getNumSettings() const override; 27 | const char* getSettingName(int i) const override; 28 | const char* getSettingValue(int i) const override; 29 | bool setSettingValue(const char* name, const char* value) override; 30 | }; 31 | 32 | extern HeltecV3Board board; 33 | extern WRAPPER_CLASS radio_driver; 34 | extern AutoDiscoverRTCClock rtc_clock; 35 | extern HWTSensorManager sensors; 36 | 37 | #ifdef DISPLAY_CLASS 38 | extern DISPLAY_CLASS display; 39 | #endif 40 | 41 | bool radio_init(); 42 | uint32_t radio_get_rng_seed(); 43 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 44 | void radio_set_tx_power(uint8_t dbm); 45 | mesh::LocalIdentity radio_new_identity(); 46 | -------------------------------------------------------------------------------- /variants/heltec_v2/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | HeltecV2Board board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | DISPLAY_CLASS display; 21 | #endif 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | fallback_clock.begin(); 29 | rtc_clock.begin(Wire); 30 | 31 | #if defined(P_LORA_SCLK) 32 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 33 | #endif 34 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); 35 | if (status != RADIOLIB_ERR_NONE) { 36 | Serial.print("ERROR: radio init failed: "); 37 | Serial.println(status); 38 | return false; // fail 39 | } 40 | 41 | #ifdef SX127X_CURRENT_LIMIT 42 | radio.setCurrentLimit(SX127X_CURRENT_LIMIT); 43 | #endif 44 | 45 | radio.setCRC(1); 46 | 47 | return true; // success 48 | } 49 | 50 | uint32_t radio_get_rng_seed() { 51 | return radio.random(0x7FFFFFFF); 52 | } 53 | 54 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 55 | radio.setFrequency(freq); 56 | radio.setSpreadingFactor(sf); 57 | radio.setBandwidth(bw); 58 | radio.setCodingRate(cr); 59 | } 60 | 61 | void radio_set_tx_power(uint8_t dbm) { 62 | radio.setOutputPower(dbm); 63 | } 64 | 65 | mesh::LocalIdentity radio_new_identity() { 66 | RadioNoiseListener rng(radio); 67 | return mesh::LocalIdentity(&rng); // create new random identity 68 | } 69 | -------------------------------------------------------------------------------- /variants/heltec_v2/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern HeltecV2Board board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/heltec_v3/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | HeltecV3Board board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | DISPLAY_CLASS display; 21 | #endif 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | fallback_clock.begin(); 29 | rtc_clock.begin(Wire); 30 | 31 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 32 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 33 | #else 34 | float tcxo = 1.6f; 35 | #endif 36 | 37 | #if defined(P_LORA_SCLK) 38 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 39 | #endif 40 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 41 | if (status != RADIOLIB_ERR_NONE) { 42 | Serial.print("ERROR: radio init failed: "); 43 | Serial.println(status); 44 | return false; // fail 45 | } 46 | 47 | radio.setCRC(1); 48 | 49 | #ifdef SX126X_CURRENT_LIMIT 50 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 51 | #endif 52 | #ifdef SX126X_DIO2_AS_RF_SWITCH 53 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 54 | #endif 55 | #ifdef SX126X_RX_BOOSTED_GAIN 56 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 57 | #endif 58 | 59 | return true; // success 60 | } 61 | 62 | uint32_t radio_get_rng_seed() { 63 | return radio.random(0x7FFFFFFF); 64 | } 65 | 66 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 67 | radio.setFrequency(freq); 68 | radio.setSpreadingFactor(sf); 69 | radio.setBandwidth(bw); 70 | radio.setCodingRate(cr); 71 | } 72 | 73 | void radio_set_tx_power(uint8_t dbm) { 74 | radio.setOutputPower(dbm); 75 | } 76 | 77 | mesh::LocalIdentity radio_new_identity() { 78 | RadioNoiseListener rng(radio); 79 | return mesh::LocalIdentity(&rng); // create new random identity 80 | } 81 | -------------------------------------------------------------------------------- /variants/heltec_v3/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern HeltecV3Board board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/lilygo_t3s3/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | ESP32Board board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | DISPLAY_CLASS display; 21 | #endif 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | fallback_clock.begin(); 29 | rtc_clock.begin(Wire); 30 | 31 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 32 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 33 | #else 34 | float tcxo = 1.6f; 35 | #endif 36 | 37 | #if defined(P_LORA_SCLK) 38 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 39 | #endif 40 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 41 | if (status != RADIOLIB_ERR_NONE) { 42 | Serial.print("ERROR: radio init failed: "); 43 | Serial.println(status); 44 | return false; // fail 45 | } 46 | 47 | radio.setCRC(1); 48 | 49 | #ifdef SX126X_CURRENT_LIMIT 50 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 51 | #endif 52 | #ifdef SX126X_DIO2_AS_RF_SWITCH 53 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 54 | #endif 55 | #ifdef SX126X_RX_BOOSTED_GAIN 56 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 57 | #endif 58 | 59 | return true; // success 60 | } 61 | 62 | uint32_t radio_get_rng_seed() { 63 | return radio.random(0x7FFFFFFF); 64 | } 65 | 66 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 67 | radio.setFrequency(freq); 68 | radio.setSpreadingFactor(sf); 69 | radio.setBandwidth(bw); 70 | radio.setCodingRate(cr); 71 | } 72 | 73 | void radio_set_tx_power(uint8_t dbm) { 74 | radio.setOutputPower(dbm); 75 | } 76 | 77 | mesh::LocalIdentity radio_new_identity() { 78 | RadioNoiseListener rng(radio); 79 | return mesh::LocalIdentity(&rng); // create new random identity 80 | } 81 | -------------------------------------------------------------------------------- /variants/lilygo_t3s3/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern ESP32Board board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/lilygo_tbeam/platformio.ini: -------------------------------------------------------------------------------- 1 | [LilyGo_TBeam] 2 | extends = esp32_base 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${esp32_base.build_flags} 6 | -I variants/lilygo_tbeam 7 | -D LILYGO_TBEAM 8 | -D RADIO_CLASS=CustomSX1276 9 | -D WRAPPER_CLASS=CustomSX1276Wrapper 10 | -D SX127X_CURRENT_LIMIT=120 11 | -D LORA_TX_POWER=20 12 | -D P_LORA_TX_LED=4 13 | -D PIN_BOARD_SDA=21 14 | -D PIN_BOARD_SCL=22 15 | -D PIN_USER_BTN=38 16 | build_src_filter = ${esp32_base.build_src_filter} 17 | +<../variants/lilygo_tbeam> 18 | board_build.partitions = min_spiffs.csv ; get around 4mb flash limit 19 | lib_deps = 20 | ${esp32_base.lib_deps} 21 | lewisxhe/XPowersLib@^0.2.7 22 | adafruit/Adafruit SSD1306 @ ^2.5.13 23 | 24 | [env:Tbeam_companion_radio_ble] 25 | extends = LilyGo_TBeam 26 | board_build.upload.maximum_ram_size=2000000 27 | build_flags = 28 | ${LilyGo_TBeam.build_flags} 29 | -D DISPLAY_CLASS=SSD1306Display 30 | -D MAX_CONTACTS=100 31 | -D MAX_GROUP_CHANNELS=8 32 | -D BLE_PIN_CODE=123456 33 | -D BLE_DEBUG_LOGGING=1 34 | -D OFFLINE_QUEUE_SIZE=256 35 | ; -D RADIOLIB_DEBUG_BASIC=1 36 | ; -D ENABLE_PRIVATE_KEY_IMPORT=1 37 | ; -D ENABLE_PRIVATE_KEY_EXPORT=1 38 | ; -D MESH_PACKET_LOGGING=1 39 | ; -D MESH_DEBUG=1 40 | build_src_filter = ${LilyGo_TBeam.build_src_filter} 41 | + 42 | + 43 | +<../examples/companion_radio> 44 | lib_deps = 45 | ${LilyGo_TBeam.lib_deps} 46 | densaugeo/base64 @ ~1.4.0 47 | 48 | [env:Tbeam_repeater] 49 | extends = LilyGo_TBeam 50 | build_flags = 51 | ${LilyGo_TBeam.build_flags} 52 | -D DISPLAY_CLASS=SSD1306Display 53 | -D ADVERT_NAME='"Tbeam Repeater"' 54 | -D ADVERT_LAT=0.0 55 | -D ADVERT_LON=0.0 56 | -D ADMIN_PASSWORD='"password"' 57 | -D MAX_NEIGHBOURS=8 58 | ; -D MESH_PACKET_LOGGING=1 59 | ; -D MESH_DEBUG=1 60 | build_src_filter = ${LilyGo_TBeam.build_src_filter} 61 | + 62 | +<../examples/simple_repeater> 63 | lib_deps = 64 | ${LilyGo_TBeam.lib_deps} 65 | ${esp32_ota.lib_deps} -------------------------------------------------------------------------------- /variants/lilygo_tbeam/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | TBeamBoard board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | DISPLAY_CLASS display; 21 | #endif 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | fallback_clock.begin(); 29 | rtc_clock.begin(Wire); 30 | 31 | #if defined(P_LORA_SCLK) 32 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 33 | #endif 34 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); 35 | if (status != RADIOLIB_ERR_NONE) { 36 | Serial.print("ERROR: radio init failed: "); 37 | Serial.println(status); 38 | return false; // fail 39 | } 40 | 41 | #ifdef SX127X_CURRENT_LIMIT 42 | radio.setCurrentLimit(SX127X_CURRENT_LIMIT); 43 | #endif 44 | 45 | radio.setCRC(1); 46 | 47 | return true; // success 48 | } 49 | 50 | uint32_t radio_get_rng_seed() { 51 | return radio.random(0x7FFFFFFF); 52 | } 53 | 54 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 55 | radio.setFrequency(freq); 56 | radio.setSpreadingFactor(sf); 57 | radio.setBandwidth(bw); 58 | radio.setCodingRate(cr); 59 | } 60 | 61 | void radio_set_tx_power(uint8_t dbm) { 62 | radio.setOutputPower(dbm); 63 | } 64 | 65 | mesh::LocalIdentity radio_new_identity() { 66 | RadioNoiseListener rng(radio); 67 | return mesh::LocalIdentity(&rng); // create new random identity 68 | } 69 | -------------------------------------------------------------------------------- /variants/lilygo_tbeam/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern TBeamBoard board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/lilygo_tbeam_SX1262/platformio.ini: -------------------------------------------------------------------------------- 1 | [LilyGo_TBeam_SX1262] 2 | extends = esp32_base 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${esp32_base.build_flags} 6 | -I variants/lilygo_tbeam_SX1262 7 | -D LILYGO_TBEAM_SX1262 8 | -D SX126X_DIO2_AS_RF_SWITCH=true 9 | -D SX126X_DIO3_TCXO_VOLTAGE=1.8 10 | -D SX126X_CURRENT_LIMIT=140 11 | -D SX126X_RX_BOOSTED_GAIN=1 12 | -D RADIO_CLASS=CustomSX1262 13 | -D WRAPPER_CLASS=CustomSX1262Wrapper 14 | -D LORA_TX_POWER=22 15 | -D P_LORA_TX_LED=4 16 | -D PIN_BOARD_SDA=21 17 | -D PIN_BOARD_SCL=22 18 | -D PIN_USER_BTN=38 19 | build_src_filter = ${esp32_base.build_src_filter} 20 | +<../variants/lilygo_tbeam_SX1262> 21 | board_build.partitions = min_spiffs.csv ; get around 4mb flash limit 22 | lib_deps = 23 | ${esp32_base.lib_deps} 24 | lewisxhe/XPowersLib@^0.2.7 25 | adafruit/Adafruit SSD1306 @ ^2.5.13 26 | 27 | [env:Tbeam_SX1262_companion_radio_ble] 28 | extends = LilyGo_TBeam_SX1262 29 | board_build.upload.maximum_ram_size=2000000 30 | build_flags = 31 | ${LilyGo_TBeam_SX1262.build_flags} 32 | -D DISPLAY_CLASS=SSD1306Display 33 | -D MAX_CONTACTS=100 34 | -D MAX_GROUP_CHANNELS=8 35 | -D BLE_PIN_CODE=123456 36 | -D OFFLINE_QUEUE_SIZE=256 37 | ; -D BLE_DEBUG_LOGGING=1 38 | ; -D MESH_PACKET_LOGGING=1 39 | ; -D MESH_DEBUG=1 40 | ; -D RADIOLIB_DEBUG_BASIC=1 41 | ; -D ENABLE_PRIVATE_KEY_IMPORT=1 42 | ; -D ENABLE_PRIVATE_KEY_EXPORT=1 43 | ; -D MESH_PACKET_LOGGING=1 44 | ; -D MESH_DEBUG=1 45 | build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} 46 | + 47 | + 48 | +<../examples/companion_radio> 49 | lib_deps = 50 | ${LilyGo_TBeam_SX1262.lib_deps} 51 | densaugeo/base64 @ ~1.4.0 52 | 53 | [env:Tbeam_SX1262_repeater] 54 | extends = LilyGo_TBeam_SX1262 55 | build_flags = 56 | ${LilyGo_TBeam_SX1262.build_flags} 57 | -D DISPLAY_CLASS=SSD1306Display 58 | -D ADVERT_NAME='"Tbeam SX1262 Repeater"' 59 | -D ADVERT_LAT=0.0 60 | -D ADVERT_LON=0.0 61 | -D ADMIN_PASSWORD='"password"' 62 | -D MAX_NEIGHBOURS=8 63 | ; -D MESH_PACKET_LOGGING=1 64 | ; -D MESH_DEBUG=1 65 | build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} 66 | + 67 | +<../examples/simple_repeater> 68 | lib_deps = 69 | ${LilyGo_TBeam_SX1262.lib_deps} 70 | ${esp32_ota.lib_deps} -------------------------------------------------------------------------------- /variants/lilygo_tbeam_SX1262/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | TBeamBoardSX1262 board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | DISPLAY_CLASS display; 21 | #endif 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | fallback_clock.begin(); 29 | rtc_clock.begin(Wire); 30 | 31 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 32 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 33 | #else 34 | float tcxo = 1.6f; 35 | #endif 36 | 37 | #if defined(P_LORA_SCLK) 38 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 39 | #endif 40 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 41 | if (status != RADIOLIB_ERR_NONE) { 42 | Serial.print("ERROR: radio init failed: "); 43 | Serial.println(status); 44 | return false; // fail 45 | } 46 | 47 | radio.setCRC(1); 48 | 49 | return true; // success 50 | } 51 | 52 | uint32_t radio_get_rng_seed() { 53 | return radio.random(0x7FFFFFFF); 54 | } 55 | 56 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 57 | radio.setFrequency(freq); 58 | radio.setSpreadingFactor(sf); 59 | radio.setBandwidth(bw); 60 | radio.setCodingRate(cr); 61 | } 62 | 63 | void radio_set_tx_power(uint8_t dbm) { 64 | radio.setOutputPower(dbm); 65 | } 66 | 67 | mesh::LocalIdentity radio_new_identity() { 68 | RadioNoiseListener rng(radio); 69 | return mesh::LocalIdentity(&rng); // create new random identity 70 | } 71 | -------------------------------------------------------------------------------- /variants/lilygo_tbeam_SX1262/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern TBeamBoardSX1262 board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/lilygo_tbeam_supreme_SX1262/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class TbeamSupSensorManager: public SensorManager { 13 | bool gps_active = false; 14 | LocationProvider * _nmea; 15 | 16 | void start_gps(); 17 | void sleep_gps(); 18 | public: 19 | TbeamSupSensorManager(LocationProvider &nmea): _nmea(&nmea) { } 20 | bool begin() override; 21 | bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; 22 | void loop() override; 23 | int getNumSettings() const override; 24 | const char* getSettingName(int i) const override; 25 | const char* getSettingValue(int i) const override; 26 | bool setSettingValue(const char* name, const char* value) override; 27 | }; 28 | 29 | extern TBeamS3SupremeBoard board; 30 | extern WRAPPER_CLASS radio_driver; 31 | extern AutoDiscoverRTCClock rtc_clock; 32 | extern TbeamSupSensorManager sensors; 33 | 34 | enum { 35 | POWERMANAGE_ONLINE = _BV(0), 36 | DISPLAY_ONLINE = _BV(1), 37 | RADIO_ONLINE = _BV(2), 38 | GPS_ONLINE = _BV(3), 39 | PSRAM_ONLINE = _BV(4), 40 | SDCARD_ONLINE = _BV(5), 41 | AXDL345_ONLINE = _BV(6), 42 | BME280_ONLINE = _BV(7), 43 | BMP280_ONLINE = _BV(8), 44 | BME680_ONLINE = _BV(9), 45 | QMC6310_ONLINE = _BV(10), 46 | QMI8658_ONLINE = _BV(11), 47 | PCF8563_ONLINE = _BV(12), 48 | OSC32768_ONLINE = _BV(13), 49 | }; 50 | 51 | bool power_init(); 52 | bool radio_init(); 53 | uint32_t radio_get_rng_seed(); 54 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 55 | void radio_set_tx_power(uint8_t dbm); 56 | mesh::LocalIdentity radio_new_identity(); -------------------------------------------------------------------------------- /variants/lilygo_tlora_v2_1/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | LilyGoTLoraBoard board; 5 | 6 | static SPIClass spi; 7 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | ESP32RTCClock fallback_clock; 12 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 13 | SensorManager sensors; 14 | 15 | #ifdef DISPLAY_CLASS 16 | DISPLAY_CLASS display; 17 | #endif 18 | 19 | #ifndef LORA_CR 20 | #define LORA_CR 5 21 | #endif 22 | 23 | bool radio_init() { 24 | fallback_clock.begin(); 25 | rtc_clock.begin(Wire); 26 | 27 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 28 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); 29 | if (status != RADIOLIB_ERR_NONE) { 30 | Serial.print("ERROR: radio init failed: "); 31 | Serial.println(status); 32 | return false; // fail 33 | } 34 | 35 | #ifdef SX127X_CURRENT_LIMIT 36 | radio.setCurrentLimit(SX127X_CURRENT_LIMIT); 37 | #endif 38 | 39 | radio.setCRC(1); 40 | 41 | return true; // success 42 | } 43 | 44 | uint32_t radio_get_rng_seed() { 45 | return radio.random(0x7FFFFFFF); 46 | } 47 | 48 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 49 | radio.setFrequency(freq); 50 | radio.setSpreadingFactor(sf); 51 | radio.setBandwidth(bw); 52 | radio.setCodingRate(cr); 53 | } 54 | 55 | void radio_set_tx_power(uint8_t dbm) { 56 | radio.setOutputPower(dbm); 57 | } 58 | 59 | mesh::LocalIdentity radio_new_identity() { 60 | RadioNoiseListener rng(radio); 61 | return mesh::LocalIdentity(&rng); // create new random identity 62 | } 63 | -------------------------------------------------------------------------------- /variants/lilygo_tlora_v2_1/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern LilyGoTLoraBoard board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/nano_g2_ultra/nano-g2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // LoRa radio module pins 7 | #define P_LORA_DIO_1 (32 + 10) 8 | #define P_LORA_NSS (32 + 13) 9 | #define P_LORA_RESET (32 + 15) 10 | #define P_LORA_BUSY (32 + 11) 11 | #define P_LORA_SCLK (0 + 12) 12 | #define P_LORA_MISO (32 + 9) 13 | #define P_LORA_MOSI (0 + 11) 14 | 15 | #define SX126X_DIO2_AS_RF_SWITCH true 16 | #define SX126X_DIO3_TCXO_VOLTAGE 1.8 17 | #define SX126X_POWER_EN 37 18 | 19 | // buttons 20 | #define PIN_BUTTON1 (32 + 6) 21 | #define BUTTON_PIN PIN_BUTTON1 22 | #define PIN_USER_BTN BUTTON_PIN 23 | 24 | // built-ins 25 | #define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 26 | 27 | #define VBAT_DIVIDER (0.5F) // 150K + 150K voltage divider on VBAT, actually 100K + 100K 28 | #define VBAT_DIVIDER_COMP (2.0F) // Compensation factor for the VBAT divider 29 | 30 | #define PIN_VBAT_READ (0 + 2) 31 | #define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB) 32 | 33 | class NanoG2Ultra : public mesh::MainBoard 34 | { 35 | protected: 36 | uint8_t startup_reason; 37 | 38 | public: 39 | void begin(); 40 | uint16_t getBattMilliVolts() override; 41 | bool startOTAUpdate(const char *id, char reply[]) override; 42 | 43 | uint8_t getStartupReason() const override 44 | { 45 | return startup_reason; 46 | } 47 | 48 | const char *getManufacturerName() const override 49 | { 50 | return "Nano G2 Ultra"; 51 | } 52 | 53 | void reboot() override 54 | { 55 | NVIC_SystemReset(); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /variants/nano_g2_ultra/platformio.ini: -------------------------------------------------------------------------------- 1 | [nrf52840_g2_ultra] 2 | extends = nrf52_base 3 | platform_packages = framework-arduinoadafruitnrf52 4 | build_flags = ${nrf52_base.build_flags} 5 | -I src/helpers/nrf52 6 | -I lib/nrf52/s140_nrf52_6.1.1_API/include 7 | -I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52 8 | lib_deps = 9 | ${nrf52_base.lib_deps} 10 | rweather/Crypto @ ^0.4.0 11 | lewisxhe/PCF8563_Library@^1.0.1 12 | 13 | [Nano_G2_Ultra] 14 | extends = nrf52840_g2_ultra 15 | board = nano-g2-ultra 16 | board_build.ldscript = boards/nrf52840_s140_v6.ld 17 | build_flags = ${nrf52840_g2_ultra.build_flags} 18 | -I variants/nano_g2_ultra 19 | -D NANO_G2_ULTRA 20 | -D RADIO_CLASS=CustomSX1262 21 | -D WRAPPER_CLASS=CustomSX1262Wrapper 22 | -D LORA_TX_POWER=22 23 | -D SX126X_CURRENT_LIMIT=140 24 | -D SX126X_RX_BOOSTED_GAIN=1 25 | -D PIN_USER_BTN=38 26 | build_src_filter = ${nrf52840_g2_ultra.build_src_filter} 27 | + 28 | +<../variants/nano_g2_ultra> 29 | debug_tool = jlink 30 | upload_protocol = nrfutil 31 | 32 | [env:Nano_G2_Ultra_companion_radio_ble] 33 | extends = Nano_G2_Ultra 34 | build_flags = 35 | ${Nano_G2_Ultra.build_flags} 36 | -I src/helpers/ui 37 | -D MAX_CONTACTS=100 38 | -D MAX_GROUP_CHANNELS=8 39 | -D BLE_PIN_CODE=0 40 | -D BLE_DEBUG_LOGGING=1 41 | -D OFFLINE_QUEUE_SIZE=256 42 | -D DISPLAY_CLASS=SH1106Display 43 | -D PIN_BUZZER=4 44 | ; -D ENABLE_PRIVATE_KEY_IMPORT=1 45 | ; -D ENABLE_PRIVATE_KEY_EXPORT=1 46 | ; -D MESH_PACKET_LOGGING=1 47 | ; -D MESH_DEBUG=1 48 | build_src_filter = ${Nano_G2_Ultra.build_src_filter} 49 | + 50 | + 51 | + 52 | +<../examples/companion_radio> 53 | lib_deps = 54 | ${Nano_G2_Ultra.lib_deps} 55 | densaugeo/base64 @ ~1.4.0 56 | adafruit/Adafruit SH110X @ ~2.1.13 57 | adafruit/Adafruit GFX Library @ ^1.12.1 58 | stevemarple/MicroNMEA @ ^2.0.6 59 | end2endzone/NonBlockingRTTTL@^1.3.0 60 | -------------------------------------------------------------------------------- /variants/nano_g2_ultra/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include "nano-g2.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | #include 14 | 15 | class NanoG2UltraSensorManager : public SensorManager 16 | { 17 | bool gps_active = false; 18 | LocationProvider *_location; 19 | 20 | void start_gps(); 21 | void stop_gps(); 22 | 23 | public: 24 | NanoG2UltraSensorManager(LocationProvider &location) : _location(&location) {} 25 | bool begin() override; 26 | bool querySensors(uint8_t requester_permissions, CayenneLPP &telemetry) override; 27 | void loop() override; 28 | int getNumSettings() const override; 29 | const char *getSettingName(int i) const override; 30 | const char *getSettingValue(int i) const override; 31 | bool setSettingValue(const char *name, const char *value) override; 32 | }; 33 | 34 | extern NanoG2Ultra board; 35 | extern WRAPPER_CLASS radio_driver; 36 | extern AutoDiscoverRTCClock rtc_clock; 37 | extern NanoG2UltraSensorManager sensors; 38 | 39 | #ifdef DISPLAY_CLASS 40 | extern DISPLAY_CLASS display; 41 | #endif 42 | 43 | bool radio_init(); 44 | uint32_t radio_get_rng_seed(); 45 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 46 | void radio_set_tx_power(uint8_t dbm); 47 | mesh::LocalIdentity radio_new_identity(); 48 | -------------------------------------------------------------------------------- /variants/nano_g2_ultra/variant.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015 Arduino LLC. All right reserved. 3 | Copyright (c) 2016 Sandeep Mistry All right reserved. 4 | Copyright (c) 2018, Adafruit Industries (adafruit.com) 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 | See the GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "variant.h" 22 | #include "nrf.h" 23 | #include "wiring_constants.h" 24 | #include "wiring_digital.h" 25 | 26 | const uint32_t g_ADigitalPinMap[] = { 27 | // P0 - pins 0 and 1 are hardwired for xtal and should never be enabled 28 | 0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 29 | 30 | // P1 31 | 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; 32 | 33 | void initVariant() 34 | { 35 | // Nothing need to be inited for now 36 | } -------------------------------------------------------------------------------- /variants/picow/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | PicoWBoard board; 6 | 7 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI1); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | VolatileRTCClock fallback_clock; 12 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 13 | SensorManager sensors; 14 | 15 | #ifndef LORA_CR 16 | #define LORA_CR 5 17 | #endif 18 | 19 | bool radio_init() { 20 | rtc_clock.begin(Wire); 21 | 22 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 23 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 24 | #else 25 | float tcxo = 1.6f; 26 | #endif 27 | 28 | SPI1.setMISO(P_LORA_MISO); 29 | //SPI1.setCS(P_LORA_NSS); // Setting CS results in freeze 30 | SPI1.setSCK(P_LORA_SCLK); 31 | SPI1.setMOSI(P_LORA_MOSI); 32 | 33 | SPI1.begin(); 34 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 35 | if (status != RADIOLIB_ERR_NONE) { 36 | Serial.print("ERROR: radio init failed: "); 37 | Serial.println(status); 38 | return false; // fail 39 | } 40 | 41 | radio.setCRC(1); 42 | 43 | #ifdef SX126X_CURRENT_LIMIT 44 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 45 | #endif 46 | #ifdef SX126X_DIO2_AS_RF_SWITCH 47 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 48 | #endif 49 | #ifdef SX126X_RX_BOOSTED_GAIN 50 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 51 | #endif 52 | 53 | return true; // success 54 | } 55 | 56 | uint32_t radio_get_rng_seed() { 57 | return radio.random(0x7FFFFFFF); 58 | } 59 | 60 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 61 | radio.setFrequency(freq); 62 | radio.setSpreadingFactor(sf); 63 | radio.setBandwidth(bw); 64 | radio.setCodingRate(cr); 65 | } 66 | 67 | void radio_set_tx_power(uint8_t dbm) { 68 | radio.setOutputPower(dbm); 69 | } 70 | 71 | mesh::LocalIdentity radio_new_identity() { 72 | RadioNoiseListener rng(radio); 73 | return mesh::LocalIdentity(&rng); // create new random identity 74 | } 75 | -------------------------------------------------------------------------------- /variants/picow/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern PicoWBoard board; 12 | extern WRAPPER_CLASS radio_driver; 13 | extern AutoDiscoverRTCClock rtc_clock; 14 | extern SensorManager sensors; 15 | 16 | bool radio_init(); 17 | uint32_t radio_get_rng_seed(); 18 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 19 | void radio_set_tx_power(uint8_t dbm); 20 | mesh::LocalIdentity radio_new_identity(); 21 | -------------------------------------------------------------------------------- /variants/promicro/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | #include 15 | 16 | extern PromicroBoard board; 17 | extern WRAPPER_CLASS radio_driver; 18 | extern AutoDiscoverRTCClock rtc_clock; 19 | extern EnvironmentSensorManager sensors; 20 | 21 | #ifdef DISPLAY_CLASS 22 | extern DISPLAY_CLASS display; 23 | #endif 24 | 25 | bool radio_init(); 26 | uint32_t radio_get_rng_seed(); 27 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 28 | void radio_set_tx_power(uint8_t dbm); 29 | mesh::LocalIdentity radio_new_identity(); 30 | 31 | -------------------------------------------------------------------------------- /variants/promicro/variant.cpp: -------------------------------------------------------------------------------- 1 | #include "variant.h" 2 | #include "wiring_constants.h" 3 | #include "wiring_digital.h" 4 | 5 | const uint32_t g_ADigitalPinMap[] = { 6 | 8, 6, 17, 20, 22, 24, 32, 11, 36, 38, 7 | 9, 10, 43, 45, 47, 2, 29, 31, 8 | 33, 34, 37, 9 | 13, 15 10 | }; 11 | 12 | void initVariant() 13 | { 14 | } 15 | 16 | -------------------------------------------------------------------------------- /variants/rak3x72/platformio.ini: -------------------------------------------------------------------------------- 1 | [rak3x72] 2 | extends = stm32_base 3 | board = rak3172 4 | board_upload.maximum_size = 229376 ; 32kb for FS 5 | build_flags = ${stm32_base.build_flags} 6 | -D RADIO_CLASS=CustomSTM32WLx 7 | -D WRAPPER_CLASS=CustomSTM32WLxWrapper 8 | -D SPI_INTERFACES_COUNT=0 9 | -D RX_BOOSTED_GAIN=true 10 | -I variants/rak3x72 11 | build_src_filter = ${stm32_base.build_src_filter} 12 | +<../variants/rak3x72> 13 | 14 | [env:rak3x72-repeater] 15 | extends = rak3x72 16 | build_flags = ${rak3x72.build_flags} 17 | -D LORA_TX_POWER=22 18 | -D ADVERT_NAME='"RAK3x72 Repeater"' 19 | -D ADMIN_PASSWORD='"password"' 20 | build_src_filter = ${rak3x72.build_src_filter} 21 | +<../examples/simple_repeater/main.cpp> 22 | 23 | [env:rak3x72_companion_radio_usb] 24 | extends = rak3x72 25 | build_flags = ${rak3x72.build_flags} 26 | ; -D FORMAT_FS=true 27 | -D LORA_TX_POWER=22 28 | -D MAX_CONTACTS=100 29 | -D MAX_GROUP_CHANNELS=8 30 | build_src_filter = ${rak3x72.build_src_filter} 31 | +<../examples/companion_radio/*.cpp> 32 | lib_deps = ${rak3x72.lib_deps} 33 | densaugeo/base64 @ ~1.4.0 34 | -------------------------------------------------------------------------------- /variants/rak3x72/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | RAK3x72Board board; 6 | 7 | RADIO_CLASS radio = new STM32WLx_Module(); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | static const uint32_t rfswitch_pins[] = {LORAWAN_RFSWITCH_PINS, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; 12 | static const Module::RfSwitchMode_t rfswitch_table[] = { 13 | {STM32WLx::MODE_IDLE, {LOW, LOW}}, 14 | {STM32WLx::MODE_RX, {HIGH, LOW}}, 15 | {STM32WLx::MODE_TX_LP, {LOW, HIGH}}, 16 | {STM32WLx::MODE_TX_HP, {LOW, HIGH}}, 17 | END_OF_MODE_TABLE, 18 | }; 19 | 20 | VolatileRTCClock rtc_clock; 21 | SensorManager sensors; 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | // rtc_clock.begin(Wire); 29 | 30 | radio.setRfSwitchTable(rfswitch_pins, rfswitch_table); 31 | 32 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, 0, 0); // TCXO set to 0 for RAK3172 33 | 34 | if (status != RADIOLIB_ERR_NONE) { 35 | Serial.print("ERROR: radio init failed: "); 36 | Serial.println(status); 37 | return false; // fail 38 | } 39 | 40 | #ifdef RX_BOOSTED_GAIN 41 | radio.setRxBoostedGainMode(RX_BOOSTED_GAIN); 42 | #endif 43 | 44 | radio.setCRC(1); 45 | 46 | return true; // success 47 | } 48 | 49 | uint32_t radio_get_rng_seed() { 50 | return radio.random(0x7FFFFFFF); 51 | } 52 | 53 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 54 | radio.setFrequency(freq); 55 | radio.setSpreadingFactor(sf); 56 | radio.setBandwidth(bw); 57 | radio.setCodingRate(cr); 58 | } 59 | 60 | void radio_set_tx_power(uint8_t dbm) { 61 | radio.setOutputPower(dbm); 62 | } 63 | 64 | mesh::LocalIdentity radio_new_identity() { 65 | RadioNoiseListener rng(radio); 66 | return mesh::LocalIdentity(&rng); // create new random identity 67 | } 68 | -------------------------------------------------------------------------------- /variants/rak3x72/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PIN_VBAT_READ A0 12 | #define ADC_MULTIPLIER (5 * 1.73 * 1000) 13 | 14 | class RAK3x72Board : public STM32Board { 15 | public: 16 | const char* getManufacturerName() const override { 17 | return "RAK 3x72"; 18 | } 19 | 20 | uint16_t getBattMilliVolts() override { 21 | uint32_t raw = analogRead(PIN_VBAT_READ); 22 | return (ADC_MULTIPLIER * raw) / 1024; 23 | } 24 | }; 25 | 26 | extern RAK3x72Board board; 27 | extern WRAPPER_CLASS radio_driver; 28 | extern VolatileRTCClock rtc_clock; 29 | extern SensorManager sensors; 30 | 31 | bool radio_init(); 32 | uint32_t radio_get_rng_seed(); 33 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 34 | void radio_set_tx_power(uint8_t dbm); 35 | mesh::LocalIdentity radio_new_identity(); 36 | -------------------------------------------------------------------------------- /variants/rak3x72/variant.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #undef RNG 6 | -------------------------------------------------------------------------------- /variants/rak4631/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | RAK4631Board board; 6 | 7 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | VolatileRTCClock fallback_clock; 12 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 13 | SensorManager sensors; 14 | 15 | #ifdef DISPLAY_CLASS 16 | DISPLAY_CLASS display; 17 | #endif 18 | 19 | #ifndef LORA_CR 20 | #define LORA_CR 5 21 | #endif 22 | 23 | bool radio_init() { 24 | rtc_clock.begin(Wire); 25 | 26 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 27 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 28 | #else 29 | float tcxo = 1.6f; 30 | #endif 31 | 32 | SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); 33 | SPI.begin(); 34 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 35 | if (status != RADIOLIB_ERR_NONE) { 36 | Serial.print("ERROR: radio init failed: "); 37 | Serial.println(status); 38 | return false; // fail 39 | } 40 | 41 | radio.setCRC(1); 42 | 43 | #ifdef SX126X_CURRENT_LIMIT 44 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 45 | #endif 46 | #ifdef SX126X_DIO2_AS_RF_SWITCH 47 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 48 | #endif 49 | #ifdef SX126X_RX_BOOSTED_GAIN 50 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 51 | #endif 52 | 53 | return true; // success 54 | } 55 | 56 | uint32_t radio_get_rng_seed() { 57 | return radio.random(0x7FFFFFFF); 58 | } 59 | 60 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 61 | radio.setFrequency(freq); 62 | radio.setSpreadingFactor(sf); 63 | radio.setBandwidth(bw); 64 | radio.setCodingRate(cr); 65 | } 66 | 67 | void radio_set_tx_power(uint8_t dbm) { 68 | radio.setOutputPower(dbm); 69 | } 70 | 71 | mesh::LocalIdentity radio_new_identity() { 72 | RadioNoiseListener rng(radio); 73 | return mesh::LocalIdentity(&rng); // create new random identity 74 | } 75 | -------------------------------------------------------------------------------- /variants/rak4631/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern RAK4631Board board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/station_g2/platformio.ini: -------------------------------------------------------------------------------- 1 | [Station_G2] 2 | extends = esp32_base 3 | board = station-g2 4 | build_flags = 5 | ${esp32_base.build_flags} 6 | -I variants/station_g2 7 | -D STATION_G2 8 | -D RADIO_CLASS=CustomSX1262 9 | -D WRAPPER_CLASS=CustomSX1262Wrapper 10 | -D LORA_TX_POWER=7 11 | ; -D P_LORA_TX_LED=35 12 | ; -D PIN_BOARD_SDA=5 13 | ; -D PIN_BOARD_SCL=6 14 | -D PIN_USER_BTN=0 15 | -D SX126X_DIO2_AS_RF_SWITCH=true 16 | -D SX126X_DIO3_TCXO_VOLTAGE=1.8 17 | -D SX126X_CURRENT_LIMIT=140 18 | ; -D SX126X_RX_BOOSTED_GAIN=1 - DO NOT ENABLE THIS! 19 | ; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance 20 | build_src_filter = ${esp32_base.build_src_filter} 21 | +<../variants/station_g2> 22 | lib_deps = 23 | ${esp32_base.lib_deps} 24 | 25 | [env:Station_G2_repeater] 26 | extends = Station_G2 27 | build_flags = 28 | ${Station_G2.build_flags} 29 | -D ADVERT_NAME='"Station G2 Repeater"' 30 | -D ADVERT_LAT=0.0 31 | -D ADVERT_LON=0.0 32 | -D ADMIN_PASSWORD='"password"' 33 | -D MAX_NEIGHBOURS=8 34 | ; -D MESH_PACKET_LOGGING=1 35 | ; -D MESH_DEBUG=1 36 | build_src_filter = ${Station_G2.build_src_filter} 37 | +<../examples/simple_repeater> 38 | lib_deps = 39 | ${Station_G2.lib_deps} 40 | ${esp32_ota.lib_deps} 41 | 42 | [env:Station_G2_room_server] 43 | extends = Station_G2 44 | build_src_filter = ${Station_G2.build_src_filter} 45 | +<../examples/simple_room_server> 46 | build_flags = 47 | ${Station_G2.build_flags} 48 | -D ADVERT_NAME='"Station G2 Room"' 49 | -D ADVERT_LAT=0.0 50 | -D ADVERT_LON=0.0 51 | -D ADMIN_PASSWORD='"password"' 52 | -D ROOM_PASSWORD='"hello"' 53 | ; -D MESH_PACKET_LOGGING=1 54 | ; -D MESH_DEBUG=1 55 | lib_deps = 56 | ${Station_G2.lib_deps} 57 | ${esp32_ota.lib_deps} 58 | -------------------------------------------------------------------------------- /variants/station_g2/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | StationG2Board board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifndef LORA_CR 20 | #define LORA_CR 5 21 | #endif 22 | 23 | bool radio_init() { 24 | fallback_clock.begin(); 25 | rtc_clock.begin(Wire); 26 | 27 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 28 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 29 | #else 30 | float tcxo = 1.6f; 31 | #endif 32 | 33 | #if defined(P_LORA_SCLK) 34 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 35 | #endif 36 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 37 | if (status != RADIOLIB_ERR_NONE) { 38 | Serial.print("ERROR: radio init failed: "); 39 | Serial.println(status); 40 | return false; // fail 41 | } 42 | 43 | radio.setCRC(1); 44 | 45 | #ifdef SX126X_CURRENT_LIMIT 46 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 47 | #endif 48 | #ifdef SX126X_DIO2_AS_RF_SWITCH 49 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 50 | #endif 51 | #ifdef SX126X_RX_BOOSTED_GAIN 52 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 53 | #endif 54 | 55 | return true; // success 56 | } 57 | 58 | uint32_t radio_get_rng_seed() { 59 | return radio.random(0x7FFFFFFF); 60 | } 61 | 62 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 63 | radio.setFrequency(freq); 64 | radio.setSpreadingFactor(sf); 65 | radio.setBandwidth(bw); 66 | radio.setCodingRate(cr); 67 | } 68 | 69 | void radio_set_tx_power(uint8_t dbm) { 70 | radio.setOutputPower(dbm); 71 | } 72 | 73 | mesh::LocalIdentity radio_new_identity() { 74 | RadioNoiseListener rng(radio); 75 | return mesh::LocalIdentity(&rng); // create new random identity 76 | } 77 | -------------------------------------------------------------------------------- /variants/station_g2/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern StationG2Board board; 12 | extern WRAPPER_CLASS radio_driver; 13 | extern AutoDiscoverRTCClock rtc_clock; 14 | extern SensorManager sensors; 15 | 16 | bool radio_init(); 17 | uint32_t radio_get_rng_seed(); 18 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 19 | void radio_set_tx_power(uint8_t dbm); 20 | mesh::LocalIdentity radio_new_identity(); 21 | -------------------------------------------------------------------------------- /variants/t1000-e/NullDisplayDriver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class NullDisplayDriver : public DisplayDriver { 6 | public: 7 | NullDisplayDriver() : DisplayDriver(128, 64) { } 8 | bool begin() { return false; } // not present 9 | 10 | bool isOn() override { return false; } 11 | void turnOn() override { } 12 | void turnOff() override { } 13 | void clear() override { } 14 | void startFrame(Color bkg = DARK) override { } 15 | void setTextSize(int sz) override { } 16 | void setColor(Color c) override { } 17 | void setCursor(int x, int y) override { } 18 | void print(const char* str) override { } 19 | void fillRect(int x, int y, int w, int h) override { } 20 | void drawRect(int x, int y, int w, int h) override { } 21 | void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override { } 22 | uint16_t getTextWidth(const char* str) override { return 0; } 23 | void endFrame() { } 24 | }; 25 | -------------------------------------------------------------------------------- /variants/t1000-e/platformio.ini: -------------------------------------------------------------------------------- 1 | ; ----------------- NRF52 T1000e--------------------- 2 | [nrf52840_t1000e] 3 | extends = nrf52_base 4 | platform_packages = framework-arduinoadafruitnrf52 5 | build_flags = ${nrf52_base.build_flags} 6 | -I src/helpers/nrf52 7 | -I lib/nrf52/s140_nrf52_7.3.0_API/include 8 | -I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52 9 | lib_ignore = 10 | BluetoothOTA 11 | lvgl 12 | lib5b4 13 | lib_deps = 14 | ${nrf52_base.lib_deps} 15 | rweather/Crypto @ ^0.4.0 16 | 17 | [t1000-e] 18 | extends = nrf52840_t1000e 19 | board = tracker-t1000-e 20 | board_build.ldscript = boards/nrf52840_s140_v7.ld 21 | build_flags = ${nrf52840_t1000e.build_flags} 22 | -I variants/t1000-e 23 | -D T1000_E 24 | -D PIN_USER_BTN=6 25 | -D USER_BTN_PRESSED=HIGH 26 | -D PIN_STATUS_LED=24 27 | -D RADIO_CLASS=CustomLR1110 28 | -D WRAPPER_CLASS=CustomLR1110Wrapper 29 | -D LORA_TX_POWER=22 30 | build_src_filter = ${nrf52840_t1000e.build_src_filter} 31 | + 32 | + 33 | +<../variants/t1000-e> 34 | debug_tool = jlink 35 | upload_protocol = nrfutil 36 | 37 | [env:t1000e_companion_radio_ble] 38 | extends = t1000-e 39 | build_flags = ${t1000-e.build_flags} 40 | -D MAX_CONTACTS=100 41 | -D MAX_GROUP_CHANNELS=8 42 | -D BLE_PIN_CODE=123456 43 | ; -D BLE_DEBUG_LOGGING=1 44 | ; -D MESH_PACKET_LOGGING=1 45 | ; -D MESH_DEBUG=1 46 | -D OFFLINE_QUEUE_SIZE=256 47 | -D RX_BOOSTED_GAIN=true 48 | -D RF_SWITCH_TABLE 49 | -D DISPLAY_CLASS=NullDisplayDriver 50 | -D PIN_BUZZER=25 51 | -D PIN_BUZZER_EN=37 ; P1/5 - required for T1000-E 52 | build_src_filter = ${t1000-e.build_src_filter} 53 | + 54 | + 55 | +<../examples/companion_radio/*.cpp> 56 | lib_deps = ${t1000-e.lib_deps} 57 | densaugeo/base64 @ ~1.4.0 58 | stevemarple/MicroNMEA @ ^2.0.6 59 | end2endzone/NonBlockingRTTTL@^1.3.0 -------------------------------------------------------------------------------- /variants/t1000-e/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #ifdef DISPLAY_CLASS 12 | #include "NullDisplayDriver.h" 13 | #endif 14 | 15 | class T1000SensorManager: public SensorManager { 16 | bool gps_active = false; 17 | LocationProvider * _nmea; 18 | 19 | void start_gps(); 20 | void sleep_gps(); 21 | void stop_gps(); 22 | public: 23 | T1000SensorManager(LocationProvider &nmea): _nmea(&nmea) { } 24 | bool begin() override; 25 | bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; 26 | void loop() override; 27 | int getNumSettings() const override; 28 | const char* getSettingName(int i) const override; 29 | const char* getSettingValue(int i) const override; 30 | bool setSettingValue(const char* name, const char* value) override; 31 | }; 32 | 33 | #ifdef DISPLAY_CLASS 34 | extern NullDisplayDriver display; 35 | #endif 36 | 37 | extern T1000eBoard board; 38 | extern WRAPPER_CLASS radio_driver; 39 | extern VolatileRTCClock rtc_clock; 40 | extern T1000SensorManager sensors; 41 | 42 | bool radio_init(); 43 | uint32_t radio_get_rng_seed(); 44 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 45 | void radio_set_tx_power(uint8_t dbm); 46 | mesh::LocalIdentity radio_new_identity(); 47 | -------------------------------------------------------------------------------- /variants/t114/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #ifdef DISPLAY_CLASS 12 | #include 13 | #endif 14 | 15 | class T114SensorManager : public SensorManager { 16 | bool gps_active = false; 17 | bool gps_detected = false; 18 | LocationProvider* _location; 19 | 20 | void start_gps(); 21 | void stop_gps(); 22 | public: 23 | T114SensorManager(LocationProvider &location): _location(&location) { } 24 | bool begin() override; 25 | bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; 26 | void loop() override; 27 | int getNumSettings() const override; 28 | const char* getSettingName(int i) const override; 29 | const char* getSettingValue(int i) const override; 30 | bool setSettingValue(const char* name, const char* value) override; 31 | }; 32 | 33 | extern T114Board board; 34 | extern WRAPPER_CLASS radio_driver; 35 | extern AutoDiscoverRTCClock rtc_clock; 36 | extern T114SensorManager sensors; 37 | 38 | #ifdef DISPLAY_CLASS 39 | extern DISPLAY_CLASS display; 40 | #endif 41 | 42 | bool radio_init(); 43 | uint32_t radio_get_rng_seed(); 44 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 45 | void radio_set_tx_power(uint8_t dbm); 46 | mesh::LocalIdentity radio_new_identity(); 47 | -------------------------------------------------------------------------------- /variants/t114/variant.cpp: -------------------------------------------------------------------------------- 1 | #include "variant.h" 2 | #include "wiring_constants.h" 3 | #include "wiring_digital.h" 4 | 5 | const uint32_t g_ADigitalPinMap[] = { 6 | 0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 7 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 8 | 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 9 | 40, 41, 42, 43, 44, 45, 46, 47 10 | }; 11 | 12 | void initVariant() 13 | { 14 | pinMode(PIN_USER_BTN, INPUT); 15 | } 16 | -------------------------------------------------------------------------------- /variants/techo/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | TechoBoard board; 6 | 7 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | VolatileRTCClock fallback_clock; 12 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 13 | SensorManager sensors; 14 | 15 | #ifdef DISPLAY_CLASS 16 | DISPLAY_CLASS display; 17 | #endif 18 | 19 | #ifndef LORA_CR 20 | #define LORA_CR 5 21 | #endif 22 | 23 | bool radio_init() { 24 | rtc_clock.begin(Wire); 25 | 26 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 27 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 28 | #else 29 | float tcxo = 1.6f; 30 | #endif 31 | 32 | SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); 33 | SPI.begin(); 34 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 35 | if (status != RADIOLIB_ERR_NONE) { 36 | Serial.print("ERROR: radio init failed: "); 37 | Serial.println(status); 38 | return false; // fail 39 | } 40 | 41 | radio.setCRC(1); 42 | 43 | #ifdef SX126X_CURRENT_LIMIT 44 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 45 | #endif 46 | #ifdef SX126X_DIO2_AS_RF_SWITCH 47 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 48 | #endif 49 | #ifdef SX126X_RX_BOOSTED_GAIN 50 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 51 | #endif 52 | 53 | return true; // success 54 | } 55 | 56 | uint32_t radio_get_rng_seed() { 57 | return radio.random(0x7FFFFFFF); 58 | } 59 | 60 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 61 | radio.setFrequency(freq); 62 | radio.setSpreadingFactor(sf); 63 | radio.setBandwidth(bw); 64 | radio.setCodingRate(cr); 65 | } 66 | 67 | void radio_set_tx_power(uint8_t dbm) { 68 | radio.setOutputPower(dbm); 69 | } 70 | 71 | mesh::LocalIdentity radio_new_identity() { 72 | RadioNoiseListener rng(radio); 73 | return mesh::LocalIdentity(&rng); // create new random identity 74 | } 75 | -------------------------------------------------------------------------------- /variants/techo/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | 15 | extern TechoBoard board; 16 | extern WRAPPER_CLASS radio_driver; 17 | extern AutoDiscoverRTCClock rtc_clock; 18 | extern SensorManager sensors; 19 | 20 | #ifdef DISPLAY_CLASS 21 | extern DISPLAY_CLASS display; 22 | #endif 23 | 24 | bool radio_init(); 25 | uint32_t radio_get_rng_seed(); 26 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 27 | void radio_set_tx_power(uint8_t dbm); 28 | mesh::LocalIdentity radio_new_identity(); 29 | -------------------------------------------------------------------------------- /variants/techo/variant.cpp: -------------------------------------------------------------------------------- 1 | #include "variant.h" 2 | #include "wiring_constants.h" 3 | #include "wiring_digital.h" 4 | 5 | const int MISO = PIN_SPI1_MISO; 6 | const int MOSI = PIN_SPI1_MOSI; 7 | const int SCK = PIN_SPI1_SCK; 8 | 9 | const uint32_t g_ADigitalPinMap[] = { 10 | 0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 11 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 12 | 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 13 | 40, 41, 42, 43, 44, 45, 46, 47 14 | }; 15 | 16 | void initVariant() { 17 | pinMode(PIN_PWR_EN, OUTPUT); 18 | digitalWrite(PIN_PWR_EN, HIGH); 19 | 20 | pinMode(PIN_BUTTON1, INPUT_PULLUP); 21 | pinMode(PIN_BUTTON2, INPUT_PULLUP); 22 | 23 | pinMode(LED_RED, OUTPUT); 24 | pinMode(LED_GREEN, OUTPUT); 25 | pinMode(LED_BLUE, OUTPUT); 26 | digitalWrite(LED_BLUE, HIGH); 27 | 28 | pinMode(PIN_TXCO, OUTPUT); 29 | digitalWrite(PIN_TXCO, HIGH); 30 | 31 | // shutdown gps 32 | pinMode(PIN_GPS_STANDBY, OUTPUT); 33 | digitalWrite(PIN_GPS_STANDBY, LOW); 34 | } 35 | -------------------------------------------------------------------------------- /variants/thinknode_m1/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | ThinkNodeM1Board board; 6 | 7 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | VolatileRTCClock fallback_clock; 12 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 13 | SensorManager sensors; 14 | 15 | #ifdef DISPLAY_CLASS 16 | DISPLAY_CLASS display; 17 | #endif 18 | 19 | #ifndef LORA_CR 20 | #define LORA_CR 5 21 | #endif 22 | 23 | bool radio_init() { 24 | rtc_clock.begin(Wire); 25 | 26 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 27 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 28 | #else 29 | float tcxo = 1.6f; 30 | #endif 31 | 32 | SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); 33 | SPI.begin(); 34 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 35 | if (status != RADIOLIB_ERR_NONE) { 36 | Serial.print("ERROR: radio init failed: "); 37 | Serial.println(status); 38 | return false; // fail 39 | } 40 | 41 | radio.setCRC(1); 42 | 43 | #ifdef SX126X_CURRENT_LIMIT 44 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 45 | #endif 46 | #ifdef SX126X_DIO2_AS_RF_SWITCH 47 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 48 | #endif 49 | #ifdef SX126X_RX_BOOSTED_GAIN 50 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 51 | #endif 52 | 53 | return true; // success 54 | } 55 | 56 | uint32_t radio_get_rng_seed() { 57 | return radio.random(0x7FFFFFFF); 58 | } 59 | 60 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 61 | radio.setFrequency(freq); 62 | radio.setSpreadingFactor(sf); 63 | radio.setBandwidth(bw); 64 | radio.setCodingRate(cr); 65 | } 66 | 67 | void radio_set_tx_power(uint8_t dbm) { 68 | radio.setOutputPower(dbm); 69 | } 70 | 71 | mesh::LocalIdentity radio_new_identity() { 72 | RadioNoiseListener rng(radio); 73 | return mesh::LocalIdentity(&rng); // create new random identity 74 | } 75 | -------------------------------------------------------------------------------- /variants/thinknode_m1/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern ThinkNodeM1Board board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/thinknode_m1/variant.cpp: -------------------------------------------------------------------------------- 1 | #include "variant.h" 2 | #include "wiring_constants.h" 3 | #include "wiring_digital.h" 4 | 5 | const int MISO = PIN_SPI1_MISO; 6 | const int MOSI = PIN_SPI1_MOSI; 7 | const int SCK = PIN_SPI1_SCK; 8 | 9 | const uint32_t g_ADigitalPinMap[] = { 10 | 0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 11 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 12 | 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 13 | 40, 41, 42, 43, 44, 45, 46, 47 14 | }; 15 | 16 | void initVariant() { 17 | pinMode(PIN_PWR_EN, OUTPUT); 18 | digitalWrite(PIN_PWR_EN, HIGH); 19 | 20 | pinMode(PIN_BUTTON1, INPUT_PULLUP); 21 | pinMode(PIN_BUTTON2, INPUT_PULLUP); 22 | 23 | pinMode(LED_RED, OUTPUT); 24 | pinMode(LED_GREEN, OUTPUT); 25 | pinMode(LED_BLUE, OUTPUT); 26 | digitalWrite(LED_BLUE, HIGH); 27 | 28 | pinMode(PIN_TXCO, OUTPUT); 29 | digitalWrite(PIN_TXCO, HIGH); 30 | 31 | // shutdown gps 32 | pinMode(PIN_GPS_STANDBY, OUTPUT); 33 | digitalWrite(PIN_GPS_STANDBY, LOW); 34 | } 35 | -------------------------------------------------------------------------------- /variants/wio-e5/platformio.ini: -------------------------------------------------------------------------------- 1 | [lora_e5] 2 | extends = stm32_base 3 | board = lora_e5_dev_board 4 | board_upload.maximum_size = 229376 ; 32kb for FS 5 | build_flags = ${stm32_base.build_flags} 6 | -D RADIO_CLASS=CustomSTM32WLx 7 | -D WRAPPER_CLASS=CustomSTM32WLxWrapper 8 | -D SPI_INTERFACES_COUNT=0 9 | -D RX_BOOSTED_GAIN=true 10 | -I variants/wio-e5 11 | build_src_filter = ${stm32_base.build_src_filter} 12 | +<../variants/wio-e5> 13 | 14 | [env:wio-e5-repeater] 15 | extends = lora_e5 16 | build_flags = ${lora_e5.build_flags} 17 | -D LORA_TX_POWER=22 18 | -D ADVERT_NAME='"WIO-E5 Repeater"' 19 | -D ADMIN_PASSWORD='"password"' 20 | build_src_filter = ${lora_e5.build_src_filter} 21 | +<../examples/simple_repeater/main.cpp> 22 | 23 | [env:wio-e5_companion_radio_usb] 24 | extends = lora_e5 25 | build_flags = ${lora_e5.build_flags} 26 | -D LORA_TX_POWER=22 27 | -D MAX_CONTACTS=100 28 | -D MAX_GROUP_CHANNELS=8 29 | build_src_filter = ${lora_e5.build_src_filter} 30 | +<../examples/companion_radio/*.cpp> 31 | lib_deps = ${lora_e5.lib_deps} 32 | densaugeo/base64 @ ~1.4.0 33 | -------------------------------------------------------------------------------- /variants/wio-e5/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | WIOE5Board board; 6 | 7 | RADIO_CLASS radio = new STM32WLx_Module(); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | static const uint32_t rfswitch_pins[] = {PA4, PA5, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; 12 | static const Module::RfSwitchMode_t rfswitch_table[] = { 13 | {STM32WLx::MODE_IDLE, {LOW, LOW}}, 14 | {STM32WLx::MODE_RX, {HIGH, LOW}}, 15 | {STM32WLx::MODE_TX_HP, {LOW, HIGH}}, // for LoRa-E5 mini 16 | // {STM32WLx::MODE_TX_LP, {HIGH, HIGH}}, // for LoRa-E5-LE mini 17 | END_OF_MODE_TABLE, 18 | }; 19 | 20 | VolatileRTCClock rtc_clock; 21 | SensorManager sensors; 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | // rtc_clock.begin(Wire); 29 | 30 | // #ifdef SX126X_DIO3_TCXO_VOLTAGE 31 | // float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 32 | // #else 33 | // float tcxo = 1.6f; 34 | // #endif 35 | 36 | radio.setRfSwitchTable(rfswitch_pins, rfswitch_table); 37 | 38 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, 1.7, 0); 39 | 40 | if (status != RADIOLIB_ERR_NONE) { 41 | Serial.print("ERROR: radio init failed: "); 42 | Serial.println(status); 43 | return false; // fail 44 | } 45 | 46 | #ifdef RX_BOOSTED_GAIN 47 | radio.setRxBoostedGainMode(RX_BOOSTED_GAIN); 48 | #endif 49 | 50 | radio.setCRC(1); 51 | 52 | return true; // success 53 | } 54 | 55 | uint32_t radio_get_rng_seed() { 56 | return radio.random(0x7FFFFFFF); 57 | } 58 | 59 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 60 | radio.setFrequency(freq); 61 | radio.setSpreadingFactor(sf); 62 | radio.setBandwidth(bw); 63 | radio.setCodingRate(cr); 64 | } 65 | 66 | void radio_set_tx_power(uint8_t dbm) { 67 | radio.setOutputPower(dbm); 68 | } 69 | 70 | mesh::LocalIdentity radio_new_identity() { 71 | RadioNoiseListener rng(radio); 72 | return mesh::LocalIdentity(&rng); // create new random identity 73 | } 74 | -------------------------------------------------------------------------------- /variants/wio-e5/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class WIOE5Board : public STM32Board { 12 | public: 13 | const char* getManufacturerName() const override { 14 | return "Seeed Wio E5"; 15 | } 16 | }; 17 | 18 | extern WIOE5Board board; 19 | extern WRAPPER_CLASS radio_driver; 20 | extern VolatileRTCClock rtc_clock; 21 | extern SensorManager sensors; 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | -------------------------------------------------------------------------------- /variants/wio-e5/variant.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // UART Definitions 4 | #ifndef SERIAL_UART_INSTANCE 5 | #define SERIAL_UART_INSTANCE 101 6 | #endif 7 | 8 | #include 9 | 10 | #undef RNG 11 | -------------------------------------------------------------------------------- /variants/xiao_c3/platformio.ini: -------------------------------------------------------------------------------- 1 | [Xiao_esp32_C3] 2 | extends = esp32_base 3 | board = seeed_xiao_esp32c3 4 | build_flags = 5 | ${esp32_base.build_flags} 6 | -I variants/xiao_c3 7 | -D LORA_TX_BOOST_PIN=D3 8 | -D P_LORA_TX_LED=D5 9 | -D PIN_VBAT_READ=D0 10 | -D P_LORA_DIO_1=D2 11 | -D P_LORA_NSS=D4 12 | -D P_LORA_RESET=RADIOLIB_NC 13 | -D P_LORA_BUSY=D1 14 | -D PIN_BOARD_SDA=D6 15 | -D PIN_BOARD_SCL=D7 16 | -D SX126X_DIO2_AS_RF_SWITCH=true 17 | -D SX126X_DIO3_TCXO_VOLTAGE=1.8 18 | -D SX126X_CURRENT_LIMIT=140 19 | build_src_filter = ${esp32_base.build_src_filter} 20 | +<../variants/xiao_c3> 21 | 22 | [env:Xiao_C3_Repeater_sx1262] 23 | extends = Xiao_esp32_C3 24 | build_src_filter = ${Xiao_esp32_C3.build_src_filter} 25 | +<../examples/simple_repeater/main.cpp> 26 | build_flags = 27 | ${Xiao_esp32_C3.build_flags} 28 | -D RADIO_CLASS=CustomSX1262 29 | -D WRAPPER_CLASS=CustomSX1262Wrapper 30 | -D SX126X_RX_BOOSTED_GAIN=1 31 | -D LORA_TX_POWER=22 32 | -D ADVERT_NAME='"Xiao Repeater"' 33 | -D ADVERT_LAT=0.0 34 | -D ADVERT_LON=0.0 35 | -D ADMIN_PASSWORD='"password"' 36 | -D MAX_NEIGHBOURS=8 37 | ; -D MESH_PACKET_LOGGING=1 38 | ; -D MESH_DEBUG=1 39 | lib_deps = 40 | ${Xiao_esp32_C3.lib_deps} 41 | ${esp32_ota.lib_deps} 42 | 43 | [env:Xiao_C3_Repeater_sx1268] 44 | extends = Xiao_esp32_C3 45 | build_src_filter = ${Xiao_esp32_C3.build_src_filter} 46 | +<../examples/simple_repeater/main.cpp> 47 | build_flags = 48 | ${Xiao_esp32_C3.build_flags} 49 | -D RADIO_CLASS=CustomSX1268 50 | -D WRAPPER_CLASS=CustomSX1268Wrapper 51 | -D LORA_TX_POWER=22 52 | -D ADVERT_NAME='"Xiao Repeater"' 53 | -D ADVERT_LAT=0.0 54 | -D ADVERT_LON=0.0 55 | -D ADMIN_PASSWORD='"password"' 56 | -D MAX_NEIGHBOURS=8 57 | ; -D MESH_PACKET_LOGGING=1 58 | ; -D MESH_DEBUG=1 59 | lib_deps = 60 | ${Xiao_esp32_C3.lib_deps} 61 | ${esp32_ota.lib_deps} 62 | -------------------------------------------------------------------------------- /variants/xiao_c3/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | XiaoC3Board board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifndef LORA_CR 20 | #define LORA_CR 5 21 | #endif 22 | 23 | bool radio_init() { 24 | fallback_clock.begin(); 25 | rtc_clock.begin(Wire); 26 | 27 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 28 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 29 | #else 30 | float tcxo = 1.6f; 31 | #endif 32 | 33 | #if defined(P_LORA_SCLK) 34 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 35 | #endif 36 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 37 | if (status != RADIOLIB_ERR_NONE) { 38 | Serial.print("ERROR: radio init failed: "); 39 | Serial.println(status); 40 | return false; // fail 41 | } 42 | 43 | radio.setCRC(1); 44 | 45 | #ifdef SX126X_CURRENT_LIMIT 46 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 47 | #endif 48 | #ifdef SX126X_DIO2_AS_RF_SWITCH 49 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 50 | #endif 51 | #ifdef SX126X_RX_BOOSTED_GAIN 52 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 53 | #endif 54 | 55 | return true; // success 56 | } 57 | 58 | uint32_t radio_get_rng_seed() { 59 | return radio.random(0x7FFFFFFF); 60 | } 61 | 62 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 63 | radio.setFrequency(freq); 64 | radio.setSpreadingFactor(sf); 65 | radio.setBandwidth(bw); 66 | radio.setCodingRate(cr); 67 | } 68 | 69 | void radio_set_tx_power(uint8_t dbm) { 70 | radio.setOutputPower(dbm); 71 | } 72 | 73 | mesh::LocalIdentity radio_new_identity() { 74 | RadioNoiseListener rng(radio); 75 | return mesh::LocalIdentity(&rng); // create new random identity 76 | } 77 | -------------------------------------------------------------------------------- /variants/xiao_c3/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | extern XiaoC3Board board; 13 | extern WRAPPER_CLASS radio_driver; 14 | extern AutoDiscoverRTCClock rtc_clock; 15 | extern SensorManager sensors; 16 | 17 | bool radio_init(); 18 | uint32_t radio_get_rng_seed(); 19 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 20 | void radio_set_tx_power(uint8_t dbm); 21 | mesh::LocalIdentity radio_new_identity(); 22 | -------------------------------------------------------------------------------- /variants/xiao_nrf52/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | #include 4 | 5 | XiaoNrf52Board board; 6 | 7 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); 8 | 9 | WRAPPER_CLASS radio_driver(radio, board); 10 | 11 | VolatileRTCClock rtc_clock; 12 | EnvironmentSensorManager sensors; 13 | 14 | #ifndef LORA_CR 15 | #define LORA_CR 5 16 | #endif 17 | 18 | bool radio_init() { 19 | // rtc_clock.begin(Wire); 20 | 21 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 22 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 23 | #else 24 | float tcxo = 1.6f; 25 | #endif 26 | 27 | SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); 28 | SPI.begin(); 29 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 30 | if (status != RADIOLIB_ERR_NONE) { 31 | Serial.print("ERROR: radio init failed: "); 32 | Serial.println(status); 33 | return false; // fail 34 | } 35 | 36 | radio.setCRC(1); 37 | 38 | #ifdef SX126X_CURRENT_LIMIT 39 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 40 | #endif 41 | #ifdef SX126X_DIO2_AS_RF_SWITCH 42 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 43 | #endif 44 | #ifdef SX126X_RX_BOOSTED_GAIN 45 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 46 | #endif 47 | 48 | return true; // success 49 | } 50 | 51 | uint32_t radio_get_rng_seed() { 52 | return radio.random(0x7FFFFFFF); 53 | } 54 | 55 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 56 | radio.setFrequency(freq); 57 | radio.setSpreadingFactor(sf); 58 | radio.setBandwidth(bw); 59 | radio.setCodingRate(cr); 60 | } 61 | 62 | void radio_set_tx_power(uint8_t dbm) { 63 | radio.setOutputPower(dbm); 64 | } 65 | 66 | mesh::LocalIdentity radio_new_identity() { 67 | RadioNoiseListener rng(radio); 68 | return mesh::LocalIdentity(&rng); // create new random identity 69 | } 70 | -------------------------------------------------------------------------------- /variants/xiao_nrf52/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern XiaoNrf52Board board; 12 | extern WRAPPER_CLASS radio_driver; 13 | extern VolatileRTCClock rtc_clock; 14 | extern EnvironmentSensorManager sensors; 15 | 16 | bool radio_init(); 17 | uint32_t radio_get_rng_seed(); 18 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 19 | void radio_set_tx_power(uint8_t dbm); 20 | mesh::LocalIdentity radio_new_identity(); 21 | -------------------------------------------------------------------------------- /variants/xiao_s3_wio/target.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "target.h" 3 | 4 | ESP32Board board; 5 | 6 | #if defined(P_LORA_SCLK) 7 | static SPIClass spi; 8 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); 9 | #else 10 | RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); 11 | #endif 12 | 13 | WRAPPER_CLASS radio_driver(radio, board); 14 | 15 | ESP32RTCClock fallback_clock; 16 | AutoDiscoverRTCClock rtc_clock(fallback_clock); 17 | SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | DISPLAY_CLASS display; 21 | #endif 22 | 23 | #ifndef LORA_CR 24 | #define LORA_CR 5 25 | #endif 26 | 27 | bool radio_init() { 28 | fallback_clock.begin(); 29 | rtc_clock.begin(Wire); 30 | pinMode(21, INPUT); 31 | pinMode(48, OUTPUT); 32 | 33 | #ifdef SX126X_DIO3_TCXO_VOLTAGE 34 | float tcxo = SX126X_DIO3_TCXO_VOLTAGE; 35 | #else 36 | float tcxo = 1.6f; 37 | #endif 38 | 39 | #if defined(P_LORA_SCLK) 40 | spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); 41 | #endif 42 | int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); 43 | if (status != RADIOLIB_ERR_NONE) { 44 | Serial.print("ERROR: radio init failed: "); 45 | Serial.println(status); 46 | return false; // fail 47 | } 48 | 49 | radio.setCRC(1); 50 | 51 | #ifdef SX126X_CURRENT_LIMIT 52 | radio.setCurrentLimit(SX126X_CURRENT_LIMIT); 53 | #endif 54 | #ifdef SX126X_DIO2_AS_RF_SWITCH 55 | radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); 56 | #endif 57 | #ifdef SX126X_RX_BOOSTED_GAIN 58 | radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); 59 | #endif 60 | 61 | return true; // success 62 | } 63 | 64 | uint32_t radio_get_rng_seed() { 65 | return radio.random(0x7FFFFFFF); 66 | } 67 | 68 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { 69 | radio.setFrequency(freq); 70 | radio.setSpreadingFactor(sf); 71 | radio.setBandwidth(bw); 72 | radio.setCodingRate(cr); 73 | } 74 | 75 | void radio_set_tx_power(uint8_t dbm) { 76 | radio.setOutputPower(dbm); 77 | } 78 | 79 | mesh::LocalIdentity radio_new_identity() { 80 | RadioNoiseListener rng(radio); 81 | return mesh::LocalIdentity(&rng); // create new random identity 82 | } 83 | -------------------------------------------------------------------------------- /variants/xiao_s3_wio/target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RADIOLIB_STATIC_ONLY 1 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef DISPLAY_CLASS 11 | #include 12 | #endif 13 | 14 | extern ESP32Board board; 15 | extern WRAPPER_CLASS radio_driver; 16 | extern AutoDiscoverRTCClock rtc_clock; 17 | extern SensorManager sensors; 18 | 19 | #ifdef DISPLAY_CLASS 20 | extern DISPLAY_CLASS display; 21 | #endif 22 | 23 | bool radio_init(); 24 | uint32_t radio_get_rng_seed(); 25 | void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); 26 | void radio_set_tx_power(uint8_t dbm); 27 | mesh::LocalIdentity radio_new_identity(); 28 | --------------------------------------------------------------------------------