├── .github ├── FUNDING.yml └── workflows │ ├── build.yml │ └── commit.yml ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── common_settings.ini ├── data └── tracker_conf.json ├── data_embed ├── bootstrap.css ├── bootstrap.js ├── favicon.png ├── index.html ├── script.js └── style.css ├── extra └── turn_slope_calculations.xlsx ├── images ├── OledScreen2.jpeg ├── Web001-Beacons.png ├── Web002-StationConfig.png ├── Web003-Display.png ├── Web004-LoRa.png ├── Web005-WxTelemetry.png ├── Web006-Bluetooth.png ├── Web007-Battery.png ├── Web008-Notifications.png ├── Web009-PttTrigger.png ├── Web010-Winlink.png ├── Web011-WiFiAP.png ├── WebFlasherTrackerGithub.png ├── github-sponsors.png └── paypalme.png ├── include ├── battery_utils.h ├── ble_utils.h ├── bluetooth_utils.h ├── button_utils.h ├── configuration.h ├── custom_characters.h ├── custom_colors.h ├── display.h ├── gps_utils.h ├── joystick_utils.h ├── keyboard_utils.h ├── kiss_utils.h ├── lora_utils.h ├── menu_utils.h ├── msg_utils.h ├── notification_utils.h ├── power_utils.h ├── sleep_utils.h ├── smartbeacon_utils.h ├── station_utils.h ├── touch_utils.h ├── utils.h ├── web_utils.h ├── wifi_utils.h ├── winlink_utils.h └── wx_utils.h ├── platformio.ini ├── src ├── LoRa_APRS_Tracker.cpp ├── battery_utils.cpp ├── ble_utils.cpp ├── bluetooth_utils.cpp ├── button_utils.cpp ├── configuration.cpp ├── display.cpp ├── gps_utils.cpp ├── joystick_utils.cpp ├── keyboard_utils.cpp ├── kiss_utils.cpp ├── lora_utils.cpp ├── menu_utils.cpp ├── msg_utils.cpp ├── notification_utils.cpp ├── power_utils.cpp ├── sleep_utils.cpp ├── smartbeacon_utils.cpp ├── station_utils.cpp ├── touch_utils.cpp ├── utils.cpp ├── web_utils.cpp ├── wifi_utils.cpp ├── winlink_utils.cpp └── wx_utils.cpp ├── tools └── compress.py └── variants ├── ESP32S3_DIY_LoRa_GPS ├── board_pinout.h └── platformio.ini ├── ESP32S3_DIY_LoRa_GPS_915 ├── board_pinout.h └── platformio.ini ├── ESP32_DIY_1W_LoRa_GPS ├── board_pinout.h └── platformio.ini ├── ESP32_DIY_1W_LoRa_GPS_915 ├── board_pinout.h └── platformio.ini ├── ESP32_DIY_1W_LoRa_GPS_LLCC68 ├── board_pinout.h └── platformio.ini ├── ESP32_DIY_LoRa_GPS ├── board_pinout.h └── platformio.ini ├── ESP32_DIY_LoRa_GPS_915 ├── board_pinout.h └── platformio.ini ├── F4GOH_1W_LoRa_Tracker ├── board_pinout.h └── platformio.ini ├── F4GOH_1W_LoRa_Tracker_LLCC68 ├── board_pinout.h └── platformio.ini ├── OE5HWN_MeshCom ├── board_pinout.h └── platformio.ini ├── QRPLabs_LightTracker_Plus_1_0 ├── board_pinout.h └── platformio.ini ├── TROY_LoRa_APRS ├── board_pinout.h └── platformio.ini ├── Wemos_ESP32_Bat_LoRa_GPS ├── board_pinout.h └── platformio.ini ├── esp32_c3_DIY_LoRa_GPS ├── board_pinout.h └── platformio.ini ├── esp32_c3_DIY_LoRa_GPS_915 ├── board_pinout.h └── platformio.ini ├── heltec-lora32-v2_GPS ├── board_pinout.h └── platformio.ini ├── heltec-lora32-v2_GPS_915 ├── board_pinout.h └── platformio.ini ├── heltec-lora32-v2_TNC ├── board_pinout.h └── platformio.ini ├── heltec_ht-ct62_GPS ├── board_pinout.h └── platformio.ini ├── heltec_wifi_lora_32_v3_2_GPS ├── board_pinout.h └── platformio.ini ├── heltec_wifi_lora_32_v3_2_TNC ├── board_pinout.h └── platformio.ini ├── heltec_wifi_lora_32_v3_GPS ├── board_pinout.h └── platformio.ini ├── heltec_wifi_lora_32_v3_TNC ├── board_pinout.h └── platformio.ini ├── heltec_wireless_stick_lite_v3_GPS_display ├── board_pinout.h └── platformio.ini ├── heltec_wireless_tracker ├── board_pinout.h └── platformio.ini ├── ttgo-t-beam-v0_7 ├── board_pinout.h └── platformio.ini ├── ttgo-t-beam-v1 ├── board_pinout.h └── platformio.ini ├── ttgo-t-beam-v1_2 ├── board_pinout.h └── platformio.ini ├── ttgo-t-beam-v1_2_915 ├── board_pinout.h └── platformio.ini ├── ttgo-t-beam-v1_2_SX1262 ├── board_pinout.h └── platformio.ini ├── ttgo-t-beam-v1_915 ├── board_pinout.h └── platformio.ini ├── ttgo-t-beam-v1_SX1268 ├── board_pinout.h └── platformio.ini ├── ttgo-t-lora32-v2_1_GPS ├── board_pinout.h └── platformio.ini ├── ttgo-t-lora32-v2_1_GPS_915 ├── board_pinout.h └── platformio.ini ├── ttgo-t-lora32-v2_1_TNC ├── board_pinout.h └── platformio.ini ├── ttgo-t-lora32-v2_1_TNC_915 ├── board_pinout.h └── platformio.ini ├── ttgo_t_beam_s3_SUPREME_v3 ├── board_pinout.h └── platformio.ini ├── ttgo_t_deck_GPS ├── board_pinout.h └── platformio.ini └── ttgo_t_deck_plus ├── board_pinout.h └── platformio.ini /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ['richonguzman'] 4 | custom: ['paypal.me/richonguzman'] 5 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Release 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | target: 14 | - name: ttgo-t-beam-v1 15 | chip: esp32 16 | - name: ttgo-t-beam-v1_915 17 | chip: esp32 18 | - name: ttgo-t-beam-v1_SX1268 19 | chip: esp32 20 | - name: ttgo-t-beam-v1_2 21 | chip: esp32 22 | - name: ttgo-t-beam-v1_2_915 23 | chip: esp32 24 | - name: ttgo-t-beam-v1_2_SX1262 25 | chip: esp32 26 | - name: ttgo_t_beam_s3_SUPREME_v3 27 | chip: esp32s3 28 | - name: ttgo_t_deck_GPS 29 | chip: esp32s3 30 | - name: ttgo_t_deck_plus 31 | chip: esp32s3 32 | - name: ttgo-t-beam-v0_7 33 | chip: esp32 34 | - name: heltec_wireless_tracker 35 | chip: esp32s3 36 | - name: heltec_wifi_lora_32_v3_GPS 37 | chip: esp32s3 38 | - name: heltec_wifi_lora_32_v3_TNC 39 | chip: esp32s3 40 | - name: heltec_wifi_lora_32_v3_2_GPS 41 | chip: esp32s3 42 | - name: heltec_wifi_lora_32_v3_2_TNC 43 | chip: esp32s3 44 | - name: heltec_wireless_stick_lite_v3_GPS_display 45 | chip: esp32s3 46 | - name: heltec-lora32-v2_GPS 47 | chip: esp32 48 | - name: heltec-lora32-v2_GPS_915 49 | chip: esp32 50 | - name: ttgo-t-lora32-v2_1_GPS 51 | chip: esp32 52 | - name: ttgo-t-lora32-v2_1_GPS_915 53 | chip: esp32 54 | - name: ttgo-t-lora32-v2_1_TNC 55 | chip: esp32 56 | - name: ttgo-t-lora32-v2_1_TNC_915 57 | chip: esp32 58 | - name: ESP32_DIY_LoRa_GPS 59 | chip: esp32 60 | - name: ESP32_DIY_LoRa_GPS_915 61 | chip: esp32 62 | - name: ESP32S3_DIY_LoRa_GPS 63 | chip: esp32s3 64 | - name: ESP32S3_DIY_LoRa_GPS_915 65 | chip: esp32s3 66 | - name: ESP32_DIY_1W_LoRa_GPS 67 | chip: esp32 68 | - name: ESP32_DIY_1W_LoRa_GPS_915 69 | chip: esp32 70 | - name: ESP32_DIY_1W_LoRa_GPS_LLCC68 71 | chip: esp32 72 | - name: OE5HWN_MeshCom 73 | chip: esp32 74 | - name: Wemos_ESP32_Bat_LoRa_GPS 75 | chip: esp32 76 | - name: esp32_c3_DIY_LoRa_GPS 77 | chip: esp32c3 78 | - name: esp32_c3_DIY_LoRa_GPS_915 79 | chip: esp32c3 80 | - name: heltec_ht-ct62_GPS 81 | chip: esp32c3 82 | - name: QRPLabs_LightTracker_Plus_1_0 83 | chip: esp32s3 84 | - name: TROY_LoRa_APRS 85 | chip: esp32 86 | - name: F4GOH_1W_LoRa_Tracker 87 | chip: esp32 88 | - name: F4GOH_1W_LoRa_Tracker_LLCC68 89 | chip: esp32 90 | steps: 91 | - uses: actions/checkout@v3 92 | 93 | - uses: actions/setup-python@v4 94 | with: 95 | python-version: "3.9" 96 | 97 | - name: Install esptool 98 | run: pip install esptool 99 | 100 | - name: Install PlatformIO Core 101 | run: pip install --upgrade platformio 102 | 103 | - name: Build target 104 | run: | 105 | pio run -e ${{ matrix.target.name }} 106 | 107 | - name: Build FS 108 | run: | 109 | pio run --target buildfs -e ${{ matrix.target.name }} 110 | 111 | - name: Move Files 112 | run: | 113 | mkdir -p installer/firmware 114 | cp .pio/build/${{ matrix.target.name }}/firmware.bin installer/ota_update.bin 115 | cp .pio/build/${{ matrix.target.name }}/firmware.bin installer/firmware/ 116 | cp .pio/build/${{ matrix.target.name }}/bootloader.bin installer/firmware/ 117 | cp .pio/build/${{ matrix.target.name }}/partitions.bin installer/firmware/ 118 | cp .pio/build/${{ matrix.target.name }}/spiffs.bin installer/firmware/ 119 | cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin installer/firmware/ 120 | 121 | - name: Merge for web flashing 122 | run: | 123 | if [ "${{ matrix.target.chip }}" == "esp32" ]; then 124 | esptool.py --chip esp32 merge_bin \ 125 | -o installer/web_factory.bin \ 126 | --flash_mode dio \ 127 | --flash_freq 40m \ 128 | --flash_size 4MB \ 129 | 0x1000 installer/firmware/bootloader.bin \ 130 | 0x8000 installer/firmware/partitions.bin \ 131 | 0xe000 installer/firmware/boot_app0.bin \ 132 | 0x10000 installer/firmware/firmware.bin \ 133 | 0x310000 installer/firmware/spiffs.bin 134 | elif [ "${{ matrix.target.chip }}" == "esp32s2" ]; then 135 | esptool.py --chip esp32s2 merge_bin \ 136 | -o installer/web_factory.bin \ 137 | --flash_mode dio \ 138 | --flash_freq 40m \ 139 | --flash_size 4MB \ 140 | 0x1000 installer/firmware/bootloader.bin \ 141 | 0x8000 installer/firmware/partitions.bin \ 142 | 0xe000 installer/firmware/boot_app0.bin \ 143 | 0x10000 installer/firmware/firmware.bin \ 144 | 0x310000 installer/firmware/spiffs.bin 145 | elif [ "${{ matrix.target.chip }}" == "esp32s3" ]; then 146 | esptool.py --chip esp32s3 merge_bin \ 147 | -o installer/web_factory.bin \ 148 | --flash_mode dio \ 149 | --flash_freq 40m \ 150 | --flash_size 8MB \ 151 | 0x0000 installer/firmware/bootloader.bin \ 152 | 0x8000 installer/firmware/partitions.bin \ 153 | 0xe000 installer/firmware/boot_app0.bin \ 154 | 0x10000 installer/firmware/firmware.bin \ 155 | 0x310000 installer/firmware/spiffs.bin 156 | elif [ "${{ matrix.target.chip }}" == "esp32c3" ]; then 157 | esptool.py --chip esp32c3 merge_bin \ 158 | -o installer/web_factory.bin \ 159 | --flash_mode dio \ 160 | --flash_freq 40m \ 161 | --flash_size 4MB \ 162 | 0x1000 installer/firmware/bootloader.bin \ 163 | 0x8000 installer/firmware/partitions.bin \ 164 | 0xe000 installer/firmware/boot_app0.bin \ 165 | 0x10000 installer/firmware/firmware.bin \ 166 | 0x310000 installer/firmware/spiffs.bin 167 | fi 168 | 169 | - name: Install Zip 170 | run: sudo apt-get install zip 171 | 172 | - name: Archive Files 173 | run: zip -r installer.zip installer/ 174 | 175 | - name: Upload Release Asset 176 | uses: actions/upload-release-asset@v1 177 | env: 178 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 179 | with: 180 | upload_url: ${{ github.event.release.upload_url }} 181 | asset_path: ./installer.zip 182 | asset_name: ${{ matrix.target.name }}.zip 183 | asset_content_type: application/zip 184 | -------------------------------------------------------------------------------- /.github/workflows/commit.yml: -------------------------------------------------------------------------------- 1 | name: Commit Test Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | target: 15 | - name: ttgo-t-beam-v1_2 16 | chip: esp32 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: actions/setup-python@v4 21 | with: 22 | python-version: "3.9" 23 | 24 | - name: Install PlatformIO Core 25 | run: pip install --upgrade platformio 26 | 27 | - name: Build target 28 | run: pio run -e ${{ matrix.target.name }} 29 | 30 | - name: Build FS 31 | run: pio run --target buildfs -e ${{ matrix.target.name }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | .DS_Store 7 | /data_embed/*.gz 8 | installer/firmware 9 | installer/*.bin 10 | **/__pycache__/ -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 4, 3 | "editor.formatOnSave": false 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ricardo Guzman (Richonguzman) 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CA2RXU LoRa APRS Tracker/Station 2 | 3 | This firmware is for using ESP32 based boards with LoRa Modules and GPS to live in the APRS world. 4 | 5 | ![Screenshot](https://github.com/richonguzman/LoRa_APRS_Tracker/blob/main/images/OledScreen2.jpeg) 6 | 7 | __(NOTE: To use Tx/Rx capabilities of this tracker you should have also an Tx/Rx LoRa iGate near you)__ 8 |
9 | 10 | ____________________________________________________ 11 | 12 | ## You can support this project to continue to grow: 13 | 14 | [](https://github.com/sponsors/richonguzman) [](http://paypal.me/richonguzman) 15 | 16 |
17 | 18 | # WEB FLASHER/INSTALLER is here 19 | 20 | ____________________________________________________ 21 | 22 | - Tracker with complete MENU !!! (see Wiki to know how to access it) 23 | - Read, Write and Delete Messages (with I2C Keyboard or Phone). 24 | - Asking Weather Report. 25 | - Listening to other Trackers arround. 26 | - Changing Display Eco Mode (turn off after 4 seconds) and Screen Brightness. 27 | - Processor from 240Mhz to 80MHz to save almost 20% power consumption. 28 | - All GPS beacons/packets are encoded for less time on RF/LoRa Tx. 29 | - Oled Screen shows Altitude+Speed+Course or BME280 Wx Data or Number of New Messages Received. 30 | - Oled Screen shows Recent Heard Trackers/Station/iGates Tx. 31 | - Bluetooth capabilities to connect (Android + APRSDroid) or (iPhone + APRS.fi app) and use it as TNC. 32 | - Led Notifications for Tx and Messages Received. 33 | - Sound Notifications with YL44 Buzzer Module. 34 | - Wx data with BME280 Module showed on Screen and transmited as Wx Telemetry. 35 | - Winlink Mails through APRSLink. 36 | - Posibility to change between 3 major Frequencies used by LoRa APRS Worldwide. 37 | ____________________________________________________ 38 | 39 | # WIKI (English / Español) 40 | 41 | ### FAQ: GPS, Bluetooth, Winlink, BME280 and more --> here 42 | 43 | ### Supported Boards and buying links --> here 44 | 45 | ### 1. Installation Guide --> here 46 | 47 | ### 2. Tracker Configuration and Explanation for each setting --> here 48 | 49 | ### 3. Upload Firmware and Filesystem --> here 50 | 51 | ### 4. Tracker Menu Guide --> here 52 | 53 | ____________________________________________________ 54 | ## Timeline (Versions): 55 | 56 | - 2025.03.28 F4GOH DIY board with ESP32 + GPS + 1W LLCC68 added. APRSPacketLib Library Updated. 57 | - 2025.03.06 F4GOH DIY board with ESP32 + GPS + 1W SX1268 added. 58 | - 2025.02.09 Now Bluetooth connections lets you decide to use BLE/BT Classic and KISS/TNC. 59 | - 2025.01.11 Added HELTEC V3.2 board support. 60 | - 2025.01.07 TROY_LoRa_APRS board added. 61 | - 2025.01.02 Buttons added for DIY Boards and Boards without buttons. 62 | - 2024.11.13 Added Heltec Wireless Stick Lite V3 + GPS + Oled Display support for another DIY ESP32 Tracker. 63 | - 2024.11.13 T-Deck Joystick and Button Pressing Fix for smother operation. 64 | - 2024.10.24 Added QRP Labs LightTracker Plus1.0 support. 65 | - 2024.10.11 Added Lilygo TTGO T-Deck Plus support. 66 | - 2024.10.10 Configuration WiFiAP stops after 1 minute of no-client connected. 67 | - 2024.10.09 WEB INSTALLER/FLASHER. 68 | - 2024.10.07 Battery Monitor process added (Voltage Sleep to protect Battery). 69 | - 2024.09.17 Battery Voltage now as Encoded Telemetry in GPS Beacon. 70 | - 2024.08.26 New reformating of code ahead of WebInstaller: SmartBeacon change. 71 | - 2024.08.16 BLE support for Android devices (not APRSDroid yet). 72 | - 2024.08.12 Added support for EByte E220 400M30S 1Watt LoRa module for DIY ESP32 Tracker (LLCC68 supports spreading factor only in range of 5 - 11!) 73 | - 2024.08.02 New gpsEcoMode added for Testing. 74 | - 2024.08.02 ESP32S3 DIY LoRa GPS added. 75 | - 2024.07.30 HELTEC V3 TNC added. 76 | - 2024.07.01 All boards with 433MHZ and 915MHz versions now. 77 | - 2024.06.21 3rd Party Packets decode added following the corrections on iGate Firmware. 78 | - 2024.06.21 If Tracker Speed > 200km/hr and/or Altitude > 9.000 mts , path ("WIDE1-1") will be omited as its probably a plane. 79 | - 2024.06.21 Wx Telemetry Tx on Tracker only if standing still > 15min. (On screen Wx Data will be available but won't be sent if moving). 80 | - 2024.06.07 Dynamic Height Correction of the BME280 Pressure readings. 81 | - 2024.05.21 WEMOS ESP32 Battery Holder + LoRa SX1278 + GPS Module support added. 82 | - 2024.05.16 all boards now work with Radiolib (LoRa) library from @jgromes. 83 | - 2024.05.13 BME modules will be autodetected (I2C Address and if it is BME280/BMP280/BME680). 84 | - 2024.05.10 PacketBuffer for Rx (25 Seg) and Tx outputPacketBuffer for sending with ACK Request. 85 | - 2024.05.07 HELTEC V3 and Wireless Tracker Battery Measurements at 30seg to avoid accelerated discharge. 86 | - 2024.05.06 New Output Buffer for Messages with retry posibilities. 87 | - 2024.04.25 Added Lilygo TTGO T-Deck (add Neo6Mv2 GPS) support. 88 | - 2024.04.12 Added HELTEC Wireless Tracker support. 89 | - 2024.03.22 3 times pressing middle button for T-Beams turns the Tracker off. 90 | - 2024.03.08 ESP32_C3 DIY LoRa + GPS board added. Thanks Julian OE1JLN. 91 | - 2024.02.29 Now you can change between (EU,PL,UK) LoRa APRS frequencies used worldwide. 92 | - 2024.02.24 New Partitions: more memory for new code/firmware (still > 500 Rx messages available) 93 | - 2024.02.21 Winlink Mails through APRSLink ( https://www.winlink.org/APRSLink/ ) 94 | - 2024.01.26 Added Helmut OE5HWN MeshCom PCB support. 95 | - 2024.01.18 BME modules have now a single reading per minute. 96 | - 2024.01.05 Added HELTEC V3 with NEO8M GPS. Thanks Asbjørn LA1HSA. 97 | - 2024.01.04 Added TTGO Lilygo T-Beam S3 Supreme V3 support. Thanks Johannes OE2JPO. 98 | - 2023.12.31 PowerManagment Library AXP192/AXP2101 updated. 99 | - 2023.12.27 Added Led-Flashlight like Baofeng UV5R Led. 100 | - 2023.12.27 Added LoRa APRS Packet Decoder to Stations Menu. 101 | - 2023.12.26 Added BME680 (to the already BME/BMP280) support for Wx Telemetry Tx. 102 | - 2023.12.22 Added APRSThrusday on Messages Menu to parcitipate from this exercise ( https://aprsph.net/aprsthursday/ ) 103 | - 2023.12.19 Added support for T-Beam V1.2 with Neo8M GPS and SX1262 LoRa Modules. 104 | - 2023.12.18 Added Mic-E encoding and decoding. 105 | - 2023.12.12 Added BMP280 (to the already BME280) support for Wx Telemetry Tx. 106 | - 2023.12.11 Added support for EByte 400M30S 1Watt LoRa module for DIY ESP32 Tracker. 107 | - 2023.12.07 Added TTGO Lilygo LoRa32 v2.1 board as Bluetooth TNC(Android/Apple) and as a Tracker (with external GPS module). 108 | - 2023.12.07 Added ESP32 as DIY Tracker (with external GPS Module) with LoRa SX1278 module. 109 | - 2023.12.06 T-Beam V1.2 as default board. 110 | - 2023.12.05 Updated packets recognition (+Objects + Mic-E). 111 | - 2023.11.28 Adding BLE connection to use it as TNC with APRS.fi app for iOS. 112 | - 2023.11.07 Digipeater Mode added in Emergency Menu. 113 | - 2023.10.23 COMPLETE New Menu for Keyboard add-on. 114 | - 2023.10.22 Added Keyboard Support over I2C ( CARDKB from https://m5stack.com ) 115 | - 2023.10.07 Screen Brightness control added. 116 | - 2023.10.01 Added Wx Telemetry Tx with BME280 Module attached to Tracker. 117 | - 2023.09.28 Added Support for V.1 board with SX1268 LoRa Module. 118 | - 2023.09.25 Wiki added. 119 | - 2023.09.16 Adding Led notification for Beacon Tx and for Message Received. 120 | - 2023.09.14 Adding buzzer sounds for BootUp, BeaconTx, MessageRx and more. 121 | - 2023.09.11 Saving last used Callsign into internal Memory to remember it at next boot. 122 | - 2023.09.05 Adding "simplified Tracker Mode": only GPS beacons Tx. 123 | - 2023.08.27 Adding support to connect BME280 and see Temperature, Humidity, Pressure. 124 | - 2023.08.12 Adding also support for old V0_7 board. Thanks Béla Török. 125 | - 2023.08.09 Adding Bluetooth capabilities with Kiss and TNC2, TTGO Lora 32. Thanks Thomas DL9SAU. 126 | - 2023.08.08 Added Maidenhead info on Screen. Thanks Mathias "mpbraendli". 127 | - 2023.08.06 Added Bluetooth Support for TNC in Android/APRSDroid. Thanks Valentin F4HVV. 128 | - 2023.08.05 New Support for SH1106 Oled Screen (0,96" and 1.3") 129 | - 2023.07.24 New Validation for Callsings, Overlay change and New Icons (Bike, Motorcycle). 130 | - 2023.07.18 Add Support for triggering PTT to external amplifier. 131 | - 2023.07.16 New Icons for Oled Screen (Runner, Car, Jeep) 132 | - 2023.07.01 Added Support for new T-Beam AXP2101 v1.2 Board. 133 | - 2023.06.26 Weather Report now stays until button pressed, to avoid missing it. 134 | - 2023.06.25 Sends comment after X count of beacons. 135 | - 2023.06.24 displayEcoMode=true doesn't turn the screen off at boot. 136 | - 2023.06.23 Return to from any Menu number to Main Menu (Tracker) after 30 segs. 137 | - 2023.06.20 Major Code Repacking. 138 | - 2023.06.01 Adding Turn Slope calculations for Smart Beacon and Display Eco Mode. 139 | - 2023.05.29 New Config file for adding more new ideas to the Tracker. 140 | - 2023.05.27 Adding Altitude + Speed or Course + Speed in the encoded GPS info. 141 | - 2023.05.21 Adding Last-Heard LoRa Stations/Trackers. 142 | - 2023.05.14 Adding Menu. 143 | - 2023.05.12 Saving Messages to Internal Memory. 144 | - 2023.04.16 Sending and Receiving LoRa Packets. 145 | 146 | ____________________________________________________ 147 | ## This code was based on the work of : 148 | - https://github.com/aprs434/lora.tracker : Serge - ON4AA on base91 byte-saving/encoding 149 | - https://github.com/lora-aprs/LoRa_APRS_Tracker : Peter - OE5BPA LoRa Tracker 150 | - https://github.com/Mane76/LoRa_APRS_Tracker : Manfred - DC2MH (Mane76) mods for multiple Callsigns and processor speed 151 | - https://github.com/dl9sau/TTGO-T-Beam-LoRa-APRS : Thomas - DL9SAU for the Kiss <> TNC2 lib 152 | ____________________________________________________ 153 | 154 | # Hope You Enjoy this, 73! CA2RXU, Valparaiso, Chile -------------------------------------------------------------------------------- /common_settings.ini: -------------------------------------------------------------------------------- 1 | [common] 2 | build_flags = 3 | -Werror -Wall 4 | -DRADIOLIB_EXCLUDE_CC1101=1 5 | -DRADIOLIB_EXCLUDE_NRF24=1 6 | -DRADIOLIB_EXCLUDE_RF69=1 7 | -DRADIOLIB_EXCLUDE_SX1231=1 8 | -DRADIOLIB_EXCLUDE_SX1233=1 9 | -DRADIOLIB_EXCLUDE_SI443X=1 10 | -DRADIOLIB_EXCLUDE_RFM2X=1 11 | -DRADIOLIB_EXCLUDE_AFSK=1 12 | -DRADIOLIB_EXCLUDE_BELL=1 13 | -DRADIOLIB_EXCLUDE_HELLSCHREIBER=1 14 | -DRADIOLIB_EXCLUDE_MORSE=1 15 | -DRADIOLIB_EXCLUDE_RTTY=1 16 | -DRADIOLIB_EXCLUDE_SSTV=1 17 | -DRADIOLIB_EXCLUDE_AX25=1 18 | -DRADIOLIB_EXCLUDE_DIRECT_RECEIVE=1 19 | -DRADIOLIB_EXCLUDE_BELL=1 20 | -DRADIOLIB_EXCLUDE_PAGER=1 21 | -DRADIOLIB_EXCLUDE_FSK4=1 22 | -DRADIOLIB_EXCLUDE_APRS=1 23 | -DRADIOLIB_EXCLUDE_LORAWAN=1 24 | -I variants/${PIOENV} 25 | lib_deps = 26 | adafruit/Adafruit BusIO @ 1.16.1 27 | adafruit/Adafruit Unified Sensor @ 1.1.14 28 | adafruit/Adafruit BME280 Library @ 2.2.4 29 | adafruit/Adafruit BMP280 Library @ 2.6.8 30 | adafruit/Adafruit BME680 Library @ 2.0.4 31 | bblanchon/ArduinoJson @ 6.21.3 32 | h2zero/NimBLE-Arduino @ 1.4.1 33 | jgromes/RadioLib @ 7.1.0 34 | mathieucarbou/AsyncTCP @ 3.2.5 35 | mathieucarbou/ESPAsyncWebServer @ 3.2.3 36 | mikalhart/TinyGPSPlus @ 1.0.3 37 | paulstoffregen/Time @ 1.6.1 38 | peterus/esp-logger @ 1.0.0 39 | richonguzman/APRSPacketLib @ 0.9.0 40 | shaggydog/OneButton @ 1.5.0 41 | display_libs = 42 | adafruit/Adafruit GFX Library @ 1.11.9 43 | adafruit/Adafruit SSD1306 @ 2.5.10 44 | usb_flags= 45 | -DARDUINO_USB_MODE=1 46 | -DARDUINO_USB_CDC_ON_BOOT=1 -------------------------------------------------------------------------------- /data/tracker_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "beacons": [ 3 | { 4 | "callsign": "NOCALL-7", 5 | "gpsEcoMode": false, 6 | "symbol": "[", 7 | "overlay": "/", 8 | "micE": "", 9 | "comment": "", 10 | "smartBeaconActive": true, 11 | "smartBeaconSetting": 0 12 | }, 13 | { 14 | "callsign": "NOCALL-7", 15 | "gpsEcoMode": false, 16 | "symbol": ">", 17 | "overlay": "/", 18 | "micE": "", 19 | "comment": "", 20 | "smartBeaconActive": true, 21 | "smartBeaconSetting": 2 22 | }, 23 | { 24 | "callsign": "NOCALL-7", 25 | "gpsEcoMode": false, 26 | "symbol": "b", 27 | "overlay": "/", 28 | "micE": "", 29 | "comment": "", 30 | "smartBeaconActive": true, 31 | "smartBeaconSetting": 1 32 | } 33 | ], 34 | "display": { 35 | "showSymbol": true, 36 | "ecoMode": false, 37 | "timeout": 4, 38 | "turn180" : false 39 | }, 40 | "battery": { 41 | "sendVoltage": false, 42 | "voltageAsTelemetry": false, 43 | "sendVoltageAlways": false, 44 | "monitorVoltage": false, 45 | "sleepVoltage": 2.9 46 | }, 47 | "other": { 48 | "simplifiedTrackerMode": false, 49 | "sendCommentAfterXBeacons": 10, 50 | "path": "WIDE1-1", 51 | "nonSmartBeaconRate": 15, 52 | "rememberStationTime": 30, 53 | "standingUpdateTime": 15, 54 | "sendAltitude": true, 55 | "disableGPS": false, 56 | "acceptOwnFrameFromTNC": false, 57 | "email": "" 58 | }, 59 | "winlink": { 60 | "password": "ABCDEF" 61 | }, 62 | "wxsensor": { 63 | "active": false, 64 | "temperatureCorrection": 0.0, 65 | "sendTelemetry": false 66 | }, 67 | "notification": { 68 | "ledTx": false, 69 | "ledTxPin": 13, 70 | "ledMessage": false, 71 | "ledMessagePin": 2, 72 | "ledFlashlight": false, 73 | "ledFlashlightPin": 14, 74 | "buzzerActive": false, 75 | "buzzerPinTone": 33, 76 | "buzzerPinVcc": 25, 77 | "bootUpBeep": false, 78 | "txBeep": false, 79 | "messageRxBeep": false, 80 | "stationBeep": false, 81 | "lowBatteryBeep": false, 82 | "shutDownBeep": false 83 | }, 84 | "lora": [ 85 | { 86 | "frequency": 433775000, 87 | "spreadingFactor": 12, 88 | "signalBandwidth": 125000, 89 | "codingRate4": 5, 90 | "power": 20 91 | }, 92 | { 93 | "frequency": 434855000, 94 | "spreadingFactor": 9, 95 | "signalBandwidth": 125000, 96 | "codingRate4": 7, 97 | "power": 20 98 | }, 99 | { 100 | "frequency": 439912500, 101 | "spreadingFactor": 12, 102 | "signalBandwidth": 125000, 103 | "codingRate4": 5, 104 | "power": 20 105 | } 106 | ], 107 | "bluetooth": { 108 | "active": false, 109 | "deviceName": "LoRaTracker", 110 | "useBLE": false, 111 | "useKISS": false 112 | }, 113 | "pttTrigger": { 114 | "active": false, 115 | "io_pin": 4, 116 | "preDelay": 0, 117 | "postDelay": 0, 118 | "reverse": false 119 | }, 120 | "wifiAP": { 121 | "active": false, 122 | "password": "1234567890" 123 | } 124 | 125 | } -------------------------------------------------------------------------------- /data_embed/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/data_embed/favicon.png -------------------------------------------------------------------------------- /data_embed/style.css: -------------------------------------------------------------------------------- 1 | .alert-fixed { 2 | position:fixed; 3 | top: 0px; 4 | left: 0px; 5 | width: 100%; 6 | z-index:9999; 7 | border-radius:0px 8 | } -------------------------------------------------------------------------------- /extra/turn_slope_calculations.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/extra/turn_slope_calculations.xlsx -------------------------------------------------------------------------------- /images/OledScreen2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/OledScreen2.jpeg -------------------------------------------------------------------------------- /images/Web001-Beacons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web001-Beacons.png -------------------------------------------------------------------------------- /images/Web002-StationConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web002-StationConfig.png -------------------------------------------------------------------------------- /images/Web003-Display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web003-Display.png -------------------------------------------------------------------------------- /images/Web004-LoRa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web004-LoRa.png -------------------------------------------------------------------------------- /images/Web005-WxTelemetry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web005-WxTelemetry.png -------------------------------------------------------------------------------- /images/Web006-Bluetooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web006-Bluetooth.png -------------------------------------------------------------------------------- /images/Web007-Battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web007-Battery.png -------------------------------------------------------------------------------- /images/Web008-Notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web008-Notifications.png -------------------------------------------------------------------------------- /images/Web009-PttTrigger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web009-PttTrigger.png -------------------------------------------------------------------------------- /images/Web010-Winlink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web010-Winlink.png -------------------------------------------------------------------------------- /images/Web011-WiFiAP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/Web011-WiFiAP.png -------------------------------------------------------------------------------- /images/WebFlasherTrackerGithub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/WebFlasherTrackerGithub.png -------------------------------------------------------------------------------- /images/github-sponsors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/github-sponsors.png -------------------------------------------------------------------------------- /images/paypalme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richonguzman/LoRa_APRS_Tracker/01ed8794464eb697d2807f0107f97734076e0006/images/paypalme.png -------------------------------------------------------------------------------- /include/battery_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef BATTERY_UTILS_H_ 2 | #define BATTERY_UTILS_H_ 3 | 4 | #include 5 | 6 | 7 | namespace BATTERY_Utils { 8 | 9 | String generateEncodedTelemetry(float voltage); 10 | String getPercentVoltageBattery(float voltage); 11 | void checkVoltageWithoutGPSFix(); 12 | 13 | } 14 | 15 | #endif -------------------------------------------------------------------------------- /include/ble_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef BLE_UTILS_H_ 2 | #define BLE_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace BLE_Utils { 7 | 8 | void stop(); 9 | void setup(); 10 | void sendToLoRa(); 11 | void sendToPhone(const String& packet); 12 | 13 | } 14 | 15 | #endif -------------------------------------------------------------------------------- /include/bluetooth_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef BLUETOOTH_UTILS_H 2 | #define BLUETOOTH_UTILS_H 3 | 4 | #include 5 | 6 | namespace BLUETOOTH_Utils { 7 | 8 | void setup(); 9 | void bluetoothCallback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param); 10 | void getData(const uint8_t *buffer, size_t size); 11 | void sendToLoRa(); 12 | void sendToPhone(const String& packet); 13 | 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /include/button_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef BUTTON_UTILS_H_ 2 | #define BUTTON_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace BUTTON_Utils { 7 | 8 | void longPress(); 9 | void doublePress(); 10 | 11 | void loop(); 12 | void setup(); 13 | 14 | } 15 | 16 | #endif -------------------------------------------------------------------------------- /include/configuration.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIGURATION_H_ 2 | #define CONFIGURATION_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class WiFiAP { 9 | public: 10 | bool active; 11 | String password; 12 | }; 13 | 14 | class Beacon { 15 | public: 16 | String callsign; 17 | String symbol; 18 | String overlay; 19 | String comment; 20 | bool smartBeaconActive; 21 | byte smartBeaconSetting; 22 | String micE; 23 | bool gpsEcoMode; 24 | }; 25 | 26 | class Display { 27 | public: 28 | bool showSymbol; 29 | bool ecoMode; 30 | int timeout; 31 | bool turn180; 32 | }; 33 | 34 | class Battery { 35 | public: 36 | bool sendVoltage; 37 | bool voltageAsTelemetry; 38 | bool sendVoltageAlways; 39 | bool monitorVoltage; 40 | float sleepVoltage; 41 | }; 42 | 43 | class Winlink { 44 | public: 45 | String password; 46 | }; 47 | 48 | class WXSENSOR { 49 | public: 50 | bool active; 51 | float temperatureCorrection; 52 | bool sendTelemetry; 53 | }; 54 | 55 | class Notification { 56 | public: 57 | bool ledTx; 58 | int ledTxPin; 59 | bool ledMessage; 60 | int ledMessagePin; 61 | bool ledFlashlight; 62 | int ledFlashlightPin; 63 | bool buzzerActive; 64 | int buzzerPinTone; 65 | int buzzerPinVcc; 66 | bool bootUpBeep; 67 | bool txBeep; 68 | bool messageRxBeep; 69 | bool stationBeep; 70 | bool lowBatteryBeep; 71 | bool shutDownBeep; 72 | }; 73 | 74 | class LoraType { 75 | public: 76 | long frequency; 77 | int spreadingFactor; 78 | long signalBandwidth; 79 | int codingRate4; 80 | int power; 81 | }; 82 | 83 | class PTT { 84 | public: 85 | bool active; 86 | int io_pin; 87 | int preDelay; 88 | int postDelay; 89 | bool reverse; 90 | }; 91 | 92 | class BLUETOOTH { 93 | public: 94 | bool active; 95 | String deviceName; 96 | bool useBLE; 97 | bool useKISS; 98 | }; 99 | 100 | 101 | class Configuration { 102 | public: 103 | 104 | WiFiAP wifiAP; 105 | std::vector beacons; 106 | Display display; 107 | Battery battery; 108 | Winlink winlink; 109 | WXSENSOR wxsensor; 110 | Notification notification; 111 | std::vector loraTypes; 112 | PTT ptt; 113 | BLUETOOTH bluetooth; 114 | 115 | bool simplifiedTrackerMode; 116 | int sendCommentAfterXBeacons; 117 | String path; 118 | String email; 119 | int nonSmartBeaconRate; 120 | int rememberStationTime; 121 | int standingUpdateTime; 122 | bool sendAltitude; 123 | bool disableGPS; 124 | bool acceptOwnFrameFromTNC; 125 | 126 | void init(); 127 | void writeFile(); 128 | Configuration(); 129 | bool validateConfigFile(const String& currentBeaconCallsign); 130 | bool validateMicE(const String& currentBeaconMicE); 131 | 132 | private: 133 | bool readFile(); 134 | }; 135 | 136 | #endif -------------------------------------------------------------------------------- /include/custom_characters.h: -------------------------------------------------------------------------------- 1 | #ifndef CUSTOM_CHARACTERS_H_ 2 | #define CUSTOM_CHARACTERS_H_ 3 | 4 | #include 5 | 6 | static const unsigned char bluetoothSymbol[] PROGMEM = { 7 | 0b00001100, 0b00000000, 8 | 0b00001111, 0b00000000, 9 | 0b00001100, 0b11000000, 10 | 0b11001100, 0b00110000, 11 | 0b00111100, 0b11000000, 12 | 0b00001111, 0b00000000, 13 | 0b00001111, 0b00000000, 14 | 0b00111100, 0b11000000, 15 | 0b11001100, 0b00110000, 16 | 0b00001100, 0b11000000, 17 | 0b00001111, 0b00000000, 18 | 0b00001100, 0b00000000, 19 | 0b00000000, 0b00000000, 20 | 0b00000000, 0b00000000 21 | }; 22 | 23 | static const unsigned char runnerSymbol[] PROGMEM = { 24 | 0b00000000, 0b11100000, 25 | 0b00000000, 0b11100000, 26 | 0b00000000, 0b01000110, 27 | 0b00000001, 0b11100110, 28 | 0b00000111, 0b11111100, 29 | 0b00000110, 0b11111000, 30 | 0b00001100, 0b11100000, 31 | 0b00001100, 0b11100000, 32 | 0b00000000, 0b11110000, 33 | 0b00000001, 0b11111000, 34 | 0b00000001, 0b10011000, 35 | 0b00000011, 0b10001100, 36 | 0b00001111, 0b00001100, 37 | 0b00011100, 0b00000110 38 | }; 39 | 40 | static const unsigned char carSymbol[] PROGMEM = { 41 | 0b00000000, 0b00000000, 42 | 0b01000000, 0b00000000, 43 | 0b00111111, 0b11000000, 44 | 0b00100100, 0b00100000, 45 | 0b01000100, 0b00010000, 46 | 0b01000100, 0b00010000, 47 | 0b01000100, 0b00001000, 48 | 0b11111111, 0b11111111, 49 | 0b10111111, 0b11111101, 50 | 0b11111111, 0b11111111, 51 | 0b11001111, 0b11110011, 52 | 0b01001000, 0b00010010, 53 | 0b00110000, 0b00001100, 54 | 0b00000000, 0b00000000 55 | }; 56 | 57 | static const unsigned char jeepSymbol[] PROGMEM = { 58 | 0b00000000, 0b00000000, 59 | 0b00000000, 0b00000000, 60 | 0b00000000, 0b00000000, 61 | 0b00000100, 0b01000000, 62 | 0b00001100, 0b00100000, 63 | 0b00010100, 0b00100000, 64 | 0b00100100, 0b00010000, 65 | 0b11111100, 0b00011111, 66 | 0b11111111, 0b11111101, 67 | 0b11111111, 0b11111111, 68 | 0b11001111, 0b11110011, 69 | 0b01001000, 0b00010010, 70 | 0b00110000, 0b00001100, 71 | 0b00000000, 0b00000000 72 | }; 73 | 74 | static const unsigned char bikeSymbol[] PROGMEM = { 75 | 0b00000001, 0b10000000, 76 | 0b00000011, 0b11000000, 77 | 0b00000001, 0b10000000, 78 | 0b00000011, 0b10000000, 79 | 0b00000111, 0b11000000, 80 | 0b00001110, 0b11100000, 81 | 0b00001110, 0b01111000, 82 | 0b00011111, 0b11010000, 83 | 0b00110111, 0b00101100, 84 | 0b01001011, 0b10010010, 85 | 0b10110101, 0b11101101, 86 | 0b10110111, 0b10101101, 87 | 0b01001001, 0b10010010, 88 | 0b00110000, 0b00001100 89 | }; 90 | 91 | static const unsigned char motorcycleSymbol[] PROGMEM = { 92 | 0b00000001, 0b10000000, 93 | 0b00000011, 0b11000000, 94 | 0b00000001, 0b10000000, 95 | 0b00000011, 0b10000000, 96 | 0b00000111, 0b11001000, 97 | 0b00001110, 0b11100100, 98 | 0b11101110, 0b01111110, 99 | 0b01111111, 0b11111110, 100 | 0b00110111, 0b00101100, 101 | 0b01001011, 0b10010010, 102 | 0b10110101, 0b11101101, 103 | 0b11111111, 0b10101101, 104 | 0b01001001, 0b10010010, 105 | 0b00110000, 0b00001100 106 | }; 107 | 108 | static const unsigned char shipSymbol[] PROGMEM = { 109 | 0b00100000, 0b00000000, 110 | 0b00010000, 0b00000000, 111 | 0b00001000, 0b00000000, 112 | 0b00111111, 0b10000000, 113 | 0b00001111, 0b11000000, 114 | 0b00001100, 0b00100000, 115 | 0b00001100, 0b00010000, 116 | 0b01001100, 0b00001000, 117 | 0b01111111, 0b11111111, 118 | 0b10000000, 0b00000001, 119 | 0b11111111, 0b11111110, 120 | 0b11111111, 0b11111000, 121 | 0b00000000, 0b00000000, 122 | 0b00000000, 0b00000000 123 | }; 124 | 125 | static const unsigned char truck18Symbol[] PROGMEM = { 126 | 0b00000000, 0b00100000, 127 | 0b00000000, 0b00010000, 128 | 0b11111111, 0b11010000, 129 | 0b11111111, 0b11011111, 130 | 0b11111111, 0b11011001, 131 | 0b11111111, 0b11011001, 132 | 0b11111111, 0b11011001, 133 | 0b11111111, 0b11011111, 134 | 0b11111111, 0b11011111, 135 | 0b11111111, 0b11011101, 136 | 0b10000000, 0b01111111, 137 | 0b11111111, 0b10000001, 138 | 0b01111101, 0b11111111, 139 | 0b01101100, 0b11000110 140 | }; 141 | 142 | static const unsigned char recreationalVehicleSymbol[] PROGMEM = { 143 | 0b00000111, 0b11111000, 144 | 0b01111110, 0b01001100, 145 | 0b11111110, 0b01001110, 146 | 0b11111111, 0b11111110, 147 | 0b11111111, 0b11111000, 148 | 0b10000100, 0b00100100, 149 | 0b10000100, 0b00100010, 150 | 0b11111100, 0b00100001, 151 | 0b11111011, 0b11011111, 152 | 0b10111011, 0b11011101, 153 | 0b11111000, 0b00011101, 154 | 0b11001111, 0b11110011, 155 | 0b01001000, 0b00010010, 156 | 0b00110000, 0b00001100 157 | }; 158 | 159 | static const unsigned char vanSymbol[] PROGMEM = { 160 | 0b00000000, 0b00000000, 161 | 0b00000000, 0b00000000, 162 | 0b01111111, 0b11110000, 163 | 0b11111111, 0b11111000, 164 | 0b10000100, 0b00100100, 165 | 0b10000100, 0b00100010, 166 | 0b10000100, 0b00100001, 167 | 0b11111111, 0b11111111, 168 | 0b10100000, 0b00000101, 169 | 0b11111111, 0b11111101, 170 | 0b11001111, 0b11100111, 171 | 0b01001000, 0b00100100, 172 | 0b00110000, 0b00011000, 173 | 0b00000000, 0b00000000 174 | }; 175 | 176 | static const unsigned char carsateliteSymbol[] PROGMEM = { 177 | 0b00000000, 0b00000100, 178 | 0b01000000, 0b00000100, 179 | 0b00111111, 0b11011111, 180 | 0b00100100, 0b00100100, 181 | 0b01000100, 0b00010100, 182 | 0b01000100, 0b00010000, 183 | 0b01000100, 0b00001000, 184 | 0b11111111, 0b11111111, 185 | 0b10111111, 0b11111101, 186 | 0b11111111, 0b11111111, 187 | 0b11001111, 0b11110011, 188 | 0b01001000, 0b00010010, 189 | 0b00110000, 0b00001100, 190 | 0b00000000, 0b00000000 191 | }; 192 | 193 | static const unsigned char tentSymbol[] PROGMEM = { 194 | 0b00000000, 0b00000000, 195 | 0b00000000, 0b00000000, 196 | 0b00001111, 0b11110000, 197 | 0b00001000, 0b00110000, 198 | 0b00010000, 0b01111000, 199 | 0b00010000, 0b01011000, 200 | 0b00100000, 0b10010100, 201 | 0b00100000, 0b10010100, 202 | 0b01000001, 0b00010010, 203 | 0b01000001, 0b00010010, 204 | 0b11100010, 0b00010001, 205 | 0b00011111, 0b11111111, 206 | 0b00000000, 0b00000000, 207 | 0b00000000, 0b00000000 208 | }; 209 | 210 | static const unsigned char houseSymbol[] PROGMEM = { 211 | 0b00000011, 0b11000000, 212 | 0b00000111, 0b11100000, 213 | 0b00001111, 0b11110110, 214 | 0b00011111, 0b11111110, 215 | 0b00111111, 0b11111110, 216 | 0b01111111, 0b11111110, 217 | 0b11111111, 0b11111111, 218 | 0b01000000, 0b00000010, 219 | 0b01001111, 0b10111010, 220 | 0b01001000, 0b10101010, 221 | 0b01001001, 0b10111010, 222 | 0b01001000, 0b10000010, 223 | 0b01001000, 0b10000010, 224 | 0b01111111, 0b11111110 225 | }; 226 | 227 | static const unsigned char truckSymbol[] PROGMEM = { 228 | 0b00000000, 0b00000000, 229 | 0b00000011, 0b11100000, 230 | 0b00000010, 0b00100000, 231 | 0b00000010, 0b00010000, 232 | 0b00000010, 0b00010000, 233 | 0b00000010, 0b00001000, 234 | 0b11111111, 0b11111111, 235 | 0b11111111, 0b11111101, 236 | 0b11111111, 0b11111101, 237 | 0b11111111, 0b11111111, 238 | 0b11001111, 0b11110011, 239 | 0b01001000, 0b00010010, 240 | 0b00110000, 0b00001100, 241 | 0b00000000, 0b00000000 242 | }; 243 | 244 | static const unsigned char canoeSymbol[] PROGMEM = { 245 | 0b00000000, 0b00000000, 246 | 0b00000001, 0b10000000, 247 | 0b00000011, 0b11000000, 248 | 0b00000001, 0b10000000, 249 | 0b00000011, 0b10000000, 250 | 0b00000011, 0b11110000, 251 | 0b00000011, 0b00100000, 252 | 0b11111111, 0b11111111, 253 | 0b01000000, 0b10000010, 254 | 0b00111111, 0b11111100, 255 | 0b00000010, 0b00000000, 256 | 0b00001110, 0b00000000, 257 | 0b00011100, 0b00000000, 258 | 0b00000000, 0b00000000 259 | }; 260 | 261 | static const unsigned char ambulanceSymbol[] PROGMEM = { 262 | 0b00000000, 0b00000000, 263 | 0b11111111, 0b11000000, 264 | 0b11111111, 0b11000000, 265 | 0b11110111, 0b11000000, 266 | 0b11110111, 0b11110000, 267 | 0b11000001, 0b11001000, 268 | 0b11110111, 0b11001000, 269 | 0b11110111, 0b11000100, 270 | 0b11111111, 0b11111111, 271 | 0b10000000, 0b00000011, 272 | 0b11111111, 0b11111101, 273 | 0b11001111, 0b11100111, 274 | 0b01001000, 0b00100100, 275 | 0b00110000, 0b00011000 276 | }; 277 | 278 | static const unsigned char yatchSymbol[] PROGMEM = { 279 | 0b00000000, 0b01000000, 280 | 0b00000001, 0b01010000, 281 | 0b00000001, 0b01010000, 282 | 0b00000011, 0b01011000, 283 | 0b00000111, 0b01011000, 284 | 0b00001111, 0b01011100, 285 | 0b00011111, 0b01011100, 286 | 0b00111111, 0b01011110, 287 | 0b01111111, 0b01011110, 288 | 0b00000001, 0b01000000, 289 | 0b00000010, 0b10110000, 290 | 0b00111111, 0b11111111, 291 | 0b01100000, 0b00000010, 292 | 0b01111111, 0b11111100 293 | }; 294 | 295 | static const unsigned char baloonSymbol[] PROGMEM = { 296 | 0b00001111, 0b11110000, 297 | 0b00111111, 0b11111100, 298 | 0b01000000, 0b00000010, 299 | 0b01111111, 0b11111110, 300 | 0b01111111, 0b11111110, 301 | 0b01000000, 0b00000010, 302 | 0b00111111, 0b11111100, 303 | 0b00011111, 0b11111000, 304 | 0b00001000, 0b00010000, 305 | 0b00000111, 0b11100000, 306 | 0b00000011, 0b11000000, 307 | 0b00000001, 0b10000000, 308 | 0b00000001, 0b10000000, 309 | 0b00000001, 0b10000000 310 | }; 311 | 312 | static const unsigned char aircraftSymbol[] PROGMEM = { 313 | 0b00000001, 0b10000000, 314 | 0b00000001, 0b10000000, 315 | 0b00000001, 0b10000000, 316 | 0b00000001, 0b10000000, 317 | 0b00000111, 0b11100000, 318 | 0b00111111, 0b11111100, 319 | 0b11111111, 0b11111111, 320 | 0b11111111, 0b11111111, 321 | 0b11100001, 0b10000111, 322 | 0b00000001, 0b10000000, 323 | 0b00000001, 0b10000000, 324 | 0b00000001, 0b10000000, 325 | 0b00000011, 0b11000000, 326 | 0b00000111, 0b11100000 327 | }; 328 | 329 | static const unsigned char trainSymbol[] PROGMEM = { 330 | 0b00000000, 0b00110000, 331 | 0b11111110, 0b00000000, 332 | 0b10000100, 0b01111000, 333 | 0b10000100, 0b00110000, 334 | 0b10000100, 0b00110000, 335 | 0b10000100, 0b00110000, 336 | 0b11111111, 0b11111100, 337 | 0b11111111, 0b11111110, 338 | 0b11111111, 0b11111110, 339 | 0b11111111, 0b11111100, 340 | 0b11111111, 0b11111110, 341 | 0b01000011, 0b00110011, 342 | 0b00100111, 0b00110010, 343 | 0b00011000, 0b11001100 344 | }; 345 | 346 | static const unsigned char yagiSymbol[] PROGMEM = { 347 | 0b01010000, 0b00000000, 348 | 0b11110001, 0b10000000, 349 | 0b01000111, 0b11100000, 350 | 0b01011111, 0b11111000, 351 | 0b01111111, 0b11111110, 352 | 0b11111111, 0b11111111, 353 | 0b01000000, 0b00000010, 354 | 0b01011000, 0b00011010, 355 | 0b01011000, 0b00011010, 356 | 0b01000011, 0b11000010, 357 | 0b01000010, 0b01000010, 358 | 0b01000010, 0b11000010, 359 | 0b01000010, 0b01000010, 360 | 0b01111111, 0b11111110 361 | }; 362 | 363 | static const unsigned char busSymbol[] PROGMEM = { 364 | 0b00000000, 0b00000000, 365 | 0b00000000, 0b00000000, 366 | 0b11111111, 0b11110000, 367 | 0b10001000, 0b10010000, 368 | 0b10001000, 0b10010000, 369 | 0b10001000, 0b10010000, 370 | 0b11111111, 0b11111110, 371 | 0b10000000, 0b00000011, 372 | 0b10000000, 0b00000001, 373 | 0b10011000, 0b00011001, 374 | 0b11100111, 0b11100111, 375 | 0b00100100, 0b00100100, 376 | 0b00011000, 0b00011000, 377 | 0b00000000, 0b00000000 378 | }; 379 | 380 | static const unsigned char dogSymbol[] PROGMEM = { 381 | 0b00000000, 0b01100000, 382 | 0b00000000, 0b10010000, 383 | 0b00000001, 0b00001000, 384 | 0b00000001, 0b00101010, 385 | 0b01000001, 0b00000101, 386 | 0b10100001, 0b00100010, 387 | 0b10010001, 0b11100010, 388 | 0b01001111, 0b10111100, 389 | 0b00100000, 0b00010000, 390 | 0b00100000, 0b00010000, 391 | 0b01001111, 0b11001000, 392 | 0b01010000, 0b00101000, 393 | 0b01001000, 0b00100100, 394 | 0b00110000, 0b00011000 395 | }; 396 | 397 | static const unsigned char wxSymbol[] PROGMEM = { 398 | 0b00000000, 0b00000000, 399 | 0b00000000, 0b00000000, 400 | 0b10001000, 0b10000000, 401 | 0b10001000, 0b10000000, 402 | 0b10001000, 0b10000000, 403 | 0b10001000, 0b10000000, 404 | 0b01010101, 0b00100010, 405 | 0b01010101, 0b00010100, 406 | 0b01010101, 0b00001000, 407 | 0b01010101, 0b00010100, 408 | 0b00100010, 0b00100010, 409 | 0b00000000, 0b00000000, 410 | 0b00000000, 0b00000000, 411 | 0b00000000, 0b00000000 412 | }; 413 | 414 | /*static const unsigned char noSymbol[] PROGMEM = { 415 | 0b00000000, 0b00000000, 416 | 0b00000000, 0b00000000, 417 | 0b00000000, 0b00000000, 418 | 0b00000000, 0b00000000, 419 | 0b00000000, 0b00000000, 420 | 0b00000000, 0b00000000, 421 | 0b00000000, 0b00000000, 422 | 0b00000000, 0b00000000, 423 | 0b00000000, 0b00000000, 424 | 0b00000000, 0b00000000, 425 | 0b00000000, 0b00000000, 426 | 0b00000000, 0b00000000, 427 | 0b00000000, 0b00000000, 428 | 0b00000000, 0b00000000 429 | };*/ 430 | 431 | #endif -------------------------------------------------------------------------------- /include/custom_colors.h: -------------------------------------------------------------------------------- 1 | #ifndef CUSTOM_COLORS_H_ 2 | #define CUSTOM_COLORS_H_ 3 | 4 | #include 5 | 6 | 7 | // COLORS https://rgbcolorpicker.com/565 8 | 9 | uint16_t redColor = 0xc8a2; 10 | uint16_t redColorLight = 0xd8c4; 11 | uint16_t redColorDark = 0xa082; 12 | 13 | uint16_t greyColor = 0x7BEF; 14 | uint16_t greyColorLight = 0xBDF7; 15 | uint16_t greyColorDark = 0x39E7; 16 | 17 | uint16_t greenColor = 0x1482; 18 | uint16_t greenColorLight = 0x1d63; 19 | uint16_t greenColorDark = 0x0b22; 20 | 21 | #endif -------------------------------------------------------------------------------- /include/display.h: -------------------------------------------------------------------------------- 1 | #ifndef DISPLAY_H_ 2 | #define DISPLAY_H_ 3 | 4 | #include 5 | 6 | void displaySetup(); 7 | void displayToggle(bool toggle); 8 | 9 | void displayShow(const String& header, const String& line1, const String& line2, int wait = 0); 10 | void displayShow(const String& header, const String& line1, const String& line2, const String& line3, const String& line4, const String& line5, int wait = 0); 11 | 12 | void startupScreen(uint8_t index, const String& version); 13 | 14 | #endif -------------------------------------------------------------------------------- /include/gps_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef GPS_UTILS_H_ 2 | #define GPS_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace GPS_Utils { 7 | 8 | void setup(); 9 | void calculateDistanceCourse(const String& callsign, double checkpointLatitude, double checkPointLongitude); 10 | void getData(); 11 | void setDateFromData(); 12 | void calculateDistanceTraveled(); 13 | void calculateHeadingDelta(int speed); 14 | void checkStartUpFrames(); 15 | String getCardinalDirection(float course); 16 | 17 | } 18 | 19 | #endif -------------------------------------------------------------------------------- /include/joystick_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef JOYSTICK_UTILS_H_ 2 | #define JOYSTICK_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace JOYSTICK_Utils { 7 | 8 | void loop(); 9 | void setup(); 10 | 11 | } 12 | 13 | #endif -------------------------------------------------------------------------------- /include/keyboard_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYBOARD_UTILS_H 2 | #define KEYBOARD_UTILS_H 3 | 4 | #include 5 | 6 | namespace KEYBOARD_Utils { 7 | 8 | void upArrow(); 9 | void downArrow(); 10 | void leftArrow(); 11 | void rightArrow(); 12 | 13 | void processPressedKey(char key); 14 | void read(); 15 | 16 | void setup(); 17 | 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/kiss_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef KISS_UTILS_H 2 | #define KISS_UTILS_H 3 | 4 | #include 5 | 6 | 7 | enum KissChar { 8 | FEND = 0xc0, 9 | FESC = 0xdb, 10 | TFEND = 0xdc, 11 | TFESC = 0xdd 12 | }; 13 | 14 | enum KissCmd { 15 | Data = 0x00 16 | }; 17 | 18 | enum AX25Char { 19 | ControlField = 0x03, 20 | InformationField = 0xF0 21 | }; 22 | 23 | #define HAS_BEEN_DIGIPITED_MASK 0b10000000 24 | #define IS_LAST_ADDRESS_POSITION_MASK 0b1 25 | 26 | 27 | namespace KISS_Utils { 28 | 29 | bool validateTNC2Frame(const String& tnc2FormattedFrame); 30 | bool validateKISSFrame(const String& kissFormattedFrame); 31 | 32 | String encodeKISS(const String& frame); 33 | String decodeKISS(const String& inputFrame, bool& dataFrame); 34 | 35 | //String encapsulateKISS(const String& ax25Frame, uint8_t command); 36 | //String decapsulateKISS(const String& frame); 37 | 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/lora_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef LORA_UTILS_H_ 2 | #define LORA_UTILS_H_ 3 | 4 | #include 5 | 6 | struct ReceivedLoRaPacket { 7 | String text; 8 | int rssi; 9 | float snr; 10 | int freqError; 11 | }; 12 | 13 | 14 | namespace LoRa_Utils { 15 | 16 | void setFlag(); 17 | void changeFreq(); 18 | void setup(); 19 | void sendNewPacket(const String& newPacket); 20 | void wakeRadio(); 21 | ReceivedLoRaPacket receiveFromSleep(); 22 | ReceivedLoRaPacket receivePacket(); 23 | void sleepRadio(); 24 | 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /include/menu_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef MENU_UTILS_H_ 2 | #define MENU_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace MENU_Utils { 7 | 8 | const String checkBTType(); 9 | const String checkProcessActive(const bool process); 10 | const String screenBrightnessAsString(const uint8_t bright); 11 | void showOnScreen(); 12 | 13 | } 14 | 15 | #endif -------------------------------------------------------------------------------- /include/msg_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef MSG_UTILS_H_ 2 | #define MSG_UTILS_H_ 3 | 4 | #include 5 | #include "lora_utils.h" 6 | 7 | struct Packet15SegBuffer { 8 | uint32_t receivedTime; 9 | String station; 10 | String payload; 11 | }; 12 | 13 | namespace MSG_Utils { 14 | 15 | bool warnNoAPRSMessages(); 16 | bool warnNoWLNKMails(); 17 | const String getLastHeardTracker(); 18 | int getNumAPRSMessages(); 19 | int getNumWLNKMails(); 20 | void loadNumMessages(); 21 | void loadMessagesFromMemory(uint8_t typeOfMessage); 22 | void ledNotification(); 23 | void deleteFile(uint8_t typeOfFile); 24 | void saveNewMessage(uint8_t typeMessage, const String& station, const String& newMessage); 25 | void sendMessage(const String& station, const String& textMessage); 26 | const String ackRequestNumberGenerator(); 27 | void addToOutputBuffer(uint8_t typeOfMessage, const String& station, const String& textMessage); 28 | void processOutputBuffer(); 29 | void clean15SegBuffer(); 30 | bool check15SegBuffer(const String& station, const String& textMessage); 31 | void checkReceivedMessage(ReceivedLoRaPacket packetReceived); 32 | 33 | } 34 | 35 | #endif -------------------------------------------------------------------------------- /include/notification_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef NOTIFICATION_UTILS_H_ 2 | #define NOTIFICATION_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace NOTIFICATION_Utils { 7 | 8 | void playTone(int frequency, uint8_t duration); 9 | void beaconTxBeep(); 10 | void messageBeep(); 11 | void stationHeardBeep(); 12 | void shutDownBeep(); 13 | void lowBatteryBeep(); 14 | void start(); 15 | 16 | } 17 | 18 | #endif -------------------------------------------------------------------------------- /include/power_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_UTILS_H_ 2 | #define POWER_UTILS_H_ 3 | 4 | #include 5 | #include "board_pinout.h" 6 | #if defined(HAS_AXP2101) || defined(HAS_AXP192) 7 | #include "XPowersLib.h" 8 | #else 9 | #include 10 | #endif 11 | 12 | namespace POWER_Utils { 13 | 14 | double getBatteryVoltage(); 15 | const String getBatteryInfoVoltage(); 16 | const String getBatteryInfoCurrent(); 17 | bool getBatteryInfoIsConnected(); 18 | 19 | void enableChgLed(); 20 | void disableChgLed(); 21 | 22 | bool isCharging(); 23 | void handleChargingLed(); 24 | double getBatteryChargeDischargeCurrent(); 25 | bool isBatteryConnected(); 26 | void obtainBatteryInfo(); 27 | void batteryManager(); 28 | 29 | void activateMeasurement(); 30 | 31 | void activateGPS(); 32 | void deactivateGPS(); 33 | 34 | void activateLoRa(); 35 | void deactivateLoRa(); 36 | 37 | void externalPinSetup(); 38 | 39 | bool begin(TwoWire &port); 40 | void setup(); 41 | 42 | void lowerCpuFrequency(); 43 | void shutdown(); 44 | 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/sleep_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef SLEEP_UTILS_H_ 2 | #define SLEEP_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace SLEEP_Utils { 7 | 8 | void gpsSleep(); 9 | void gpsWakeUp(); 10 | void checkIfGPSShouldSleep(); 11 | 12 | } 13 | 14 | #endif -------------------------------------------------------------------------------- /include/smartbeacon_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef SMARTBEACON_UTILS_H_ 2 | #define SMARTBEACON_UTILS_H_ 3 | 4 | #include 5 | 6 | struct SmartBeaconValues { 7 | int slowRate; 8 | int slowSpeed; 9 | int fastRate; 10 | int fastSpeed; 11 | int minTxDist; 12 | int minDeltaBeacon; 13 | int turnMinDeg; 14 | int turnSlope; 15 | }; 16 | 17 | 18 | namespace SMARTBEACON_Utils { 19 | 20 | void checkSettings(byte index); 21 | void checkInterval(int speed); 22 | void checkFixedBeaconTime(); 23 | void checkState(); 24 | 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /include/station_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef STATION_UTILS_H_ 2 | #define STATION_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace STATION_Utils { 7 | 8 | void nearTrackerInit(); 9 | const String getNearTracker(uint8_t position); 10 | 11 | void deleteListenedTrackersbyTime(); 12 | void checkListenedTrackersByTimeAndDelete(); 13 | void orderListenedTrackersByDistance(const String& callsign, float distance, float course); 14 | 15 | void checkStandingUpdateTime(); 16 | void sendBeacon(uint8_t type); 17 | void checkTelemetryTx(); 18 | void saveIndex(uint8_t type, uint8_t index); 19 | void loadIndex(uint8_t type); 20 | 21 | } 22 | 23 | #endif -------------------------------------------------------------------------------- /include/touch_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef TOUCH_UTILS_H_ 2 | #define TOUCH_UTILS_H_ 3 | 4 | #include 5 | 6 | 7 | struct TouchButton { 8 | int Xmin; 9 | int Xmax; 10 | int Ymin; 11 | int Ymax; 12 | String label; // Optional: for button text or identification 13 | int color; 14 | void (*action)(); // Pointer to a function for button press action 15 | }; 16 | 17 | 18 | namespace TOUCH_Utils { 19 | 20 | void loop(); 21 | void setup(); 22 | 23 | } 24 | 25 | #endif -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H_ 2 | #define UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace Utils { 8 | 9 | char *getMaidenheadLocator(double lat, double lon, uint8_t size); 10 | String createDateString(time_t t); 11 | String createTimeString(time_t t); 12 | void checkStatus(); 13 | void checkDisplayEcoMode(); 14 | String getSmartBeaconState(); 15 | void checkFlashlight(); 16 | void i2cScannerForPeripherals(); 17 | 18 | } 19 | 20 | #endif -------------------------------------------------------------------------------- /include/web_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef WEB_UTILS_H_ 2 | #define WEB_UTILS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | namespace WEB_Utils { 12 | 13 | void handleNotFound(AsyncWebServerRequest *request); 14 | void handleStatus(AsyncWebServerRequest *request); 15 | void handleHome(AsyncWebServerRequest *request); 16 | void handleStyle(AsyncWebServerRequest *request); 17 | void handleScript(AsyncWebServerRequest *request); 18 | void handleBootstrapStyle(AsyncWebServerRequest *request); 19 | void handleBootstrapScript(AsyncWebServerRequest *request); 20 | 21 | void setup(); 22 | 23 | } 24 | 25 | #endif -------------------------------------------------------------------------------- /include/wifi_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef WIFI_UTILS_H_ 2 | #define WIFI_UTILS_H_ 3 | 4 | #include 5 | 6 | 7 | namespace WIFI_Utils { 8 | 9 | void startAutoAP(); 10 | void checkIfWiFiAP(); 11 | 12 | } 13 | 14 | #endif -------------------------------------------------------------------------------- /include/winlink_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef WINLINK_UTILS_H_ 2 | #define WINLINK_UTILS_H_ 3 | 4 | #include 5 | 6 | namespace WINLINK_Utils { 7 | 8 | void processWinlinkChallenge(const String& winlinkInteger); 9 | void login(); 10 | 11 | } 12 | 13 | #endif -------------------------------------------------------------------------------- /include/wx_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef WX_UTILS_H_ 2 | #define WX_UTILS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | namespace WX_Utils { 12 | 13 | void setup(); 14 | const String generateTempString(const float sensorTemp, const uint8_t type); 15 | const String generateHumString(const float sensorHum, const uint8_t type); 16 | const String generatePresString(const float sensorPress, const uint8_t type); 17 | const String readDataSensor(const uint8_t type); 18 | 19 | } 20 | 21 | #endif -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | default_envs = ttgo-t-beam-v1_2 13 | 14 | extra_configs = 15 | common_settings.ini 16 | variants/*/platformio.ini 17 | 18 | [env] 19 | framework = arduino 20 | monitor_speed = 115200 21 | lib_ldf_mode = deep+ 22 | 23 | [env:esp32] 24 | extends = env 25 | platform = espressif32 @ 6.7.0 26 | board_build.partitions = huge_app.csv 27 | monitor_filters = esp32_exception_decoder 28 | board_build.embed_files = 29 | data_embed/index.html.gz 30 | data_embed/style.css.gz 31 | data_embed/script.js.gz 32 | data_embed/bootstrap.css.gz 33 | data_embed/bootstrap.js.gz 34 | data_embed/favicon.png.gz 35 | extra_scripts = 36 | pre:tools/compress.py 37 | debug_tool = esp-prog -------------------------------------------------------------------------------- /src/LoRa_APRS_Tracker.cpp: -------------------------------------------------------------------------------- 1 | /*___________________________________________________________________ 2 | 3 | ██╗ ██████╗ ██████╗ █████╗ █████╗ ██████╗ ██████╗ ███████╗ 4 | ██║ ██╔═══██╗██╔══██╗██╔══██╗ ██╔══██╗██╔══██╗██╔══██╗██╔════╝ 5 | ██║ ██║ ██║██████╔╝███████║ ███████║██████╔╝██████╔╝███████╗ 6 | ██║ ██║ ██║██╔══██╗██╔══██║ ██╔══██║██╔═══╝ ██╔══██╗╚════██║ 7 | ███████╗╚██████╔╝██║ ██║██║ ██║ ██║ ██║██║ ██║ ██║███████║ 8 | ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝ 9 | 10 | ████████╗██████╗ █████╗ ██████╗██╗ ██╗███████╗██████╗ 11 | ╚══██╔══╝██╔══██╗██╔══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗ 12 | ██║ ██████╔╝███████║██║ █████╔╝ █████╗ ██████╔╝ 13 | ██║ ██╔══██╗██╔══██║██║ ██╔═██╗ ██╔══╝ ██╔══██╗ 14 | ██║ ██║ ██║██║ ██║╚██████╗██║ ██╗███████╗██║ ██║ 15 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ 16 | 17 | Ricardo Guzman - CA2RXU 18 | https://github.com/richonguzman/LoRa_APRS_Tracker 19 | (donations : http://paypal.me/richonguzman) 20 | ____________________________________________________________________*/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "smartbeacon_utils.h" 29 | #include "bluetooth_utils.h" 30 | #include "keyboard_utils.h" 31 | #include "joystick_utils.h" 32 | #include "configuration.h" 33 | #include "battery_utils.h" 34 | #include "station_utils.h" 35 | #include "board_pinout.h" 36 | #include "button_utils.h" 37 | #include "power_utils.h" 38 | #include "sleep_utils.h" 39 | #include "menu_utils.h" 40 | #include "lora_utils.h" 41 | #include "wifi_utils.h" 42 | #include "msg_utils.h" 43 | #include "gps_utils.h" 44 | #include "web_utils.h" 45 | #include "ble_utils.h" 46 | #include "wx_utils.h" 47 | #include "display.h" 48 | #include "utils.h" 49 | #ifdef HAS_TOUCHSCREEN 50 | #include "touch_utils.h" 51 | #endif 52 | 53 | Configuration Config; 54 | HardwareSerial gpsSerial(1); 55 | TinyGPSPlus gps; 56 | #ifdef HAS_BT_CLASSIC 57 | BluetoothSerial SerialBT; 58 | #endif 59 | 60 | String versionDate = "2025.04.11"; 61 | 62 | uint8_t myBeaconsIndex = 0; 63 | int myBeaconsSize = Config.beacons.size(); 64 | Beacon *currentBeacon = &Config.beacons[myBeaconsIndex]; 65 | uint8_t loraIndex = 0; 66 | int loraIndexSize = Config.loraTypes.size(); 67 | LoraType *currentLoRaType = &Config.loraTypes[loraIndex]; 68 | 69 | int menuDisplay = 100; 70 | 71 | bool statusState = true; 72 | bool displayEcoMode = Config.display.ecoMode; 73 | bool displayState = true; 74 | uint32_t displayTime = millis(); 75 | uint32_t refreshDisplayTime = millis(); 76 | 77 | bool sendUpdate = true; 78 | 79 | bool bluetoothActive = Config.bluetooth.active; 80 | bool bluetoothConnected = false; 81 | 82 | uint32_t lastTx = 0.0; 83 | uint32_t txInterval = 60000L; 84 | uint32_t lastTxTime = 0; 85 | double lastTxLat = 0.0; 86 | double lastTxLng = 0.0; 87 | double lastTxDistance = 0.0; 88 | 89 | uint32_t menuTime = millis(); 90 | 91 | bool flashlight = false; 92 | bool digipeaterActive = false; 93 | bool sosActive = false; 94 | 95 | bool miceActive = false; 96 | 97 | bool smartBeaconActive = true; 98 | 99 | int ackRequestNumber; 100 | 101 | uint32_t lastGPSTime = 0; 102 | 103 | APRSPacket lastReceivedPacket; 104 | 105 | logging::Logger logger; 106 | //#define DEBUG 107 | 108 | extern bool gpsIsActive; 109 | 110 | void setup() { 111 | Serial.begin(115200); 112 | 113 | #ifndef DEBUG 114 | logger.setDebugLevel(logging::LoggerLevel::LOGGER_LEVEL_INFO); 115 | #endif 116 | 117 | POWER_Utils::setup(); 118 | displaySetup(); 119 | POWER_Utils::externalPinSetup(); 120 | 121 | STATION_Utils::loadIndex(0); // callsign Index 122 | STATION_Utils::loadIndex(1); // lora freq settins Index 123 | STATION_Utils::nearTrackerInit(); 124 | startupScreen(loraIndex, versionDate); 125 | 126 | WIFI_Utils::checkIfWiFiAP(); 127 | 128 | MSG_Utils::loadNumMessages(); 129 | GPS_Utils::setup(); 130 | currentLoRaType = &Config.loraTypes[loraIndex]; 131 | LoRa_Utils::setup(); 132 | Utils::i2cScannerForPeripherals(); 133 | WX_Utils::setup(); 134 | 135 | ackRequestNumber = random(1,999); 136 | 137 | WiFi.mode(WIFI_OFF); 138 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Main", "WiFi controller stopped"); 139 | 140 | if (bluetoothActive) { 141 | if (Config.bluetooth.useBLE) { 142 | BLE_Utils::setup(); 143 | } else { 144 | #ifdef HAS_BT_CLASSIC 145 | BLUETOOTH_Utils::setup(); 146 | #endif 147 | } 148 | } 149 | 150 | if (!Config.simplifiedTrackerMode) { 151 | #ifdef BUTTON_PIN 152 | BUTTON_Utils::setup(); 153 | #endif 154 | #ifdef HAS_JOYSTICK 155 | JOYSTICK_Utils::setup(); 156 | #endif 157 | KEYBOARD_Utils::setup(); 158 | #ifdef HAS_TOUCHSCREEN 159 | TOUCH_Utils::setup(); 160 | #endif 161 | } 162 | 163 | POWER_Utils::lowerCpuFrequency(); 164 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Main", "Smart Beacon is: %s", Utils::getSmartBeaconState()); 165 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Setup Done!"); 166 | menuDisplay = 0; 167 | } 168 | 169 | void loop() { 170 | currentBeacon = &Config.beacons[myBeaconsIndex]; 171 | if (statusState) { 172 | if (Config.validateConfigFile(currentBeacon->callsign)) { 173 | KEYBOARD_Utils::rightArrow(); 174 | currentBeacon = &Config.beacons[myBeaconsIndex]; 175 | } 176 | miceActive = Config.validateMicE(currentBeacon->micE); 177 | } 178 | POWER_Utils::batteryManager(); 179 | 180 | SMARTBEACON_Utils::checkSettings(currentBeacon->smartBeaconSetting); 181 | SMARTBEACON_Utils::checkState(); 182 | 183 | if (!Config.simplifiedTrackerMode) { 184 | #ifdef BUTTON_PIN 185 | BUTTON_Utils::loop(); 186 | #endif 187 | } 188 | 189 | Utils::checkDisplayEcoMode(); 190 | 191 | KEYBOARD_Utils::read(); 192 | #ifdef HAS_JOYSTICK 193 | JOYSTICK_Utils::loop(); 194 | #endif 195 | #ifdef HAS_TOUCHSCREEN 196 | TOUCH_Utils::loop(); 197 | #endif 198 | 199 | 200 | ReceivedLoRaPacket packet = LoRa_Utils::receivePacket(); 201 | 202 | MSG_Utils::checkReceivedMessage(packet); 203 | MSG_Utils::processOutputBuffer(); 204 | MSG_Utils::clean15SegBuffer(); 205 | 206 | if (bluetoothActive && bluetoothConnected) { 207 | if (Config.bluetooth.useBLE) { 208 | BLE_Utils::sendToPhone(packet.text.substring(3)); 209 | BLE_Utils::sendToLoRa(); 210 | } else { 211 | #ifdef HAS_BT_CLASSIC 212 | BLUETOOTH_Utils::sendToPhone(packet.text.substring(3)); 213 | BLUETOOTH_Utils::sendToLoRa(); 214 | #endif 215 | } 216 | } 217 | 218 | MSG_Utils::ledNotification(); 219 | Utils::checkFlashlight(); 220 | STATION_Utils::checkListenedTrackersByTimeAndDelete(); 221 | 222 | lastTx = millis() - lastTxTime; 223 | if (gpsIsActive) { 224 | GPS_Utils::getData(); 225 | bool gps_time_update = gps.time.isUpdated(); 226 | bool gps_loc_update = gps.location.isUpdated(); 227 | GPS_Utils::setDateFromData(); 228 | 229 | int currentSpeed = (int) gps.speed.kmph(); 230 | 231 | if (gps_loc_update) { 232 | Utils::checkStatus(); 233 | STATION_Utils::checkTelemetryTx(); 234 | } 235 | 236 | if (!gps.location.isValid()) BATTERY_Utils::checkVoltageWithoutGPSFix(); 237 | 238 | if (!sendUpdate && gps_loc_update && smartBeaconActive) { 239 | GPS_Utils::calculateDistanceTraveled(); 240 | if (!sendUpdate) GPS_Utils::calculateHeadingDelta(currentSpeed); 241 | STATION_Utils::checkStandingUpdateTime(); 242 | } 243 | SMARTBEACON_Utils::checkFixedBeaconTime(); 244 | if (sendUpdate && gps_loc_update) STATION_Utils::sendBeacon(0); 245 | if (gps_time_update) SMARTBEACON_Utils::checkInterval(currentSpeed); 246 | 247 | if (millis() - refreshDisplayTime >= 1000 || gps_time_update) { 248 | GPS_Utils::checkStartUpFrames(); 249 | MENU_Utils::showOnScreen(); 250 | refreshDisplayTime = millis(); 251 | } 252 | SLEEP_Utils::checkIfGPSShouldSleep(); 253 | } else { 254 | if (millis() - lastGPSTime > txInterval) { 255 | SLEEP_Utils::gpsWakeUp(); 256 | } 257 | STATION_Utils::checkStandingUpdateTime(); 258 | if (millis() - refreshDisplayTime >= 1000) { 259 | MENU_Utils::showOnScreen(); 260 | refreshDisplayTime = millis(); 261 | } 262 | } 263 | } 264 | 265 | // eliminar keyboardConnected y reemplazar por validar si es distinto de 0x00 ? -------------------------------------------------------------------------------- /src/battery_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "battery_utils.h" 3 | #include "board_pinout.h" 4 | #include "power_utils.h" 5 | #include "display.h" 6 | 7 | 8 | int telemetryCounter = random(1,999); 9 | uint32_t lastNoGPSCheckTime = 0; 10 | 11 | 12 | namespace BATTERY_Utils { 13 | 14 | String generateEncodedTelemetryBytes(float value, bool firstBytes, byte voltageType) { // 0 = internal battery(0-4,2V) , 1 = external battery(0-15V) 15 | String encodedBytes; 16 | int tempValue; 17 | 18 | if (firstBytes) { 19 | tempValue = value; 20 | } else { 21 | switch (voltageType) { 22 | case 0: 23 | tempValue = value * 100; // Internal voltage calculation 24 | break; 25 | case 1: 26 | tempValue = (value * 100) / 2; // External voltage calculation 27 | break; 28 | default: 29 | tempValue = value; 30 | break; 31 | } 32 | } 33 | 34 | int firstByte = tempValue / 91; 35 | tempValue -= firstByte * 91; 36 | 37 | encodedBytes = char(firstByte + 33); 38 | encodedBytes += char(tempValue + 33); 39 | return encodedBytes; 40 | } 41 | 42 | String generateEncodedTelemetry(float voltage) { 43 | String telemetry = "|"; 44 | telemetry += generateEncodedTelemetryBytes(telemetryCounter, true, 0); 45 | telemetryCounter++; 46 | if (telemetryCounter == 1000) { 47 | telemetryCounter = 0; 48 | } 49 | telemetry += generateEncodedTelemetryBytes(voltage, false, 0); 50 | telemetry += "|"; 51 | return telemetry; 52 | } 53 | 54 | String getPercentVoltageBattery(float voltage) { 55 | int percent = ((voltage - 3.0) / (4.2 - 3.0)) * 100; 56 | return (percent < 100) ? (((percent < 10) ? " ": " ") + String(percent)) : "100"; 57 | } 58 | 59 | void checkVoltageWithoutGPSFix() { 60 | #ifdef BATTERY_PIN 61 | if (lastNoGPSCheckTime == 0 || millis() - lastNoGPSCheckTime > 15 * 60 * 1000) { 62 | String batteryVoltage = POWER_Utils::getBatteryInfoVoltage(); 63 | if (batteryVoltage.toFloat() < 3.0) { 64 | displayShow("!BATTERY!", "", "LOW BATTERY VOLTAGE!",5000); 65 | POWER_Utils::shutdown(); 66 | } 67 | lastNoGPSCheckTime = millis(); 68 | } 69 | #endif 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /src/ble_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "configuration.h" 3 | #include "lora_utils.h" 4 | #include "kiss_utils.h" 5 | #include "ble_utils.h" 6 | #include "display.h" 7 | #include "logger.h" 8 | 9 | #define BLE_CHUNK_SIZE 256 10 | 11 | 12 | // APPLE - APRS.fi app 13 | #define SERVICE_UUID_0 "00000001-ba2a-46c9-ae49-01b0961f68bb" 14 | #define CHARACTERISTIC_UUID_TX_0 "00000003-ba2a-46c9-ae49-01b0961f68bb" 15 | #define CHARACTERISTIC_UUID_RX_0 "00000002-ba2a-46c9-ae49-01b0961f68bb" 16 | 17 | // ANDROID - BLE Terminal app (Serial Bluetooth Terminal from Playstore) 18 | #define SERVICE_UUID_1 "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" 19 | #define CHARACTERISTIC_UUID_TX_1 "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" 20 | #define CHARACTERISTIC_UUID_RX_1 "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" 21 | 22 | BLEServer *pServer; 23 | BLECharacteristic *pCharacteristicTx; 24 | BLECharacteristic *pCharacteristicRx; 25 | 26 | extern Configuration Config; 27 | extern Beacon *currentBeacon; 28 | extern logging::Logger logger; 29 | extern bool bluetoothConnected; 30 | extern bool bluetoothActive; 31 | 32 | bool shouldSendBLEtoLoRa = false; 33 | String BLEToLoRaPacket = ""; 34 | String kissSerialBuffer = ""; 35 | 36 | 37 | class MyServerCallbacks : public NimBLEServerCallbacks { 38 | void onConnect(NimBLEServer* pServer) { 39 | bluetoothConnected = true; 40 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BLE", "%s", "BLE Client Connected"); 41 | delay(100); 42 | } 43 | 44 | void onDisconnect(NimBLEServer* pServer) { 45 | bluetoothConnected = false; 46 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BLE", "%s", "BLE client Disconnected, Started Advertising"); 47 | delay(100); 48 | pServer->startAdvertising(); 49 | } 50 | }; 51 | 52 | class MyCallbacks : public NimBLECharacteristicCallbacks { 53 | void onWrite(NimBLECharacteristic *pCharacteristic) { 54 | if (Config.bluetooth.useKISS) { // KISS (AX.25) 55 | std::string receivedData = pCharacteristic->getValue(); 56 | delay(100); 57 | for (int i = 0; i < receivedData.length(); i++) { 58 | char character = receivedData[i]; 59 | 60 | if (kissSerialBuffer.length() == 0 && character != (char)KissChar::FEND) continue; 61 | kissSerialBuffer += receivedData[i]; 62 | 63 | if (character == (char)KissChar::FEND && kissSerialBuffer.length() > 3) { 64 | bool isDataFrame = false; 65 | 66 | BLEToLoRaPacket = KISS_Utils::decodeKISS(kissSerialBuffer, isDataFrame); 67 | 68 | if (isDataFrame) { 69 | shouldSendBLEtoLoRa = true; 70 | kissSerialBuffer = ""; 71 | } 72 | } 73 | } 74 | } else { // TNC2 75 | std::string receivedData = pCharacteristic->getValue(); 76 | String receivedString = ""; 77 | for (int i = 0; i < receivedData.length(); i++) receivedString += receivedData[i]; 78 | BLEToLoRaPacket = receivedString; 79 | shouldSendBLEtoLoRa = true; 80 | } 81 | } 82 | }; 83 | 84 | 85 | namespace BLE_Utils { 86 | 87 | void stop() { 88 | BLEDevice::deinit(); 89 | } 90 | 91 | void setup() { 92 | String BLEid = Config.bluetooth.deviceName; 93 | BLEDevice::init(BLEid.c_str()); 94 | pServer = BLEDevice::createServer(); 95 | pServer->setCallbacks(new MyServerCallbacks()); 96 | 97 | BLEService *pService = nullptr; 98 | 99 | // KISS (AX.25) or TNC2 100 | bool useKISS = Config.bluetooth.useKISS; 101 | pService = pServer->createService(useKISS ? SERVICE_UUID_0 : SERVICE_UUID_1); 102 | pCharacteristicTx = pService->createCharacteristic(useKISS ? CHARACTERISTIC_UUID_TX_0 : CHARACTERISTIC_UUID_TX_1, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY); 103 | pCharacteristicRx = pService->createCharacteristic(useKISS ? CHARACTERISTIC_UUID_RX_0 : CHARACTERISTIC_UUID_RX_1, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR); 104 | 105 | if (pService != nullptr) { 106 | pCharacteristicRx->setCallbacks(new MyCallbacks()); 107 | pService->start(); 108 | 109 | BLEAdvertising* pAdvertising = BLEDevice::getAdvertising(); 110 | pAdvertising->addServiceUUID(useKISS ? SERVICE_UUID_0 : SERVICE_UUID_1); 111 | 112 | pServer->getAdvertising()->setScanResponse(true); 113 | pServer->getAdvertising()->setMinPreferred(0x06); 114 | pServer->getAdvertising()->setMaxPreferred(0x0C); 115 | pAdvertising->start(); 116 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "BLE", "%s", "Waiting for BLE central to connect..."); 117 | } else { 118 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "BLE", "Failed to create BLE service"); 119 | } 120 | } 121 | 122 | void sendToLoRa() { 123 | if (!shouldSendBLEtoLoRa) return; 124 | 125 | if (!Config.acceptOwnFrameFromTNC && BLEToLoRaPacket.indexOf("::") == -1) { 126 | String sender = BLEToLoRaPacket.substring(0, BLEToLoRaPacket.indexOf(">")); 127 | if (sender == currentBeacon->callsign) { 128 | BLEToLoRaPacket = ""; 129 | shouldSendBLEtoLoRa = false; 130 | return; 131 | } 132 | } 133 | 134 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "BLE Tx", "%s", BLEToLoRaPacket.c_str()); 135 | displayShow("BLE Tx >>", "", BLEToLoRaPacket, 1000); 136 | LoRa_Utils::sendNewPacket(BLEToLoRaPacket); 137 | BLEToLoRaPacket = ""; 138 | shouldSendBLEtoLoRa = false; 139 | } 140 | 141 | void txBLE(uint8_t p) { 142 | pCharacteristicTx->setValue(&p,1); 143 | pCharacteristicTx->notify(); 144 | delay(3); 145 | } 146 | 147 | void txToPhoneOverBLE(const String& frame) { 148 | if (Config.bluetooth.useKISS) { // KISS (AX.25) 149 | const String kissEncodedFrame = KISS_Utils::encodeKISS(frame); 150 | 151 | const char* t = kissEncodedFrame.c_str(); 152 | int length = kissEncodedFrame.length(); 153 | for (int i = 0; i < length; i += BLE_CHUNK_SIZE) { 154 | int chunkSize = (length - i < BLE_CHUNK_SIZE) ? (length - i) : BLE_CHUNK_SIZE; 155 | 156 | uint8_t* chunk = new uint8_t[chunkSize]; 157 | memcpy(chunk, t + i, chunkSize); 158 | 159 | pCharacteristicTx->setValue(chunk, chunkSize); 160 | pCharacteristicTx->notify(); 161 | delete[] chunk; 162 | delay(200); 163 | } 164 | } else { // TNC2 165 | for (int n = 0; n < frame.length(); n++) txBLE(frame[n]); 166 | txBLE('\n'); 167 | } 168 | } 169 | 170 | void sendToPhone(const String& packet) { 171 | if (!packet.isEmpty() && bluetoothConnected) { 172 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "BLE Rx", "%s", packet.c_str()); 173 | String receivedPacketString = ""; 174 | for (int i = 0; i < packet.length(); i++) receivedPacketString += packet[i]; 175 | txToPhoneOverBLE(receivedPacketString); 176 | } 177 | } 178 | 179 | } -------------------------------------------------------------------------------- /src/bluetooth_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "bluetooth_utils.h" 4 | #include "configuration.h" 5 | #include "lora_utils.h" 6 | #include "kiss_utils.h" 7 | #include "display.h" 8 | #include "logger.h" 9 | 10 | 11 | extern Configuration Config; 12 | extern Beacon *currentBeacon; 13 | extern BluetoothSerial SerialBT; 14 | extern logging::Logger logger; 15 | extern TinyGPSPlus gps; 16 | extern bool bluetoothConnected; 17 | extern bool bluetoothActive; 18 | 19 | namespace BLUETOOTH_Utils { 20 | String serialReceived; 21 | bool shouldSendToLoRa = false; 22 | bool useKiss = Config.bluetooth.useKISS? true : false; 23 | 24 | void setup() { 25 | if (!bluetoothActive) { 26 | btStop(); 27 | esp_bt_controller_disable(); 28 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "BT controller disabled"); 29 | return; 30 | } 31 | 32 | serialReceived.reserve(255); 33 | 34 | SerialBT.register_callback(BLUETOOTH_Utils::bluetoothCallback); 35 | SerialBT.onData(BLUETOOTH_Utils::getData); // callback instead of while to avoid RX buffer limit when NMEA data received 36 | 37 | String BTid = Config.bluetooth.deviceName; 38 | 39 | if (!SerialBT.begin(String(BTid))) { 40 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "Bluetooth", "Starting Bluetooth failed!"); 41 | displayShow("ERROR", "Starting Bluetooth failed!", ""); 42 | while(true) { 43 | delay(1000); 44 | } 45 | } 46 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Bluetooth", "Bluetooth Classic init done!"); 47 | } 48 | 49 | void bluetoothCallback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) { 50 | if (event == ESP_SPP_SRV_OPEN_EVT) { 51 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Bluetooth", "Client connected !"); 52 | bluetoothConnected = true; 53 | } else if (event == ESP_SPP_CLOSE_EVT) { 54 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Bluetooth", "Client disconnected !"); 55 | bluetoothConnected = false; 56 | } else { 57 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Bluetooth", "Status: %d", event); 58 | } 59 | } 60 | 61 | void getData(const uint8_t *buffer, size_t size) { 62 | if (size == 0) return; 63 | shouldSendToLoRa = false; 64 | serialReceived.clear(); 65 | bool isNmea = buffer[0] == '$'; 66 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "bluetooth", "Received buffer size %d. Nmea=%d. %s", size, isNmea, buffer); 67 | 68 | for (int i = 0; i < size; i++) { 69 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "bluetooth", "[%d/%d] %x -> %c", i + 1, size, buffer[i], buffer[i]); 70 | } 71 | for (int i = 0; i < size; i++) { 72 | char c = (char) buffer[i]; 73 | if (isNmea) { 74 | gps.encode(c); 75 | } else { 76 | serialReceived += c; 77 | } 78 | } 79 | // Test if we have to send frame 80 | isNmea = serialReceived.indexOf("$G") != -1 || serialReceived.indexOf("$B") != -1; 81 | if (isNmea) useKiss = false; 82 | if (isNmea || serialReceived.isEmpty()) return; 83 | if (KISS_Utils::validateKISSFrame(serialReceived)) { 84 | bool dataFrame; 85 | String decodeKiss = KISS_Utils::decodeKISS(serialReceived, dataFrame); 86 | serialReceived.clear(); 87 | serialReceived += decodeKiss; 88 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "bluetooth", "It's a kiss frame. dataFrame: %d", dataFrame); 89 | useKiss = true; 90 | } else { 91 | useKiss = false; 92 | } 93 | if (KISS_Utils::validateTNC2Frame(serialReceived)) { 94 | shouldSendToLoRa = true; 95 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "bluetooth", "Data received should be transmitted to RF => %s", serialReceived.c_str()); 96 | } 97 | } 98 | 99 | void sendToLoRa() { 100 | if (!shouldSendToLoRa) return; 101 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "BT TX", "%s", serialReceived.c_str()); 102 | displayShow("BT Tx >>", "", serialReceived, 1000); 103 | LoRa_Utils::sendNewPacket(serialReceived); 104 | shouldSendToLoRa = false; 105 | } 106 | 107 | void sendToPhone(const String& packet) { 108 | if (!packet.isEmpty()) { 109 | if (useKiss) { 110 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "BT RX Kiss", "%s", serialReceived.c_str()); 111 | SerialBT.println(KISS_Utils::encodeKISS(packet)); 112 | } else { 113 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "BT RX TNC2", "%s", serialReceived.c_str()); 114 | SerialBT.println(packet); 115 | } 116 | } 117 | } 118 | 119 | } -------------------------------------------------------------------------------- /src/button_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "keyboard_utils.h" 3 | #include "board_pinout.h" 4 | #include "button_utils.h" 5 | #include "power_utils.h" 6 | #include "display.h" 7 | 8 | #ifdef BUTTON_PIN 9 | 10 | extern int menuDisplay; 11 | extern uint32_t displayTime; 12 | extern uint32_t menuTime; 13 | 14 | 15 | namespace BUTTON_Utils { 16 | 17 | OneButton userButton = OneButton(BUTTON_PIN, true, true); 18 | 19 | static bool buttonSinglePressed; 20 | static bool buttonLongPressed; 21 | static bool buttonDoublePressed; 22 | static bool buttonMultiPressed; 23 | 24 | void singlePress() { 25 | menuTime = millis(); 26 | KEYBOARD_Utils::downArrow(); 27 | } 28 | 29 | void longPress() { 30 | menuTime = millis(); 31 | KEYBOARD_Utils::rightArrow(); 32 | } 33 | 34 | void doublePress() { 35 | displayToggle(true); 36 | menuTime = millis(); 37 | if (menuDisplay == 0) { 38 | menuDisplay = 1; 39 | } else if (menuDisplay > 0) { 40 | menuDisplay = 0; 41 | displayTime = millis(); 42 | } 43 | } 44 | 45 | void multiPress() { 46 | displayToggle(true); 47 | menuTime = millis(); 48 | menuDisplay = 9000; 49 | } 50 | 51 | void isrSinglePress() { 52 | buttonSinglePressed = true; 53 | } 54 | 55 | void isrLongPress() { 56 | buttonLongPressed = true; 57 | } 58 | 59 | void isrDoublePress() { 60 | buttonDoublePressed = true; 61 | } 62 | 63 | void isrMultiPress() { 64 | buttonMultiPressed = true; 65 | } 66 | 67 | void IRAM_ATTR buttonIsr() { // Interrupt Service Routine 68 | userButton.tick(); 69 | } 70 | 71 | void loop() { 72 | noInterrupts(); 73 | userButton.tick(); 74 | interrupts(); 75 | 76 | if (buttonSinglePressed) { 77 | buttonSinglePressed = false; 78 | singlePress(); 79 | } 80 | if (buttonLongPressed) { 81 | buttonLongPressed = false; 82 | longPress(); 83 | } 84 | if (buttonDoublePressed) { 85 | buttonDoublePressed = false; 86 | doublePress(); 87 | } 88 | if (buttonMultiPressed) { 89 | buttonMultiPressed = false; 90 | multiPress(); 91 | } 92 | } 93 | 94 | void setup() { 95 | userButton.attachClick(BUTTON_Utils::isrSinglePress); 96 | userButton.attachLongPressStart(BUTTON_Utils::isrLongPress); 97 | userButton.attachDoubleClick(BUTTON_Utils::isrDoublePress); 98 | userButton.attachMultiClick(BUTTON_Utils::isrMultiPress); 99 | attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonIsr, FALLING); 100 | } 101 | 102 | } 103 | 104 | #endif -------------------------------------------------------------------------------- /src/gps_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "TimeLib.h" 3 | #include 4 | #include "smartbeacon_utils.h" 5 | #include "configuration.h" 6 | #include "station_utils.h" 7 | #include "board_pinout.h" 8 | #include "power_utils.h" 9 | #include "sleep_utils.h" 10 | #include "gps_utils.h" 11 | #include "display.h" 12 | #include "logger.h" 13 | 14 | 15 | #ifdef GPS_BAUDRATE 16 | #define GPS_BAUD GPS_BAUDRATE 17 | #else 18 | #define GPS_BAUD 9600 19 | #endif 20 | 21 | 22 | extern Configuration Config; 23 | extern HardwareSerial gpsSerial; 24 | extern TinyGPSPlus gps; 25 | extern Beacon *currentBeacon; 26 | extern logging::Logger logger; 27 | extern bool sendUpdate; 28 | extern bool sendStandingUpdate; 29 | 30 | extern uint32_t lastTxTime; 31 | extern uint32_t txInterval; 32 | extern double lastTxLat; 33 | extern double lastTxLng; 34 | extern double lastTxDistance; 35 | extern uint32_t lastTx; 36 | extern bool disableGPS; 37 | extern bool gpsShouldSleep; 38 | extern SmartBeaconValues currentSmartBeaconValues; 39 | 40 | double currentHeading = 0; 41 | double previousHeading = 0; 42 | float bearing = 0; 43 | 44 | bool gpsIsActive = true; 45 | 46 | 47 | namespace GPS_Utils { 48 | 49 | void setup() { 50 | if (disableGPS) { 51 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Main", "GPS disabled"); 52 | return; 53 | } 54 | #ifdef LIGHTTRACKER_PLUS_1_0 55 | pinMode(GPS_VCC, OUTPUT); 56 | digitalWrite(GPS_VCC, LOW); 57 | delay(200); 58 | #endif 59 | #if defined(F4GOH_1W_LoRa_Tracker) || defined(F4GOH_1W_LoRa_Tracker_LLCC68) 60 | pinMode(GPS_VCC, OUTPUT); 61 | digitalWrite(GPS_VCC, HIGH); 62 | delay(200); 63 | #endif 64 | 65 | gpsSerial.begin(GPS_BAUD, SERIAL_8N1, GPS_TX, GPS_RX); 66 | } 67 | 68 | void calculateDistanceCourse(const String& callsign, double checkpointLatitude, double checkPointLongitude) { 69 | double distanceKm = TinyGPSPlus::distanceBetween(gps.location.lat(), gps.location.lng(), checkpointLatitude, checkPointLongitude) / 1000.0; 70 | double courseTo = TinyGPSPlus::courseTo(gps.location.lat(), gps.location.lng(), checkpointLatitude, checkPointLongitude); 71 | STATION_Utils::deleteListenedTrackersbyTime(); 72 | STATION_Utils::orderListenedTrackersByDistance(callsign, distanceKm, courseTo); 73 | } 74 | 75 | void getData() { 76 | if (disableGPS) return; 77 | while (gpsSerial.available() > 0) gps.encode(gpsSerial.read()); 78 | } 79 | 80 | void setDateFromData() { 81 | if (gps.time.isValid()) setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), gps.date.day(), gps.date.month(), gps.date.year()); 82 | } 83 | 84 | void calculateDistanceTraveled() { 85 | currentHeading = gps.course.deg(); 86 | lastTxDistance = TinyGPSPlus::distanceBetween(gps.location.lat(), gps.location.lng(), lastTxLat, lastTxLng); 87 | if (lastTx >= txInterval) { 88 | if (lastTxDistance > currentSmartBeaconValues.minTxDist) { 89 | sendUpdate = true; 90 | sendStandingUpdate = false; 91 | } else { 92 | if (currentBeacon->gpsEcoMode) { 93 | // 94 | Serial.print("minTxDistance not achieved : "); 95 | Serial.println(lastTxDistance); 96 | // 97 | gpsShouldSleep = true; 98 | } 99 | } 100 | } 101 | } 102 | 103 | void calculateHeadingDelta(int speed) { 104 | uint8_t TurnMinAngle; 105 | double headingDelta = abs(previousHeading - currentHeading); 106 | if (lastTx > currentSmartBeaconValues.minDeltaBeacon * 1000) { 107 | if (speed == 0) { 108 | TurnMinAngle = currentSmartBeaconValues.turnMinDeg + (currentSmartBeaconValues.turnSlope/(speed + 1)); 109 | } else { 110 | TurnMinAngle = currentSmartBeaconValues.turnMinDeg + (currentSmartBeaconValues.turnSlope/speed); 111 | } 112 | if (headingDelta > TurnMinAngle && lastTxDistance > currentSmartBeaconValues.minTxDist) { 113 | sendUpdate = true; 114 | sendStandingUpdate = false; 115 | } 116 | } 117 | } 118 | 119 | void checkStartUpFrames() { 120 | if (disableGPS) return; 121 | if ((millis() > 10000 && gps.charsProcessed() < 10)) { 122 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "GPS", 123 | "No GPS frames detected! Try to reset the GPS Chip with this " 124 | "firmware: https://github.com/richonguzman/TTGO_T_BEAM_GPS_RESET"); 125 | displayShow("ERROR", "No GPS frames!", "Reset the GPS Chip", 2000); 126 | } 127 | } 128 | 129 | String getHumanBearing(const String& left, const String& center, const String& right) { 130 | String bearing = ">."; 131 | bearing += left; 132 | for (int i = 0; i < 9; i++) { 133 | bearing += "."; 134 | } 135 | bearing += "("; 136 | bearing += center; 137 | bearing += ")....."; 138 | if (right.length() == 1 && center.length() != 2) bearing += "."; 139 | bearing += right; 140 | bearing += ".<"; 141 | return bearing; 142 | } 143 | 144 | String getCardinalDirection(float course) { 145 | if (gps.speed.kmph() > 0.5) bearing = course; 146 | 147 | if (bearing >= 354.375 || bearing < 5.625) return ">.NW.....(N).....NE.<"; // N 148 | if (bearing >= 5.675 && bearing < 16.875) return ">.......N.|.....NE..<"; 149 | if (bearing >= 16.875 && bearing < 28.125) return ">.....N...|...NE....<"; // NEN 150 | if (bearing >= 28.125 && bearing < 39.375) return ">...N.....|.NE......<"; 151 | if (bearing >= 39.375 && bearing < 50.625) return ">.N......(NE).....E.<"; // NE 152 | if (bearing >= 50.625 && bearing < 61.875) return ">.......NE|.....E...<"; 153 | if (bearing >= 61.875 && bearing < 73.125) return ">.....NE..|...E.....<"; // ENE 154 | if (bearing >= 73.125 && bearing < 84.375) return ">...NE....|.E.......<"; 155 | if (bearing >= 84.375 && bearing < 95.625) return ">.NE.....(E).....SE.<"; // E 156 | if (bearing >= 95.625 && bearing < 106.875) return ">.......E.|.....SE..<"; 157 | if (bearing >= 106.875 && bearing < 118.125) return ">.....E...|...SE....<"; // ESE 158 | if (bearing >= 118.125 && bearing < 129.375) return ">...E.....|.SE......<"; 159 | if (bearing >= 129.375 && bearing < 140.625) return ">.E......(SE).....S.<"; // SE 160 | if (bearing >= 140.625 && bearing < 151.875) return ">.......SE|.....S...<"; 161 | if (bearing >= 151.875 && bearing < 163.125) return ">.....SE..|...S.....<"; // SES 162 | if (bearing >= 163.125 && bearing < 174.375) return ">...SE....|.S.......<"; 163 | if (bearing >= 174.375 && bearing < 185.625) return ">.SE.....(S).....SW.<"; // S 164 | if (bearing >= 185.625 && bearing < 196.875) return ">.......S.|.....SW..<"; 165 | if (bearing >= 196.875 && bearing < 208.125) return ">.....S...|...SW....<"; // SWS 166 | if (bearing >= 208.125 && bearing < 219.375) return ">...S.....|.SW......<"; 167 | if (bearing >= 219.375 && bearing < 230.625) return ">.S......(SW).....W.<"; // SW 168 | if (bearing >= 230.625 && bearing < 241.875) return ">.......SW|.....W...<"; 169 | if (bearing >= 241.875 && bearing < 253.125) return ">.....SW..|...W.....<"; // WSW 170 | if (bearing >= 253.125 && bearing < 264.375) return ">...SW....|.W.......<"; 171 | if (bearing >= 264.375 && bearing < 275.625) return ">.SW.....(W).....NW.<"; // W 172 | if (bearing >= 275.625 && bearing < 286.875) return ">.......W.|.....NW..<"; 173 | if (bearing >= 286.875 && bearing < 298.125) return ">.....W...|...NW....<"; // WNW 174 | if (bearing >= 298.125 && bearing < 309.375) return ">...W.....|.NW......<"; 175 | if (bearing >= 309.375 && bearing < 320.625) return ">.W......(NW).....N.<"; // NW 176 | if (bearing >= 320.625 && bearing < 331.875) return ">.......NW|.....N...<"; 177 | if (bearing >= 331.875 && bearing < 343.125) return ">.....NW..|...N.....<"; // NWN 178 | if (bearing >= 343.125 && bearing < 354.375) return ">...NW....|.N.......<"; 179 | return ""; 180 | } 181 | 182 | } -------------------------------------------------------------------------------- /src/joystick_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "joystick_utils.h" 2 | #include "keyboard_utils.h" 3 | #include "board_pinout.h" 4 | #include "button_utils.h" 5 | 6 | extern int menuDisplay; 7 | 8 | bool exitJoystickInterrupt = false; 9 | 10 | typedef void (*DirectionFunc)(); 11 | 12 | #ifdef HAS_JOYSTICK 13 | 14 | namespace JOYSTICK_Utils { 15 | 16 | int debounceDelay = 400; 17 | uint32_t lastInterruptTime = 0; 18 | 19 | bool checkLastJoystickInterrupTime() { 20 | if ((millis() - lastInterruptTime) > debounceDelay) { 21 | lastInterruptTime = millis(); 22 | return true; 23 | } else { 24 | return false; 25 | } 26 | } 27 | 28 | bool checkMenuDisplayToExitInterrupt(int menu) { 29 | if (menu == 10 || menu == 120 || (menu >= 130 && menu <= 133) || menu == 200 || menu == 210 || menu == 1300 || menu == 1310 || (menu >= 2210 && menu <= 2212) || menu == 51 || (menu >= 50100 && menu <= 50101) || (menu >= 50110 && menu <= 50111) || menu == 9001) { 30 | return true; // read / delete/ callsignIndex / loraIndex / brightness x 3 / readW / readW / delete / enter WiFiAP 31 | } else { 32 | return false; 33 | } 34 | } 35 | 36 | void loop() { // for running process with SPIFFS outside interrupt 37 | if (checkMenuDisplayToExitInterrupt(menuDisplay) && exitJoystickInterrupt) BUTTON_Utils::longPress(); 38 | } 39 | 40 | void IRAM_ATTR joystickHandler(DirectionFunc directionFunc) { 41 | if (checkLastJoystickInterrupTime() && menuDisplay != 0) { 42 | if (checkMenuDisplayToExitInterrupt(menuDisplay) && directionFunc == BUTTON_Utils::longPress) { 43 | exitJoystickInterrupt = true; 44 | } else { 45 | exitJoystickInterrupt = false; 46 | directionFunc(); 47 | } 48 | } 49 | } 50 | 51 | void IRAM_ATTR joystickUp() { joystickHandler(KEYBOARD_Utils::upArrow); } 52 | void IRAM_ATTR joystickDown() { joystickHandler(KEYBOARD_Utils::downArrow); } 53 | void IRAM_ATTR joystickLeft() { joystickHandler(KEYBOARD_Utils::leftArrow); } 54 | void IRAM_ATTR joystickRight() { joystickHandler(BUTTON_Utils::longPress); } 55 | 56 | void setup() { 57 | pinMode(JOYSTICK_CENTER, INPUT_PULLUP); 58 | pinMode(JOYSTICK_UP, INPUT_PULLUP); 59 | pinMode(JOYSTICK_DOWN, INPUT_PULLUP); 60 | pinMode(JOYSTICK_LEFT, INPUT_PULLUP); 61 | pinMode(JOYSTICK_RIGHT, INPUT_PULLUP); 62 | 63 | attachInterrupt(digitalPinToInterrupt(JOYSTICK_UP), joystickUp, FALLING); 64 | attachInterrupt(digitalPinToInterrupt(JOYSTICK_DOWN), joystickDown, FALLING); 65 | attachInterrupt(digitalPinToInterrupt(JOYSTICK_LEFT), joystickLeft, FALLING); 66 | attachInterrupt(digitalPinToInterrupt(JOYSTICK_RIGHT), joystickRight, FALLING); 67 | } 68 | } 69 | 70 | #endif -------------------------------------------------------------------------------- /src/kiss_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "kiss_utils.h" 2 | 3 | 4 | namespace KISS_Utils { 5 | 6 | bool validateTNC2Frame(const String& tnc2FormattedFrame) { 7 | int colonPos = tnc2FormattedFrame.indexOf(':'); 8 | int greaterThanPos = tnc2FormattedFrame.indexOf('>'); 9 | return (colonPos != -1) && (greaterThanPos != -1) && (colonPos > greaterThanPos); 10 | } 11 | 12 | bool validateKISSFrame(const String& kissFormattedFrame) { 13 | return kissFormattedFrame.charAt(0) == (char)KissChar::FEND && kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char)KissChar::FEND; 14 | } 15 | 16 | String decodeAddressAX25(const String& ax25Address, bool& isLastAddress, bool isRelay) { 17 | String address = ""; 18 | for (int i = 0; i < 6; ++i) { 19 | uint8_t currentCharacter = ax25Address.charAt(i); 20 | currentCharacter >>= 1; 21 | if (currentCharacter != ' ') address += (char)currentCharacter; 22 | } 23 | auto ssidChar = (uint8_t)ax25Address.charAt(6); 24 | bool hasBeenDigipited = ssidChar & HAS_BEEN_DIGIPITED_MASK; 25 | isLastAddress = ssidChar & IS_LAST_ADDRESS_POSITION_MASK; 26 | ssidChar >>= 1; 27 | 28 | int ssid = 0b1111 & ssidChar; 29 | if (ssid) { 30 | address += '-'; 31 | address += ssid; 32 | } 33 | if (isRelay && hasBeenDigipited) address += '*'; 34 | return address; 35 | } 36 | 37 | String decapsulateKISS(const String& frame) { 38 | String ax25Frame = ""; 39 | for (int i = 2; i < frame.length() - 1; ++i) { 40 | char currentChar = frame.charAt(i); 41 | if (currentChar == (char)KissChar::FESC) { 42 | char nextChar = frame.charAt(i + 1); 43 | if (nextChar == (char)KissChar::TFEND) { 44 | ax25Frame += (char)KissChar::FEND; 45 | } else if (nextChar == (char)KissChar::TFESC) { 46 | ax25Frame += (char)KissChar::FESC; 47 | } 48 | i++; 49 | } else { 50 | ax25Frame += currentChar; 51 | } 52 | } 53 | return ax25Frame; 54 | } 55 | 56 | String encapsulateKISS(const String& ax25Frame, uint8_t command) { 57 | String kissFrame = ""; 58 | kissFrame += (char)KissChar::FEND; 59 | kissFrame += (char)(0x0f & command); 60 | 61 | for (int i = 0; i < ax25Frame.length(); ++i) { 62 | char currentChar = ax25Frame.charAt(i); 63 | if (currentChar == (char)KissChar::FEND) { 64 | kissFrame += (char)KissChar::FESC; 65 | kissFrame += (char)KissChar::TFEND; 66 | } else if (currentChar == (char)KissChar::FESC) { 67 | kissFrame += (char)KissChar::FESC; 68 | kissFrame += (char)KissChar::TFESC; 69 | } else { 70 | kissFrame += currentChar; 71 | } 72 | } 73 | kissFrame += (char)KissChar::FEND; // end of frame 74 | return kissFrame; 75 | } 76 | 77 | String encodeAddressAX25(String address) { 78 | bool hasBeenDigipited = address.indexOf('*') != -1; 79 | if (address.indexOf('-') == -1) { 80 | if (hasBeenDigipited) address = address.substring(0, address.length() - 1); 81 | address += "-0"; 82 | } 83 | 84 | int separatorIndex = address.indexOf('-'); 85 | int ssid = address.substring(separatorIndex + 1).toInt(); 86 | String kissAddress = ""; 87 | for (int i = 0; i < 6; ++i) { 88 | char addressChar = ' '; 89 | if (address.length() > i && i < separatorIndex) addressChar = address.charAt(i); 90 | kissAddress += (char)(addressChar << 1); 91 | } 92 | kissAddress += (char)((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0)); 93 | return kissAddress; 94 | } 95 | 96 | String decodeKISS(const String& inputFrame, bool& dataFrame) { 97 | String frame = ""; 98 | if (KISS_Utils::validateKISSFrame(inputFrame)) { 99 | dataFrame = inputFrame.charAt(1) == KissCmd::Data; 100 | if (dataFrame) { 101 | String ax25Frame = decapsulateKISS(inputFrame); 102 | bool isLastAddress = false; 103 | String dstAddr = decodeAddressAX25(ax25Frame.substring(0, 7), isLastAddress, false); 104 | String srcAddr = decodeAddressAX25(ax25Frame.substring(7, 14), isLastAddress, false); 105 | 106 | frame = srcAddr + ">" + dstAddr; 107 | 108 | int digiInfoIndex = 14; 109 | while (!isLastAddress && digiInfoIndex + 7 < ax25Frame.length()) { 110 | String digiAddr = decodeAddressAX25(ax25Frame.substring(digiInfoIndex, digiInfoIndex + 7), isLastAddress, true); 111 | frame += ',' + digiAddr; 112 | digiInfoIndex += 7; 113 | } 114 | frame += ':'; 115 | frame += ax25Frame.substring(digiInfoIndex + 2); 116 | } else { 117 | frame += inputFrame; 118 | } 119 | } 120 | return frame; 121 | } 122 | 123 | String encodeKISS(const String& frame) { 124 | String ax25Frame = ""; 125 | 126 | if (KISS_Utils::validateTNC2Frame(frame)) { 127 | int colonIndex = frame.indexOf(':'); 128 | 129 | String address = ""; 130 | bool destinationAddressWritten = false; 131 | for (int i = 0; i <= colonIndex; i++) { 132 | char currentChar = frame.charAt(i); 133 | if (currentChar == ':' || currentChar == '>' || currentChar == ',') { 134 | if (!destinationAddressWritten && (currentChar == ',' || currentChar == ':')) { 135 | ax25Frame = encodeAddressAX25(address) + ax25Frame; 136 | destinationAddressWritten = true; 137 | } else { 138 | ax25Frame += encodeAddressAX25(address); 139 | } 140 | address = ""; 141 | } else { 142 | address += currentChar; 143 | } 144 | } 145 | auto lastAddressChar = (uint8_t)ax25Frame.charAt(ax25Frame.length() - 1); 146 | ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK)); 147 | ax25Frame += (char)AX25Char::ControlField; 148 | ax25Frame += (char)AX25Char::InformationField; 149 | ax25Frame += frame.substring(colonIndex + 1); 150 | } 151 | String kissFrame = encapsulateKISS(ax25Frame, KissCmd::Data); 152 | return kissFrame; 153 | } 154 | 155 | } -------------------------------------------------------------------------------- /src/lora_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "notification_utils.h" 5 | #include "configuration.h" 6 | #include "board_pinout.h" 7 | #include "lora_utils.h" 8 | #include "display.h" 9 | 10 | extern logging::Logger logger; 11 | extern Configuration Config; 12 | extern LoraType *currentLoRaType; 13 | extern uint8_t loraIndex; 14 | extern int loraIndexSize; 15 | 16 | bool operationDone = true; 17 | bool transmitFlag = true; 18 | 19 | #if defined(HAS_SX1262) 20 | SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); 21 | #endif 22 | #if defined(HAS_SX1268) 23 | #if defined(LIGHTTRACKER_PLUS_1_0) 24 | SPIClass loraSPI(FSPI); 25 | SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN, loraSPI); 26 | #else 27 | SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); 28 | #endif 29 | #endif 30 | #if defined(HAS_SX1278) 31 | SX1278 radio = new Module(RADIO_CS_PIN, RADIO_BUSY_PIN, RADIO_RST_PIN); 32 | #endif 33 | #if defined(HAS_SX1276) 34 | SX1276 radio = new Module(RADIO_CS_PIN, RADIO_BUSY_PIN, RADIO_RST_PIN); 35 | #endif 36 | #if defined(HAS_LLCC68) // LLCC68 supports spreading factor only in range of 5-11! 37 | LLCC68 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); 38 | #endif 39 | 40 | namespace LoRa_Utils { 41 | 42 | void setFlag(void) { 43 | operationDone = true; 44 | } 45 | 46 | void changeFreq() { 47 | if(loraIndex >= (loraIndexSize - 1)) { 48 | loraIndex = 0; 49 | } else { 50 | loraIndex++; 51 | } 52 | currentLoRaType = &Config.loraTypes[loraIndex]; 53 | 54 | float freq = (float)currentLoRaType->frequency/1000000; 55 | radio.setFrequency(freq); 56 | radio.setSpreadingFactor(currentLoRaType->spreadingFactor); 57 | float signalBandwidth = currentLoRaType->signalBandwidth/1000; 58 | radio.setBandwidth(signalBandwidth); 59 | radio.setCodingRate(currentLoRaType->codingRate4); 60 | #if (defined(HAS_SX1268) || defined(HAS_SX1262)) && !defined(HAS_1W_LORA) 61 | radio.setOutputPower(currentLoRaType->power + 2); // values available: 10, 17, 22 --> if 20 in tracker_conf.json it will be updated to 22. 62 | #endif 63 | #if defined(HAS_SX1278) || defined(HAS_SX1276) || defined(HAS_1W_LORA) 64 | radio.setOutputPower(currentLoRaType->power); 65 | #endif 66 | 67 | String loraCountryFreq; 68 | switch (loraIndex) { 69 | case 0: loraCountryFreq = "EU/WORLD"; break; 70 | case 1: loraCountryFreq = "POLAND"; break; 71 | case 2: loraCountryFreq = "UK"; break; 72 | } 73 | String currentLoRainfo = "LoRa "; 74 | currentLoRainfo += loraCountryFreq; 75 | currentLoRainfo += " / Freq: "; 76 | currentLoRainfo += String(currentLoRaType->frequency); 77 | currentLoRainfo += " / SF:"; 78 | currentLoRainfo += String(currentLoRaType->spreadingFactor); 79 | currentLoRainfo += " / CR: "; 80 | currentLoRainfo += String(currentLoRaType->codingRate4); 81 | 82 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "LoRa", currentLoRainfo.c_str()); 83 | displayShow("LORA FREQ>", "", "CHANGED TO: " + loraCountryFreq, "", "", "", 2000); 84 | } 85 | 86 | void setup() { 87 | #ifdef LIGHTTRACKER_PLUS_1_0 88 | pinMode(RADIO_VCC_PIN,OUTPUT); 89 | digitalWrite(RADIO_VCC_PIN,HIGH); 90 | #endif 91 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "LoRa", "Set SPI pins!"); 92 | #if defined(LIGHTTRACKER_PLUS_1_0) 93 | loraSPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN, RADIO_CS_PIN); 94 | #else 95 | SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN); 96 | #endif 97 | float freq = (float)currentLoRaType->frequency/1000000; 98 | #if defined(RADIO_HAS_XTAL) 99 | radio.XTAL = true; 100 | #endif 101 | int state = radio.begin(freq); 102 | if (state == RADIOLIB_ERR_NONE) { 103 | #if defined(HAS_SX1262) || defined(HAS_SX1268) 104 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "Initializing SX126X ..."); 105 | #else 106 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "Initializing SX127X ..."); 107 | #endif 108 | } else { 109 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "Starting LoRa failed! State: %d", state); 110 | while (true); 111 | } 112 | #if defined(HAS_SX1262) || defined(HAS_SX1268) || defined(HAS_LLCC68) 113 | radio.setDio1Action(setFlag); 114 | #endif 115 | #if defined(HAS_SX1278) || defined(HAS_SX1276) 116 | radio.setDio0Action(setFlag, RISING); 117 | #endif 118 | radio.setSpreadingFactor(currentLoRaType->spreadingFactor); 119 | float signalBandwidth = currentLoRaType->signalBandwidth/1000; 120 | radio.setBandwidth(signalBandwidth); 121 | radio.setCodingRate(currentLoRaType->codingRate4); 122 | radio.setCRC(true); 123 | 124 | #if defined(RADIO_RXEN) && defined(RADIO_TXEN) 125 | radio.setRfSwitchPins(RADIO_RXEN, RADIO_TXEN); 126 | #endif 127 | 128 | #ifdef HAS_1W_LORA // Ebyte E22 400M30S (SX1268) / 900M30S (SX1262) / Ebyte E220 400M30S (LLCC68) 129 | state = radio.setOutputPower(currentLoRaType->power); // max value 20 (when 20dB in setup 30dB in output as 400M30S has Low Noise Amp) 130 | radio.setCurrentLimit(140); // to be validated (100 , 120, 140)? 131 | #endif 132 | 133 | #if (defined(HAS_SX1268) || defined(HAS_SX1262)) && !defined(HAS_1W_LORA) 134 | state = radio.setOutputPower(currentLoRaType->power + 2); // values available: 10, 17, 22 --> if 20 in tracker_conf.json it will be updated to 22. 135 | radio.setCurrentLimit(140); 136 | #endif 137 | 138 | #if defined(HAS_SX1278) || defined(HAS_SX1276) 139 | state = radio.setOutputPower(currentLoRaType->power); 140 | radio.setCurrentLimit(100); // to be validated (80 , 100)? 141 | #endif 142 | 143 | #if defined(HAS_SX1262) || defined(HAS_SX1268) || defined(HAS_LLCC68) 144 | radio.setRxBoostedGainMode(true); 145 | #endif 146 | 147 | if (state == RADIOLIB_ERR_NONE) { 148 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "LoRa init done!"); 149 | } else { 150 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "Starting LoRa failed! State: %d", state); 151 | while (true); 152 | } 153 | } 154 | 155 | void sendNewPacket(const String& newPacket) { 156 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa Tx","---> %s", newPacket.c_str()); 157 | /*logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "LoRa","Send data: %s", newPacket.c_str()); 158 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa","Send data: %s", newPacket.c_str()); 159 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "LoRa","Send data: %s", newPacket.c_str());*/ 160 | 161 | if (Config.ptt.active) { 162 | digitalWrite(Config.ptt.io_pin, Config.ptt.reverse ? LOW : HIGH); 163 | delay(Config.ptt.preDelay); 164 | } 165 | if (Config.notification.ledTx) digitalWrite(Config.notification.ledTxPin, HIGH); 166 | if (Config.notification.buzzerActive && Config.notification.txBeep) NOTIFICATION_Utils::beaconTxBeep(); 167 | 168 | int state = radio.transmit("\x3c\xff\x01" + newPacket); 169 | transmitFlag = true; 170 | if (state == RADIOLIB_ERR_NONE) { 171 | //Serial.println(F("success!")); 172 | } else { 173 | Serial.print(F("failed, code ")); 174 | Serial.println(state); 175 | } 176 | 177 | if (Config.notification.ledTx) digitalWrite(Config.notification.ledTxPin, LOW); 178 | if (Config.ptt.active) { 179 | delay(Config.ptt.postDelay); 180 | digitalWrite(Config.ptt.io_pin, Config.ptt.reverse ? HIGH : LOW); 181 | } 182 | /*#ifdef HAS_TFT 183 | cleanTFT(); 184 | #endif*/ 185 | } 186 | 187 | void wakeRadio() { 188 | radio.startReceive(); 189 | } 190 | 191 | ReceivedLoRaPacket receiveFromSleep() { 192 | ReceivedLoRaPacket receivedLoraPacket; 193 | String packet = ""; 194 | int state = radio.readData(packet); 195 | if (state == RADIOLIB_ERR_NONE) { 196 | receivedLoraPacket.text = packet; 197 | receivedLoraPacket.rssi = radio.getRSSI(); 198 | receivedLoraPacket.snr = radio.getSNR(); 199 | receivedLoraPacket.freqError = radio.getFrequencyError(); 200 | } else { 201 | // 202 | } 203 | return receivedLoraPacket; 204 | } 205 | 206 | ReceivedLoRaPacket receivePacket() { 207 | ReceivedLoRaPacket receivedLoraPacket; 208 | String packet = ""; 209 | if (operationDone) { 210 | operationDone = false; 211 | if (transmitFlag) { 212 | radio.startReceive(); 213 | transmitFlag = false; 214 | } else { 215 | int state = radio.readData(packet); 216 | if (state == RADIOLIB_ERR_NONE) { 217 | if(!packet.isEmpty()) { 218 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa Rx","---> %s", packet.substring(3).c_str()); 219 | receivedLoraPacket.text = packet; 220 | receivedLoraPacket.rssi = radio.getRSSI(); 221 | receivedLoraPacket.snr = radio.getSNR(); 222 | receivedLoraPacket.freqError = radio.getFrequencyError(); 223 | } 224 | } else { 225 | Serial.print(F("failed, code ")); // 7 = CRC mismatch 226 | Serial.println(state); 227 | } 228 | } 229 | } 230 | return receivedLoraPacket; 231 | } 232 | 233 | void sleepRadio() { 234 | radio.sleep(); 235 | } 236 | 237 | } -------------------------------------------------------------------------------- /src/notification_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "notification_utils.h" 2 | #include "configuration.h" 3 | 4 | uint8_t channel = 0; 5 | uint8_t resolution = 8; 6 | uint8_t pauseDuration = 20; 7 | 8 | int startUpSound[] = {440, 880, 440, 1760}; 9 | uint8_t startUpSoundDuration[] = {100, 100, 100, 200}; 10 | 11 | int shutDownSound[] = {1720, 880, 400}; 12 | uint8_t shutDownSoundDuration[] = {60, 60, 200}; 13 | 14 | extern Configuration Config; 15 | extern bool digipeaterActive; 16 | 17 | namespace NOTIFICATION_Utils { 18 | 19 | void playTone(int frequency, uint8_t duration) { 20 | ledcSetup(channel, frequency, resolution); 21 | ledcAttachPin(Config.notification.buzzerPinTone, 0); 22 | ledcWrite(channel, 128); 23 | delay(duration); 24 | ledcWrite(channel, 0); 25 | delay(pauseDuration); 26 | } 27 | 28 | void beaconTxBeep() { 29 | digitalWrite(Config.notification.buzzerPinVcc, HIGH); 30 | playTone(1320,100); 31 | if (digipeaterActive) { 32 | playTone(1560,100); 33 | } 34 | digitalWrite(Config.notification.buzzerPinVcc, LOW); 35 | } 36 | 37 | void messageBeep() { 38 | digitalWrite(Config.notification.buzzerPinVcc, HIGH); 39 | playTone(1100,100); 40 | playTone(1100,100); 41 | digitalWrite(Config.notification.buzzerPinVcc, LOW); 42 | } 43 | 44 | void stationHeardBeep() { 45 | digitalWrite(Config.notification.buzzerPinVcc, HIGH); 46 | playTone(1200,100); 47 | playTone(600,100); 48 | digitalWrite(Config.notification.buzzerPinVcc, LOW); 49 | } 50 | 51 | void shutDownBeep() { 52 | digitalWrite(Config.notification.buzzerPinVcc, HIGH); 53 | for (int i = 0; i < sizeof(shutDownSound) / sizeof(shutDownSound[0]); i++) { 54 | playTone(shutDownSound[i], shutDownSoundDuration[i]); 55 | } 56 | digitalWrite(Config.notification.buzzerPinVcc, LOW); 57 | } 58 | 59 | void lowBatteryBeep() { 60 | digitalWrite(Config.notification.buzzerPinVcc, HIGH); 61 | playTone(1550,100); 62 | playTone(650,100); 63 | playTone(1550,100); 64 | playTone(650,100); 65 | digitalWrite(Config.notification.buzzerPinVcc, LOW); 66 | } 67 | 68 | void start() { 69 | digitalWrite(Config.notification.buzzerPinVcc, HIGH); 70 | for (int i = 0; i < sizeof(startUpSound) / sizeof(startUpSound[0]); i++) { 71 | playTone(startUpSound[i], startUpSoundDuration[i]); 72 | } 73 | digitalWrite(Config.notification.buzzerPinVcc, LOW); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/sleep_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "board_pinout.h" 2 | #include "sleep_utils.h" 3 | #include "power_utils.h" 4 | 5 | 6 | extern uint32_t lastGPSTime; 7 | extern bool gpsIsActive; 8 | 9 | bool gpsShouldSleep = false; 10 | 11 | 12 | namespace SLEEP_Utils { 13 | 14 | void gpsSleep() { 15 | #ifdef HAS_GPS_CTRL 16 | if (gpsIsActive) { 17 | POWER_Utils::deactivateGPS(); 18 | lastGPSTime = millis(); 19 | // 20 | Serial.println("GPS SLEEPING"); 21 | // 22 | } 23 | #endif 24 | } 25 | 26 | void gpsWakeUp() { 27 | #ifdef HAS_GPS_CTRL 28 | if (!gpsIsActive) { 29 | POWER_Utils::activateGPS(); 30 | gpsShouldSleep = false; 31 | // 32 | Serial.println("GPS WAKEUP"); 33 | // 34 | } 35 | #endif 36 | } 37 | 38 | void checkIfGPSShouldSleep() { 39 | if (gpsShouldSleep) { 40 | gpsSleep(); 41 | } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/smartbeacon_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "smartbeacon_utils.h" 2 | #include "configuration.h" 3 | #include "winlink_utils.h" 4 | 5 | extern Configuration Config; 6 | extern Beacon *currentBeacon; 7 | extern bool smartBeaconActive; 8 | extern uint32_t txInterval; 9 | extern uint32_t lastTxTime; 10 | extern bool sendUpdate; 11 | extern uint8_t winlinkStatus; 12 | 13 | 14 | SmartBeaconValues currentSmartBeaconValues; 15 | byte smartBeaconSettingsIndex = 10; 16 | bool wxRequestStatus = false; 17 | uint32_t wxRequestTime = 0; 18 | 19 | 20 | SmartBeaconValues smartBeaconSettings[3] = { 21 | {120, 3, 60, 15, 50, 20, 12, 60}, // Runner settings = SLOW 22 | {120, 5, 60, 40, 100, 12, 12, 60}, // Bike settings = MEDIUM 23 | {120, 10, 60, 70, 100, 12, 10, 80} // Car settings = FAST 24 | }; 25 | 26 | 27 | namespace SMARTBEACON_Utils { 28 | 29 | void checkSettings(byte index) { 30 | if (smartBeaconSettingsIndex != index) { 31 | currentSmartBeaconValues = smartBeaconSettings[index]; 32 | smartBeaconSettingsIndex = index; 33 | } 34 | } 35 | 36 | void checkInterval(int speed) { 37 | if (smartBeaconActive) { 38 | if (speed < currentSmartBeaconValues.slowSpeed) { 39 | txInterval = currentSmartBeaconValues.slowRate * 1000; 40 | } else if (speed > currentSmartBeaconValues.fastSpeed) { 41 | txInterval = currentSmartBeaconValues.fastRate * 1000; 42 | } else { 43 | txInterval = min(currentSmartBeaconValues.slowRate, currentSmartBeaconValues.fastSpeed * currentSmartBeaconValues.fastRate / speed) * 1000; 44 | } 45 | } 46 | } 47 | 48 | void checkFixedBeaconTime() { 49 | if (!smartBeaconActive) { 50 | uint32_t lastTxSmartBeacon = millis() - lastTxTime; 51 | if (lastTxSmartBeacon >= Config.nonSmartBeaconRate * 60 * 1000) sendUpdate = true; 52 | } 53 | } 54 | 55 | void checkState() { 56 | if (wxRequestStatus && (millis() - wxRequestTime) > 20000) wxRequestStatus = false; 57 | smartBeaconActive = (winlinkStatus == 0 && !wxRequestStatus) ? currentBeacon->smartBeaconActive : false; 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /src/touch_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "board_pinout.h" 2 | #include "button_utils.h" 3 | #include "touch_utils.h" 4 | 5 | #ifdef HAS_TOUCHSCREEN 6 | 7 | #define TOUCH_MODULES_GT911 8 | #include 9 | 10 | extern uint8_t touchModuleAddress; 11 | 12 | TouchLib touch(Wire, BOARD_I2C_SDA, BOARD_I2C_SCL, 0x00); 13 | 14 | void (*lastCalledAction)() = nullptr; // keep track of last calledAction from Touch 15 | 16 | extern bool sendUpdate; 17 | 18 | int16_t xCalibratedMin = 5; 19 | int16_t xCalibratedMax = 314; 20 | int16_t yCalibratedMin = 6; 21 | int16_t yCalibratedMax = 233; 22 | 23 | int16_t xValueMax = 320; 24 | int16_t yValueMax = 240; 25 | 26 | int touchDebounce = 300; 27 | uint32_t lastTouchTime = 0; 28 | 29 | int16_t xlastValue = 0; 30 | int16_t ylastValue = 0; 31 | 32 | extern int menuDisplay; 33 | 34 | 35 | namespace TOUCH_Utils { 36 | 37 | void sendBeaconFromTouch() { sendUpdate = true;} 38 | 39 | void enterMenuFromTouch() { BUTTON_Utils::doublePress();} 40 | 41 | void exitFromTouch() { 42 | menuDisplay = 0; 43 | //Serial.println("CANCEL BUTTON PRESSED"); 44 | } 45 | 46 | TouchButton touchButtons_0[] = { 47 | {30, 110, 0, 28, "Send", 1, sendBeaconFromTouch}, // Button Send //drawButton(30, 210, 80, 28, "Send", 1); 48 | {125, 205, 0, 28, "Menu", 0, enterMenuFromTouch}, // Button Menu //drawButton(125, 210, 80, 28, "Menu", 0); 49 | {210, 305, 0, 28, "Exit", 2, exitFromTouch} // Button Exit //drawButton(210, 210, 95, 28, "Exit", 2); 50 | }; 51 | 52 | 53 | bool touchButtonPressed(int touchX, int touchY, int Xmin, int Xmax, int Ymin, int Ymax) { 54 | return (touchX >= (Xmin - 5) && touchX <= (Xmax + 5) && touchY >= (Ymin - 5) && touchY <= (Ymax + 5)); 55 | } 56 | 57 | void checkLiveButtons(uint16_t x, uint16_t y) { 58 | for (int i = 0; i < sizeof(touchButtons_0) / sizeof(touchButtons_0[0]); i++) { 59 | if (touchButtonPressed(x, y, touchButtons_0[i].Xmin, touchButtons_0[i].Xmax, touchButtons_0[i].Ymin, touchButtons_0[i].Ymax)) { 60 | 61 | if (touchButtons_0[i].action != nullptr && touchButtons_0[i].action != lastCalledAction) { // Call the action function associated with the button 62 | Serial.println(touchButtons_0[i].label + " pressed"); 63 | touchButtons_0[i].action(); // Call the function pointer 64 | lastCalledAction = touchButtons_0[i].action; // Update the last called action 65 | } else { 66 | Serial.println("No action assigned to this button!"); 67 | } 68 | } 69 | } 70 | } 71 | 72 | void loop() { 73 | if (touch.read() && (millis() - lastTouchTime > touchDebounce)) { 74 | TP_Point touchPoint = touch.getPoint(0); 75 | uint16_t xValueTouched = map(touchPoint.y, xCalibratedMin, xCalibratedMax, 0, xValueMax); // x and y values are inverted because 76 | uint16_t yValueTouched = map(touchPoint.x, yCalibratedMin, yCalibratedMax, 0, yValueMax); // TFT screen is rotated!!!! 77 | lastTouchTime = millis(); 78 | //Serial.print(" X="); Serial.print(xValueTouched); Serial.print(" Y="); Serial.println(yValueTouched); 79 | checkLiveButtons(xValueTouched, yValueTouched); 80 | } 81 | if (millis() - lastTouchTime > 1000) lastCalledAction = nullptr; // reset touchButton when staying in same menu (like Tx/Send) 82 | } 83 | 84 | void setup() { 85 | if (touchModuleAddress != 0x00) { 86 | if (touchModuleAddress == 0x14) { 87 | touch = TouchLib(Wire, BOARD_I2C_SDA, BOARD_I2C_SCL, GT911_SLAVE_ADDRESS2); 88 | touch.init(); 89 | } else if (touchModuleAddress == 0x5d) { 90 | touch = TouchLib(Wire, BOARD_I2C_SDA, BOARD_I2C_SCL, GT911_SLAVE_ADDRESS1); 91 | touch.init(); 92 | } else { 93 | Serial.println("No Touch Module Address found"); 94 | } 95 | } 96 | } 97 | 98 | } 99 | 100 | #endif -------------------------------------------------------------------------------- /src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "configuration.h" 5 | #include "board_pinout.h" 6 | #include "lora_utils.h" 7 | #include "display.h" 8 | #include "utils.h" 9 | 10 | extern Beacon *currentBeacon; 11 | extern Configuration Config; 12 | extern logging::Logger logger; 13 | 14 | extern uint32_t lastTx; 15 | extern uint32_t lastTxTime; 16 | 17 | extern bool displayEcoMode; 18 | extern uint32_t displayTime; 19 | extern bool displayState; 20 | extern int menuDisplay; 21 | extern String versionDate; 22 | extern bool flashlight; 23 | 24 | extern bool statusState; 25 | 26 | uint32_t statusTime = millis(); 27 | uint8_t wxModuleAddress = 0x00; 28 | uint8_t keyboardAddress = 0x00; 29 | uint8_t touchModuleAddress = 0x00; 30 | 31 | 32 | namespace Utils { 33 | 34 | static char locator[11]; // letterize and getMaidenheadLocator functions are Copyright (c) 2021 Mateusz Salwach - MIT License 35 | 36 | static char letterize(int x) { 37 | return (char) x + 65; 38 | } 39 | 40 | char *getMaidenheadLocator(double lat, double lon, uint8_t size) { 41 | double LON_F[]={20,2.0,0.083333,0.008333,0.0003472083333333333}; 42 | double LAT_F[]={10,1.0,0.0416665,0.004166,0.0001735833333333333}; 43 | int i; 44 | lon += 180; 45 | lat += 90; 46 | 47 | if (size <= 0 || size > 10) size = 6; 48 | size/=2; size*=2; 49 | 50 | for (i = 0; i < size/2; i++) { 51 | if (i % 2 == 1) { 52 | locator[i*2] = (char) (lon/LON_F[i] + '0'); 53 | locator[i*2+1] = (char) (lat/LAT_F[i] + '0'); 54 | } else { 55 | locator[i*2] = letterize((int) (lon/LON_F[i])); 56 | locator[i*2+1] = letterize((int) (lat/LAT_F[i])); 57 | } 58 | lon = fmod(lon, LON_F[i]); 59 | lat = fmod(lat, LAT_F[i]); 60 | } 61 | locator[i*2]=0; 62 | return locator; 63 | } 64 | 65 | static String padding(unsigned int number, unsigned int width) { 66 | String result; 67 | String num(number); 68 | if (num.length() > width) width = num.length(); 69 | for (unsigned int i = 0; i < width - num.length(); i++) { 70 | result.concat('0'); 71 | } 72 | result.concat(num); 73 | return result; 74 | } 75 | 76 | String createDateString(time_t t) { 77 | String dateString = padding(year(t), 4); 78 | dateString += "-"; 79 | dateString += padding(month(t), 2); 80 | dateString += "-"; 81 | dateString += padding(day(t), 2); 82 | return dateString; 83 | } 84 | 85 | String createTimeString(time_t t) { 86 | String timeString = padding(hour(t), 2); 87 | timeString += ":"; 88 | timeString += padding(minute(t), 2); 89 | timeString += ":"; 90 | timeString += padding(second(t), 2); 91 | return timeString; 92 | } 93 | 94 | void checkStatus() { 95 | if (statusState) { 96 | uint32_t currentTime = millis(); 97 | uint32_t statusTx = currentTime - statusTime; 98 | lastTx = currentTime - lastTxTime; 99 | if (statusTx > 10 * 60 * 1000 && lastTx > 10 * 1000) { 100 | LoRa_Utils::sendNewPacket(APRSPacketLib::generateStatusPacket(currentBeacon->callsign, "APLRT1", Config.path, "https://github.com/richonguzman/LoRa_APRS_Tracker " + versionDate)); 101 | statusState = false; 102 | } 103 | } 104 | } 105 | 106 | void checkDisplayEcoMode() { 107 | if (displayState && displayEcoMode && menuDisplay == 0) { 108 | uint32_t currentTime = millis(); 109 | uint32_t lastDisplayTime = currentTime - displayTime; 110 | if (currentTime > 10 * 1000 && lastDisplayTime >= Config.display.timeout * 1000) { 111 | displayToggle(false); 112 | displayState = false; 113 | } 114 | } 115 | } 116 | 117 | String getSmartBeaconState() { 118 | if (currentBeacon->smartBeaconActive) return "On"; 119 | return "Off"; 120 | } 121 | 122 | void checkFlashlight() { 123 | if (flashlight && !digitalRead(Config.notification.ledFlashlightPin)) { 124 | digitalWrite(Config.notification.ledFlashlightPin, HIGH); 125 | } else if (!flashlight && digitalRead(Config.notification.ledFlashlightPin)) { 126 | digitalWrite(Config.notification.ledFlashlightPin, LOW); 127 | } 128 | } 129 | 130 | void i2cScannerForPeripherals() { 131 | uint8_t err, addr; 132 | if (Config.wxsensor.active) { 133 | for (addr = 1; addr < 0x7F; addr++) { 134 | #if defined(HELTEC_V3_GPS) || defined(HELTEC_V3_2_GPS) 135 | Wire1.beginTransmission(addr); 136 | err = Wire1.endTransmission(); 137 | #else 138 | Wire.beginTransmission(addr); 139 | err = Wire.endTransmission(); 140 | #endif 141 | if (err == 0) { 142 | //Serial.println(addr); this shows any connected board to I2C 143 | if (addr == 0x76 || addr == 0x77) { 144 | wxModuleAddress = addr; 145 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Wx Module Connected to I2C"); 146 | } 147 | } 148 | } 149 | } 150 | 151 | for (addr = 1; addr < 0x7F; addr++) { 152 | Wire.beginTransmission(addr); 153 | err = Wire.endTransmission(); 154 | if (err == 0) { 155 | //Serial.println(addr); this shows any connected board to I2C 156 | if (addr == 0x55) { // T-Deck internal keyboard (Keyboard Backlight On = ALT + B) 157 | keyboardAddress = addr; 158 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "T-Deck Keyboard Connected to I2C"); 159 | } else if (addr == 0x5F) { // CARDKB from m5stack.com (YEL - SDA / WTH SCL) 160 | keyboardAddress = addr; 161 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "CARDKB Keyboard Connected to I2C"); 162 | } 163 | } 164 | } 165 | 166 | #ifdef HAS_TOUCHSCREEN 167 | for (addr = 1; addr < 0x7F; addr++) { 168 | Wire.beginTransmission(addr); 169 | err = Wire.endTransmission(); 170 | if (err == 0) { 171 | if (addr == 0x14 || addr == 0x5D ) { 172 | touchModuleAddress = addr; 173 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Touch Module Connected to I2C"); 174 | } 175 | } 176 | } 177 | #endif 178 | } 179 | 180 | } -------------------------------------------------------------------------------- /src/wifi_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "configuration.h" 4 | #include "web_utils.h" 5 | #include "display.h" 6 | 7 | 8 | extern Configuration Config; 9 | extern logging::Logger logger; 10 | 11 | uint32_t noClientsTime = 0; 12 | 13 | 14 | namespace WIFI_Utils { 15 | 16 | void startAutoAP() { 17 | WiFi.mode(WIFI_MODE_NULL); 18 | WiFi.mode(WIFI_AP); 19 | WiFi.softAP("LoRaTracker-AP", Config.wifiAP.password); 20 | } 21 | 22 | void checkIfWiFiAP() { 23 | if (Config.wifiAP.active || Config.beacons[0].callsign == "NOCALL-7"){ 24 | displayShow(" LoRa APRS", " ** WEB-CONF **","", "WiFiAP:LoRaTracker-AP", "IP : 192.168.4.1",""); 25 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Main", "WebConfiguration Started!"); 26 | startAutoAP(); 27 | WEB_Utils::setup(); 28 | while (true) { 29 | if (WiFi.softAPgetStationNum() > 0) { 30 | noClientsTime = 0; 31 | } else { 32 | if (noClientsTime == 0) { 33 | noClientsTime = millis(); 34 | } else if ((millis() - noClientsTime) > 2 * 60 * 1000) { 35 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Main", "WebConfiguration Stopped!"); 36 | displayShow("", "", " STOPPING WiFi AP", 2000); 37 | Config.wifiAP.active = false; 38 | Config.writeFile(); 39 | WiFi.softAPdisconnect(true); 40 | ESP.restart(); 41 | } 42 | } 43 | } 44 | } else { 45 | WiFi.mode(WIFI_OFF); 46 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Main", "WiFi controller stopped"); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/winlink_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "winlink_utils.h" 2 | #include "configuration.h" 3 | #include "msg_utils.h" 4 | #include "display.h" 5 | #include "logger.h" 6 | 7 | 8 | extern Configuration Config; 9 | extern int menuDisplay; 10 | extern logging::Logger logger; 11 | 12 | uint8_t winlinkStatus = 0; 13 | String winlinkMailNumber = "_?"; 14 | String winlinkAddressee = ""; 15 | String winlinkSubject = ""; 16 | String winlinkBody = ""; 17 | String winlinkAlias = ""; 18 | String winlinkAliasComplete = ""; 19 | bool winlinkCommentState = false; 20 | 21 | uint32_t lastChallengeTime = 0; 22 | String challengeAnswer; 23 | 24 | 25 | 26 | namespace WINLINK_Utils { 27 | 28 | void processWinlinkChallenge(const String& winlinkInteger) { 29 | uint32_t currenTime = millis(); 30 | if (lastChallengeTime == 0 || (currenTime - lastChallengeTime) > 10 * 60 * 10000) { 31 | challengeAnswer = ""; 32 | for (char c : winlinkInteger) { 33 | int digit = c - '0'; // Convert '0'-'9' to 0-9 34 | if (digit < 1 || digit > Config.winlink.password.length()) { // Ensure valid range 35 | displayShow(" WINLINK", "", "PASS Length Start Login"); 51 | displayShow(" WINLINK", "" , "Login Initiation ...", "", "" , " 2 | #include 3 | #ifdef LIGHTTRACKER_PLUS_1_0 4 | #include "Adafruit_SHTC3.h" 5 | #endif 6 | #include "wx_utils.h" 7 | #include "configuration.h" 8 | #include "display.h" 9 | 10 | #define SEALEVELPRESSURE_HPA (1013.25) 11 | #define CORRECTION_FACTOR (8.2296) // for meters 12 | 13 | extern Configuration Config; 14 | extern logging::Logger logger; 15 | extern TinyGPSPlus gps; 16 | 17 | extern uint8_t wxModuleAddress; 18 | 19 | float newHum, newTemp, newPress, newGas; 20 | 21 | uint32_t sensorLastReading = -60000; 22 | int wxModuleType = 0; 23 | 24 | bool wxModuleFound = false; 25 | 26 | 27 | Adafruit_BME280 bme280; 28 | #if defined(HELTEC_V3_GPS) || defined(HELTEC_V3_TNC) || defined(HELTEC_V3_2_GPS) || defined(HELTEC_V3_2_TNC) 29 | Adafruit_BMP280 bmp280(&Wire1); 30 | #else 31 | Adafruit_BMP280 bmp280; 32 | Adafruit_BME680 bme680; 33 | #endif 34 | #ifdef LIGHTTRACKER_PLUS_1_0 35 | Adafruit_SHTC3 shtc3 = Adafruit_SHTC3(); 36 | #endif 37 | 38 | 39 | 40 | namespace WX_Utils { 41 | 42 | void setup() { 43 | if (Config.wxsensor.active) { 44 | #ifdef LIGHTTRACKER_PLUS_1_0 45 | if (!shtc3.begin()) { 46 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " SHTC3 sensor not found"); 47 | while (1) delay(1); 48 | } 49 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " SHTC3 sensor found"); 50 | wxModuleFound = true; 51 | wxModuleType = 4; 52 | #else 53 | if (wxModuleAddress != 0x00) { 54 | #if defined(HELTEC_V3_GPS) || defined(HELTEC_V3_TNC) || defined(HELTEC_V3_2_GPS) || defined(HELTEC_V3_2_TNC) 55 | if (bme280.begin(wxModuleAddress, &Wire1)) { 56 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " BME280 sensor found"); 57 | wxModuleType = 1; 58 | wxModuleFound = true; 59 | } 60 | #else 61 | if (bme280.begin(wxModuleAddress)) { 62 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " BME280 sensor found"); 63 | wxModuleType = 1; 64 | wxModuleFound = true; 65 | } 66 | if (!wxModuleFound) { 67 | if (bme680.begin(wxModuleAddress)) { 68 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " BME680 sensor found"); 69 | wxModuleType = 3; 70 | wxModuleFound = true; 71 | } 72 | } 73 | #endif 74 | if (!wxModuleFound) { 75 | if (bmp280.begin(wxModuleAddress)) { 76 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " BMP280 sensor found"); 77 | wxModuleType = 2; 78 | wxModuleFound = true; 79 | } 80 | } 81 | if (!wxModuleFound) { 82 | displayShow("ERROR", "BME/BMP sensor active", "but no sensor found...", 2000); 83 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "BME", " BME/BMP sensor Active in config but not found! Check Wiring"); 84 | } else { 85 | switch (wxModuleType) { 86 | case 1: 87 | bme280.setSampling(Adafruit_BME280::MODE_FORCED, 88 | Adafruit_BME280::SAMPLING_X1, 89 | Adafruit_BME280::SAMPLING_X1, 90 | Adafruit_BME280::SAMPLING_X1, 91 | Adafruit_BME280::FILTER_OFF 92 | ); 93 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " BME280 Module init done!"); 94 | break; 95 | case 2: 96 | bmp280.setSampling(Adafruit_BMP280::MODE_FORCED, 97 | Adafruit_BMP280::SAMPLING_X1, 98 | Adafruit_BMP280::SAMPLING_X1, 99 | Adafruit_BMP280::FILTER_OFF 100 | ); 101 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BMP", " BMP280 Module init done!"); 102 | break; 103 | case 3: 104 | #if !defined(HELTEC_V3_GPS) && !defined(HELTEC_V3_TNC) && !defined(HELTEC_V3_2_GPS) && !defined(HELTEC_V3_2_TNC) 105 | bme680.setTemperatureOversampling(BME680_OS_1X); 106 | bme680.setHumidityOversampling(BME680_OS_1X); 107 | bme680.setPressureOversampling(BME680_OS_1X); 108 | bme680.setIIRFilterSize(BME680_FILTER_SIZE_0); 109 | logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BME", " BMP680 Module init done!"); 110 | #endif 111 | break; 112 | } 113 | } 114 | } 115 | #endif 116 | } 117 | } 118 | 119 | const String generateTempString(const float sensorTemp, const uint8_t type) { 120 | String strTemp; 121 | if (type == 1) { // OLED 122 | strTemp = String((int)sensorTemp); 123 | } else { 124 | strTemp = String((int)((sensorTemp * 1.8) + 32)); 125 | } 126 | switch (strTemp.length()) { 127 | case 1: 128 | if (type == 1) { 129 | return " " + strTemp; 130 | } else { 131 | return "00" + strTemp; 132 | } 133 | case 2: 134 | if (type == 1) { 135 | return " " + strTemp; 136 | } else { 137 | return "0" + strTemp; 138 | } 139 | case 3: 140 | return strTemp; 141 | default: 142 | return "-999"; 143 | } 144 | } 145 | 146 | const String generateHumString(const float sensorHum, const uint8_t type) { 147 | String strHum = String((int)sensorHum); 148 | switch (strHum.length()) { 149 | case 1: 150 | if (type == 1) { 151 | return " " + strHum; 152 | } else { 153 | return "0" + strHum; 154 | } 155 | case 2: 156 | return strHum; 157 | case 3: 158 | if ((int)sensorHum == 100) { 159 | if (type == 1) { 160 | return " "; 161 | } else { 162 | return "00"; 163 | } 164 | } else { 165 | return "-99"; 166 | } 167 | default: 168 | return "-99"; 169 | } 170 | } 171 | 172 | const String generatePresString(const float sensorPress, const uint8_t type) { 173 | String strPress = String((int)sensorPress); 174 | String decPress = String(int((sensorPress - int(sensorPress)) * 10)); 175 | switch (strPress.length()) { 176 | case 1: 177 | if (type == 1) { 178 | return "000" + strPress; 179 | } else { 180 | return "000" + strPress + decPress; 181 | } 182 | case 2: 183 | if (type == 1) { 184 | return "00" + strPress; 185 | } else { 186 | return "00" + strPress + decPress; 187 | } 188 | case 3: 189 | if (type == 1) { 190 | return "0" + strPress; 191 | } else { 192 | return "0" + strPress + decPress; 193 | } 194 | case 4: 195 | if (type == 1) { 196 | return strPress; 197 | } else { 198 | return strPress + decPress; 199 | } 200 | case 5: 201 | return strPress; 202 | default: 203 | return "-99999"; 204 | } 205 | } 206 | 207 | const String readDataSensor(const uint8_t type) { 208 | uint32_t lastReading = millis() - sensorLastReading; 209 | if (lastReading > 60 * 1000) { 210 | #ifdef LIGHTTRACKER_PLUS_1_0 211 | sensors_event_t humidity, temp; 212 | shtc3.getEvent(&humidity, &temp); 213 | newTemp = temp.temperature; 214 | newHum = humidity.relative_humidity; 215 | newPress = 0; 216 | #else 217 | switch (wxModuleType) { 218 | case 1: // BME280 219 | bme280.takeForcedMeasurement(); 220 | newTemp = bme280.readTemperature(); 221 | newPress = (bme280.readPressure() / 100.0F); 222 | newHum = bme280.readHumidity(); 223 | break; 224 | case 2: // BMP280 225 | bmp280.takeForcedMeasurement(); 226 | newTemp = bmp280.readTemperature(); 227 | newPress = (bmp280.readPressure() / 100.0F); 228 | newHum = 0; 229 | break; 230 | case 3: // BME680 231 | #if !defined(HELTEC_V3_GPS) && !defined(HELTEC_V3_TNC) && !defined(HELTEC_V3_2_GPS) && !defined(HELTEC_V3_2_TNC) 232 | bme680.performReading(); 233 | delay(50); 234 | if (bme680.endReading()) { 235 | newTemp = bme680.temperature; 236 | newPress = (bme680.pressure / 100.0F); 237 | newHum = bme680.humidity; 238 | newGas = bme680.gas_resistance / 1000.0; // in Kilo ohms 239 | } 240 | #endif 241 | break; 242 | } 243 | #endif 244 | sensorLastReading = millis(); 245 | } 246 | 247 | String wx; 248 | if (isnan(newTemp) || isnan(newHum) || isnan(newPress)) { 249 | Serial.println("WX Sensor data failed"); 250 | wx = ((type == 1) ? " - C - % - hPa" : ".../...g...t..."); 251 | return wx; 252 | } else { 253 | String tempStr = generateTempString(newTemp + Config.wxsensor.temperatureCorrection, type); 254 | String humStr; 255 | #ifdef LIGHTTRACKER_PLUS_1_0 256 | humStr = generateHumString(newHum,type); 257 | #else 258 | if (wxModuleType == 1 || wxModuleType == 3) { 259 | humStr = generateHumString(newHum,type); 260 | } else if (wxModuleType == 2) { 261 | humStr = ".."; 262 | } 263 | #endif 264 | String presStr = generatePresString(newPress + (gps.altitude.meters()/CORRECTION_FACTOR), type); 265 | #ifdef LIGHTTRACKER_PLUS_1_0 266 | if (type == 1) { 267 | wx = tempStr; 268 | wx += "C "; 269 | wx += humStr; 270 | wx += "% "; 271 | } else { 272 | wx = ".../...g...t"; 273 | wx += tempStr; 274 | wx += "h"; 275 | wx += humStr; 276 | } 277 | #else 278 | if (type == 1) { 279 | if (wxModuleType == 1 || wxModuleType == 3) { 280 | wx = tempStr; 281 | wx += "C "; 282 | wx += humStr; 283 | wx += "% "; 284 | wx += presStr; 285 | wx += "hPa"; 286 | } else if (wxModuleType == 2) { 287 | wx = "T: "; 288 | wx += tempStr; 289 | wx += "C P: "; 290 | wx += presStr; 291 | wx += "hPa"; 292 | } 293 | } else { 294 | wx = ".../...g...t"; 295 | wx += tempStr; 296 | wx += "h"; 297 | wx += humStr; 298 | wx += "b"; 299 | wx += presStr; 300 | if (wxModuleType == 3) { 301 | wx += "Gas: "; 302 | wx += String(newGas); 303 | wx += "Kohms"; 304 | } 305 | } 306 | #endif 307 | return wx; 308 | } 309 | } 310 | 311 | } -------------------------------------------------------------------------------- /tools/compress.py: -------------------------------------------------------------------------------- 1 | import gzip 2 | import os 3 | import datetime 4 | Import("env") 5 | 6 | files = [ 7 | 'data_embed/index.html', 8 | 'data_embed/script.js', 9 | 'data_embed/style.css', 10 | 'data_embed/bootstrap.js', 11 | 'data_embed/bootstrap.css', 12 | 'data_embed/favicon.png', 13 | ] 14 | 15 | string_to_find_str = "String" 16 | string_to_find_ver = "versionDate" 17 | 18 | with open('src/LoRa_APRS_Tracker.cpp', encoding='utf-8') as cpp_file: 19 | for line in cpp_file: 20 | if string_to_find_str in line and string_to_find_ver in line: 21 | start = line.find('"') + 1 22 | end = line.find('"', start) 23 | if start > 0 and end > start: 24 | versionDate = line[start:end] 25 | break 26 | 27 | for src in files: 28 | out = src + ".gz" 29 | 30 | 31 | with open(src, 'rb') as f: 32 | content = f.read() 33 | 34 | if src == 'data_embed/index.html': 35 | env_vars = env["BOARD"] + "
" + ','.join(env["BUILD_FLAGS"]).replace('-Werror -Wall,', '').replace(',-DELEGANTOTA_USE_ASYNC_WEBSERVER=1', '') + "
" + "Version date: " + versionDate 36 | current_date = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') + " UTC" 37 | build_info = f'{env_vars}
Build date: {current_date}'.encode() 38 | 39 | content = content.replace(b'%BUILD_INFO%', build_info) 40 | 41 | with open(out, 'wb') as f: 42 | f.write(gzip.compress(content, compresslevel=9)) -------------------------------------------------------------------------------- /variants/ESP32S3_DIY_LoRa_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define GPS_RX 12 24 | #define GPS_TX 34 25 | 26 | // OTHER 27 | #define BUTTON_PIN 15 28 | #define BATTERY_PIN 35 //LoRa32 Battery PIN 100k/100k 29 | 30 | #endif -------------------------------------------------------------------------------- /variants/ESP32S3_DIY_LoRa_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ESP32S3_DIY_LoRa_GPS] 2 | extends = env:esp32 3 | board = esp32-s3-devkitc-1 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D ESP32S3_DIY_LoRa_GPS 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} 12 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ESP32S3_DIY_LoRa_GPS_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1276 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define GPS_RX 12 24 | #define GPS_TX 34 25 | 26 | // OTHER 27 | #define BUTTON_PIN 15 28 | #define BATTERY_PIN 35 //LoRa32 Battery PIN 100k/100k 29 | 30 | #endif -------------------------------------------------------------------------------- /variants/ESP32S3_DIY_LoRa_GPS_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ESP32S3_DIY_LoRa_GPS_915] 2 | extends = env:esp32 3 | board = esp32-s3-devkitc-1 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D ESP32S3_DIY_LoRa_GPS_915 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} 12 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ESP32_DIY_1W_LoRa_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1268 6 | #define HAS_1W_LORA 7 | #define RADIO_SCLK_PIN 18 8 | #define RADIO_MISO_PIN 19 9 | #define RADIO_MOSI_PIN 23 10 | #define RADIO_CS_PIN 5 11 | #define RADIO_RST_PIN 27 12 | #define RADIO_DIO1_PIN 12 13 | #define RADIO_BUSY_PIN 14 14 | #define RADIO_RXEN 32 15 | #define RADIO_TXEN 25 16 | 17 | // Display 18 | #undef OLED_SDA 19 | #undef OLED_SCL 20 | #undef OLED_RST 21 | 22 | #define OLED_SDA 21 23 | #define OLED_SCL 22 24 | #define OLED_RST -1 25 | 26 | // GPS 27 | #define GPS_RX 17 28 | #define GPS_TX 16 29 | 30 | // OTHER 31 | #define BUTTON_PIN 15 32 | #define BATTERY_PIN 35 33 | 34 | #define HAS_BT_CLASSIC 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/ESP32_DIY_1W_LoRa_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ESP32_DIY_1W_LoRa_GPS] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D ESP32_DIY_1W_LoRa_GPS 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ESP32_DIY_1W_LoRa_GPS_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define HAS_1W_LORA 7 | #define RADIO_SCLK_PIN 18 8 | #define RADIO_MISO_PIN 19 9 | #define RADIO_MOSI_PIN 23 10 | #define RADIO_CS_PIN 5 11 | #define RADIO_RST_PIN 27 12 | #define RADIO_DIO1_PIN 12 13 | #define RADIO_BUSY_PIN 14 14 | #define RADIO_RXEN 32 15 | #define RADIO_TXEN 25 16 | 17 | // Display 18 | #undef OLED_SDA 19 | #undef OLED_SCL 20 | #undef OLED_RST 21 | 22 | #define OLED_SDA 21 23 | #define OLED_SCL 22 24 | #define OLED_RST -1 25 | 26 | // GPS 27 | #define GPS_RX 17 28 | #define GPS_TX 16 29 | 30 | // OTHER 31 | #define BUTTON_PIN 15 32 | #define BATTERY_PIN 35 33 | 34 | #define HAS_BT_CLASSIC 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/ESP32_DIY_1W_LoRa_GPS_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ESP32_DIY_1W_LoRa_GPS_915] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D ESP32_DIY_1W_LoRa_GPS_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ESP32_DIY_1W_LoRa_GPS_LLCC68/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_LLCC68 6 | #define HAS_1W_LORA 7 | #define RADIO_SCLK_PIN 18 8 | #define RADIO_MISO_PIN 19 9 | #define RADIO_MOSI_PIN 23 10 | #define RADIO_CS_PIN 5 11 | #define RADIO_RST_PIN 27 12 | #define RADIO_DIO1_PIN 12 13 | #define RADIO_BUSY_PIN 14 14 | #define RADIO_RXEN 32 15 | #define RADIO_TXEN 25 16 | 17 | // Display 18 | #undef OLED_SDA 19 | #undef OLED_SCL 20 | #undef OLED_RST 21 | 22 | #define OLED_SDA 21 23 | #define OLED_SCL 22 24 | #define OLED_RST -1 25 | 26 | // GPS 27 | #define GPS_RX 17 28 | #define GPS_TX 16 29 | 30 | // OTHER 31 | #define BUTTON_PIN 15 32 | #define BATTERY_PIN 35 33 | 34 | #define HAS_BT_CLASSIC 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/ESP32_DIY_1W_LoRa_GPS_LLCC68/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ESP32_DIY_1W_LoRa_GPS_LLCC68] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D ESP32_DIY_1W_LoRa_GPS_LLCC68 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ESP32_DIY_LoRa_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define GPS_RX 12 24 | #define GPS_TX 34 25 | 26 | // OTHER 27 | #define BUTTON_PIN 15 28 | #define BATTERY_PIN 35 //LoRa32 Battery PIN 100k/100k 29 | 30 | #define HAS_BT_CLASSIC 31 | 32 | #endif -------------------------------------------------------------------------------- /variants/ESP32_DIY_LoRa_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ESP32_DIY_LoRa_GPS] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D ESP32_DIY_LoRa_GPS 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ESP32_DIY_LoRa_GPS_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define GPS_RX 12 24 | #define GPS_TX 34 25 | 26 | // OTHER 27 | #define BUTTON_PIN 15 28 | #define BATTERY_PIN 35 //LoRa32 Battery PIN 100k/100k 29 | 30 | #define HAS_BT_CLASSIC 31 | 32 | #endif -------------------------------------------------------------------------------- /variants/ESP32_DIY_LoRa_GPS_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ESP32_DIY_LoRa_GPS_915] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D ESP32_DIY_LoRa_GPS_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/F4GOH_1W_LoRa_Tracker/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1268 6 | #define HAS_1W_LORA 7 | #define RADIO_SCLK_PIN 5 8 | #define RADIO_MISO_PIN 19 9 | #define RADIO_MOSI_PIN 27 10 | #define RADIO_CS_PIN 18 11 | #define RADIO_RST_PIN 23 12 | #define RADIO_DIO1_PIN 33 13 | #define RADIO_BUSY_PIN 32 14 | #define RADIO_RXEN 14 15 | #define RADIO_TXEN 13 16 | 17 | // Display 18 | #undef OLED_SDA 19 | #undef OLED_SCL 20 | #undef OLED_RST 21 | 22 | #define OLED_SDA 21 23 | #define OLED_SCL 22 24 | #define OLED_RST -1 25 | 26 | // GPS 27 | #define GPS_RX 17 28 | #define GPS_TX 16 29 | #define GPS_VCC 4 30 | 31 | // OTHER 32 | #define BUTTON_PIN 12 33 | #define BATTERY_PIN 35 34 | 35 | #define HAS_BT_CLASSIC 36 | 37 | #endif -------------------------------------------------------------------------------- /variants/F4GOH_1W_LoRa_Tracker/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:F4GOH_1W_LoRa_Tracker] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D F4GOH_1W_LoRa_Tracker 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/F4GOH_1W_LoRa_Tracker_LLCC68/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_LLCC68 6 | #define HAS_1W_LORA 7 | #define RADIO_SCLK_PIN 5 8 | #define RADIO_MISO_PIN 19 9 | #define RADIO_MOSI_PIN 27 10 | #define RADIO_CS_PIN 18 11 | #define RADIO_RST_PIN 23 12 | #define RADIO_DIO1_PIN 33 13 | #define RADIO_BUSY_PIN 32 14 | #define RADIO_RXEN 14 15 | #define RADIO_TXEN 13 16 | 17 | // Display 18 | #undef OLED_SDA 19 | #undef OLED_SCL 20 | #undef OLED_RST 21 | 22 | #define OLED_SDA 21 23 | #define OLED_SCL 22 24 | #define OLED_RST -1 25 | 26 | // GPS 27 | #define GPS_RX 17 28 | #define GPS_TX 16 29 | #define GPS_VCC 4 30 | 31 | // OTHER 32 | #define BUTTON_PIN 12 33 | #define BATTERY_PIN 35 34 | 35 | #define HAS_BT_CLASSIC 36 | 37 | #endif -------------------------------------------------------------------------------- /variants/F4GOH_1W_LoRa_Tracker_LLCC68/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:F4GOH_1W_LoRa_Tracker_LLCC68] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D F4GOH_1W_LoRa_Tracker_LLCC68 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/OE5HWN_MeshCom/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1268 6 | #define HAS_1W_LORA 7 | #define RADIO_SCLK_PIN 18 8 | #define RADIO_MISO_PIN 19 9 | #define RADIO_MOSI_PIN 23 10 | #define RADIO_CS_PIN 5 11 | #define RADIO_RST_PIN 27 12 | #define RADIO_DIO1_PIN 33 13 | #define RADIO_BUSY_PIN 26 14 | #define RADIO_RXEN 14 15 | #define RADIO_TXEN 13 16 | 17 | // Display 18 | #undef OLED_SDA 19 | #undef OLED_SCL 20 | #undef OLED_RST 21 | 22 | #define OLED_SDA 21 23 | #define OLED_SCL 22 24 | #define OLED_RST -1 25 | 26 | // GPS 27 | #define GPS_RX 17 28 | #define GPS_TX 16 29 | 30 | // OTHER 31 | #define BUTTON_PIN 12 32 | #define BATTERY_PIN 35 33 | 34 | #define HAS_BT_CLASSIC 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/OE5HWN_MeshCom/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:OE5HWN_MeshCom] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D OE5HWN_MeshCom 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/QRPLabs_LightTracker_Plus_1_0/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1268 6 | #define HAS_1W_LORA 7 | #define RADIO_VCC_PIN 21 8 | #define RADIO_SCLK_PIN 12 9 | #define RADIO_MISO_PIN 13 10 | #define RADIO_MOSI_PIN 11 11 | #define RADIO_CS_PIN 10 12 | #define RADIO_RST_PIN 9 13 | #define RADIO_DIO1_PIN 5 14 | #define RADIO_BUSY_PIN 6 15 | #define RADIO_RXEN 42 16 | #define RADIO_TXEN 14 17 | 18 | // Display 19 | #undef OLED_SDA 20 | #undef OLED_SCL 21 | #undef OLED_RST 22 | 23 | #define OLED_SDA 3 24 | #define OLED_SCL 4 25 | #define OLED_RST -1 26 | 27 | // GPS 28 | #define GPS_RX 17 29 | #define GPS_TX 18 30 | #define GPS_VCC 33 //#define LED_PIN 16 31 | 32 | // OTHER 33 | #define BUTTON_PIN 0 34 | #define BATTERY_PIN 1 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/QRPLabs_LightTracker_Plus_1_0/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:QRPLabs_LightTracker_Plus_1_0] 2 | extends = env:esp32 3 | board = esp32-s3-devkitc-1 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D LIGHTTRACKER_PLUS_1_0 9 | lib_deps = 10 | ${common.lib_deps} 11 | adafruit/Adafruit SHTC3 Library @ 1.0.1 -------------------------------------------------------------------------------- /variants/TROY_LoRa_APRS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST -1 21 | 22 | // GPS 23 | #define GPS_RX 12 24 | #define GPS_TX 34 25 | 26 | // OTHER 27 | #define BUTTON_PIN 4 28 | 29 | #define HAS_BT_CLASSIC 30 | 31 | #endif -------------------------------------------------------------------------------- /variants/TROY_LoRa_APRS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:TROY_LoRa_APRS] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D TROY_LoRa_APRS 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/Wemos_ESP32_Bat_LoRa_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 18 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 23 9 | #define RADIO_CS_PIN 5 10 | #define RADIO_RST_PIN 27 11 | #define RADIO_DIO1_PIN 12 12 | #define RADIO_BUSY_PIN 14 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define OLED_SDA 21 20 | #define OLED_SCL 22 21 | #define OLED_RST -1 22 | 23 | // GPS 24 | #define GPS_RX 4 25 | #define GPS_TX 17 26 | 27 | // OTHER 28 | #define BUTTON_PIN 15 29 | #define BATTERY_PIN 35 30 | 31 | #define HAS_BT_CLASSIC 32 | 33 | #endif -------------------------------------------------------------------------------- /variants/Wemos_ESP32_Bat_LoRa_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:Wemos_ESP32_Bat_LoRa_GPS] 2 | extends = env:esp32 3 | board = esp32dev 4 | build_flags = 5 | ${common.build_flags} 6 | -D WEMOS_ESP32_Bat_LoRa_GPS 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/esp32_c3_DIY_LoRa_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 4 7 | #define RADIO_MISO_PIN 5 8 | #define RADIO_MOSI_PIN 6 9 | #define RADIO_CS_PIN 7 10 | #define RADIO_RST_PIN 3 11 | #define RADIO_BUSY_PIN 2 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 8 19 | #define OLED_SCL 9 20 | #define OLED_RST 10 21 | 22 | // GPS 23 | #define GPS_RX 20 24 | #define GPS_TX 21 25 | 26 | // OTHER 27 | #define BATTERY_PIN 1 28 | 29 | #endif -------------------------------------------------------------------------------- /variants/esp32_c3_DIY_LoRa_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:esp32_c3_DIY_LoRa_GPS] 2 | extends = env:esp32 3 | board = esp32-c3-devkitm-1 4 | board_build.mcu = esp32c3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D ESP32_C3_DIY_LoRa_GPS 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} 12 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/esp32_c3_DIY_LoRa_GPS_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1276 6 | #define RADIO_SCLK_PIN 4 7 | #define RADIO_MISO_PIN 5 8 | #define RADIO_MOSI_PIN 6 9 | #define RADIO_CS_PIN 7 10 | #define RADIO_RST_PIN 3 11 | #define RADIO_BUSY_PIN 2 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 8 19 | #define OLED_SCL 9 20 | #define OLED_RST 10 21 | 22 | // GPS 23 | #define GPS_RX 20 24 | #define GPS_TX 21 25 | 26 | // OTHER 27 | #define BATTERY_PIN 1 28 | 29 | #endif -------------------------------------------------------------------------------- /variants/esp32_c3_DIY_LoRa_GPS_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:esp32_c3_DIY_LoRa_GPS_915] 2 | extends = env:esp32 3 | board = esp32-c3-devkitm-1 4 | board_build.mcu = esp32c3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D ESP32_C3_DIY_LoRa_GPS_915 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} 12 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/heltec-lora32-v2_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 14 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 4 19 | #define OLED_SCL 15 20 | #define OLED_RST 16 21 | #define OLED_DISPLAY_HAS_RST_PIN 22 | 23 | // GPS 24 | #define GPS_RX 12 25 | #define GPS_TX 34 26 | 27 | // OTHER 28 | #define BATTERY_PIN 37 29 | #define BUTTON_PIN 0 30 | #define ADC_CTRL 21 31 | 32 | #define HAS_BT_CLASSIC 33 | 34 | #endif -------------------------------------------------------------------------------- /variants/heltec-lora32-v2_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec-lora32-v2_GPS] 2 | extends = env:esp32 3 | board = heltec_wifi_lora_32_V2 4 | build_flags = 5 | ${common.build_flags} 6 | -D HELTEC_V2_GPS 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec-lora32-v2_GPS_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1276 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 14 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 4 19 | #define OLED_SCL 15 20 | #define OLED_RST 16 21 | #define OLED_DISPLAY_HAS_RST_PIN 22 | 23 | // GPS 24 | #define GPS_RX 12 25 | #define GPS_TX 34 26 | 27 | // OTHER 28 | #define BATTERY_PIN 37 29 | #define BUTTON_PIN 0 30 | #define ADC_CTRL 21 31 | 32 | #define HAS_BT_CLASSIC 33 | 34 | #endif -------------------------------------------------------------------------------- /variants/heltec-lora32-v2_GPS_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec-lora32-v2_GPS_915] 2 | extends = env:esp32 3 | board = heltec_wifi_lora_32_V2 4 | build_flags = 5 | ${common.build_flags} 6 | -D HELTEC_V2_GPS_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec-lora32-v2_TNC/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 14 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 4 19 | #define OLED_SCL 15 20 | #define OLED_RST 16 21 | #define OLED_DISPLAY_HAS_RST_PIN 22 | 23 | // GPS 24 | #define HAS_NO_GPS 25 | #define GPS_RX -1 26 | #define GPS_TX -1 27 | 28 | // OTHER 29 | #define BATTERY_PIN 37 30 | #define BUTTON_PIN 0 31 | #define ADC_CTRL 21 32 | 33 | #define HAS_BT_CLASSIC 34 | 35 | #endif -------------------------------------------------------------------------------- /variants/heltec-lora32-v2_TNC/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec-lora32-v2_TNC] 2 | extends = env:esp32 3 | board = heltec_wifi_lora_32_V2 4 | build_flags = 5 | ${common.build_flags} 6 | -D HELTEC_V2_TNC 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec_ht-ct62_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 10 7 | #define RADIO_MISO_PIN 6 8 | #define RADIO_MOSI_PIN 7 9 | #define RADIO_CS_PIN 8 10 | #define RADIO_RST_PIN 5 11 | #define RADIO_DIO1_PIN 3 12 | #define RADIO_BUSY_PIN 4 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define OLED_SDA 18 20 | #define OLED_SCL 19 21 | #define OLED_RST -1 22 | 23 | // GPS 24 | #define GPS_RX 0 25 | #define GPS_TX 1 26 | 27 | #endif -------------------------------------------------------------------------------- /variants/heltec_ht-ct62_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec_ht-ct62_GPS] 2 | extends = env:esp32 3 | board = heltec_wireless_stick_lite 4 | board_build.mcu = esp32c3 5 | build_flags = 6 | ${common.build_flags} 7 | -D HELTEC_HTCT62_GPS 8 | lib_deps = 9 | ${common.lib_deps} 10 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_2_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 9 7 | #define RADIO_MISO_PIN 11 8 | #define RADIO_MOSI_PIN 10 9 | #define RADIO_CS_PIN 8 10 | #define RADIO_RST_PIN 12 11 | #define RADIO_DIO1_PIN 14 12 | #define RADIO_BUSY_PIN 13 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define OLED_SDA 17 20 | #define OLED_SCL 18 21 | #define OLED_RST 21 22 | 23 | // GPS 24 | #define GPS_RX 47 25 | #define GPS_TX 48 26 | 27 | // OTHER 28 | #define BUTTON_PIN 0 29 | #define BATTERY_PIN 1 30 | #define VEXT_CTRL 36 31 | #define ADC_CTRL 37 32 | 33 | #define BOARD_I2C_SDA 41 34 | #define BOARD_I2C_SCL 42 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_2_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec_wifi_lora_32_v3_2_GPS] 2 | extends = env:esp32 3 | board = heltec_wifi_lora_32_V3 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D HELTEC_V3_2_GPS 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_2_TNC/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 9 7 | #define RADIO_MISO_PIN 11 8 | #define RADIO_MOSI_PIN 10 9 | #define RADIO_CS_PIN 8 10 | #define RADIO_RST_PIN 12 11 | #define RADIO_DIO1_PIN 14 12 | #define RADIO_BUSY_PIN 13 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define OLED_SDA 17 20 | #define OLED_SCL 18 21 | #define OLED_RST 21 22 | 23 | // GPS 24 | #define HAS_NO_GPS 25 | #define GPS_RX -1 26 | #define GPS_TX -1 27 | 28 | // OTHER 29 | #define BUTTON_PIN 0 30 | #define BATTERY_PIN 1 31 | #define VEXT_CTRL 36 32 | #define ADC_CTRL 37 // Heltec V3 needs ADC_CTRL = LOW powers the voltage divider to read BatteryPin 33 | 34 | #define BOARD_I2C_SDA 41 35 | #define BOARD_I2C_SCL 42 36 | 37 | #endif -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_2_TNC/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec_wifi_lora_32_v3_2_TNC] 2 | extends = env:esp32 3 | board = heltec_wifi_lora_32_V3 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D HELTEC_V3_2_TNC 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 9 7 | #define RADIO_MISO_PIN 11 8 | #define RADIO_MOSI_PIN 10 9 | #define RADIO_CS_PIN 8 10 | #define RADIO_RST_PIN 12 11 | #define RADIO_DIO1_PIN 14 12 | #define RADIO_BUSY_PIN 13 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define OLED_SDA 17 20 | #define OLED_SCL 18 21 | #define OLED_RST 21 22 | 23 | // GPS 24 | #define GPS_RX 47 25 | #define GPS_TX 48 26 | 27 | // OTHER 28 | #define BUTTON_PIN 0 29 | #define BATTERY_PIN 1 30 | #define VEXT_CTRL 36 31 | #define ADC_CTRL 37 32 | 33 | #define BOARD_I2C_SDA 41 34 | #define BOARD_I2C_SCL 42 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec_wifi_lora_32_v3_GPS] 2 | extends = env:esp32 3 | board = heltec_wifi_lora_32_V3 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D HELTEC_V3_GPS 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_TNC/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 9 7 | #define RADIO_MISO_PIN 11 8 | #define RADIO_MOSI_PIN 10 9 | #define RADIO_CS_PIN 8 10 | #define RADIO_RST_PIN 12 11 | #define RADIO_DIO1_PIN 14 12 | #define RADIO_BUSY_PIN 13 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define OLED_SDA 17 20 | #define OLED_SCL 18 21 | #define OLED_RST 21 22 | 23 | // GPS 24 | #define HAS_NO_GPS 25 | #define GPS_RX -1 26 | #define GPS_TX -1 27 | 28 | // OTHER 29 | #define BUTTON_PIN 0 30 | #define BATTERY_PIN 1 31 | #define VEXT_CTRL 36 32 | #define ADC_CTRL 37 // Heltec V3 needs ADC_CTRL = LOW powers the voltage divider to read BatteryPin 33 | 34 | #define BOARD_I2C_SDA 41 35 | #define BOARD_I2C_SCL 42 36 | 37 | #endif -------------------------------------------------------------------------------- /variants/heltec_wifi_lora_32_v3_TNC/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec_wifi_lora_32_v3_TNC] 2 | extends = env:esp32 3 | board = heltec_wifi_lora_32_V3 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D HELTEC_V3_TNC 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} -------------------------------------------------------------------------------- /variants/heltec_wireless_stick_lite_v3_GPS_display/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 9 7 | #define RADIO_MISO_PIN 11 8 | #define RADIO_MOSI_PIN 10 9 | #define RADIO_CS_PIN 8 10 | #define RADIO_RST_PIN 12 11 | #define RADIO_DIO1_PIN 14 12 | #define RADIO_BUSY_PIN 13 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define OLED_SDA 17 20 | #define OLED_SCL 18 21 | #define OLED_RST -1 22 | 23 | // GPS 24 | #define GPS_RX 47 25 | #define GPS_TX 48 26 | 27 | // OTHER 28 | #define BUTTON_PIN 0 29 | #define BATTERY_PIN 1 30 | #define VEXT_CTRL 36 31 | #define ADC_CTRL 37 // Heltec V3 needs ADC_CTRL = LOW powers the voltage divider to read BatteryPin 32 | 33 | #define BOARD_I2C_SDA 41 34 | #define BOARD_I2C_SCL 42 35 | 36 | #endif -------------------------------------------------------------------------------- /variants/heltec_wireless_stick_lite_v3_GPS_display/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec_wireless_stick_lite_v3_GPS_display] 2 | extends = env:esp32 3 | board = esp32-s3-devkitc-1 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D HELTEC_WSL_V3_GPS_DISPLAY 9 | lib_deps = 10 | ${common.lib_deps} -------------------------------------------------------------------------------- /variants/heltec_wireless_tracker/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 9 7 | #define RADIO_MISO_PIN 11 8 | #define RADIO_MOSI_PIN 10 9 | #define RADIO_CS_PIN 8 10 | #define RADIO_RST_PIN 12 11 | #define RADIO_DIO1_PIN 14 12 | #define RADIO_BUSY_PIN 13 13 | #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN 14 | #define WAKEUP_RADIO GPIO_SEL_14 15 | 16 | // Display 17 | #undef OLED_SDA 18 | #undef OLED_SCL 19 | #undef OLED_RST 20 | 21 | #define HAS_TFT 22 | #define BOARD_BL_PIN 21 23 | 24 | // GPS 25 | #define HAS_GPS_CTRL 26 | #define GPS_RX 34 27 | #define GPS_TX 33 28 | #define GPS_PPS 36 29 | #define GPS_RESET 35 30 | #define GPS_BAUDRATE 115200 31 | 32 | // OTHER 33 | #define BUTTON_PIN 0 34 | #define WAKEUP_BUTTON GPIO_NUM_0 35 | #define BATTERY_PIN 1 36 | #define ADC_CTRL 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1 37 | #define VEXT_CTRL 3 // To turn on GPS and TFT 38 | 39 | #define BOARD_I2C_SDA 7 40 | #define BOARD_I2C_SCL 6 41 | 42 | #endif -------------------------------------------------------------------------------- /variants/heltec_wireless_tracker/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:heltec_wireless_tracker] 2 | extends = env:esp32 3 | board = esp32-s3-devkitc-1 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D HELTEC_WIRELESS_TRACKER 9 | -D USER_SETUP_LOADED 10 | -D TFT_WIDTH=80 11 | -D TFT_HEIGHT=160 12 | -D ST7735_DRIVER 13 | -D ST7735_GREENTAB160x80 14 | -D TFT_RGB_ORDER=TFT_BGR 15 | -D TFT_MOSI=42 16 | -D TFT_SCLK=41 17 | -D TFT_CS=38 18 | -D TFT_DC=40 19 | -D TFT_RST=39 20 | -D TFT_BL=21 21 | -D TFT_BACKLIGHT_ON=1 22 | -D TOUCH_CS=-1 23 | -D LOAD_GLCD 24 | -D LOAD_FONT2 25 | -D LOAD_FONT4 26 | -D LOAD_FONT6 27 | -D LOAD_FONT7 28 | -D LOAD_FONT8 29 | -D SPI_FREQUENCY=27000000 30 | -D USE_HSPI_PORT 31 | lib_deps = 32 | ${common.lib_deps} 33 | bodmer/TFT_eSPI @ 2.5.43 -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v0_7/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define GPS_RX 15 24 | #define GPS_TX 12 25 | 26 | // OTHER 27 | #define BUTTON_PIN 39 // The middle button GPIO on the T-Beam 28 | #define BATTERY_PIN 35 29 | 30 | #define HAS_BT_CLASSIC 31 | 32 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v0_7/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-beam-v0_7] 2 | extends = env:esp32 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_Beam_V0_7 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define HAS_GPS_CTRL 24 | #define GPS_RX 12 25 | #define GPS_TX 34 26 | 27 | // OTHER 28 | #define BUTTON_PIN 38 // The middle button GPIO on the T-Beam 29 | 30 | #define HAS_AXP192 31 | #define HAS_BT_CLASSIC 32 | 33 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-beam-v1] 2 | extends = env:esp32 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_Beam_V1_0 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | lewisxhe/XPowersLib @ 0.2.4 11 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_2/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define HAS_GPS_CTRL 24 | #define GPS_RX 12 25 | #define GPS_TX 34 26 | 27 | // OTHER 28 | #define BUTTON_PIN 38 // The middle button GPIO on the T-Beam 29 | 30 | #define HAS_AXP2101 31 | #define HAS_BT_CLASSIC 32 | 33 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_2/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-beam-v1_2] 2 | extends = env:esp32 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_Beam_V1_2 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | lewisxhe/XPowersLib @ 0.2.4 11 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_2_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1276 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define HAS_GPS_CTRL 24 | #define GPS_RX 12 25 | #define GPS_TX 34 26 | 27 | // OTHER 28 | #define BUTTON_PIN 38 // The middle button GPIO on the T-Beam 29 | 30 | #define HAS_AXP2101 31 | #define HAS_BT_CLASSIC 32 | 33 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_2_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-beam-v1_2_915] 2 | extends = env:esp32 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_Beam_V1_2_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | lewisxhe/XPowersLib @ 0.2.4 11 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_2_SX1262/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_DIO0_PIN 26 11 | #define RADIO_RST_PIN 23 12 | #define RADIO_DIO1_PIN 33 13 | #define RADIO_BUSY_PIN 32 14 | 15 | // Display 16 | #undef OLED_SDA 17 | #undef OLED_SCL 18 | #undef OLED_RST 19 | 20 | #define OLED_SDA 21 21 | #define OLED_SCL 22 22 | #define OLED_RST 16 23 | 24 | // GPS 25 | #define HAS_GPS_CTRL 26 | #define GPS_RX 12 27 | #define GPS_TX 34 28 | 29 | // OTHER 30 | #define BUTTON_PIN 38 // The middle button GPIO on the T-Beam 31 | 32 | #define HAS_AXP2101 33 | #define HAS_BT_CLASSIC 34 | 35 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_2_SX1262/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-beam-v1_2_SX1262] 2 | extends = env:esp32 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_Beam_V1_2_SX1262 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | lewisxhe/XPowersLib @ 0.2.4 11 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1276 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define HAS_GPS_CTRL 24 | #define GPS_RX 12 25 | #define GPS_TX 34 26 | 27 | // OTHER 28 | #define BUTTON_PIN 38 // The middle button GPIO on the T-Beam 29 | 30 | #define HAS_AXP192 31 | #define HAS_BT_CLASSIC 32 | 33 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-beam-v1_915] 2 | extends = env:esp32 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_Beam_V1_0_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | lewisxhe/XPowersLib @ 0.2.4 11 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_SX1268/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1268 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_DIO0_PIN 26 11 | #define RADIO_RST_PIN 23 12 | #define RADIO_DIO1_PIN 33 13 | #define RADIO_BUSY_PIN 32 14 | 15 | // Display 16 | #undef OLED_SDA 17 | #undef OLED_SCL 18 | #undef OLED_RST 19 | 20 | #define OLED_SDA 21 21 | #define OLED_SCL 22 22 | #define OLED_RST 16 23 | 24 | // GPS 25 | #define HAS_GPS_CTRL 26 | #define GPS_RX 12 27 | #define GPS_TX 34 28 | 29 | // OTHER 30 | #define BUTTON_PIN 38 // The middle button GPIO on the T-Beam 31 | 32 | #define HAS_AXP192 33 | #define HAS_BT_CLASSIC 34 | 35 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-beam-v1_SX1268/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-beam-v1_SX1268] 2 | extends = env:esp32 3 | board = ttgo-t-beam 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_Beam_V1_0_SX1268 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | lewisxhe/XPowersLib @ 0.2.4 11 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define GPS_RX 12 24 | #define GPS_TX 34 25 | 26 | // OTHER 27 | #define BUTTON_PIN 15 28 | #define BATTERY_PIN 35 29 | 30 | #define HAS_BT_CLASSIC 31 | 32 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-lora32-v2_1_GPS] 2 | extends = env:esp32 3 | board = ttgo-lora32-v21 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_LORA32_V2_1_GPS 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_GPS_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1276 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define GPS_RX 12 24 | #define GPS_TX 34 25 | 26 | // OTHER 27 | #define BUTTON_PIN 15 28 | #define BATTERY_PIN 35 29 | 30 | #define HAS_BT_CLASSIC 31 | 32 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_GPS_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-lora32-v2_1_GPS_915] 2 | extends = env:esp32 3 | board = ttgo-lora32-v21 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_LORA32_V2_1_GPS_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_TNC/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1278 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define HAS_NO_GPS 24 | #define GPS_RX -1 25 | #define GPS_TX -1 26 | 27 | // OTHER 28 | #define BUTTON_PIN 15 29 | #define BATTERY_PIN 35 30 | 31 | #define HAS_BT_CLASSIC 32 | 33 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_TNC/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-lora32-v2_1_TNC] 2 | extends = env:esp32 3 | board = ttgo-lora32-v21 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_LORA32_V2_1_TNC_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_TNC_915/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1276 6 | #define RADIO_SCLK_PIN 5 7 | #define RADIO_MISO_PIN 19 8 | #define RADIO_MOSI_PIN 27 9 | #define RADIO_CS_PIN 18 10 | #define RADIO_RST_PIN 23 11 | #define RADIO_BUSY_PIN 26 12 | 13 | // Display 14 | #undef OLED_SDA 15 | #undef OLED_SCL 16 | #undef OLED_RST 17 | 18 | #define OLED_SDA 21 19 | #define OLED_SCL 22 20 | #define OLED_RST 16 21 | 22 | // GPS 23 | #define HAS_NO_GPS 24 | #define GPS_RX -1 25 | #define GPS_TX -1 26 | 27 | // OTHER 28 | #define BUTTON_PIN 15 29 | #define BATTERY_PIN 35 30 | 31 | #define HAS_BT_CLASSIC 32 | 33 | #endif -------------------------------------------------------------------------------- /variants/ttgo-t-lora32-v2_1_TNC_915/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo-t-lora32-v2_1_TNC_915] 2 | extends = env:esp32 3 | board = ttgo-lora32-v21 4 | build_flags = 5 | ${common.build_flags} 6 | -D TTGO_T_LORA32_V2_1_TNC_915 7 | lib_deps = 8 | ${common.lib_deps} 9 | ${common.display_libs} 10 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo_t_beam_s3_SUPREME_v3/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 12 7 | #define RADIO_MISO_PIN 13 8 | #define RADIO_MOSI_PIN 11 9 | #define RADIO_CS_PIN 10 10 | #define RADIO_DIO0_PIN -1 11 | #define RADIO_RST_PIN 5 12 | #define RADIO_DIO1_PIN 1 13 | #define RADIO_BUSY_PIN 4 14 | 15 | // Display 16 | #undef OLED_SDA 17 | #undef OLED_SCL 18 | #undef OLED_RST 19 | 20 | #define OLED_SDA 17 21 | #define OLED_SCL 18 22 | #define OLED_RST 16 23 | 24 | // GPS 25 | #define HAS_GPS_CTRL 26 | #define GPS_RX 8 27 | #define GPS_TX 9 28 | 29 | // OTHER 30 | #define BUTTON_PIN 0 31 | 32 | #define HAS_AXP2101 33 | #define BOARD_HAS_PSRAM 34 | 35 | #endif -------------------------------------------------------------------------------- /variants/ttgo_t_beam_s3_SUPREME_v3/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo_t_beam_s3_SUPREME_v3] 2 | extends = env:esp32 3 | board = esp32-s3-devkitc-1 4 | board_build.mcu = esp32s3 5 | build_flags = 6 | ${common.build_flags} 7 | ${common.usb_flags} 8 | -D TTGO_T_Beam_S3_SUPREME_V3 9 | lib_deps = 10 | ${common.lib_deps} 11 | ${common.display_libs} 12 | lewisxhe/XPowersLib @ 0.2.4 13 | adafruit/Adafruit SH110X @ 2.1.10 -------------------------------------------------------------------------------- /variants/ttgo_t_deck_GPS/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 40 7 | #define RADIO_MISO_PIN 38 8 | #define RADIO_MOSI_PIN 41 9 | #define RADIO_CS_PIN 9 10 | #define RADIO_RST_PIN 17 11 | #define RADIO_DIO1_PIN 45 12 | #define RADIO_BUSY_PIN 13 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define HAS_TFT 20 | 21 | // GPS 22 | #define GPS_RX 43 23 | #define GPS_TX 44 24 | 25 | // OTHER 26 | #define BATTERY_PIN 4 27 | 28 | #define BOARD_POWERON 10 29 | #define BOARD_SDCARD_CS 39 30 | #define BOARD_BL_PIN 42 31 | 32 | #define BOARD_I2C_SDA 18 33 | #define BOARD_I2C_SCL 8 34 | 35 | // JOYSTICK 36 | #define HAS_JOYSTICK 37 | #define JOYSTICK_CENTER 0 38 | #define BUTTON_PIN JOYSTICK_CENTER 39 | #define JOYSTICK_UP 3 // G S1 40 | #define JOYSTICK_DOWN 15 // G S3 41 | #define JOYSTICK_LEFT 1 // G S4 42 | #define JOYSTICK_RIGHT 2 // G S2 43 | 44 | #define HAS_TOUCHSCREEN 45 | #define HAS_I2S 46 | #define DAC_I2S_WS 5 47 | #define DAC_I2S_DOUT 6 48 | #define DAC_I2S_BCK 7 49 | #define SPK_I2S_PORT I2S_NUM_0 50 | #define MIC_I2S_SAMPLE_RATE 16000 51 | #define MIC_I2S_PORT I2S_NUM_1 52 | 53 | #endif -------------------------------------------------------------------------------- /variants/ttgo_t_deck_GPS/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo_t_deck_GPS] 2 | extends = env 3 | platform = espressif32 @ 6.3.1 4 | board_build.partitions = huge_app.csv 5 | monitor_filters = esp32_exception_decoder 6 | board = esp32-s3-devkitc-1 7 | board_build.mcu = esp32s3 8 | board_build.embed_files = 9 | data_embed/index.html.gz 10 | data_embed/style.css.gz 11 | data_embed/script.js.gz 12 | data_embed/bootstrap.css.gz 13 | data_embed/bootstrap.js.gz 14 | data_embed/favicon.png.gz 15 | extra_scripts = 16 | pre:tools/compress.py 17 | debug_tool = esp-prog 18 | build_flags = 19 | ${common.build_flags} 20 | ${common.usb_flags} 21 | -D TTGO_T_DECK_GPS 22 | -D BOARD_HAS_PSRAM 23 | -D USER_SETUP_LOADED 24 | -D ST7789_DRIVER 25 | -D TFT_WIDTH=240 26 | -D TFT_HEIGHT=320 27 | -D TFT_RGB_ORDER=TFT_BGR 28 | -D TFT_INVERSION_ON 29 | -D TFT_MISO=38 30 | -D TFT_MOSI=41 31 | -D TFT_SCLK=40 32 | -D TFT_CS=12 33 | -D TFT_DC=11 34 | -D TFT_RST=-1 35 | -D TFT_BUSY=-1 36 | -D TFT_BL=42 37 | -D TFT_BACKLIGHT_ON=1 38 | -D TOUCH_CS=-1 39 | -D LOAD_GLCD 40 | -D LOAD_FONT2 41 | -D LOAD_FONT4 42 | -D LOAD_FONT6 43 | -D LOAD_FONT7 44 | -D LOAD_FONT8 45 | -D SPI_FREQUENCY=40000000 46 | -D SPI_READ_FREQUENCY=16000000 47 | lib_deps = 48 | ${common.lib_deps} 49 | bodmer/TFT_eSPI @ 2.5.43 50 | https://github.com/mmMicky/TouchLib.git -------------------------------------------------------------------------------- /variants/ttgo_t_deck_plus/board_pinout.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_PINOUT_H_ 2 | #define BOARD_PINOUT_H_ 3 | 4 | // LoRa Radio 5 | #define HAS_SX1262 6 | #define RADIO_SCLK_PIN 40 7 | #define RADIO_MISO_PIN 38 8 | #define RADIO_MOSI_PIN 41 9 | #define RADIO_CS_PIN 9 10 | #define RADIO_RST_PIN 17 11 | #define RADIO_DIO1_PIN 45 12 | #define RADIO_BUSY_PIN 13 13 | 14 | // Display 15 | #undef OLED_SDA 16 | #undef OLED_SCL 17 | #undef OLED_RST 18 | 19 | #define HAS_TFT 20 | 21 | // GPS 22 | #define GPS_RX 43 23 | #define GPS_TX 44 24 | #define GPS_BAUDRATE 38400 25 | 26 | // OTHER 27 | #define BATTERY_PIN 4 28 | 29 | #define BOARD_POWERON 10 30 | #define BOARD_SDCARD_CS 39 31 | #define BOARD_BL_PIN 42 32 | 33 | #define BOARD_I2C_SDA 18 34 | #define BOARD_I2C_SCL 8 35 | 36 | // JOYSTICK 37 | #define HAS_JOYSTICK 38 | #define JOYSTICK_CENTER 0 39 | #define BUTTON_PIN JOYSTICK_CENTER 40 | #define JOYSTICK_UP 3 // G S1 41 | #define JOYSTICK_DOWN 15 // G S3 42 | #define JOYSTICK_LEFT 1 // G S4 43 | #define JOYSTICK_RIGHT 2 // G S2 44 | 45 | #define HAS_TOUCHSCREEN 46 | #define HAS_I2S 47 | #define DAC_I2S_WS 5 48 | #define DAC_I2S_DOUT 6 49 | #define DAC_I2S_BCK 7 50 | #define SPK_I2S_PORT I2S_NUM_0 51 | #define MIC_I2S_SAMPLE_RATE 16000 52 | #define MIC_I2S_PORT I2S_NUM_1 53 | 54 | #endif -------------------------------------------------------------------------------- /variants/ttgo_t_deck_plus/platformio.ini: -------------------------------------------------------------------------------- 1 | [env:ttgo_t_deck_plus] 2 | extends = env 3 | platform = espressif32 @ 6.3.1 4 | board_build.partitions = huge_app.csv 5 | monitor_filters = esp32_exception_decoder 6 | board = esp32-s3-devkitc-1 7 | board_build.mcu = esp32s3 8 | board_build.embed_files = 9 | data_embed/index.html.gz 10 | data_embed/style.css.gz 11 | data_embed/script.js.gz 12 | data_embed/bootstrap.css.gz 13 | data_embed/bootstrap.js.gz 14 | data_embed/favicon.png.gz 15 | extra_scripts = 16 | pre:tools/compress.py 17 | debug_tool = esp-prog 18 | build_flags = 19 | ${common.build_flags} 20 | ${common.usb_flags} 21 | -D TTGO_T_DECK_PLUS 22 | -D BOARD_HAS_PSRAM 23 | -D USER_SETUP_LOADED 24 | -D ST7789_DRIVER 25 | -D TFT_WIDTH=240 26 | -D TFT_HEIGHT=320 27 | -D TFT_RGB_ORDER=TFT_BGR 28 | -D TFT_INVERSION_ON 29 | -D TFT_MISO=38 30 | -D TFT_MOSI=41 31 | -D TFT_SCLK=40 32 | -D TFT_CS=12 33 | -D TFT_DC=11 34 | -D TFT_RST=-1 35 | -D TFT_BUSY=-1 36 | -D TFT_BL=42 37 | -D TFT_BACKLIGHT_ON=1 38 | -D TOUCH_CS=-1 39 | -D LOAD_GLCD 40 | -D LOAD_FONT2 41 | -D LOAD_FONT4 42 | -D LOAD_FONT6 43 | -D LOAD_FONT7 44 | -D LOAD_FONT8 45 | -D SPI_FREQUENCY=40000000 46 | -D SPI_READ_FREQUENCY=16000000 47 | lib_deps = 48 | ${common.lib_deps} 49 | bodmer/TFT_eSPI @ 2.5.43 50 | https://github.com/mmMicky/TouchLib.git --------------------------------------------------------------------------------