Compare commits

..

25 Commits

Author SHA1 Message Date
github-actions[bot]
b5e952b008 Upgrade trunk (#9128)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-01-01 19:17:55 -06:00
renovate[bot]
11b5f1a4fe chore(deps): update dorny/test-reporter action to v2.4.0 (#9135)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-01 18:04:13 -06:00
renovate[bot]
f9c9350f45 chore(deps): update meshtastic/device-ui digest to a8e2f94 (#9140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-01 18:03:27 -06:00
Jonathan Bennett
a5b2d4a9d5 Add null check for p_encrypted before MQTT publish (#9136)
* Add null check for p_encrypted before MQTT publish

A user on BayMesh observed a strange crash in MQTT::onSend that seemed to be a null pointer dereference of this value.

* Trunk
2026-01-01 13:53:36 -06:00
Ben Meadors
7fb95841e4 Apparently I marked board level extra on the wrong tbeam target 2026-01-01 08:25:33 -06:00
renovate[bot]
eaab8f04b5 chore(deps): update meshtastic/device-ui digest to 940ba85 (#9129)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-01 10:58:56 +11:00
Eric Severance
9058ccecf9 Calculate hops correctly even when hop_start==0 (#9120)
* Calculate hops correctly even when hop_start==0.

* Use the same type (int8_t) in the loop, avoiding signed/unsigned mismatches.

* Clarify defaultIfUnknown is returned for encrypted packets.
2025-12-30 19:03:51 -06:00
Ben Meadors
1b83501ee2 Revert "Upgrade all esp32 targets to NimBLE 2.X (#9003)" (#9125)
This reverts commit 40f1f91c0d.
2025-12-30 17:23:50 -06:00
github-actions[bot]
ac571d5dd2 Upgrade trunk (#9121)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-12-30 07:10:36 -06:00
renovate[bot]
ef30fd850d Update meshtastic/device-ui digest to 7656d49 (#9111)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-29 19:09:44 +01:00
renovate[bot]
b9a0015149 chore(deps): update meshtastic/device-ui digest to d234bd9 (#9108)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-29 06:50:12 -06:00
github-actions[bot]
9673cfb0b2 Upgrade trunk (#9106)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-12-29 06:03:03 -06:00
renovate[bot]
757f7b68d6 Update meshtastic/device-ui digest to caff403 (#9104)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-29 13:35:31 +11:00
Jason P
5510dae8d3 Implement HAS_PHYSICAL_KEYBOARD for devices with physical keyboards (#9071)
- Implement HAS_PHYSICAL_KEYBOARD for devices with physical keyboards
- Add HAS_PHYSICAL_KEYBOARD to variant.h for:
  - TDeck
  - TLora Pager
  - TDeck Pro
2025-12-27 06:53:55 -06:00
Tom
52fd362720 Fix gps pin defs for various NRF variants. (#9034)
* fix on nrf52_promicro

* try fix for GPS issue

* fix GPS pin assignment in variant.h

* cleared up some comments and confirmed pinouts from schematics

---------

Co-authored-by: macvenez <macvenez@gmail.com>
2025-12-27 06:50:07 -06:00
github-actions[bot]
33e1f58f6e Upgrade trunk (#9076)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-12-26 17:45:57 -06:00
Jonathan Bennett
9dc7ef612e In autoconf, don't probe Wire unless i2c device is set (#9081)
Found another bit of code that crashes my desktop, by probing the wrong i2c bus.
2025-12-26 14:33:17 -06:00
github-actions[bot]
b2c82bdc41 Upgrade trunk (#9072)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-12-25 06:34:38 -06:00
Jonathan Bennett
54a928f47f M6 shutdown and LEDs work (#9065)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-12-24 07:48:14 -06:00
github-actions[bot]
33f18659c8 Upgrade trunk (#9067)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-12-24 05:20:22 -06:00
github-actions[bot]
3a7093a973 Upgrade trunk (#9047)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-12-23 18:55:54 -06:00
renovate[bot]
a4f6f4515a Update meshtastic-esp8266-oled-ssd1306 digest to b34c681 (#9062)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-23 18:55:37 -06:00
Jonathan Bennett
d609d05698 In statusLEDModule, also detect isCharging (#9050) 2025-12-23 07:48:55 -06:00
Ben Meadors
83c6161ac6 Revert "Automated version bumps (#9025)"
This reverts commit 1021d967da.
2025-12-20 14:10:02 -06:00
Ben Meadors
d93d68d31e Fix -ota.zip in manifest and build output 2025-12-20 14:09:05 -06:00
202 changed files with 677 additions and 2918 deletions

View File

@@ -143,7 +143,7 @@ jobs:
merge-multiple: true merge-multiple: true
- name: Test Report - name: Test Report
uses: dorny/test-reporter@v2.3.0 uses: dorny/test-reporter@v2.4.0
with: with:
name: PlatformIO Tests name: PlatformIO Tests
path: testreport.xml path: testreport.xml

View File

@@ -16,7 +16,7 @@ jobs:
submodules: true submodules: true
- name: Update submodule - name: Update submodule
if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' }} if: ${{ github.ref == 'refs/heads/master' }}
run: | run: |
git submodule update --remote protobufs git submodule update --remote protobufs

View File

@@ -8,10 +8,10 @@ plugins:
uri: https://github.com/trunk-io/plugins uri: https://github.com/trunk-io/plugins
lint: lint:
enabled: enabled:
- checkov@3.2.495 - checkov@3.2.497
- renovate@42.64.1 - renovate@42.69.2
- prettier@3.7.4 - prettier@3.7.4
- trufflehog@3.92.3 - trufflehog@3.92.4
- yamllint@1.37.1 - yamllint@1.37.1
- bandit@1.9.2 - bandit@1.9.2
- trivy@0.68.2 - trivy@0.68.2
@@ -21,7 +21,7 @@ lint:
- markdownlint@0.47.0 - markdownlint@0.47.0
- oxipng@10.0.0 - oxipng@10.0.0
- svgo@4.0.0 - svgo@4.0.0
- actionlint@1.7.9 - actionlint@1.7.10
- flake8@7.3.0 - flake8@7.3.0
- hadolint@2.14.0 - hadolint@2.14.0
- shfmt@3.6.0 - shfmt@3.6.0

View File

@@ -21,13 +21,14 @@ rm -f $BUILDDIR/firmware*
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION basename=firmware-$1-$VERSION
ota_basename=${basename}-ota
pio run --environment $1 -t mtjson # -v pio run --environment $1 -t mtjson # -v
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
echo "Copying NRF52 dfu (OTA) file" echo "Copying NRF52 dfu (OTA) file"
cp $BUILDDIR/$basename.zip $OUTDIR/$basename.zip cp $BUILDDIR/$basename.zip $OUTDIR/$ota_basename.zip
echo "Copying NRF52 UF2 file" echo "Copying NRF52 UF2 file"
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2 cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2

View File

@@ -87,9 +87,6 @@
</screenshots> </screenshots>
<releases> <releases>
<release version="2.7.18" date="2025-12-20">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.18</url>
</release>
<release version="2.7.17" date="2025-11-28"> <release version="2.7.17" date="2025-11-28">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.17</url> <url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.17</url>
</release> </release>

View File

@@ -17,6 +17,8 @@ lfsbin = f"{progname.replace('firmware-', 'littlefs-')}.bin"
def manifest_gather(source, target, env): def manifest_gather(source, target, env):
out = [] out = []
board_platform = env.BoardConfig().get("platform")
needs_ota_suffix = board_platform == "nordicnrf52"
check_paths = [ check_paths = [
progname, progname,
f"{progname}.elf", f"{progname}.elf",
@@ -32,8 +34,11 @@ def manifest_gather(source, target, env):
for p in check_paths: for p in check_paths:
f = env.File(env.subst(f"$BUILD_DIR/{p}")) f = env.File(env.subst(f"$BUILD_DIR/{p}"))
if f.exists(): if f.exists():
manifest_name = p
if needs_ota_suffix and p == f"{progname}.zip":
manifest_name = f"{progname}-ota.zip"
d = { d = {
"name": p, "name": manifest_name,
"md5": f.get_content_hash(), # Returns MD5 hash "md5": f.get_content_hash(), # Returns MD5 hash
"bytes": f.get_size() # Returns file size in bytes "bytes": f.get_size() # Returns file size in bytes
} }

6
debian/changelog vendored
View File

@@ -1,9 +1,3 @@
meshtasticd (2.7.18.0) unstable; urgency=medium
* Version 2.7.18
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sat, 20 Dec 2025 15:47:25 +0000
meshtasticd (2.7.17.0) unstable; urgency=medium meshtasticd (2.7.17.0) unstable; urgency=medium
* Version 2.7.17 * Version 2.7.17

View File

@@ -64,7 +64,7 @@ monitor_speed = 115200
monitor_filters = direct monitor_filters = direct
lib_deps = lib_deps =
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/2887bf4a19f64d92c984dcc8fd5ca7429e425e4a.zip https://github.com/meshtastic/esp8266-oled-ssd1306/archive/b34c6817c25d6faabb3a8a162b5d14fb75395433.zip
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master # renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master # renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
@@ -103,13 +103,17 @@ lib_deps =
thingsboard/TBPubSubClient@2.12.1 thingsboard/TBPubSubClient@2.12.1
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient # renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
arduino-libraries/NTPClient@3.2.1 arduino-libraries/NTPClient@3.2.1
; Extra TCP/IP networking libs for supported devices
[networking_extra]
lib_deps =
# renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog # renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog
arcao/Syslog@2.0.0 arcao/Syslog@2.0.0
; Minimal networking libs for nrf52 (excludes Syslog to save flash)
[nrf52_networking_base]
lib_deps =
# renovate: datasource=custom.pio depName=TBPubSubClient packageName=thingsboard/library/TBPubSubClient
thingsboard/TBPubSubClient@2.12.1
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
arduino-libraries/NTPClient@3.2.1
[radiolib_base] [radiolib_base]
lib_deps = lib_deps =
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib # renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
@@ -119,7 +123,7 @@ lib_deps =
[device-ui_base] [device-ui_base]
lib_deps = lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/862ed040c4ab44f0dfbbe492691f144886102588.zip https://github.com/meshtastic/device-ui/archive/a8e2f947f7abaf0c5ac8e6dd189a22156335beaa.zip
; Common libs for environmental measurements in telemetry module ; Common libs for environmental measurements in telemetry module
[environmental_base] [environmental_base]
@@ -158,8 +162,8 @@ lib_deps =
emotibit/EmotiBit MLX90632@1.0.8 emotibit/EmotiBit MLX90632@1.0.8
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library # renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
adafruit/Adafruit MLX90614 Library@2.1.5 adafruit/Adafruit MLX90614 Library@2.1.5
# renovate: datasource=git-refs depName=INA3221 packageName=https://github.com/sgtwilko/INA3221 gitBranch=FixOverflow # renovate: datasource=github-tags depName=INA3221 packageName=sgtwilko/INA3221
https://github.com/sgtwilko/INA3221/archive/bb03d7e9bfcc74fc798838a54f4f99738f29fc6a.zip https://github.com/sgtwilko/INA3221#bb03d7e9bfcc74fc798838a54f4f99738f29fc6a
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass # renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
mprograms/QMC5883LCompass@1.2.3 mprograms/QMC5883LCompass@1.2.3
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU # renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU

View File

@@ -13,81 +13,41 @@ const Emote emotes[] = {
{"\U0001F44E", thumbdown, thumbs_width, thumbs_height}, // 👎 Thumbs Down {"\U0001F44E", thumbdown, thumbs_width, thumbs_height}, // 👎 Thumbs Down
// --- Smileys (Multiple Unicode Aliases) --- // --- Smileys (Multiple Unicode Aliases) ---
{"\U0001F60A", smiling_eyes, smiling_eyes_width, smiling_eyes_height}, // 😊 Smiling Eyes {"\U0001F60A", Smiling_Eyes, Smiling_Eyes_width, Smiling_Eyes_height}, // 😊 Smiling Eyes
{"\U0001F600", grinning, grinning_width, grinning_height}, // 😀 Grinning Face {"\U0001F600", Grinning, Grinning_width, Grinning_height}, // 😀 Grinning Face
{"\U0001F642", slightly_smiling, slightly_smiling_width, slightly_smiling_height}, // 🙂 Slightly Smiling Face {"\U0001F642", Slightly_Smiling, Slightly_Smiling_width, Slightly_Smiling_height}, // 🙂 Slightly Smiling Face
{"\U0001F609", winking_face, winking_face_width, winking_face_height}, // 😉 Winking Face {"\U0001F609", Winking_Face, Winking_Face_width, Winking_Face_height}, // 😉 Winking Face
{"\U0001F601", grinning_smiling_eyes, grinning_smiling_eyes_width, grinning_smiling_eyes_height}, // 😁 Grinning Smiling Eyes {"\U0001F601", Grinning_Smiling_Eyes, Grinning_Smiling_Eyes_width, Grinning_Smiling_Eyes_height}, // 😁 Grinning Smiling Eyes
{"\U0001F60D", heart_eyes, heart_eyes_width, heart_eyes_height}, // 😍 Heart Eyes {"\U0001F60D", Heart_eyes, Heart_eyes_width, Heart_eyes_height}, // 😍 Heart Eyes
{"\U0001F970", heart_smile, heart_smile_width, heart_smile_height}, // 🥰 Smiling Face with Hearts {"\U0001F970", heart_smile, heart_smile_width, heart_smile_height}, // 🥰 Smiling Face with Hearts
// --- Question/Alert --- // --- Question/Alert ---
{"\u2753", question, question_width, question_height}, // ❓ Question Mark {"\u2753", question, question_width, question_height}, // ❓ Question Mark
{"\u203C\uFE0F", bang, bang_width, bang_height}, // ‼️ Double Exclamation Mark {"\u203C\uFE0F", bang, bang_width, bang_height}, // ‼️ Double Exclamation Mark
{"\u26A0\uFE0F", caution, caution_width, caution_height}, // ⚠️ Warning Sign
// --- Laughing Faces --- // --- Laughing Faces ---
{"\U0001F602", haha, haha_width, haha_height}, // 😂 Face with Tears of Joy {"\U0001F602", haha, haha_width, haha_height}, // 😂 Face with Tears of Joy
{"\U0001F923", rofl, rofl_width, rofl_height}, // 🤣 Rolling on the Floor Laughing {"\U0001F923", ROFL, ROFL_width, ROFL_height}, // 🤣 Rolling on the Floor Laughing
{"\U0001F606", smiling_closed_eyes, smiling_closed_eyes_width, smiling_closed_eyes_height}, // 😆 Smiling Closed Eyes {"\U0001F606", Smiling_Closed_Eyes, Smiling_Closed_Eyes_width, Smiling_Closed_Eyes_height}, // 😆 Smiling Closed Eyes
{"\U0001F605", haha, haha_width, haha_height}, // 😅 Smiling with Sweat {"\U0001F605", haha, haha_width, haha_height}, // 😅 Smiling with Sweat
{"\U0001F604", grinning_smiling_eyes_2, grinning_smiling_eyes_2_width, {"\U0001F604", Grinning_SmilingEyes2, Grinning_SmilingEyes2_width,
grinning_smiling_eyes_2_height}, // 😄 Grinning Face with Smiling Eyes Grinning_SmilingEyes2_height}, // 😄 Grinning Face with Smiling Eyes
{"\U0001F62D", loudly_crying_face, loudly_crying_face_width, loudly_crying_face_height}, // 😭 Loudly Crying Face {"\U0001F62D", Loudly_Crying_Face, Loudly_Crying_Face_width, Loudly_Crying_Face_height}, // 😭 Loudly Crying Face
{"\U0001F92E", vomiting, vomiting_width, vomiting_height}, // 🤮 Face Vomiting
{"\U0001F60E", cool, cool_width, cool_height}, // 😎 Smiling Face with Sunglasses
{"\U0001F440", eyes, eyes_width, eyes_height}, // 👀 Eyes
{"\U0001F441\uFE0F", eye, eye_width, eye_height}, // 👁️ Eye
// --- Gestures and People --- // --- Gestures and People ---
{"\U0001F44B", wave_icon, wave_icon_width, wave_icon_height}, // 👋 Waving Hand {"\U0001F44B", wave_icon, wave_icon_width, wave_icon_height}, // 👋 Waving Hand
{"\u270C\uFE0F", peace_sign, peace_sign_width, peace_sign_height}, // ✌️ Victory Hand {"\u270C\uFE0F", peace_sign, peace_sign_width, peace_sign_height}, // ✌️ Victory Hand
{"\U0001F596", vulcan_salute, vulcan_salute_width, vulcan_salute_height}, // 🖖 Vulcan Salute {"\U0001F596", vulcan_salute, vulcan_salute_width, vulcan_salute_height}, // 🖖 Vulcan Salute
{"\U0001F64F", praying, praying_width, praying_height}, // 🙏 Praying Hands {"\U0001F64F", Praying, Praying_width, Praying_height}, // 🙏 Praying Hands
{"\U0001F4AA", strong, strong_width, strong_height}, // 💪 Flexed Biceps
{"\U0001F937", shrug, shrug_width, shrug_height}, // 🤷 Person Shrugging
{"\U0001F920", cowboy, cowboy_width, cowboy_height}, // 🤠 Cowboy Hat Face {"\U0001F920", cowboy, cowboy_width, cowboy_height}, // 🤠 Cowboy Hat Face
{"\U0001F3A7", deadmau5, deadmau5_width, deadmau5_height}, // 🎧 Headphones {"\U0001F3A7", deadmau5, deadmau5_width, deadmau5_height}, // 🎧 Headphones
// --- Symbols ---
{"\u2714\uFE0F", check_mark, check_mark_width, check_mark_height}, // ✔️ Check Mark
{"\u2705", check_mark, check_mark_width, check_mark_height}, // ✅ Check Mark Button
{"\u2611\uFE0F", check_mark, check_mark_width, check_mark_height}, // ☑️ Check Box with Check
{"\U0001F3E0", house, house_width, house_height}, // 🏠 House
// --- Weather --- // --- Weather ---
{"\u2600", sun, sun_width, sun_height}, // ☀ Sun (without variation selector) {"\u2600", sun, sun_width, sun_height}, // ☀ Sun (without variation selector)
{"\u2600\uFE0F", sun, sun_width, sun_height}, // ☀️ Sun (with variation selector) {"\u2600\uFE0F", sun, sun_width, sun_height}, // ☀️ Sun (with variation selector)
{"\U0001F327\uFE0F", rain, rain_width, rain_height}, // 🌧️ Cloud with Rain {"\U0001F327\uFE0F", rain, rain_width, rain_height}, // 🌧️ Cloud with Rain
{"\u2601\uFE0F", cloud, cloud_width, cloud_height}, // ☁️ Cloud {"\u2601\uFE0F", cloud, cloud_width, cloud_height}, // ☁️ Cloud
{"\U0001F32B\uFE0F", fog, fog_width, fog_height}, // 🌫️ Fog {"\U0001F32B\uFE0F", fog, fog_width, fog_height}, // 🌫️ Fog
{"\u2744\uFE0F", snowflake, snowflake_width, snowflake_height}, // ❄️ Snowflake
{"\U0001F4A7", drop, drop_width, drop_height}, // 💧 Droplet
{"\U0001F321\uFE0F", thermometer, thermometer_width, thermometer_height}, // 🌡️ Thermometer
{"\U0001F326\uFE0F", sun_behind_raincloud, sun_behind_raincloud_width,
sun_behind_raincloud_height}, // 🌦️ Sun Behind Rain Cloud
{"\u26C5", sun_behind_cloud, sun_behind_cloud_width, sun_behind_cloud_height}, // ⛅ Sun Behind Cloud
{"\u26C5\uFE0F", sun_behind_cloud, sun_behind_cloud_width, sun_behind_cloud_height}, // ⛅️ Sun Behind Cloud
{"\U0001F328\uFE0F", cloud_with_snow, cloud_with_snow_width, cloud_with_snow_height}, // 🌨️ Cloud with Snow
{"\U0001F329\uFE0F", cloud_with_lightning, cloud_with_lightning_width,
cloud_with_lightning_height}, // 🌩️ Cloud with Lightning
{"\u26C8", cloud_with_lightning_rain, cloud_with_lightning_rain_width,
cloud_with_lightning_rain_height}, // ⛈ Cloud with Lightning and Rain
{"\u26C8\uFE0F", cloud_with_lightning_rain, cloud_with_lightning_rain_width,
cloud_with_lightning_rain_height}, // ⛈️ Cloud with Lightning and Rain
{"\U0001F32C\uFE0F", wind_face, wind_face_width, wind_face_height}, // 🌬️ Wind Face
// --- Moon Phases ---
{"\U0001F311", new_moon, new_moon_width, new_moon_height}, // 🌑 New Moon
{"\U0001F312", waxing_crescent_moon, waxing_crescent_moon_width, waxing_crescent_moon_height}, // 🌒 Waxing Crescent Moon
{"\U0001F313", first_quarter_moon, first_quarter_moon_width, first_quarter_moon_height}, // 🌓 First Quarter Moon
{"\U0001F314", waxing_gibbous_moon, waxing_gibbous_moon_width, waxing_gibbous_moon_height}, // 🌔 Waxing Gibbous Moon
{"\U0001F315", full_moon, full_moon_width, full_moon_height}, // 🌕 Full Moon
{"\U0001F316", waning_gibbous_moon, waning_gibbous_moon_width, waning_gibbous_moon_height}, // 🌖 Waning Gibbous Moon
{"\U0001F317", last_quarter_moon, last_quarter_moon_width, last_quarter_moon_height}, // 🌗 Last Quarter Moon
{"\U0001F318", waning_crescent_moon, waning_crescent_moon_width, waning_crescent_moon_height}, // 🌘 Waning Crescent Moon
{"\U0001F31B", first_quarter_moon_face, first_quarter_moon_face_width,
first_quarter_moon_face_height}, // 🌛 First Quarter Moon Face
// --- Misc Faces --- // --- Misc Faces ---
{"\U0001F608", devil, devil_width, devil_height}, // 😈 Smiling Face with Horns {"\U0001F608", devil, devil_width, devil_height}, // 😈 Smiling Face with Horns
@@ -107,49 +67,13 @@ const Emote emotes[] = {
{"\U0001F498", heart, heart_width, heart_height}, // 💘 Heart with Arrow {"\U0001F498", heart, heart_width, heart_height}, // 💘 Heart with Arrow
// --- Objects --- // --- Objects ---
{"\U0001F4A9", poo, poo_width, poo_height}, // 💩 Pile of Poo {"\U0001F4A9", poo, poo_width, poo_height}, // 💩 Pile of Poo
{"\U0001F514", bell_icon, bell_icon_width, bell_icon_height}, // 🔔 Bell {"\U0001F514", bell_icon, bell_icon_width, bell_icon_height}, // 🔔 Bell
{"\U0001F4CB", clipboard, clipboard_width, clipboard_height}, // 📋 Clipboard {"\U0001F36A", cookie, cookie_width, cookie_height}, // 🍪 Cookie
{"\U0001F36A", cookie, cookie_width, cookie_height}, // 🍪 Cookie {"\U0001F525", Fire, Fire_width, Fire_height}, // 🔥 Fire
{"\U0001F370", shortcake, shortcake_width, shortcake_height}, // 🍰 Shortcake {"\u2728", Sparkles, Sparkles_width, Sparkles_height}, // Sparkles
{"\U0001F351", peach, peach_width, peach_height}, // 🍑 Peach {"\U0001F573\uFE0F", hole, hole_width, hole_height}, // 🕳️ Hole
{"\U0001F983", turkey, turkey_width, turkey_height}, // 🦃 Turkey {"\U0001F3B3", bowling, bowling_width, bowling_height} // 🎳 Bowling
{"\U0001F357", turkey_leg, turkey_leg_width, turkey_leg_height}, // 🍗 Poultry Leg
{"\U0001F525", fire, fire_width, fire_height}, // 🔥 Fire
{"\u2728", sparkles, sparkles_width, sparkles_height}, // ✨ Sparkles
{"\U0001F573\uFE0F", hole, hole_width, hole_height}, // 🕳️ Hole
{"\U0001F3B3", bowling, bowling_width, bowling_height}, // 🎳 Bowling
// --- Arrows ---
{"\u2193", downwards_arrow, downwards_arrow_width, downwards_arrow_height}, // ↓ Downwards Arrow
{"\u2193\uFE0E", downwards_arrow, downwards_arrow_width, downwards_arrow_height}, // ↓︎ Downwards Arrow (text)
{"\u2193\uFE0F", downwards_arrow, downwards_arrow_width, downwards_arrow_height}, // ↓️ Downwards Arrow (emoji)
{"\u2199", south_west_arrow, south_west_arrow_width, south_west_arrow_height}, // ↙ South West Arrow
{"\u2199\uFE0E", south_west_arrow, south_west_arrow_width, south_west_arrow_height}, // ↙︎ South West Arrow (text)
{"\u2199\uFE0F", south_west_arrow, south_west_arrow_width, south_west_arrow_height}, // ↙️ South West Arrow (emoji)
{"\u2190", leftwards_arrow, leftwards_arrow_width, leftwards_arrow_height}, // ← Leftwards Arrow
{"\u2190\uFE0E", leftwards_arrow, leftwards_arrow_width, leftwards_arrow_height}, // ←︎ Leftwards Arrow (text)
{"\u2190\uFE0F", leftwards_arrow, leftwards_arrow_width, leftwards_arrow_height}, // ←️ Leftwards Arrow (emoji)
{"\u2196", north_west_arrow, north_west_arrow_width, north_west_arrow_height}, // ↖ North West Arrow
{"\u2196\uFE0E", north_west_arrow, north_west_arrow_width, north_west_arrow_height}, // ↖︎ North West Arrow (text)
{"\u2196\uFE0F", north_west_arrow, north_west_arrow_width, north_west_arrow_height}, // ↖️ North West Arrow (emoji)
{"\u2191", upwards_arrow, upwards_arrow_width, upwards_arrow_height}, // ↑ Upwards Arrow
{"\u2191\uFE0E", upwards_arrow, upwards_arrow_width, upwards_arrow_height}, // ↑︎ Upwards Arrow (text)
{"\u2191\uFE0F", upwards_arrow, upwards_arrow_width, upwards_arrow_height}, // ↑️ Upwards Arrow (emoji)
{"\u2197", north_east_arrow, north_east_arrow_width, north_east_arrow_height}, // ↗ North East Arrow
{"\u2197\uFE0E", north_east_arrow, north_east_arrow_width, north_east_arrow_height}, // ↗︎ North East Arrow (text)
{"\u2197\uFE0F", north_east_arrow, north_east_arrow_width, north_east_arrow_height}, // ↗️ North East Arrow (emoji)
{"\u2192", rightwards_arrow, rightwards_arrow_width, rightwards_arrow_height}, // → Rightwards Arrow
{"\u2192\uFE0E", rightwards_arrow, rightwards_arrow_width, rightwards_arrow_height}, // →︎ Rightwards Arrow (text)
{"\u2192\uFE0F", rightwards_arrow, rightwards_arrow_width, rightwards_arrow_height}, // →️ Rightwards Arrow (emoji)
{"\u2198", south_east_arrow, south_east_arrow_width, south_east_arrow_height}, // ↘ South East Arrow
{"\u2198\uFE0E", south_east_arrow, south_east_arrow_width, south_east_arrow_height}, // ↘︎ South East Arrow (text)
{"\u2198\uFE0F", south_east_arrow, south_east_arrow_width, south_east_arrow_height}, // ↘️ South East Arrow (emoji)
// --- Halloween ---
{"\U0001F383", jack_o_lantern, jack_o_lantern_width, jack_o_lantern_height}, // 🎃 Jack-O-Lantern
{"\U0001F47B", ghost, ghost_width, ghost_height}, // 👻 Ghost
{"\U0001F480", skull, skull_width, skull_height} // 💀 Skull
#endif #endif
}; };
@@ -164,23 +88,23 @@ const unsigned char thumbdown[] PROGMEM = {0xF0, 0x1F, 0x08, 0x20, 0x06, 0x30, 0
0x40, 0x06, 0x70, 0x06, 0x40, 0x06, 0x3F, 0x18, 0x02, 0x20, 0x02, 0x40, 0x06, 0x70, 0x06, 0x40, 0x06, 0x3F, 0x18, 0x02, 0x20, 0x02,
0x40, 0x04, 0x80, 0x04, 0x80, 0x04, 0x00, 0x03, 0x00, 0x00}; 0x40, 0x04, 0x80, 0x04, 0x80, 0x04, 0x00, 0x03, 0x00, 0x00};
const unsigned char smiling_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52, const unsigned char Smiling_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
0x4A, 0x02, 0x40, 0x02, 0x40, 0x22, 0x44, 0x22, 0x44, 0xC2, 0x43, 0x4A, 0x02, 0x40, 0x02, 0x40, 0x22, 0x44, 0x22, 0x44, 0xC2, 0x43,
0x04, 0x20, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0x04, 0x20, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char grinning[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42, const unsigned char Grinning[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
0x42, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44, 0x42, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char slightly_smiling[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42, const unsigned char Slightly_Smiling[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
0x42, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44, 0x42, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char winking_face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x20, 0x42, const unsigned char Winking_Face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x20, 0x42,
0x46, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44, 0x46, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char grinning_smiling_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52, const unsigned char Grinning_Smiling_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
0x4A, 0x02, 0x40, 0xFA, 0x5F, 0x0A, 0x50, 0x0A, 0x50, 0x12, 0x48, 0x4A, 0x02, 0x40, 0xFA, 0x5F, 0x0A, 0x50, 0x0A, 0x50, 0x12, 0x48,
0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
@@ -188,7 +112,7 @@ const unsigned char heart_smile[] PROGMEM = {0x00, 0x00, 0x6C, 0x07, 0x7C, 0x18,
0x0A, 0x02, 0xD8, 0x02, 0xF8, 0x22, 0xFC, 0x20, 0x74, 0xDB, 0x23, 0x0A, 0x02, 0xD8, 0x02, 0xF8, 0x22, 0xFC, 0x20, 0x74, 0xDB, 0x23,
0x1F, 0x00, 0x1F, 0x20, 0x0E, 0x18, 0xE4, 0x07, 0x00, 0x00}; 0x1F, 0x00, 0x1F, 0x20, 0x0E, 0x18, 0xE4, 0x07, 0x00, 0x00};
const unsigned char heart_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x54, 0x2A, 0xFA, const unsigned char Heart_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x54, 0x2A, 0xFA,
0x5F, 0x72, 0x4E, 0x22, 0x44, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x5F, 0x72, 0x4E, 0x22, 0x44, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48,
0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
@@ -204,19 +128,19 @@ const unsigned char haha[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04,
0x4A, 0x0A, 0x50, 0x0E, 0x70, 0xF2, 0x4F, 0x12, 0x48, 0x32, 0x44, 0x4A, 0x0A, 0x50, 0x0E, 0x70, 0xF2, 0x4F, 0x12, 0x48, 0x32, 0x44,
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char rofl[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x84, 0x21, 0x84, 0x20, 0x02, const unsigned char ROFL[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x84, 0x21, 0x84, 0x20, 0x02,
0x4C, 0x02, 0x4A, 0x1A, 0x49, 0x8A, 0x48, 0x42, 0x48, 0x22, 0x44, 0x4C, 0x02, 0x4A, 0x1A, 0x49, 0x8A, 0x48, 0x42, 0x48, 0x22, 0x44,
0xE4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0xE4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char smiling_closed_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x42, const unsigned char Smiling_Closed_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x42,
0x42, 0x22, 0x44, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44, 0x42, 0x22, 0x44, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char grinning_smiling_eyes_2[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52, const unsigned char Grinning_SmilingEyes2[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
0x4A, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44, 0x4A, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char loudly_crying_face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x34, 0x2C, 0x4A, const unsigned char Loudly_Crying_Face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x34, 0x2C, 0x4A,
0x52, 0x12, 0x48, 0x12, 0x48, 0x92, 0x49, 0x52, 0x4A, 0x52, 0x4A, 0x52, 0x12, 0x48, 0x12, 0x48, 0x92, 0x49, 0x52, 0x4A, 0x52, 0x4A,
0x54, 0x2A, 0x94, 0x29, 0x18, 0x18, 0xF0, 0x0F, 0x00, 0x00}; 0x54, 0x2A, 0x94, 0x29, 0x18, 0x18, 0xF0, 0x0F, 0x00, 0x00};
@@ -268,7 +192,7 @@ const unsigned char cookie[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04
0x40, 0x02, 0x58, 0x82, 0x5B, 0x92, 0x43, 0x82, 0x43, 0x02, 0x40, 0x40, 0x02, 0x58, 0x82, 0x5B, 0x92, 0x43, 0x82, 0x43, 0x02, 0x40,
0x64, 0x28, 0x64, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00}; 0x64, 0x28, 0x64, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char fire[] PROGMEM = {0x30, 0x00, 0xF0, 0x00, 0xF8, 0x03, 0xF8, 0x07, 0xFC, 0x1F, 0xFC, const unsigned char Fire[] PROGMEM = {0x30, 0x00, 0xF0, 0x00, 0xF8, 0x03, 0xF8, 0x07, 0xFC, 0x1F, 0xFC,
0x1F, 0xFE, 0x3E, 0x7E, 0x3E, 0x3E, 0x7C, 0x1E, 0x78, 0x1E, 0x70, 0x1F, 0xFE, 0x3E, 0x7E, 0x3E, 0x3E, 0x7C, 0x1E, 0x78, 0x1E, 0x70,
0x1C, 0x70, 0x1C, 0x70, 0x38, 0x38, 0x30, 0x38, 0x60, 0x0C}; 0x1C, 0x70, 0x1C, 0x70, 0x38, 0x38, 0x30, 0x38, 0x60, 0x0C};
@@ -276,11 +200,11 @@ const unsigned char peace_sign[] PROGMEM = {0xC0, 0x30, 0x40, 0x29, 0x40, 0x25,
0x0A, 0x54, 0x68, 0x54, 0x58, 0x54, 0x44, 0x3C, 0x22, 0x04, 0x22, 0x0A, 0x54, 0x68, 0x54, 0x58, 0x54, 0x44, 0x3C, 0x22, 0x04, 0x22,
0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00}; 0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00};
const unsigned char praying[] PROGMEM = {0x00, 0x00, 0x40, 0x02, 0xA0, 0x05, 0x90, 0x09, 0x90, 0x09, 0x90, const unsigned char Praying[] PROGMEM = {0x00, 0x00, 0x40, 0x02, 0xA0, 0x05, 0x90, 0x09, 0x90, 0x09, 0x90,
0x09, 0x98, 0x19, 0x94, 0x29, 0xA4, 0x25, 0xA4, 0x25, 0x84, 0x21, 0x09, 0x98, 0x19, 0x94, 0x29, 0xA4, 0x25, 0xA4, 0x25, 0x84, 0x21,
0x84, 0x21, 0x86, 0x61, 0x4E, 0x72, 0x7F, 0x7E, 0x3F, 0xFC}; 0x84, 0x21, 0x86, 0x61, 0x4E, 0x72, 0x7F, 0x7E, 0x3F, 0xFC};
const unsigned char sparkles[] PROGMEM = {0x00, 0x00, 0x10, 0x00, 0x38, 0x04, 0x10, 0x04, 0x00, 0x0E, 0x00, const unsigned char Sparkles[] PROGMEM = {0x00, 0x00, 0x10, 0x00, 0x38, 0x04, 0x10, 0x04, 0x00, 0x0E, 0x00,
0x1F, 0x80, 0x3F, 0xE0, 0xFF, 0x80, 0x3F, 0x10, 0x1F, 0x10, 0x0E, 0x1F, 0x80, 0x3F, 0xE0, 0xFF, 0x80, 0x3F, 0x10, 0x1F, 0x10, 0x0E,
0x38, 0x04, 0xFE, 0x04, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00}; 0x38, 0x04, 0xFE, 0x04, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
@@ -303,179 +227,7 @@ const unsigned char bowling[] PROGMEM = {0x00, 0x38, 0x00, 0x44, 0x00, 0x44, 0x0
const unsigned char vulcan_salute[] PROGMEM = {0x08, 0x02, 0x16, 0x0D, 0x15, 0x15, 0x15, 0x15, 0xA9, 0x12, 0x4A, const unsigned char vulcan_salute[] PROGMEM = {0x08, 0x02, 0x16, 0x0D, 0x15, 0x15, 0x15, 0x15, 0xA9, 0x12, 0x4A,
0x0A, 0x02, 0x38, 0x04, 0x48, 0x04, 0x44, 0x04, 0x22, 0x04, 0x22, 0x0A, 0x02, 0x38, 0x04, 0x48, 0x04, 0x44, 0x04, 0x22, 0x04, 0x22,
0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00}; 0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00};
const unsigned char jack_o_lantern[] PROGMEM = {0xC0, 0x00, 0x80, 0x01, 0xB8, 0x1D, 0xC4, 0x23, 0x22, 0x44, 0x05,
0xA0, 0x31, 0x8C, 0x51, 0x8A, 0x61, 0x86, 0x09, 0x90, 0xB9, 0x9D,
0x49, 0x92, 0xB2, 0x4D, 0x42, 0x42, 0x04, 0x20, 0xF8, 0x1F};
const unsigned char ghost[] PROGMEM = {0xC0, 0x03, 0xF0, 0x0F, 0xF8, 0x1F, 0xDC, 0x3B, 0xBC, 0x3D, 0xDF,
0xFB, 0xFF, 0xFF, 0x1F, 0xF8, 0x1E, 0x78, 0x1C, 0x38, 0x3C, 0x3C,
0xFC, 0x3F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0x8C, 0x31};
const unsigned char skull[] PROGMEM = {0xE0, 0x07, 0xF8, 0x1F, 0xFC, 0x3F, 0xFE, 0x7F, 0xFE, 0x7F, 0xC7,
0xE3, 0x87, 0xE1, 0x87, 0xE1, 0x8F, 0xF1, 0xFE, 0x7F, 0x7C, 0x3E,
0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xF8, 0x1F, 0xB0, 0x0D};
const unsigned char vomiting[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x04, 0x20, 0x22,
0x44, 0x42, 0x42, 0x22, 0x44, 0x02, 0x40, 0x02, 0x40, 0xC2, 0x43,
0x64, 0x26, 0x64, 0x26, 0x68, 0x16, 0x50, 0x0A, 0xF8, 0x1F};
const unsigned char cool[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0xFC, 0x3F, 0xFA,
0x5F, 0x72, 0x4E, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char shortcake[] PROGMEM = {0x00, 0x00, 0x00, 0x0F, 0x80, 0x3F, 0xE0, 0xFC, 0xE0, 0xE1, 0xF0,
0xB8, 0x10, 0x87, 0xC8, 0x80, 0x3C, 0xE0, 0x06, 0x98, 0x02, 0xC7,
0xE2, 0x30, 0x1A, 0x0E, 0xC6, 0x01, 0x32, 0x00, 0x0E, 0x00};
const unsigned char caution[] PROGMEM = {0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x60, 0x06, 0x60,
0x06, 0x70, 0x0E, 0x70, 0x0E, 0x78, 0x1E, 0x78, 0x1E, 0x7C, 0x3E,
0xFC, 0x3F, 0x7E, 0x7E, 0x7E, 0x7E, 0xFC, 0x3F, 0x00, 0x00};
const unsigned char clipboard[] PROGMEM = {0xC0, 0x03, 0x7E, 0x7E, 0xC2, 0x43, 0xFA, 0x5F, 0x0A, 0x5B, 0xFA,
0x5F, 0x8A, 0x54, 0xFA, 0x5F, 0x4A, 0x58, 0xFA, 0x5F, 0x2A, 0x51,
0xFA, 0x5F, 0x0A, 0x59, 0xFA, 0x5F, 0x02, 0x40, 0xFE, 0x7F};
const unsigned char snowflake[] PROGMEM = {0x00, 0x00, 0x40, 0x01, 0x88, 0x08, 0x8C, 0x18, 0xD0, 0x05, 0x60,
0x03, 0x32, 0x26, 0x1C, 0x1C, 0x32, 0x26, 0x60, 0x03, 0xD0, 0x05,
0x8C, 0x18, 0x88, 0x08, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00};
const unsigned char drop[] PROGMEM = {0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xE0,
0x0F, 0xF0, 0x1F, 0xF0, 0x1F, 0xF8, 0x3F, 0xF8, 0x3F, 0xF8, 0x3F,
0xF8, 0x3F, 0xF0, 0x1F, 0xE0, 0x0F, 0x80, 0x03, 0x00, 0x00};
const unsigned char thermometer[] PROGMEM = {0x00, 0x00, 0x0C, 0x00, 0x16, 0x00, 0x2E, 0x00, 0x5C, 0x00, 0xB8,
0x00, 0x70, 0x01, 0xE0, 0x02, 0xC0, 0x05, 0x80, 0x3B, 0x00, 0x47,
0x00, 0xBE, 0x00, 0x9E, 0x00, 0xBE, 0x00, 0x7C, 0x00, 0x38};
const unsigned char sun_behind_raincloud[] PROGMEM = {0xC0, 0x03, 0x20, 0x04, 0x10, 0x0E, 0x38, 0x1F, 0xFC, 0x37, 0xEE,
0x77, 0xDE, 0x7B, 0x3E, 0x7C, 0xFC, 0x3F, 0x00, 0x00, 0x48, 0x12,
0x48, 0x12, 0x24, 0x09, 0x24, 0x09, 0x00, 0x00, 0x00, 0x00};
const unsigned char sun_behind_cloud[] PROGMEM = {0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x04, 0x0E, 0x3C, 0x1B, 0xFC,
0x3B, 0xFE, 0x7B, 0xFA, 0x7B, 0xF6, 0x7D, 0x0C, 0x3E, 0xF8, 0x1F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char cloud_with_snow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC, 0x3F, 0xFE,
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x00, 0x08, 0x02,
0x40, 0x10, 0x00, 0x00, 0x24, 0x09, 0x00, 0x00, 0x00, 0x00};
const unsigned char cloud_with_lightning[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC, 0x3F, 0xFE,
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x01, 0x80, 0x01,
0x80, 0x01, 0xC0, 0x07, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01};
const unsigned char cloud_with_lightning_rain[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC, 0x3F, 0xFE,
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x01, 0x90, 0x21,
0x90, 0x21, 0xC8, 0x17, 0x08, 0x13, 0x00, 0x03, 0x00, 0x01};
const unsigned char wind_face[] PROGMEM = {0xFF, 0x00, 0x01, 0x01, 0x01, 0x01, 0xF9, 0x00, 0xF9, 0x01, 0xD9,
0x01, 0x99, 0x01, 0xF9, 0x01, 0xF9, 0x33, 0xFD, 0x4B, 0xFD, 0x85,
0xFD, 0x9A, 0xFD, 0x75, 0xFD, 0x09, 0xFD, 0x01, 0xFF, 0x00};
const unsigned char new_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x04, 0x20, 0x02,
0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40,
0x04, 0x20, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char waxing_crescent_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x1F, 0x04, 0x3E, 0x04, 0x3C, 0x02,
0x78, 0x02, 0x78, 0x02, 0x78, 0x02, 0x78, 0x02, 0x78, 0x02, 0x78,
0x04, 0x3C, 0x04, 0x3E, 0x18, 0x1F, 0xE0, 0x07, 0x00, 0x00};
const unsigned char first_quarter_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x1F, 0x04, 0x3F, 0x04, 0x3F, 0x02,
0x7F, 0x02, 0x7F, 0x02, 0x7F, 0x02, 0x7F, 0x02, 0x7F, 0x02, 0x7F,
0x04, 0x3F, 0x04, 0x3F, 0x18, 0x1F, 0xE0, 0x07, 0x00, 0x00};
const unsigned char waxing_gibbous_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x1F, 0x84, 0x3F, 0xC4, 0x3F, 0xC2,
0x7F, 0xC2, 0x7F, 0xC2, 0x7F, 0xC2, 0x7F, 0xC2, 0x7F, 0xC2, 0x7F,
0xC4, 0x3F, 0x84, 0x3F, 0x18, 0x1F, 0xE0, 0x07, 0x00, 0x00};
const unsigned char full_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x1F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFE,
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F,
0xFC, 0x3F, 0xFC, 0x3F, 0xF8, 0x1F, 0xE0, 0x07, 0x00, 0x00};
const unsigned char waning_gibbous_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x18, 0xFC, 0x21, 0xFC, 0x23, 0xFE,
0x43, 0xFE, 0x43, 0xFE, 0x43, 0xFE, 0x43, 0xFE, 0x43, 0xFE, 0x43,
0xFC, 0x23, 0xFC, 0x21, 0xF8, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char last_quarter_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x18, 0xFC, 0x20, 0xFC, 0x20, 0xFE,
0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x40,
0xFC, 0x20, 0xFC, 0x20, 0xF8, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char waning_crescent_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x18, 0x7C, 0x20, 0x3C, 0x20, 0x1E,
0x40, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x40,
0x3C, 0x20, 0x7C, 0x20, 0xF8, 0x18, 0xE0, 0x07, 0x00, 0x00};
const unsigned char first_quarter_moon_face[] PROGMEM = {0x00, 0x0F, 0x00, 0x12, 0x00, 0x24, 0x00, 0x44, 0x00, 0x48, 0x00,
0x88, 0x00, 0x84, 0x80, 0x93, 0x80, 0x80, 0x03, 0x81, 0x8D, 0x80,
0x71, 0x40, 0x82, 0x41, 0x02, 0x20, 0x0C, 0x18, 0xF0, 0x07};
const unsigned char peach[] PROGMEM = {0x70, 0x0F, 0x88, 0x10, 0x78, 0x1F, 0x88, 0x11, 0x04, 0x22, 0x02,
0x44, 0x02, 0x44, 0x02, 0x44, 0x02, 0x44, 0x02, 0x42, 0x02, 0x40,
0x04, 0x20, 0x04, 0x20, 0x08, 0x10, 0x30, 0x0C, 0xC0, 0x03};
const unsigned char turkey[] PROGMEM = {0x00, 0x00, 0x38, 0x00, 0x44, 0x38, 0x56, 0x54, 0x45, 0x52, 0xE2,
0x21, 0x2C, 0x56, 0x14, 0x58, 0x0A, 0x37, 0x86, 0x68, 0x82, 0x50,
0x82, 0x20, 0x04, 0x41, 0xF8, 0x7F, 0x40, 0x02, 0xF0, 0x07};
const unsigned char turkey_leg[] PROGMEM = {0x0C, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x2F, 0x00, 0x46, 0x00, 0x88,
0x01, 0x10, 0x0E, 0x20, 0x30, 0x20, 0x40, 0x40, 0x40, 0x40, 0x80,
0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x43, 0x00, 0x3C};
const unsigned char south_west_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1C, 0x00, 0x3E, 0x00,
0x1F, 0x80, 0x0F, 0xC2, 0x07, 0xE6, 0x03, 0xFE, 0x01, 0xFE, 0x00,
0x7E, 0x00, 0x7E, 0x00, 0xFE, 0x00, 0xFE, 0x01, 0x00, 0x00};
const unsigned char south_east_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x7C, 0x00, 0xF8,
0x00, 0xF0, 0x01, 0xE0, 0x43, 0xC0, 0x67, 0x80, 0x7F, 0x00, 0x7F,
0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00};
const unsigned char north_west_arrow[] PROGMEM = {0x00, 0x00, 0xFE, 0x01, 0xFE, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0xFE,
0x00, 0xFE, 0x01, 0xE6, 0x03, 0xC2, 0x07, 0x80, 0x0F, 0x00, 0x1F,
0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
const unsigned char north_east_arrow[] PROGMEM = {0x00, 0x00, 0x80, 0x7F, 0x00, 0x7F, 0x00, 0x7E, 0x00, 0x7E, 0x00,
0x7F, 0x80, 0x7F, 0xC0, 0x67, 0xE0, 0x43, 0xF0, 0x01, 0xF8, 0x00,
0x7C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char downwards_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xFC, 0x3F,
0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01};
const unsigned char leftwards_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x38, 0x00, 0x3C,
0x00, 0xFE, 0x3F, 0xFF, 0x3F, 0xFF, 0x3F, 0xFE, 0x3F, 0x3C, 0x00,
0x38, 0x00, 0x30, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char upwards_arrow[] PROGMEM = {0x80, 0x01, 0xC0, 0x03, 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0xFC,
0x3F, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03,
0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00};
const unsigned char rightwards_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x1C, 0x00,
0x3C, 0xFC, 0x7F, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0x7F, 0x00, 0x3C,
0x00, 0x1C, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
const unsigned char strong[] PROGMEM = {0x38, 0x00, 0x44, 0x00, 0x62, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3A,
0x00, 0x11, 0x3C, 0x11, 0x42, 0xD1, 0x81, 0x31, 0x82, 0x11, 0x82,
0x21, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x40, 0xFC, 0x3F};
const unsigned char check_mark[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x70, 0x00, 0x3C, 0x00,
0x1E, 0x00, 0x0F, 0x80, 0x07, 0xC3, 0x03, 0xEE, 0x03, 0xFC, 0x01,
0xF8, 0x00, 0xF0, 0x00, 0x70, 0x00, 0x60, 0x00, 0x20, 0x00};
const unsigned char house[] PROGMEM = {0x80, 0x01, 0x5C, 0x02, 0x34, 0x04, 0x14, 0x08, 0x0C, 0x10, 0x04,
0x20, 0x02, 0x40, 0xFF, 0xFF, 0x02, 0x40, 0x7A, 0x5F, 0x4A, 0x55,
0x4A, 0x5F, 0x6A, 0x55, 0x4A, 0x5F, 0x4A, 0x40, 0xFE, 0x7F};
const unsigned char shrug[] PROGMEM = {0xC0, 0x03, 0x20, 0x04, 0x10, 0x08, 0x50, 0x0A, 0x10, 0x08, 0x90,
0x09, 0x27, 0xE4, 0x49, 0x92, 0xAA, 0x55, 0x16, 0x68, 0x12, 0x48,
0x02, 0x40, 0x02, 0x40, 0x0C, 0x30, 0x08, 0x10, 0xF8, 0x1F};
const unsigned char eyes[] PROGMEM = {0x00, 0x00, 0x3C, 0x3C, 0x42, 0x42, 0x81, 0x81, 0x85, 0x85, 0x8F,
0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
0x85, 0x85, 0x81, 0x81, 0x42, 0x42, 0x3C, 0x3C, 0x00, 0x00};
const unsigned char eye[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0xF8, 0x1F, 0xF4,
0x2F, 0x7A, 0x5E, 0x39, 0x9C, 0x39, 0x9C, 0x7A, 0x5E, 0xF4, 0x2F,
0xF8, 0x1F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif #endif
} // namespace graphics } // namespace graphics
#endif #endif

View File

@@ -22,33 +22,33 @@ extern const int numEmotes;
extern const unsigned char thumbup[] PROGMEM; extern const unsigned char thumbup[] PROGMEM;
extern const unsigned char thumbdown[] PROGMEM; extern const unsigned char thumbdown[] PROGMEM;
#define smiling_eyes_height 16 #define Smiling_Eyes_height 16
#define smiling_eyes_width 16 #define Smiling_Eyes_width 16
extern const unsigned char smiling_eyes[] PROGMEM; extern const unsigned char Smiling_Eyes[] PROGMEM;
#define grinning_height 16 #define Grinning_height 16
#define grinning_width 16 #define Grinning_width 16
extern const unsigned char grinning[] PROGMEM; extern const unsigned char Grinning[] PROGMEM;
#define slightly_smiling_height 16 #define Slightly_Smiling_height 16
#define slightly_smiling_width 16 #define Slightly_Smiling_width 16
extern const unsigned char slightly_smiling[] PROGMEM; extern const unsigned char Slightly_Smiling[] PROGMEM;
#define winking_face_height 16 #define Winking_Face_height 16
#define winking_face_width 16 #define Winking_Face_width 16
extern const unsigned char winking_face[] PROGMEM; extern const unsigned char Winking_Face[] PROGMEM;
#define grinning_smiling_eyes_height 16 #define Grinning_Smiling_Eyes_height 16
#define grinning_smiling_eyes_width 16 #define Grinning_Smiling_Eyes_width 16
extern const unsigned char grinning_smiling_eyes[] PROGMEM; extern const unsigned char Grinning_Smiling_Eyes[] PROGMEM;
#define heart_smile_height 16 #define heart_smile_height 16
#define heart_smile_width 16 #define heart_smile_width 16
extern const unsigned char heart_smile[] PROGMEM; extern const unsigned char heart_smile[] PROGMEM;
#define heart_eyes_height 16 #define Heart_eyes_height 16
#define heart_eyes_width 16 #define Heart_eyes_width 16
extern const unsigned char heart_eyes[] PROGMEM; extern const unsigned char Heart_eyes[] PROGMEM;
#define question_height 16 #define question_height 16
#define question_width 16 #define question_width 16
@@ -62,21 +62,21 @@ extern const unsigned char bang[] PROGMEM;
#define haha_width 16 #define haha_width 16
extern const unsigned char haha[] PROGMEM; extern const unsigned char haha[] PROGMEM;
#define rofl_height 16 #define ROFL_height 16
#define rofl_width 16 #define ROFL_width 16
extern const unsigned char rofl[] PROGMEM; extern const unsigned char ROFL[] PROGMEM;
#define smiling_closed_eyes_height 16 #define Smiling_Closed_Eyes_height 16
#define smiling_closed_eyes_width 16 #define Smiling_Closed_Eyes_width 16
extern const unsigned char smiling_closed_eyes[] PROGMEM; extern const unsigned char Smiling_Closed_Eyes[] PROGMEM;
#define grinning_smiling_eyes_2_height 16 #define Grinning_SmilingEyes2_height 16
#define grinning_smiling_eyes_2_width 16 #define Grinning_SmilingEyes2_width 16
extern const unsigned char grinning_smiling_eyes_2[] PROGMEM; extern const unsigned char Grinning_SmilingEyes2[] PROGMEM;
#define loudly_crying_face_height 16 #define Loudly_Crying_Face_height 16
#define loudly_crying_face_width 16 #define Loudly_Crying_Face_width 16
extern const unsigned char loudly_crying_face[] PROGMEM; extern const unsigned char Loudly_Crying_Face[] PROGMEM;
#define wave_icon_height 16 #define wave_icon_height 16
#define wave_icon_width 16 #define wave_icon_width 16
@@ -126,21 +126,21 @@ extern const unsigned char bell_icon[] PROGMEM;
#define cookie_height 16 #define cookie_height 16
extern const unsigned char cookie[] PROGMEM; extern const unsigned char cookie[] PROGMEM;
#define fire_width 16 #define Fire_width 16
#define fire_height 16 #define Fire_height 16
extern const unsigned char fire[] PROGMEM; extern const unsigned char Fire[] PROGMEM;
#define peace_sign_width 16 #define peace_sign_width 16
#define peace_sign_height 16 #define peace_sign_height 16
extern const unsigned char peace_sign[] PROGMEM; extern const unsigned char peace_sign[] PROGMEM;
#define praying_width 16 #define Praying_width 16
#define praying_height 16 #define Praying_height 16
extern const unsigned char praying[] PROGMEM; extern const unsigned char Praying[] PROGMEM;
#define sparkles_width 16 #define Sparkles_width 16
#define sparkles_height 16 #define Sparkles_height 16
extern const unsigned char sparkles[] PROGMEM; extern const unsigned char Sparkles[] PROGMEM;
#define clown_width 16 #define clown_width 16
#define clown_height 16 #define clown_height 16
@@ -161,178 +161,6 @@ extern const unsigned char bowling[] PROGMEM;
#define vulcan_salute_width 16 #define vulcan_salute_width 16
#define vulcan_salute_height 16 #define vulcan_salute_height 16
extern const unsigned char vulcan_salute[] PROGMEM; extern const unsigned char vulcan_salute[] PROGMEM;
#define jack_o_lantern_width 16
#define jack_o_lantern_height 16
extern const unsigned char jack_o_lantern[] PROGMEM;
#define ghost_width 16
#define ghost_height 16
extern const unsigned char ghost[] PROGMEM;
#define skull_width 16
#define skull_height 16
extern const unsigned char skull[] PROGMEM;
#define vomiting_width 16
#define vomiting_height 16
extern const unsigned char vomiting[] PROGMEM;
#define cool_width 16
#define cool_height 16
extern const unsigned char cool[] PROGMEM;
#define shortcake_width 16
#define shortcake_height 16
extern const unsigned char shortcake[] PROGMEM;
#define caution_width 16
#define caution_height 16
extern const unsigned char caution[] PROGMEM;
#define clipboard_width 16
#define clipboard_height 16
extern const unsigned char clipboard[] PROGMEM;
#define snowflake_width 16
#define snowflake_height 16
extern const unsigned char snowflake[] PROGMEM;
#define drop_width 16
#define drop_height 16
extern const unsigned char drop[] PROGMEM;
#define thermometer_width 16
#define thermometer_height 16
extern const unsigned char thermometer[] PROGMEM;
#define sun_behind_raincloud_width 16
#define sun_behind_raincloud_height 16
extern const unsigned char sun_behind_raincloud[] PROGMEM;
#define sun_behind_cloud_width 16
#define sun_behind_cloud_height 16
extern const unsigned char sun_behind_cloud[] PROGMEM;
#define cloud_with_snow_width 16
#define cloud_with_snow_height 16
extern const unsigned char cloud_with_snow[] PROGMEM;
#define cloud_with_lightning_width 16
#define cloud_with_lightning_height 16
extern const unsigned char cloud_with_lightning[] PROGMEM;
#define cloud_with_lightning_rain_width 16
#define cloud_with_lightning_rain_height 16
extern const unsigned char cloud_with_lightning_rain[] PROGMEM;
#define wind_face_width 16
#define wind_face_height 16
extern const unsigned char wind_face[] PROGMEM;
#define new_moon_width 16
#define new_moon_height 16
extern const unsigned char new_moon[] PROGMEM;
#define waxing_crescent_moon_width 16
#define waxing_crescent_moon_height 16
extern const unsigned char waxing_crescent_moon[] PROGMEM;
#define first_quarter_moon_width 16
#define first_quarter_moon_height 16
extern const unsigned char first_quarter_moon[] PROGMEM;
#define waxing_gibbous_moon_width 16
#define waxing_gibbous_moon_height 16
extern const unsigned char waxing_gibbous_moon[] PROGMEM;
#define full_moon_width 16
#define full_moon_height 16
extern const unsigned char full_moon[] PROGMEM;
#define waning_gibbous_moon_width 16
#define waning_gibbous_moon_height 16
extern const unsigned char waning_gibbous_moon[] PROGMEM;
#define last_quarter_moon_width 16
#define last_quarter_moon_height 16
extern const unsigned char last_quarter_moon[] PROGMEM;
#define waning_crescent_moon_width 16
#define waning_crescent_moon_height 16
extern const unsigned char waning_crescent_moon[] PROGMEM;
#define first_quarter_moon_face_width 16
#define first_quarter_moon_face_height 16
extern const unsigned char first_quarter_moon_face[] PROGMEM;
#define peach_width 16
#define peach_height 16
extern const unsigned char peach[] PROGMEM;
#define turkey_width 16
#define turkey_height 16
extern const unsigned char turkey[] PROGMEM;
#define turkey_leg_width 16
#define turkey_leg_height 16
extern const unsigned char turkey_leg[] PROGMEM;
#define south_west_arrow_width 16
#define south_west_arrow_height 16
extern const unsigned char south_west_arrow[] PROGMEM;
#define south_east_arrow_width 16
#define south_east_arrow_height 16
extern const unsigned char south_east_arrow[] PROGMEM;
#define north_west_arrow_width 16
#define north_west_arrow_height 16
extern const unsigned char north_west_arrow[] PROGMEM;
#define north_east_arrow_width 16
#define north_east_arrow_height 16
extern const unsigned char north_east_arrow[] PROGMEM;
#define downwards_arrow_width 16
#define downwards_arrow_height 16
extern const unsigned char downwards_arrow[] PROGMEM;
#define leftwards_arrow_width 16
#define leftwards_arrow_height 16
extern const unsigned char leftwards_arrow[] PROGMEM;
#define upwards_arrow_width 16
#define upwards_arrow_height 16
extern const unsigned char upwards_arrow[] PROGMEM;
#define rightwards_arrow_width 16
#define rightwards_arrow_height 16
extern const unsigned char rightwards_arrow[] PROGMEM;
#define strong_width 16
#define strong_height 16
extern const unsigned char strong[] PROGMEM;
#define check_mark_width 16
#define check_mark_height 16
extern const unsigned char check_mark[] PROGMEM;
#define house_width 16
#define house_height 16
extern const unsigned char house[] PROGMEM;
#define shrug_width 16
#define shrug_height 16
extern const unsigned char shrug[] PROGMEM;
#define eyes_width 16
#define eyes_height 16
extern const unsigned char eyes[] PROGMEM;
#define eye_width 16
#define eye_height 16
extern const unsigned char eye[] PROGMEM;
#endif // EXCLUDE_EMOJI #endif // EXCLUDE_EMOJI
} // namespace graphics } // namespace graphics

View File

@@ -88,14 +88,8 @@ class Applet : public GFX
virtual void onForeground() {} virtual void onForeground() {}
virtual void onBackground() {} virtual void onBackground() {}
virtual void onShutdown() {} virtual void onShutdown() {}
virtual void onButtonShortPress() {} virtual void onButtonShortPress() {} // (System Applets only)
virtual void onButtonLongPress() {} virtual void onButtonLongPress() {} // (System Applets only)
virtual void onExitShort() {}
virtual void onExitLong() {}
virtual void onNavUp() {}
virtual void onNavDown() {}
virtual void onNavLeft() {}
virtual void onNavRight() {}
virtual bool approveNotification(Notification &n); // Allow an applet to veto a notification virtual bool approveNotification(Notification &n); // Allow an applet to veto a notification

View File

@@ -1,205 +0,0 @@
#ifdef MESHTASTIC_INCLUDE_INKHUD
#include "./AlignStickApplet.h"
using namespace NicheGraphics;
InkHUD::AlignStickApplet::AlignStickApplet()
{
if (!settings->joystick.aligned)
bringToForeground();
}
void InkHUD::AlignStickApplet::onRender()
{
setFont(fontMedium);
printAt(0, 0, "Align Joystick:");
setFont(fontSmall);
std::string instructions = "Move joystick in the direction indicated";
printWrapped(0, fontMedium.lineHeight() * 1.5, width(), instructions);
// Size of the region in which the joystick graphic should fit
uint16_t joyXLimit = X(0.8);
uint16_t contentH = fontMedium.lineHeight() * 1.5 + fontSmall.lineHeight() * 1;
if (getTextWidth(instructions) > width())
contentH += fontSmall.lineHeight();
uint16_t freeY = height() - contentH - fontSmall.lineHeight() * 1.2;
uint16_t joyYLimit = freeY * 0.8;
// Use the shorter of the two
uint16_t joyWidth = joyXLimit < joyYLimit ? joyXLimit : joyYLimit;
// Center the joystick graphic
uint16_t centerX = X(0.5);
uint16_t centerY = contentH + freeY * 0.5;
// Draw joystick graphic
drawStick(centerX, centerY, joyWidth);
setFont(fontSmall);
printAt(X(0.5), Y(1.0) - fontSmall.lineHeight() * 0.2, "Long press to skip", CENTER, BOTTOM);
}
// Draw a scalable joystick graphic
void InkHUD::AlignStickApplet::drawStick(uint16_t centerX, uint16_t centerY, uint16_t width)
{
if (width < 9) // too small to draw
return;
else if (width < 40) { // only draw up arrow
uint16_t chamfer = width < 20 ? 1 : 2;
// Draw filled up arrow
drawDirection(centerX, centerY - width / 4, Direction::UP, width, chamfer, BLACK);
} else { // large enough to draw the full thing
uint16_t chamfer = width < 80 ? 1 : 2;
uint16_t stroke = 3; // pixels
uint16_t arrowW = width * 0.22;
uint16_t hollowW = arrowW - stroke * 2;
// Draw center circle
fillCircle((int16_t)centerX, (int16_t)centerY, (int16_t)(width * 0.2), BLACK);
fillCircle((int16_t)centerX, (int16_t)centerY, (int16_t)(width * 0.2) - stroke, WHITE);
// Draw filled up arrow
drawDirection(centerX, centerY - width / 2, Direction::UP, arrowW, chamfer, BLACK);
// Draw down arrow
drawDirection(centerX, centerY + width / 2, Direction::DOWN, arrowW, chamfer, BLACK);
drawDirection(centerX, centerY + width / 2 - stroke, Direction::DOWN, hollowW, 0, WHITE);
// Draw left arrow
drawDirection(centerX - width / 2, centerY, Direction::LEFT, arrowW, chamfer, BLACK);
drawDirection(centerX - width / 2 + stroke, centerY, Direction::LEFT, hollowW, 0, WHITE);
// Draw right arrow
drawDirection(centerX + width / 2, centerY, Direction::RIGHT, arrowW, chamfer, BLACK);
drawDirection(centerX + width / 2 - stroke, centerY, Direction::RIGHT, hollowW, 0, WHITE);
}
}
// Draw a scalable joystick direction arrow
// a right-triangle with blunted tips
/*
_ <--point
^ / \
| / \
size / \
| / \
v |_________|
*/
void InkHUD::AlignStickApplet::drawDirection(uint16_t pointX, uint16_t pointY, Direction direction, uint16_t size,
uint16_t chamfer, Color color)
{
uint16_t chamferW = chamfer * 2 + 1;
uint16_t triangleW = size - chamferW;
// Draw arrow
switch (direction) {
case Direction::UP:
fillRect(pointX - chamfer, pointY, chamferW, triangleW, color);
fillRect(pointX - chamfer - triangleW, pointY + triangleW, chamferW + triangleW * 2, chamferW, color);
fillTriangle(pointX - chamfer, pointY, pointX - chamfer - triangleW, pointY + triangleW, pointX - chamfer,
pointY + triangleW, color);
fillTriangle(pointX + chamfer, pointY, pointX + chamfer + triangleW, pointY + triangleW, pointX + chamfer,
pointY + triangleW, color);
break;
case Direction::DOWN:
fillRect(pointX - chamfer, pointY - triangleW + 1, chamferW, triangleW, color);
fillRect(pointX - chamfer - triangleW, pointY - size + 1, chamferW + triangleW * 2, chamferW, color);
fillTriangle(pointX - chamfer, pointY, pointX - chamfer - triangleW, pointY - triangleW, pointX - chamfer,
pointY - triangleW, color);
fillTriangle(pointX + chamfer, pointY, pointX + chamfer + triangleW, pointY - triangleW, pointX + chamfer,
pointY - triangleW, color);
break;
case Direction::LEFT:
fillRect(pointX, pointY - chamfer, triangleW, chamferW, color);
fillRect(pointX + triangleW, pointY - chamfer - triangleW, chamferW, chamferW + triangleW * 2, color);
fillTriangle(pointX, pointY - chamfer, pointX + triangleW, pointY - chamfer - triangleW, pointX + triangleW,
pointY - chamfer, color);
fillTriangle(pointX, pointY + chamfer, pointX + triangleW, pointY + chamfer + triangleW, pointX + triangleW,
pointY + chamfer, color);
break;
case Direction::RIGHT:
fillRect(pointX - triangleW + 1, pointY - chamfer, triangleW, chamferW, color);
fillRect(pointX - size + 1, pointY - chamfer - triangleW, chamferW, chamferW + triangleW * 2, color);
fillTriangle(pointX, pointY - chamfer, pointX - triangleW, pointY - chamfer - triangleW, pointX - triangleW,
pointY - chamfer, color);
fillTriangle(pointX, pointY + chamfer, pointX - triangleW, pointY + chamfer + triangleW, pointX - triangleW,
pointY + chamfer, color);
break;
}
}
void InkHUD::AlignStickApplet::onForeground()
{
// Prevent most other applets from requesting update, and skip their rendering entirely
// Another system applet with a higher precedence can potentially ignore this
SystemApplet::lockRendering = true;
SystemApplet::lockRequests = true;
handleInput = true; // Intercept the button input for our applet
}
void InkHUD::AlignStickApplet::onBackground()
{
// Allow normal update behavior to resume
SystemApplet::lockRendering = false;
SystemApplet::lockRequests = false;
SystemApplet::handleInput = false;
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
// Usually, onBackground is followed by another applet's onForeground (which requests update), but not in this case
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onButtonLongPress()
{
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onExitLong()
{
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavUp()
{
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavDown()
{
inkhud->rotateJoystick(2); // 180 deg
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavLeft()
{
inkhud->rotateJoystick(3); // 270 deg
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavRight()
{
inkhud->rotateJoystick(1); // 90 deg
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
#endif

View File

@@ -1,50 +0,0 @@
#ifdef MESHTASTIC_INCLUDE_INKHUD
/*
System Applet for manually aligning the joystick with the screen
should be run at startup if the joystick is enabled
and not aligned to the screen
*/
#pragma once
#include "configuration.h"
#include "graphics/niche/InkHUD/SystemApplet.h"
namespace NicheGraphics::InkHUD
{
class AlignStickApplet : public SystemApplet
{
public:
AlignStickApplet();
void onRender() override;
void onForeground() override;
void onBackground() override;
void onButtonLongPress() override;
void onExitLong() override;
void onNavUp() override;
void onNavDown() override;
void onNavLeft() override;
void onNavRight() override;
protected:
enum Direction {
UP,
DOWN,
LEFT,
RIGHT,
};
void drawStick(uint16_t centerX, uint16_t centerY, uint16_t width);
void drawDirection(uint16_t pointX, uint16_t pointY, Direction direction, uint16_t size, uint16_t chamfer, Color color);
};
} // namespace NicheGraphics::InkHUD
#endif

View File

@@ -30,7 +30,6 @@ enum MenuAction {
TOGGLE_AUTOSHOW_APPLET, TOGGLE_AUTOSHOW_APPLET,
SET_RECENTS, SET_RECENTS,
ROTATE, ROTATE,
ALIGN_JOYSTICK,
LAYOUT, LAYOUT,
TOGGLE_BATTERY_ICON, TOGGLE_BATTERY_ICON,
TOGGLE_NOTIFICATIONS, TOGGLE_NOTIFICATIONS,

View File

@@ -178,10 +178,6 @@ void InkHUD::MenuApplet::execute(MenuItem item)
inkhud->rotate(); inkhud->rotate();
break; break;
case ALIGN_JOYSTICK:
inkhud->openAlignStick();
break;
case LAYOUT: case LAYOUT:
// Todo: smarter incrementing of tile count // Todo: smarter incrementing of tile count
settings->userTiles.count++; settings->userTiles.count++;
@@ -291,17 +287,14 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
// items.push_back(MenuItem("Display Off", MenuPage::EXIT)); // TODO // items.push_back(MenuItem("Display Off", MenuPage::EXIT)); // TODO
items.push_back(MenuItem("Save & Shut Down", MenuAction::SHUTDOWN)); items.push_back(MenuItem("Save & Shut Down", MenuAction::SHUTDOWN));
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::EXIT;
break; break;
case SEND: case SEND:
populateSendPage(); populateSendPage();
previousPage = MenuPage::ROOT;
break; break;
case CANNEDMESSAGE_RECIPIENT: case CANNEDMESSAGE_RECIPIENT:
populateRecipientPage(); populateRecipientPage();
previousPage = MenuPage::OPTIONS;
break; break;
case OPTIONS: case OPTIONS:
@@ -328,8 +321,6 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
if (settings->userTiles.maxCount > 1) if (settings->userTiles.maxCount > 1)
items.push_back(MenuItem("Layout", MenuAction::LAYOUT, MenuPage::OPTIONS)); items.push_back(MenuItem("Layout", MenuAction::LAYOUT, MenuPage::OPTIONS));
items.push_back(MenuItem("Rotate", MenuAction::ROTATE, MenuPage::OPTIONS)); items.push_back(MenuItem("Rotate", MenuAction::ROTATE, MenuPage::OPTIONS));
if (settings->joystick.enabled)
items.push_back(MenuItem("Align Joystick", MenuAction::ALIGN_JOYSTICK, MenuPage::EXIT));
items.push_back(MenuItem("Notifications", MenuAction::TOGGLE_NOTIFICATIONS, MenuPage::OPTIONS, items.push_back(MenuItem("Notifications", MenuAction::TOGGLE_NOTIFICATIONS, MenuPage::OPTIONS,
&settings->optionalFeatures.notifications)); &settings->optionalFeatures.notifications));
items.push_back(MenuItem("Battery Icon", MenuAction::TOGGLE_BATTERY_ICON, MenuPage::OPTIONS, items.push_back(MenuItem("Battery Icon", MenuAction::TOGGLE_BATTERY_ICON, MenuPage::OPTIONS,
@@ -341,24 +332,20 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
items.push_back( items.push_back(
MenuItem("12-Hour Clock", MenuAction::TOGGLE_12H_CLOCK, MenuPage::OPTIONS, &config.display.use_12h_clock)); MenuItem("12-Hour Clock", MenuAction::TOGGLE_12H_CLOCK, MenuPage::OPTIONS, &config.display.use_12h_clock));
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::ROOT;
break; break;
case APPLETS: case APPLETS:
populateAppletPage(); populateAppletPage();
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::OPTIONS;
break; break;
case AUTOSHOW: case AUTOSHOW:
populateAutoshowPage(); populateAutoshowPage();
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::OPTIONS;
break; break;
case RECENTS: case RECENTS:
populateRecentsPage(); populateRecentsPage();
previousPage = MenuPage::OPTIONS;
break; break;
case EXIT: case EXIT:
@@ -492,21 +479,12 @@ void InkHUD::MenuApplet::onButtonShortPress()
// Push the auto-close timer back // Push the auto-close timer back
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL); OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
if (!settings->joystick.enabled) { // Move menu cursor to next entry, then update
// Move menu cursor to next entry, then update if (cursorShown)
if (cursorShown) cursor = (cursor + 1) % items.size();
cursor = (cursor + 1) % items.size(); else
else cursorShown = true;
cursorShown = true; requestUpdate(Drivers::EInk::UpdateTypes::FAST);
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
} else {
if (cursorShown)
execute(items.at(cursor));
else
showPage(MenuPage::EXIT);
if (!wantsToRender())
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
} }
void InkHUD::MenuApplet::onButtonLongPress() void InkHUD::MenuApplet::onButtonLongPress()
@@ -526,62 +504,6 @@ void InkHUD::MenuApplet::onButtonLongPress()
requestUpdate(Drivers::EInk::UpdateTypes::FAST); requestUpdate(Drivers::EInk::UpdateTypes::FAST);
} }
void InkHUD::MenuApplet::onExitShort()
{
// Exit the menu
showPage(MenuPage::EXIT);
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavUp()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
// Move menu cursor to previous entry, then update
if (cursor == 0)
cursor = items.size() - 1;
else
cursor--;
if (!cursorShown)
cursorShown = true;
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavDown()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
// Move menu cursor to next entry, then update
if (cursorShown)
cursor = (cursor + 1) % items.size();
else
cursorShown = true;
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavLeft()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
// Go to the previous menu page
showPage(previousPage);
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavRight()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
if (cursorShown)
execute(items.at(cursor));
if (!wantsToRender())
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
// Dynamically create MenuItem entries for activating / deactivating Applets, for the "Applet Selection" submenu // Dynamically create MenuItem entries for activating / deactivating Applets, for the "Applet Selection" submenu
void InkHUD::MenuApplet::populateAppletPage() void InkHUD::MenuApplet::populateAppletPage()
{ {
@@ -874,4 +796,4 @@ void InkHUD::MenuApplet::freeCannedMessageResources()
cm.recipientItems.clear(); cm.recipientItems.clear();
} }
#endif #endif

View File

@@ -27,11 +27,6 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
void onBackground() override; void onBackground() override;
void onButtonShortPress() override; void onButtonShortPress() override;
void onButtonLongPress() override; void onButtonLongPress() override;
void onExitShort() override;
void onNavUp() override;
void onNavDown() override;
void onNavLeft() override;
void onNavRight() override;
void onRender() override; void onRender() override;
void show(Tile *t); // Open the menu, onto a user tile void show(Tile *t); // Open the menu, onto a user tile
@@ -57,7 +52,6 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
void freeCannedMessageResources(); // Clear MenuApplet's canned message processing data void freeCannedMessageResources(); // Clear MenuApplet's canned message processing data
MenuPage currentPage = MenuPage::ROOT; MenuPage currentPage = MenuPage::ROOT;
MenuPage previousPage = MenuPage::EXIT;
uint8_t cursor = 0; // Which menu item is currently highlighted uint8_t cursor = 0; // Which menu item is currently highlighted
bool cursorShown = false; // Is *any* item highlighted? (Root menu: no initial selection) bool cursorShown = false; // Is *any* item highlighted? (Root menu: no initial selection)
@@ -103,4 +97,4 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
} // namespace NicheGraphics::InkHUD } // namespace NicheGraphics::InkHUD
#endif #endif

View File

@@ -153,42 +153,6 @@ void InkHUD::NotificationApplet::onButtonLongPress()
inkhud->forceUpdate(EInk::UpdateTypes::FULL); inkhud->forceUpdate(EInk::UpdateTypes::FULL);
} }
void InkHUD::NotificationApplet::onExitShort()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onExitLong()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavUp()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavDown()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavLeft()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavRight()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
// Ask the WindowManager to check whether any displayed applets are already displaying the info from this notification // Ask the WindowManager to check whether any displayed applets are already displaying the info from this notification
// Called internally when we first get a "notifiable event", and then again before render, // Called internally when we first get a "notifiable event", and then again before render,
// in case autoshow swapped which applet was displayed // in case autoshow swapped which applet was displayed

View File

@@ -31,12 +31,6 @@ class NotificationApplet : public SystemApplet
void onBackground() override; void onBackground() override;
void onButtonShortPress() override; void onButtonShortPress() override;
void onButtonLongPress() override; void onButtonLongPress() override;
void onExitShort() override;
void onExitLong() override;
void onNavUp() override;
void onNavDown() override;
void onNavLeft() override;
void onNavRight() override;
int onReceiveTextMessage(const meshtastic_MeshPacket *p); int onReceiveTextMessage(const meshtastic_MeshPacket *p);

View File

@@ -112,21 +112,12 @@ void InkHUD::TipsApplet::onRender()
setFont(fontSmall); setFont(fontSmall);
int16_t cursorY = fontMedium.lineHeight() * 1.5; int16_t cursorY = fontMedium.lineHeight() * 1.5;
if (!settings->joystick.enabled) { printAt(0, cursorY, "User Button");
printAt(0, cursorY, "User Button"); cursorY += fontSmall.lineHeight() * 1.2;
cursorY += fontSmall.lineHeight() * 1.2; printAt(0, cursorY, "- short press: next");
printAt(0, cursorY, "- short press: next"); cursorY += fontSmall.lineHeight() * 1.2;
cursorY += fontSmall.lineHeight() * 1.2; printAt(0, cursorY, "- long press: select / open menu");
printAt(0, cursorY, "- long press: select / open menu"); cursorY += fontSmall.lineHeight() * 1.5;
} else {
printAt(0, cursorY, "Joystick");
cursorY += fontSmall.lineHeight() * 1.2;
printAt(0, cursorY, "- open menu / select");
cursorY += fontSmall.lineHeight() * 1.5;
printAt(0, cursorY, "Exit Button");
cursorY += fontSmall.lineHeight() * 1.2;
printAt(0, cursorY, "- switch tile / close menu");
}
printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM); printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM);
} break; } break;
@@ -136,13 +127,8 @@ void InkHUD::TipsApplet::onRender()
printAt(0, 0, "Tip: Rotation"); printAt(0, 0, "Tip: Rotation");
setFont(fontSmall); setFont(fontSmall);
if (!settings->joystick.enabled) { printWrapped(0, fontMedium.lineHeight() * 1.5, width(),
printWrapped(0, fontMedium.lineHeight() * 1.5, width(), "To rotate the display, use the InkHUD menu. Long-press the user button > Options > Rotate.");
"To rotate the display, use the InkHUD menu. Long-press the user button > Options > Rotate.");
} else {
printWrapped(0, fontMedium.lineHeight() * 1.5, width(),
"To rotate the display, use the InkHUD menu. Press the user button > Options > Rotate.");
}
printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM); printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM);
@@ -246,10 +232,4 @@ void InkHUD::TipsApplet::onButtonShortPress()
requestUpdate(); requestUpdate();
} }
// Functions the same as the user button in this instance
void InkHUD::TipsApplet::onExitShort()
{
onButtonShortPress();
}
#endif #endif

View File

@@ -36,7 +36,6 @@ class TipsApplet : public SystemApplet
void onForeground() override; void onForeground() override;
void onBackground() override; void onBackground() override;
void onButtonShortPress() override; void onButtonShortPress() override;
void onExitShort() override;
protected: protected:
void renderWelcome(); // Very first screen of tutorial void renderWelcome(); // Very first screen of tutorial

View File

@@ -1,6 +1,7 @@
#ifdef MESHTASTIC_INCLUDE_INKHUD #ifdef MESHTASTIC_INCLUDE_INKHUD
#include "./PositionsApplet.h" #include "./PositionsApplet.h"
#include "NodeDB.h"
using namespace NicheGraphics; using namespace NicheGraphics;
@@ -49,8 +50,8 @@ ProcessMessage InkHUD::PositionsApplet::handleReceived(const meshtastic_MeshPack
if (!hasPosition) if (!hasPosition)
return ProcessMessage::CONTINUE; return ProcessMessage::CONTINUE;
bool hasHopsAway = (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start); // From NodeDB::updateFrom const int8_t hopsAway = getHopsAway(mp);
uint8_t hopsAway = mp.hop_start - mp.hop_limit; const bool hasHopsAway = hopsAway >= 0;
// Determine if the position packet would change anything on-screen // Determine if the position packet would change anything on-screen
// ----------------------------------------------------------------- // -----------------------------------------------------------------

View File

@@ -55,15 +55,10 @@ void InkHUD::Events::onButtonShort()
} }
// If no system applet is handling input, default behavior instead is to cycle applets // If no system applet is handling input, default behavior instead is to cycle applets
// or open menu if joystick is enabled if (consumer)
if (consumer) {
consumer->onButtonShortPress(); consumer->onButtonShortPress();
} else if (!dismissedExt) { // Don't change applet if this button press silenced the external notification module else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
if (!settings->joystick.enabled) inkhud->nextApplet();
inkhud->nextApplet();
else
inkhud->openMenu();
}
} }
void InkHUD::Events::onButtonLong() void InkHUD::Events::onButtonLong()
@@ -88,156 +83,6 @@ void InkHUD::Events::onButtonLong()
inkhud->openMenu(); inkhud->openMenu();
} }
void InkHUD::Events::onExitShort()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
// If no system applet is handling input, default behavior instead is change tiles
if (consumer)
consumer->onExitShort();
else if (!dismissedExt) // Don't change tile if this button press silenced the external notification module
inkhud->nextTile();
}
}
void InkHUD::Events::onExitLong()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Slightly longer than playChirp
playBoop();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
if (consumer)
consumer->onExitLong();
}
}
void InkHUD::Events::onNavUp()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
if (consumer)
consumer->onNavUp();
}
}
void InkHUD::Events::onNavDown()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
if (consumer)
consumer->onNavDown();
}
}
void InkHUD::Events::onNavLeft()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
// If no system applet is handling input, default behavior instead is to cycle applets
if (consumer)
consumer->onNavLeft();
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
inkhud->prevApplet();
}
}
void InkHUD::Events::onNavRight()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
// If no system applet is handling input, default behavior instead is to cycle applets
if (consumer)
consumer->onNavRight();
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
inkhud->nextApplet();
}
}
// Callback for deepSleepObserver // Callback for deepSleepObserver
// Returns 0 to signal that we agree to sleep now // Returns 0 to signal that we agree to sleep now
int InkHUD::Events::beforeDeepSleep(void *unused) int InkHUD::Events::beforeDeepSleep(void *unused)

View File

@@ -29,12 +29,6 @@ class Events
void onButtonShort(); // User button: short press void onButtonShort(); // User button: short press
void onButtonLong(); // User button: long press void onButtonLong(); // User button: long press
void onExitShort(); // Exit button: short press
void onExitLong(); // Exit button: long press
void onNavUp(); // Navigate up
void onNavDown(); // Navigate down
void onNavLeft(); // Navigate left
void onNavRight(); // Navigate right
int beforeDeepSleep(void *unused); // Prepare for shutdown int beforeDeepSleep(void *unused); // Prepare for shutdown
int beforeReboot(void *unused); // Prepare for reboot int beforeReboot(void *unused); // Prepare for reboot

View File

@@ -80,94 +80,6 @@ void InkHUD::InkHUD::longpress()
events->onButtonLong(); events->onButtonLong();
} }
// Call this when your exit button gets a short press
void InkHUD::InkHUD::exitShort()
{
events->onExitShort();
}
// Call this when your exit button gets a long press
void InkHUD::InkHUD::exitLong()
{
events->onExitLong();
}
// Call this when your joystick gets an up input
void InkHUD::InkHUD::navUp()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavLeft();
break;
case 2: // 180 deg
events->onNavDown();
break;
case 3: // 270 deg
events->onNavRight();
break;
default: // 0 deg
events->onNavUp();
break;
}
}
// Call this when your joystick gets a down input
void InkHUD::InkHUD::navDown()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavRight();
break;
case 2: // 180 deg
events->onNavUp();
break;
case 3: // 270 deg
events->onNavLeft();
break;
default: // 0 deg
events->onNavDown();
break;
}
}
// Call this when your joystick gets a left input
void InkHUD::InkHUD::navLeft()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavDown();
break;
case 2: // 180 deg
events->onNavRight();
break;
case 3: // 270 deg
events->onNavUp();
break;
default: // 0 deg
events->onNavLeft();
break;
}
}
// Call this when your joystick gets a right input
void InkHUD::InkHUD::navRight()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavUp();
break;
case 2: // 180 deg
events->onNavLeft();
break;
case 3: // 270 deg
events->onNavDown();
break;
default: // 0 deg
events->onNavRight();
break;
}
}
// Cycle the next user applet to the foreground // Cycle the next user applet to the foreground
// Only activated applets are cycled // Only activated applets are cycled
// If user has a multi-applet layout, the applets will cycle on the "focused tile" // If user has a multi-applet layout, the applets will cycle on the "focused tile"
@@ -176,14 +88,6 @@ void InkHUD::InkHUD::nextApplet()
windowManager->nextApplet(); windowManager->nextApplet();
} }
// Cycle the previous user applet to the foreground
// Only activated applets are cycled
// If user has a multi-applet layout, the applets will cycle on the "focused tile"
void InkHUD::InkHUD::prevApplet()
{
windowManager->prevApplet();
}
// Show the menu (on the the focused tile) // Show the menu (on the the focused tile)
// The applet previously displayed there will be restored once the menu closes // The applet previously displayed there will be restored once the menu closes
void InkHUD::InkHUD::openMenu() void InkHUD::InkHUD::openMenu()
@@ -191,12 +95,6 @@ void InkHUD::InkHUD::openMenu()
windowManager->openMenu(); windowManager->openMenu();
} }
// Bring AlignStick applet to the foreground
void InkHUD::InkHUD::openAlignStick()
{
windowManager->openAlignStick();
}
// In layouts where multiple applets are shown at once, change which tile is focused // In layouts where multiple applets are shown at once, change which tile is focused
// The focused tile in the one which cycles applets on button short press, and displays menu on long press // The focused tile in the one which cycles applets on button short press, and displays menu on long press
void InkHUD::InkHUD::nextTile() void InkHUD::InkHUD::nextTile()
@@ -204,26 +102,12 @@ void InkHUD::InkHUD::nextTile()
windowManager->nextTile(); windowManager->nextTile();
} }
// In layouts where multiple applets are shown at once, change which tile is focused
// The focused tile in the one which cycles applets on button short press, and displays menu on long press
void InkHUD::InkHUD::prevTile()
{
windowManager->prevTile();
}
// Rotate the display image by 90 degrees // Rotate the display image by 90 degrees
void InkHUD::InkHUD::rotate() void InkHUD::InkHUD::rotate()
{ {
windowManager->rotate(); windowManager->rotate();
} }
// rotate the joystick in 90 degree increments
void InkHUD::InkHUD::rotateJoystick(uint8_t angle)
{
persistence->settings.joystick.alignment += angle;
persistence->settings.joystick.alignment %= 4;
}
// Show / hide the battery indicator in top-right // Show / hide the battery indicator in top-right
void InkHUD::InkHUD::toggleBatteryIcon() void InkHUD::InkHUD::toggleBatteryIcon()
{ {

View File

@@ -55,25 +55,15 @@ class InkHUD
void shortpress(); void shortpress();
void longpress(); void longpress();
void exitShort();
void exitLong();
void navUp();
void navDown();
void navLeft();
void navRight();
// Trigger UI changes // Trigger UI changes
// - called by various InkHUD components // - called by various InkHUD components
// - suitable(?) for use by aux button, connected in variant nicheGraphics.h // - suitable(?) for use by aux button, connected in variant nicheGraphics.h
void nextApplet(); void nextApplet();
void prevApplet();
void openMenu(); void openMenu();
void openAlignStick();
void nextTile(); void nextTile();
void prevTile();
void rotate(); void rotate();
void rotateJoystick(uint8_t angle = 1); // rotate 90 deg by default
void toggleBatteryIcon(); void toggleBatteryIcon();
// Updating the display // Updating the display

View File

@@ -29,7 +29,7 @@ class Persistence
// Used to invalidate old settings, if needed // Used to invalidate old settings, if needed
// Version 0 is reserved for testing, and will always load defaults // Version 0 is reserved for testing, and will always load defaults
static constexpr uint32_t SETTINGS_VERSION = 3; static constexpr uint32_t SETTINGS_VERSION = 2;
struct Settings { struct Settings {
struct Meta { struct Meta {
@@ -96,19 +96,6 @@ class Persistence
bool safeShutdownSeen = false; bool safeShutdownSeen = false;
} tips; } tips;
// Joystick settings for enabling and aligning to the screen
struct Joystick {
// Modifies the UI for joystick use
bool enabled = false;
// gets set to true when AlignStick applet is completed
bool aligned = false;
// Rotation of the joystick
// Multiples of 90 degrees clockwise
uint8_t alignment = 0;
} joystick;
// Rotation of the display // Rotation of the display
// Multiples of 90 degrees clockwise // Multiples of 90 degrees clockwise
// Most commonly: rotation is 0 when flex connector is oriented below display // Most commonly: rotation is 0 when flex connector is oriented below display

View File

@@ -8,5 +8,4 @@ build_flags =
-D MESHTASTIC_EXCLUDE_INPUTBROKER ; Suppress default input handling -D MESHTASTIC_EXCLUDE_INPUTBROKER ; Suppress default input handling
-D HAS_BUTTON=0 ; Suppress default ButtonThread -D HAS_BUTTON=0 ; Suppress default ButtonThread
lib_deps = lib_deps =
# TODO renovate https://github.com/ZinggJM/GFX_Root#2.0.0 ; Used by InkHUD as a "slimmer" version of AdafruitGFX
https://github.com/ZinggJM/GFX_Root#2.0.0 ; Used by InkHUD as a "slimmer" version of AdafruitGFX

View File

@@ -2,7 +2,6 @@
#include "./WindowManager.h" #include "./WindowManager.h"
#include "./Applets/System/AlignStick/AlignStickApplet.h"
#include "./Applets/System/BatteryIcon/BatteryIconApplet.h" #include "./Applets/System/BatteryIcon/BatteryIconApplet.h"
#include "./Applets/System/Logo/LogoApplet.h" #include "./Applets/System/Logo/LogoApplet.h"
#include "./Applets/System/Menu/MenuApplet.h" #include "./Applets/System/Menu/MenuApplet.h"
@@ -99,38 +98,6 @@ void InkHUD::WindowManager::nextTile()
userTiles.at(settings->userTiles.focused)->requestHighlight(); userTiles.at(settings->userTiles.focused)->requestHighlight();
} }
// Focus on a different tile but decrement index
void InkHUD::WindowManager::prevTile()
{
// Close the menu applet if open
// We don't *really* want to do this, but it simplifies handling *a lot*
MenuApplet *menu = (MenuApplet *)inkhud->getSystemApplet("Menu");
bool menuWasOpen = false;
if (menu->isForeground()) {
menu->sendToBackground();
menuWasOpen = true;
}
// Swap to next tile
if (settings->userTiles.focused == 0)
settings->userTiles.focused = settings->userTiles.count - 1;
else
settings->userTiles.focused--;
// Make sure that we don't get stuck on the placeholder tile
refocusTile();
if (menuWasOpen)
menu->show(userTiles.at(settings->userTiles.focused));
// Ask the tile to draw an indicator showing which tile is now focused
// Requests a render
// We only draw this indicator if the device uses an aux button to switch tiles.
// Assume aux button is used to switch tiles if the "next tile" menu item is hidden
if (!settings->optionalMenuItems.nextTile)
userTiles.at(settings->userTiles.focused)->requestHighlight();
}
// Show the menu (on the the focused tile) // Show the menu (on the the focused tile)
// The applet previously displayed there will be restored once the menu closes // The applet previously displayed there will be restored once the menu closes
void InkHUD::WindowManager::openMenu() void InkHUD::WindowManager::openMenu()
@@ -139,15 +106,6 @@ void InkHUD::WindowManager::openMenu()
menu->show(userTiles.at(settings->userTiles.focused)); menu->show(userTiles.at(settings->userTiles.focused));
} }
// Bring the AlignStick applet to the foreground
void InkHUD::WindowManager::openAlignStick()
{
if (settings->joystick.enabled) {
AlignStickApplet *alignStick = (AlignStickApplet *)inkhud->getSystemApplet("AlignStick");
alignStick->bringToForeground();
}
}
// On the currently focussed tile: cycle to the next available user applet // On the currently focussed tile: cycle to the next available user applet
// Applets available for this must be activated, and not already displayed on another tile // Applets available for this must be activated, and not already displayed on another tile
void InkHUD::WindowManager::nextApplet() void InkHUD::WindowManager::nextApplet()
@@ -197,59 +155,6 @@ void InkHUD::WindowManager::nextApplet()
inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST
} }
// On the currently focussed tile: cycle to the previous available user applet
// Applets available for this must be activated, and not already displayed on another tile
void InkHUD::WindowManager::prevApplet()
{
Tile *t = userTiles.at(settings->userTiles.focused);
// Abort if zero applets available
// nullptr means WindowManager::refocusTile determined that there were no available applets
if (!t->getAssignedApplet())
return;
// Find the index of the applet currently shown on the tile
uint8_t appletIndex = -1;
for (uint8_t i = 0; i < inkhud->userApplets.size(); i++) {
if (inkhud->userApplets.at(i) == t->getAssignedApplet()) {
appletIndex = i;
break;
}
}
// Confirm that we did find the applet
assert(appletIndex != (uint8_t)-1);
// Iterate forward through the WindowManager::applets, looking for the previous valid applet
Applet *prevValidApplet = nullptr;
for (uint8_t i = 1; i < inkhud->userApplets.size(); i++) {
uint8_t newAppletIndex = 0;
if (i > appletIndex)
newAppletIndex = inkhud->userApplets.size() + appletIndex - i;
else
newAppletIndex = (appletIndex - i);
Applet *a = inkhud->userApplets.at(newAppletIndex);
// Looking for an applet which is active (enabled by user), but currently in background
if (a->isActive() && !a->isForeground()) {
prevValidApplet = a;
settings->userTiles.displayedUserApplet[settings->userTiles.focused] =
newAppletIndex; // Remember this setting between boots!
break;
}
}
// Confirm that we found another applet
if (!prevValidApplet)
return;
// Hide old applet, show new applet
t->getAssignedApplet()->sendToBackground();
t->assignApplet(prevValidApplet);
prevValidApplet->bringToForeground();
inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST
}
// Rotate the display image by 90 degrees // Rotate the display image by 90 degrees
void InkHUD::WindowManager::rotate() void InkHUD::WindowManager::rotate()
{ {
@@ -433,8 +338,6 @@ void InkHUD::WindowManager::createSystemApplets()
addSystemApplet("Logo", new LogoApplet, new Tile); addSystemApplet("Logo", new LogoApplet, new Tile);
addSystemApplet("Pairing", new PairingApplet, new Tile); addSystemApplet("Pairing", new PairingApplet, new Tile);
addSystemApplet("Tips", new TipsApplet, new Tile); addSystemApplet("Tips", new TipsApplet, new Tile);
if (settings->joystick.enabled)
addSystemApplet("AlignStick", new AlignStickApplet, new Tile);
addSystemApplet("Menu", new MenuApplet, nullptr); addSystemApplet("Menu", new MenuApplet, nullptr);
@@ -457,8 +360,6 @@ void InkHUD::WindowManager::placeSystemTiles()
inkhud->getSystemApplet("Logo")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height()); inkhud->getSystemApplet("Logo")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
inkhud->getSystemApplet("Pairing")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height()); inkhud->getSystemApplet("Pairing")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
inkhud->getSystemApplet("Tips")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height()); inkhud->getSystemApplet("Tips")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
if (settings->joystick.enabled)
inkhud->getSystemApplet("AlignStick")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
inkhud->getSystemApplet("Notification")->getTile()->setRegion(0, 0, inkhud->width(), 20); inkhud->getSystemApplet("Notification")->getTile()->setRegion(0, 0, inkhud->width(), 20);

View File

@@ -28,11 +28,8 @@ class WindowManager
// - call these to make stuff change // - call these to make stuff change
void nextTile(); void nextTile();
void prevTile();
void openMenu(); void openMenu();
void openAlignStick();
void nextApplet(); void nextApplet();
void prevApplet();
void rotate(); void rotate();
void toggleBatteryIcon(); void toggleBatteryIcon();

View File

@@ -1,523 +0,0 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./TwoButtonExtended.h"
#include "NodeDB.h" // For the helper function TwoButtonExtended::getUserButtonPin
#include "PowerFSM.h"
#include "sleep.h"
using namespace NicheGraphics::Inputs;
TwoButtonExtended::TwoButtonExtended() : concurrency::OSThread("TwoButtonExtended")
{
// Don't start polling buttons for release immediately
// Assume they are in a "released" state at boot
OSThread::disable();
#ifdef ARCH_ESP32
// Register callbacks for before and after lightsleep
lsObserver.observe(&notifyLightSleep);
lsEndObserver.observe(&notifyLightSleepEnd);
#endif
// Explicitly initialize these, just to keep cppcheck quiet..
buttons[0] = Button();
buttons[1] = Button();
joystick[Direction::UP] = SimpleButton();
joystick[Direction::DOWN] = SimpleButton();
joystick[Direction::LEFT] = SimpleButton();
joystick[Direction::RIGHT] = SimpleButton();
}
// Get access to (or create) the singleton instance of this class
// Accessible inside the ISRs, even though we maybe shouldn't
TwoButtonExtended *TwoButtonExtended::getInstance()
{
// Instantiate the class the first time this method is called
static TwoButtonExtended *const singletonInstance = new TwoButtonExtended;
return singletonInstance;
}
// Begin receiving button input
// We probably need to do this after sleep, as well as at boot
void TwoButtonExtended::start()
{
if (buttons[0].pin != 0xFF)
attachInterrupt(buttons[0].pin, TwoButtonExtended::isrPrimary, buttons[0].activeLogic == LOW ? FALLING : RISING);
if (buttons[1].pin != 0xFF)
attachInterrupt(buttons[1].pin, TwoButtonExtended::isrSecondary, buttons[1].activeLogic == LOW ? FALLING : RISING);
if (joystick[Direction::UP].pin != 0xFF)
attachInterrupt(joystick[Direction::UP].pin, TwoButtonExtended::isrJoystickUp,
joystickActiveLogic == LOW ? FALLING : RISING);
if (joystick[Direction::DOWN].pin != 0xFF)
attachInterrupt(joystick[Direction::DOWN].pin, TwoButtonExtended::isrJoystickDown,
joystickActiveLogic == LOW ? FALLING : RISING);
if (joystick[Direction::LEFT].pin != 0xFF)
attachInterrupt(joystick[Direction::LEFT].pin, TwoButtonExtended::isrJoystickLeft,
joystickActiveLogic == LOW ? FALLING : RISING);
if (joystick[Direction::RIGHT].pin != 0xFF)
attachInterrupt(joystick[Direction::RIGHT].pin, TwoButtonExtended::isrJoystickRight,
joystickActiveLogic == LOW ? FALLING : RISING);
}
// Stop receiving button input, and run custom sleep code
// Called before device sleeps. This might be power-off, or just ESP32 light sleep
// Some devices will want to attach interrupts here, for the user button to wake from sleep
void TwoButtonExtended::stop()
{
if (buttons[0].pin != 0xFF)
detachInterrupt(buttons[0].pin);
if (buttons[1].pin != 0xFF)
detachInterrupt(buttons[1].pin);
if (joystick[Direction::UP].pin != 0xFF)
detachInterrupt(joystick[Direction::UP].pin);
if (joystick[Direction::DOWN].pin != 0xFF)
detachInterrupt(joystick[Direction::DOWN].pin);
if (joystick[Direction::LEFT].pin != 0xFF)
detachInterrupt(joystick[Direction::LEFT].pin);
if (joystick[Direction::RIGHT].pin != 0xFF)
detachInterrupt(joystick[Direction::RIGHT].pin);
}
// Attempt to resolve a GPIO pin for the user button, honoring userPrefs.jsonc and device settings
// This helper method isn't used by the TwoButtonExtended class itself, it could be moved elsewhere.
// Intention is to pass this value to TwoButtonExtended::setWiring in the setupNicheGraphics method.
uint8_t TwoButtonExtended::getUserButtonPin()
{
uint8_t pin = 0xFF; // Unset
// Use default pin for variant, if no better source
#ifdef BUTTON_PIN
pin = BUTTON_PIN;
#endif
// From userPrefs.jsonc, if set
#ifdef USERPREFS_BUTTON_PIN
pin = USERPREFS_BUTTON_PIN;
#endif
// From user's override in device settings, if set
if (config.device.button_gpio)
pin = config.device.button_gpio;
return pin;
}
// Configures the wiring and logic of either button
// Called when outlining your NicheGraphics implementation, in variant/nicheGraphics.cpp
void TwoButtonExtended::setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup)
{
// Prevent the same GPIO being assigned to multiple buttons
// Allows an edge case when the user remaps hardware buttons using device settings, due to a broken user button
for (uint8_t i = 0; i < whichButton; i++) {
if (buttons[i].pin == pin) {
LOG_WARN("Attempted reuse of GPIO %d. Ignoring assignment whichButton=%d", pin, whichButton);
return;
}
}
assert(whichButton < 2);
buttons[whichButton].pin = pin;
buttons[whichButton].activeLogic = LOW;
pinMode(buttons[whichButton].pin, internalPullup ? INPUT_PULLUP : INPUT);
}
// Configures the wiring and logic of the joystick buttons
// Called when outlining your NicheGraphics implementation, in variant/nicheGraphics.cpp
void TwoButtonExtended::setJoystickWiring(uint8_t uPin, uint8_t dPin, uint8_t lPin, uint8_t rPin, bool internalPullup)
{
if (joystick[Direction::UP].pin == uPin || joystick[Direction::DOWN].pin == dPin || joystick[Direction::LEFT].pin == lPin ||
joystick[Direction::RIGHT].pin == rPin) {
LOG_WARN("Attempted reuse of Joystick GPIO. Ignoring assignment");
return;
}
joystick[Direction::UP].pin = uPin;
joystick[Direction::DOWN].pin = dPin;
joystick[Direction::LEFT].pin = lPin;
joystick[Direction::RIGHT].pin = rPin;
joystickActiveLogic = LOW;
pinMode(joystick[Direction::UP].pin, internalPullup ? INPUT_PULLUP : INPUT);
pinMode(joystick[Direction::DOWN].pin, internalPullup ? INPUT_PULLUP : INPUT);
pinMode(joystick[Direction::LEFT].pin, internalPullup ? INPUT_PULLUP : INPUT);
pinMode(joystick[Direction::RIGHT].pin, internalPullup ? INPUT_PULLUP : INPUT);
}
void TwoButtonExtended::setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs)
{
assert(whichButton < 2);
buttons[whichButton].debounceLength = debounceMs;
buttons[whichButton].longpressLength = longpressMs;
}
void TwoButtonExtended::setJoystickDebounce(uint32_t debounceMs)
{
joystickDebounceLength = debounceMs;
}
// Set what should happen when a button becomes pressed
// Use this to implement a "while held" behavior
void TwoButtonExtended::setHandlerDown(uint8_t whichButton, Callback onDown)
{
assert(whichButton < 2);
buttons[whichButton].onDown = onDown;
}
// Set what should happen when a button becomes unpressed
// Use this to implement a "While held" behavior
void TwoButtonExtended::setHandlerUp(uint8_t whichButton, Callback onUp)
{
assert(whichButton < 2);
buttons[whichButton].onUp = onUp;
}
// Set what should happen when a "short press" event has occurred
void TwoButtonExtended::setHandlerShortPress(uint8_t whichButton, Callback onPress)
{
assert(whichButton < 2);
buttons[whichButton].onPress = onPress;
}
// Set what should happen when a "long press" event has fired
// Note: this will occur while the button is still held
void TwoButtonExtended::setHandlerLongPress(uint8_t whichButton, Callback onLongPress)
{
assert(whichButton < 2);
buttons[whichButton].onLongPress = onLongPress;
}
// Set what should happen when a joystick button becomes pressed
// Use this to implement a "while held" behavior
void TwoButtonExtended::setJoystickDownHandlers(Callback uDown, Callback dDown, Callback lDown, Callback rDown)
{
joystick[Direction::UP].onDown = uDown;
joystick[Direction::DOWN].onDown = dDown;
joystick[Direction::LEFT].onDown = lDown;
joystick[Direction::RIGHT].onDown = rDown;
}
// Set what should happen when a joystick button becomes unpressed
// Use this to implement a "while held" behavior
void TwoButtonExtended::setJoystickUpHandlers(Callback uUp, Callback dUp, Callback lUp, Callback rUp)
{
joystick[Direction::UP].onUp = uUp;
joystick[Direction::DOWN].onUp = dUp;
joystick[Direction::LEFT].onUp = lUp;
joystick[Direction::RIGHT].onUp = rUp;
}
// Set what should happen when a "press" event has fired
// Note: this will occur while the joystick button is still held
void TwoButtonExtended::setJoystickPressHandlers(Callback uPress, Callback dPress, Callback lPress, Callback rPress)
{
joystick[Direction::UP].onPress = uPress;
joystick[Direction::DOWN].onPress = dPress;
joystick[Direction::LEFT].onPress = lPress;
joystick[Direction::RIGHT].onPress = rPress;
}
// Handle the start of a press to the primary button
// Wakes our button thread
void TwoButtonExtended::isrPrimary()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->buttons[0].state == State::REST) {
b->buttons[0].state = State::IRQ;
b->buttons[0].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
// Handle the start of a press to the secondary button
// Wakes our button thread
void TwoButtonExtended::isrSecondary()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->buttons[1].state == State::REST) {
b->buttons[1].state = State::IRQ;
b->buttons[1].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
// Handle the start of a press to the joystick buttons
// Also wakes our button thread
void TwoButtonExtended::isrJoystickUp()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::UP].state == State::REST) {
b->joystick[Direction::UP].state = State::IRQ;
b->joystick[Direction::UP].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
void TwoButtonExtended::isrJoystickDown()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::DOWN].state == State::REST) {
b->joystick[Direction::DOWN].state = State::IRQ;
b->joystick[Direction::DOWN].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
void TwoButtonExtended::isrJoystickLeft()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::LEFT].state == State::REST) {
b->joystick[Direction::LEFT].state = State::IRQ;
b->joystick[Direction::LEFT].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
void TwoButtonExtended::isrJoystickRight()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::RIGHT].state == State::REST) {
b->joystick[Direction::RIGHT].state = State::IRQ;
b->joystick[Direction::RIGHT].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
// Concise method to start our button thread
// Follows an ISR, listening for button release
void TwoButtonExtended::startThread()
{
if (!OSThread::enabled) {
OSThread::setInterval(10);
OSThread::enabled = true;
}
}
// Concise method to stop our button thread
// Called when we no longer need to poll for button release
void TwoButtonExtended::stopThread()
{
if (OSThread::enabled) {
OSThread::disable();
}
// Reset both buttons manually
// Just in case an IRQ fires during the process of resetting the system
// Can occur with super rapid presses?
buttons[0].state = REST;
buttons[1].state = REST;
joystick[Direction::UP].state = REST;
joystick[Direction::DOWN].state = REST;
joystick[Direction::LEFT].state = REST;
joystick[Direction::RIGHT].state = REST;
}
// Our button thread
// Started by an IRQ, on either button
// Polls for button releases
// Stops when both buttons released
int32_t TwoButtonExtended::runOnce()
{
constexpr uint8_t BUTTON_COUNT = sizeof(buttons) / sizeof(Button);
constexpr uint8_t JOYSTICK_COUNT = sizeof(joystick) / sizeof(SimpleButton);
// Allow either button to request that our thread should continue polling
bool awaitingRelease = false;
// Check both primary and secondary buttons
for (uint8_t i = 0; i < BUTTON_COUNT; i++) {
switch (buttons[i].state) {
// No action: button has not been pressed
case REST:
break;
// New press detected by interrupt
case IRQ:
powerFSM.trigger(EVENT_PRESS); // Tell PowerFSM that press occurred (resets sleep timer)
buttons[i].onDown(); // Run callback: press has begun (possible hold behavior)
buttons[i].state = State::POLLING_UNFIRED; // Mark that button-down has been handled
awaitingRelease = true; // Mark that polling-for-release should continue
break;
// An existing press continues
// Not held long enough to register as longpress
case POLLING_UNFIRED: {
uint32_t length = millis() - buttons[i].irqAtMillis;
// If button released since last thread tick,
if (digitalRead(buttons[i].pin) != buttons[i].activeLogic) {
buttons[i].onUp(); // Run callback: press has ended (possible release of a hold)
buttons[i].state = State::REST; // Mark that the button has reset
if (length > buttons[i].debounceLength && length < buttons[i].longpressLength) // If too short for longpress,
buttons[i].onPress(); // Run callback: press
}
// If button not yet released
else {
awaitingRelease = true; // Mark that polling-for-release should continue
if (length >= buttons[i].longpressLength) {
// Run callback: long press (once)
// Then continue waiting for release, to rearm
buttons[i].state = State::POLLING_FIRED;
buttons[i].onLongPress();
}
}
break;
}
// Button still held, but duration long enough that longpress event already fired
// Just waiting for release
case POLLING_FIRED:
// Release detected
if (digitalRead(buttons[i].pin) != buttons[i].activeLogic) {
buttons[i].state = State::REST;
buttons[i].onUp(); // Callback: release of hold (in this case: *after* longpress has fired)
}
// Not yet released, keep polling
else
awaitingRelease = true;
break;
}
}
// Check all the joystick directions
for (uint8_t i = 0; i < JOYSTICK_COUNT; i++) {
switch (joystick[i].state) {
// No action: button has not been pressed
case REST:
break;
// New press detected by interrupt
case IRQ:
powerFSM.trigger(EVENT_PRESS); // Tell PowerFSM that press occurred (resets sleep timer)
joystick[i].onDown(); // Run callback: press has begun (possible hold behavior)
joystick[i].state = State::POLLING_UNFIRED; // Mark that button-down has been handled
awaitingRelease = true; // Mark that polling-for-release should continue
break;
// An existing press continues
// Not held long enough to register as press
case POLLING_UNFIRED: {
uint32_t length = millis() - joystick[i].irqAtMillis;
// If button released since last thread tick,
if (digitalRead(joystick[i].pin) != joystickActiveLogic) {
joystick[i].onUp(); // Run callback: press has ended (possible release of a hold)
joystick[i].state = State::REST; // Mark that the button has reset
}
// If button not yet released
else {
awaitingRelease = true; // Mark that polling-for-release should continue
if (length >= joystickDebounceLength) {
// Run callback: long press (once)
// Then continue waiting for release, to rearm
joystick[i].state = State::POLLING_FIRED;
joystick[i].onPress();
}
}
break;
}
// Button still held after press
// Just waiting for release
case POLLING_FIRED:
// Release detected
if (digitalRead(joystick[i].pin) != joystickActiveLogic) {
joystick[i].state = State::REST;
joystick[i].onUp(); // Callback: release of hold
}
// Not yet released, keep polling
else
awaitingRelease = true;
break;
}
}
// If all buttons are now released
// we don't need to waste cpu resources polling
// IRQ will restart this thread when we next need it
if (!awaitingRelease)
stopThread();
// Run this method again, or don't..
// Use whatever behavior was previously set by stopThread() or startThread()
return OSThread::interval;
}
#ifdef ARCH_ESP32
// Detach our class' interrupts before lightsleep
// Allows sleep.cpp to configure its own interrupts, which wake the device on user-button press
int TwoButtonExtended::beforeLightSleep(void *unused)
{
stop();
return 0; // Indicates success
}
// Reconfigure our interrupts
// Our class' interrupts were disconnected during sleep, to allow the user button to wake the device from sleep
int TwoButtonExtended::afterLightSleep(esp_sleep_wakeup_cause_t cause)
{
start();
// Manually trigger the button-down ISR
// - during light sleep, our ISR is disabled
// - if light sleep ends by button press, pretend our own ISR caught it
// - need to manually confirm by reading pin ourselves, to avoid occasional false positives
// (false positive only when using internal pullup resistors?)
if (cause == ESP_SLEEP_WAKEUP_GPIO && digitalRead(buttons[0].pin) == buttons[0].activeLogic)
isrPrimary();
return 0; // Indicates success
}
#endif
#endif

View File

@@ -1,136 +0,0 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
/*
Re-usable NicheGraphics input source
Short and Long press for up to two buttons
Interrupt driven
*/
/*
This expansion adds support for four more buttons
These buttons are single-action only, no long press
Interrupt driven
*/
#pragma once
#include "configuration.h"
#include "assert.h"
#include "functional"
#ifdef ARCH_ESP32
#include "esp_sleep.h" // For light-sleep handling
#endif
#include "Observer.h"
namespace NicheGraphics::Inputs
{
class TwoButtonExtended : protected concurrency::OSThread
{
public:
typedef std::function<void()> Callback;
static uint8_t getUserButtonPin(); // Resolve the GPIO, considering the various possible source of definition
static TwoButtonExtended *getInstance(); // Create or get the singleton instance
void start(); // Start handling button input
void stop(); // Stop handling button input (disconnect ISRs for sleep)
void setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup = false);
void setJoystickWiring(uint8_t uPin, uint8_t dPin, uint8_t lPin, uint8_t rPin, bool internalPullup = false);
void setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs);
void setJoystickDebounce(uint32_t debounceMs);
void setHandlerDown(uint8_t whichButton, Callback onDown);
void setHandlerUp(uint8_t whichButton, Callback onUp);
void setHandlerShortPress(uint8_t whichButton, Callback onShortPress);
void setHandlerLongPress(uint8_t whichButton, Callback onLongPress);
void setJoystickDownHandlers(Callback uDown, Callback dDown, Callback ldown, Callback rDown);
void setJoystickUpHandlers(Callback uUp, Callback dUp, Callback lUp, Callback rUp);
void setJoystickPressHandlers(Callback uPress, Callback dPress, Callback lPress, Callback rPress);
// Disconnect and reconnect interrupts for light sleep
#ifdef ARCH_ESP32
int beforeLightSleep(void *unused);
int afterLightSleep(esp_sleep_wakeup_cause_t cause);
#endif
private:
// Internal state of a specific button
enum State {
REST, // Up, no activity
IRQ, // Down detected, not yet handled
POLLING_UNFIRED, // Down handled, polling for release
POLLING_FIRED, // Longpress fired, button still held
};
// Joystick Directions
enum Direction { UP = 0, DOWN, LEFT, RIGHT };
// Data used for direction (single-action) buttons
class SimpleButton
{
public:
// Per-button config
uint8_t pin = 0xFF; // 0xFF: unset
volatile State state = State::REST; // Internal state
volatile uint32_t irqAtMillis; // millis() when button went down
// Per-button event callbacks
static void noop(){};
std::function<void()> onDown = noop;
std::function<void()> onUp = noop;
std::function<void()> onPress = noop;
};
// Data used for double-action buttons
class Button : public SimpleButton
{
public:
// Per-button extended config
bool activeLogic = LOW; // Active LOW by default.
uint32_t debounceLength = 50; // Minimum length for shortpress in ms
uint32_t longpressLength = 500; // Time until longpress in ms
// Per-button event callbacks
std::function<void()> onLongPress = noop;
};
#ifdef ARCH_ESP32
// Get notified when lightsleep begins and ends
CallbackObserver<TwoButtonExtended, void *> lsObserver =
CallbackObserver<TwoButtonExtended, void *>(this, &TwoButtonExtended::beforeLightSleep);
CallbackObserver<TwoButtonExtended, esp_sleep_wakeup_cause_t> lsEndObserver =
CallbackObserver<TwoButtonExtended, esp_sleep_wakeup_cause_t>(this, &TwoButtonExtended::afterLightSleep);
#endif
int32_t runOnce() override; // Timer method. Polls for button release
void startThread(); // Start polling for release
void stopThread(); // Stop polling for release
static void isrPrimary(); // User Button ISR
static void isrSecondary(); // optional aux button or joystick center
static void isrJoystickUp();
static void isrJoystickDown();
static void isrJoystickLeft();
static void isrJoystickRight();
TwoButtonExtended(); // Constructor made private: force use of Button::instance()
// Info about both buttons
Button buttons[2];
bool joystickActiveLogic = LOW; // Active LOW by default
uint32_t joystickDebounceLength = 50; // time until press in ms
SimpleButton joystick[4];
};
}; // namespace NicheGraphics::Inputs
#endif

View File

@@ -27,7 +27,9 @@ bool RotaryEncoderInterruptImpl1::init()
RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB, RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB,
RotaryEncoderInterruptImpl1::handleIntPressed); RotaryEncoderInterruptImpl1::handleIntPressed);
inputBroker->registerSource(this); inputBroker->registerSource(this);
#ifndef HAS_PHYSICAL_KEYBOARD
osk_found = true; osk_found = true;
#endif
return true; return true;
} }

View File

@@ -45,7 +45,9 @@ void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLef
LOG_DEBUG("Trackball GPIO initialized - UP:%d DOWN:%d LEFT:%d RIGHT:%d PRESS:%d", this->_pinUp, this->_pinDown, LOG_DEBUG("Trackball GPIO initialized - UP:%d DOWN:%d LEFT:%d RIGHT:%d PRESS:%d", this->_pinUp, this->_pinDown,
this->_pinLeft, this->_pinRight, pinPress); this->_pinLeft, this->_pinRight, pinPress);
#ifndef HAS_PHYSICAL_KEYBOARD
osk_found = true; osk_found = true;
#endif
this->setInterval(100); this->setInterval(100);
} }

View File

@@ -29,7 +29,9 @@ bool UpDownInterruptImpl1::init()
eventDownLong, UpDownInterruptImpl1::handleIntDown, UpDownInterruptImpl1::handleIntUp, eventDownLong, UpDownInterruptImpl1::handleIntDown, UpDownInterruptImpl1::handleIntUp,
UpDownInterruptImpl1::handleIntPressed); UpDownInterruptImpl1::handleIntPressed);
inputBroker->registerSource(this); inputBroker->registerSource(this);
#ifndef HAS_PHYSICAL_KEYBOARD
osk_found = true; osk_found = true;
#endif
return true; return true;
} }

View File

@@ -428,17 +428,10 @@ void setup()
#endif #endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
RTCQuality ourQuality = RTCQualityDevice;
std::string timeCommandResult = exec("timedatectl status | grep synchronized | grep yes -c");
if (timeCommandResult[0] == '1') {
ourQuality = RTCQualityNTP;
}
struct timeval tv; struct timeval tv;
tv.tv_sec = time(NULL); tv.tv_sec = time(NULL);
tv.tv_usec = 0; tv.tv_usec = 0;
perhapsSetRTC(ourQuality, &tv); perhapsSetRTC(RTCQualityDevice, &tv);
#endif #endif
powerMonInit(); powerMonInit();
@@ -1465,8 +1458,10 @@ void setup()
#endif #endif
#if defined(HAS_TRACKBALL) || (defined(INPUTDRIVER_ENCODER_TYPE) && INPUTDRIVER_ENCODER_TYPE == 2) #if defined(HAS_TRACKBALL) || (defined(INPUTDRIVER_ENCODER_TYPE) && INPUTDRIVER_ENCODER_TYPE == 2)
#ifndef HAS_PHYSICAL_KEYBOARD
osk_found = true; osk_found = true;
#endif #endif
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
// Start web server thread. // Start web server thread.

View File

@@ -96,8 +96,6 @@ class Channels
bool setDefaultPresetCryptoForHash(ChannelHash channelHash); bool setDefaultPresetCryptoForHash(ChannelHash channelHash);
int16_t getHash(ChannelIndex i) { return hashes[i]; }
private: private:
/** Given a channel index, change to use the crypto key specified by that index /** Given a channel index, change to use the crypto key specified by that index
* *
@@ -115,6 +113,8 @@ class Channels
*/ */
int16_t generateHash(ChannelIndex channelNum); int16_t generateHash(ChannelIndex channelNum);
int16_t getHash(ChannelIndex i) { return hashes[i]; }
/** /**
* Validate a channel, fixing any errors as needed * Validate a channel, fixing any errors as needed
*/ */

View File

@@ -195,7 +195,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
// but opted NOT TO. Because it is not a good idea to let remote nodes 'probe' to find out which PSKs were "good" vs // but opted NOT TO. Because it is not a good idea to let remote nodes 'probe' to find out which PSKs were "good" vs
// bad. // bad.
routingModule->sendAckNak(meshtastic_Routing_Error_NO_RESPONSE, getFrom(&mp), mp.id, mp.channel, routingModule->sendAckNak(meshtastic_Routing_Error_NO_RESPONSE, getFrom(&mp), mp.id, mp.channel,
routingModule->getHopLimitForResponse(mp.hop_start, mp.hop_limit)); routingModule->getHopLimitForResponse(mp));
} }
} }
@@ -235,7 +235,7 @@ void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to)
assert(p->which_payload_variant == meshtastic_MeshPacket_decoded_tag); // Should already be set by now assert(p->which_payload_variant == meshtastic_MeshPacket_decoded_tag); // Should already be set by now
p->to = getFrom(&to); // Make sure that if we are sending to the local node, we use our local node addr, not 0 p->to = getFrom(&to); // Make sure that if we are sending to the local node, we use our local node addr, not 0
p->channel = to.channel; // Use the same channel that the request came in on p->channel = to.channel; // Use the same channel that the request came in on
p->hop_limit = routingModule->getHopLimitForResponse(to.hop_start, to.hop_limit); p->hop_limit = routingModule->getHopLimitForResponse(to);
// No need for an ack if we are just delivering locally (it just generates an ignored ack) // No need for an ack if we are just delivering locally (it just generates an ignored ack)
p->want_ack = (to.from != 0) ? to.want_ack : false; p->want_ack = (to.from != 0) ? to.want_ack : false;

View File

@@ -93,11 +93,8 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user && } else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user &&
nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) { nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) {
if (airTime->isTxAllowedChannelUtil(true)) { if (airTime->isTxAllowedChannelUtil(true)) {
// Hops used by the request. If somebody in between running modified firmware modified it, ignore it const int8_t hopsUsed = getHopsAway(*mp, config.lora.hop_limit);
auto hopStart = mp->hop_start; if (hopsUsed > (int32_t)(config.lora.hop_limit + 2)) {
auto hopLimit = mp->hop_limit;
uint8_t hopsUsed = hopStart < hopLimit ? config.lora.hop_limit : hopStart - hopLimit;
if (hopsUsed > config.lora.hop_limit + 2) {
LOG_DEBUG("Skip send NodeInfo: %d hops away is too far away", hopsUsed); LOG_DEBUG("Skip send NodeInfo: %d hops away is too far away", hopsUsed);
} else { } else {
LOG_INFO("Heard new node on ch. %d, send NodeInfo and ask for response", mp->channel); LOG_INFO("Heard new node on ch. %d, send NodeInfo and ask for response", mp->channel);

View File

@@ -64,7 +64,7 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
perhapsRebroadcast(p); perhapsRebroadcast(p);
} }
} else { } else {
bool isRepeated = p->hop_start > 0 && p->hop_start == p->hop_limit; bool isRepeated = getHopsAway(*p) == 0;
// If repeated and not in Tx queue anymore, try relaying again, or if we are the destination, send the ACK again // If repeated and not in Tx queue anymore, try relaying again, or if we are the destination, send the ACK again
if (isRepeated) { if (isRepeated) {
if (!findInTxQueue(p->from, p->id)) { if (!findInTxQueue(p->from, p->id)) {
@@ -101,8 +101,7 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast
bool wasAlreadyRelayer = wasRelayer(p->relay_node, p->decoded.request_id, p->to); bool wasAlreadyRelayer = wasRelayer(p->relay_node, p->decoded.request_id, p->to);
bool weWereSoleRelayer = false; bool weWereSoleRelayer = false;
bool weWereRelayer = wasRelayer(ourRelayID, p->decoded.request_id, p->to, &weWereSoleRelayer); bool weWereRelayer = wasRelayer(ourRelayID, p->decoded.request_id, p->to, &weWereSoleRelayer);
if ((weWereRelayer && wasAlreadyRelayer) || if ((weWereRelayer && wasAlreadyRelayer) || (getHopsAway(*p) == 0 && weWereSoleRelayer)) {
(p->hop_start != 0 && p->hop_start == p->hop_limit && weWereSoleRelayer)) {
if (origTx->next_hop != p->relay_node) { // Not already set if (origTx->next_hop != p->relay_node) { // Not already set
LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply (was relayer %d we were sole %d)", p->from, LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply (was relayer %d we were sole %d)", p->from,
p->relay_node, wasAlreadyRelayer, weWereSoleRelayer); p->relay_node, wasAlreadyRelayer, weWereSoleRelayer);

View File

@@ -805,7 +805,8 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.external_notification.output_ms = 500; moduleConfig.external_notification.output_ms = 500;
moduleConfig.external_notification.nag_timeout = 2; moduleConfig.external_notification.nag_timeout = 2;
#endif #endif
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312) || defined(MUZI_BASE) || defined(ELECROW_ThinkNode_M3) #if defined(RAK4630) || defined(RAK11310) || defined(RAK3312) || defined(MUZI_BASE) || defined(ELECROW_ThinkNode_M3) || \
defined(ELECROW_ThinkNode_M6)
// Default to PIN_LED2 for external notification output (LED color depends on device variant) // Default to PIN_LED2 for external notification output (LED color depends on device variant)
moduleConfig.external_notification.enabled = true; moduleConfig.external_notification.enabled = true;
moduleConfig.external_notification.output = PIN_LED2; moduleConfig.external_notification.output = PIN_LED2;
@@ -1548,6 +1549,23 @@ uint32_t sinceReceived(const meshtastic_MeshPacket *p)
return delta; return delta;
} }
int8_t getHopsAway(const meshtastic_MeshPacket &p, int8_t defaultIfUnknown)
{
// Firmware prior to 2.3.0 (585805c) lacked a hop_start field. Firmware version 2.5.0 (bf34329) introduced a
// bitfield that is always present. Use the presence of the bitfield to determine if the origin's firmware
// version is guaranteed to have hop_start populated. Note that this can only be done for decoded packets as
// the bitfield is encrypted under the channel encryption key. For encrypted packets, this returns
// defaultIfUnknown when hop_start is 0.
if (p.hop_start == 0 && !(p.which_payload_variant == meshtastic_MeshPacket_decoded_tag && p.decoded.has_bitfield))
return defaultIfUnknown; // Cannot reliably determine the number of hops.
// Guard against invalid values.
if (p.hop_start < p.hop_limit)
return defaultIfUnknown;
return p.hop_start - p.hop_limit;
}
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline #define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
size_t NodeDB::getNumOnlineMeshNodes(bool localOnly) size_t NodeDB::getNumOnlineMeshNodes(bool localOnly)
@@ -1800,9 +1818,10 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
info->via_mqtt = mp.via_mqtt; // Store if we received this packet via MQTT info->via_mqtt = mp.via_mqtt; // Store if we received this packet via MQTT
// If hopStart was set and there wasn't someone messing with the limit in the middle, add hopsAway // If hopStart was set and there wasn't someone messing with the limit in the middle, add hopsAway
if (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start) { const int8_t hopsAway = getHopsAway(mp);
if (hopsAway >= 0) {
info->has_hops_away = true; info->has_hops_away = true;
info->hops_away = mp.hop_start - mp.hop_limit; info->hops_away = hopsAway;
} }
sortMeshDB(); sortMeshDB();
} }

View File

@@ -110,6 +110,10 @@ uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
/// Given a packet, return how many seconds in the past (vs now) it was received /// Given a packet, return how many seconds in the past (vs now) it was received
uint32_t sinceReceived(const meshtastic_MeshPacket *p); uint32_t sinceReceived(const meshtastic_MeshPacket *p);
/// Given a packet, return the number of hops used to reach this node.
/// Returns defaultIfUnknown if the number of hops couldn't be determined.
int8_t getHopsAway(const meshtastic_MeshPacket &p, int8_t defaultIfUnknown = -1);
enum LoadFileResult { enum LoadFileResult {
// Successfully opened the file // Successfully opened the file
LOAD_SUCCESS = 1, LOAD_SUCCESS = 1,

View File

@@ -1,6 +1,7 @@
#include "ReliableRouter.h" #include "ReliableRouter.h"
#include "Default.h" #include "Default.h"
#include "MeshTypes.h" #include "MeshTypes.h"
#include "NodeDB.h"
#include "configuration.h" #include "configuration.h"
#include "memGet.h" #include "memGet.h"
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
@@ -108,12 +109,12 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
// If this packet should always be ACKed reliably with want_ack back to the original sender, make sure we // If this packet should always be ACKed reliably with want_ack back to the original sender, make sure we
// do that unconditionally. // do that unconditionally.
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit), true); routingModule->getHopLimitForResponse(*p), true);
} else if (!p->decoded.request_id && !p->decoded.reply_id) { } else if (!p->decoded.request_id && !p->decoded.reply_id) {
// If it's not an ACK or a reply, send an ACK. // If it's not an ACK or a reply, send an ACK.
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit)); routingModule->getHopLimitForResponse(*p));
} else if ((p->hop_start > 0 && p->hop_start == p->hop_limit) || p->next_hop != NO_NEXT_HOP_PREFERENCE) { } else if ((getHopsAway(*p) == 0) || p->next_hop != NO_NEXT_HOP_PREFERENCE) {
// If we received the packet directly from the original sender, send a 0-hop ACK since the original sender // If we received the packet directly from the original sender, send a 0-hop ACK since the original sender
// won't overhear any implicit ACKs. If we received the packet via NextHopRouter, also send a 0-hop ACK to // won't overhear any implicit ACKs. If we received the packet via NextHopRouter, also send a 0-hop ACK to
// stop the immediate relayer's retransmissions. // stop the immediate relayer's retransmissions.
@@ -123,11 +124,11 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) { (nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY"); LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY");
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(), sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit)); routingModule->getHopLimitForResponse(*p));
} else { } else {
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded // Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(), sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit)); routingModule->getHopLimitForResponse(*p));
} }
} else if (p->next_hop == nodeDB->getLastByteOfNodeNum(getNodeNum()) && p->hop_limit > 0) { } else if (p->next_hop == nodeDB->getLastByteOfNodeNum(getNodeNum()) && p->hop_limit > 0) {
// No wantAck, but we need to ACK with hop limit of 0 if we were the next hop to stop their retransmissions // No wantAck, but we need to ACK with hop limit of 0 if we were the next hop to stop their retransmissions

View File

@@ -81,8 +81,7 @@ Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRA
bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p) bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p)
{ {
// First hop MUST always decrement to prevent retry issues // First hop MUST always decrement to prevent retry issues
bool isFirstHop = (p->hop_start != 0 && p->hop_start == p->hop_limit); if (getHopsAway(*p) == 0) {
if (isFirstHop) {
return true; // Always decrement on first hop return true; // Always decrement on first hop
} }
@@ -692,7 +691,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
// Store a copy of encrypted packet for MQTT // Store a copy of encrypted packet for MQTT
DEBUG_HEAP_BEFORE; DEBUG_HEAP_BEFORE;
p_encrypted = packetPool.allocCopy(*p); meshtastic_MeshPacket *p_encrypted = packetPool.allocCopy(*p);
DEBUG_HEAP_AFTER("Router::handleReceived", p_encrypted); DEBUG_HEAP_AFTER("Router::handleReceived", p_encrypted);
// Take those raw bytes and convert them back into a well structured protobuf we can understand // Take those raw bytes and convert them back into a well structured protobuf we can understand
@@ -745,20 +744,23 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
MeshModule::callModules(*p, src); MeshModule::callModules(*p, src);
#if !MESHTASTIC_EXCLUDE_MQTT #if !MESHTASTIC_EXCLUDE_MQTT
// Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not to if (p_encrypted == nullptr) {
// us (because we would be able to decrypt it) LOG_WARN("p_encrypted is null, skipping MQTT publish");
if (decodedState == DecodeState::DECODE_FAILURE && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 && } else {
!isBroadcast(p->to) && !isToUs(p)) // Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not
p_encrypted->pki_encrypted = true; // to us (because we would be able to decrypt it)
// After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet if (decodedState == DecodeState::DECODE_FAILURE && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 &&
if ((decodedState == DecodeState::DECODE_SUCCESS || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled && !isBroadcast(p->to) && !isToUs(p))
!isFromUs(p) && mqtt) p_encrypted->pki_encrypted = true;
mqtt->onSend(*p_encrypted, *p, p->channel); // After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet
if ((decodedState == DecodeState::DECODE_SUCCESS || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled &&
!isFromUs(p) && mqtt)
mqtt->onSend(*p_encrypted, *p, p->channel);
}
#endif #endif
} }
packetPool.release(p_encrypted); // Release the encrypted packet packetPool.release(p_encrypted); // Release the encrypted packet
p_encrypted = nullptr;
} }
void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)

View File

@@ -91,9 +91,6 @@ class Router : protected concurrency::OSThread, protected PacketHistory
before us */ before us */
uint32_t rxDupe = 0, txRelayCanceled = 0; uint32_t rxDupe = 0, txRelayCanceled = 0;
// pointer to the encrypted packet
meshtastic_MeshPacket *p_encrypted = nullptr;
protected: protected:
friend class RoutingModule; friend class RoutingModule;

View File

@@ -33,5 +33,3 @@ PB_BIND(meshtastic_KeyVerificationAdmin, meshtastic_KeyVerificationAdmin, AUTO)

View File

@@ -16,16 +16,6 @@
#endif #endif
/* Enum definitions */ /* Enum definitions */
/* Firmware update mode for OTA updates */
typedef enum _meshtastic_OTAMode {
/* Do not reboot into OTA mode */
meshtastic_OTAMode_NO_REBOOT_OTA = 0,
/* Reboot into OTA mode for BLE firmware update */
meshtastic_OTAMode_OTA_BLE = 1,
/* Reboot into OTA mode for WiFi firmware update */
meshtastic_OTAMode_OTA_WIFI = 2
} meshtastic_OTAMode;
/* TODO: REPLACE */ /* TODO: REPLACE */
typedef enum _meshtastic_AdminMessage_ConfigType { typedef enum _meshtastic_AdminMessage_ConfigType {
/* TODO: REPLACE */ /* TODO: REPLACE */
@@ -268,13 +258,10 @@ typedef struct _meshtastic_AdminMessage {
meshtastic_SharedContact add_contact; meshtastic_SharedContact add_contact;
/* Initiate or respond to a key verification request */ /* Initiate or respond to a key verification request */
meshtastic_KeyVerificationAdmin key_verification; meshtastic_KeyVerificationAdmin key_verification;
/* Tell the node to reboot into OTA mode for firmware update via BLE or WiFi (ESP32 only for now) */
meshtastic_OTAMode reboot_ota_mode;
/* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */ /* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */
int32_t factory_reset_device; int32_t factory_reset_device;
/* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) /* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. */
Deprecated in favor of reboot_ota_mode in 2.7.17 */
int32_t reboot_ota_seconds; int32_t reboot_ota_seconds;
/* This message is only supported for the simulator Portduino build. /* This message is only supported for the simulator Portduino build.
If received the simulator will exit successfully. */ If received the simulator will exit successfully. */
@@ -301,10 +288,6 @@ extern "C" {
#endif #endif
/* Helper constants for enums */ /* Helper constants for enums */
#define _meshtastic_OTAMode_MIN meshtastic_OTAMode_NO_REBOOT_OTA
#define _meshtastic_OTAMode_MAX meshtastic_OTAMode_OTA_WIFI
#define _meshtastic_OTAMode_ARRAYSIZE ((meshtastic_OTAMode)(meshtastic_OTAMode_OTA_WIFI+1))
#define _meshtastic_AdminMessage_ConfigType_MIN meshtastic_AdminMessage_ConfigType_DEVICE_CONFIG #define _meshtastic_AdminMessage_ConfigType_MIN meshtastic_AdminMessage_ConfigType_DEVICE_CONFIG
#define _meshtastic_AdminMessage_ConfigType_MAX meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG #define _meshtastic_AdminMessage_ConfigType_MAX meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG
#define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG+1)) #define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG+1))
@@ -326,7 +309,6 @@ extern "C" {
#define meshtastic_AdminMessage_payload_variant_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation #define meshtastic_AdminMessage_payload_variant_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation
#define meshtastic_AdminMessage_payload_variant_restore_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation #define meshtastic_AdminMessage_payload_variant_restore_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation
#define meshtastic_AdminMessage_payload_variant_remove_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation #define meshtastic_AdminMessage_payload_variant_remove_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation
#define meshtastic_AdminMessage_payload_variant_reboot_ota_mode_ENUMTYPE meshtastic_OTAMode
@@ -414,7 +396,6 @@ extern "C" {
#define meshtastic_AdminMessage_commit_edit_settings_tag 65 #define meshtastic_AdminMessage_commit_edit_settings_tag 65
#define meshtastic_AdminMessage_add_contact_tag 66 #define meshtastic_AdminMessage_add_contact_tag 66
#define meshtastic_AdminMessage_key_verification_tag 67 #define meshtastic_AdminMessage_key_verification_tag 67
#define meshtastic_AdminMessage_reboot_ota_mode_tag 68
#define meshtastic_AdminMessage_factory_reset_device_tag 94 #define meshtastic_AdminMessage_factory_reset_device_tag 94
#define meshtastic_AdminMessage_reboot_ota_seconds_tag 95 #define meshtastic_AdminMessage_reboot_ota_seconds_tag 95
#define meshtastic_AdminMessage_exit_simulator_tag 96 #define meshtastic_AdminMessage_exit_simulator_tag 96
@@ -473,7 +454,6 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_ed
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,add_contact,add_contact), 66) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,add_contact,add_contact), 66) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification,key_verification), 67) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification,key_verification), 67) \
X(a, STATIC, ONEOF, UENUM, (payload_variant,reboot_ota_mode,reboot_ota_mode), 68) \
X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \ X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \ X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \

View File

@@ -24,9 +24,6 @@ PB_BIND(meshtastic_Data, meshtastic_Data, 2)
PB_BIND(meshtastic_KeyVerification, meshtastic_KeyVerification, AUTO) PB_BIND(meshtastic_KeyVerification, meshtastic_KeyVerification, AUTO)
PB_BIND(meshtastic_StoreForwardPlusPlus, meshtastic_StoreForwardPlusPlus, 2)
PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO) PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO)
@@ -124,8 +121,6 @@ PB_BIND(meshtastic_ChunkedPayloadResponse, meshtastic_ChunkedPayloadResponse, AU

View File

@@ -478,22 +478,6 @@ typedef enum _meshtastic_Routing_Error {
meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED = 38 meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED = 38
} meshtastic_Routing_Error; } meshtastic_Routing_Error;
/* Enum of message types */
typedef enum _meshtastic_StoreForwardPlusPlus_SFPP_message_type {
/* Send an announcement of the canonical tip of a chain */
meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE = 0,
/* Query whether a specific link is on the chain */
meshtastic_StoreForwardPlusPlus_SFPP_message_type_CHAIN_QUERY = 1,
/* Request the next link in the chain */
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_REQUEST = 3,
/* Provide a link to add to the chain */
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE = 4,
/* If we must fragment, send the first half */
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_FIRSTHALF = 5,
/* If we must fragment, send the second half */
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF = 6
} meshtastic_StoreForwardPlusPlus_SFPP_message_type;
/* The priority of this message for sending. /* The priority of this message for sending.
Higher priorities are sent first (when managing the transmit queue). Higher priorities are sent first (when managing the transmit queue).
This field is never sent over the air, it is only used internally inside of a local device node. This field is never sent over the air, it is only used internally inside of a local device node.
@@ -798,32 +782,6 @@ typedef struct _meshtastic_KeyVerification {
meshtastic_KeyVerification_hash2_t hash2; meshtastic_KeyVerification_hash2_t hash2;
} meshtastic_KeyVerification; } meshtastic_KeyVerification;
typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_message_hash_t;
typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_commit_hash_t;
typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_root_hash_t;
typedef PB_BYTES_ARRAY_T(240) meshtastic_StoreForwardPlusPlus_message_t;
/* The actual over-the-mesh message doing store and forward++ */
typedef struct _meshtastic_StoreForwardPlusPlus {
/* Which message type is this */
meshtastic_StoreForwardPlusPlus_SFPP_message_type sfpp_message_type;
/* The hash of the specific message */
meshtastic_StoreForwardPlusPlus_message_hash_t message_hash;
/* The hash of a link on a chain */
meshtastic_StoreForwardPlusPlus_commit_hash_t commit_hash;
/* the root hash of a chain */
meshtastic_StoreForwardPlusPlus_root_hash_t root_hash;
/* The encrypted bytes from a message */
meshtastic_StoreForwardPlusPlus_message_t message;
/* Message ID of the contained message */
uint32_t encapsulated_id;
/* Destination of the contained message */
uint32_t encapsulated_to;
/* Sender of the contained message */
uint32_t encapsulated_from;
/* The receive time of the message in question */
uint32_t encapsulated_rxtime;
} meshtastic_StoreForwardPlusPlus;
/* Waypoint message, used to share arbitrary locations across the mesh */ /* Waypoint message, used to share arbitrary locations across the mesh */
typedef struct _meshtastic_Waypoint { typedef struct _meshtastic_Waypoint {
/* Id of the waypoint */ /* Id of the waypoint */
@@ -1352,10 +1310,6 @@ extern "C" {
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED #define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED+1)) #define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED+1))
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1))
#define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET #define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET
#define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX #define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX
#define _meshtastic_MeshPacket_Priority_ARRAYSIZE ((meshtastic_MeshPacket_Priority)(meshtastic_MeshPacket_Priority_MAX+1)) #define _meshtastic_MeshPacket_Priority_ARRAYSIZE ((meshtastic_MeshPacket_Priority)(meshtastic_MeshPacket_Priority_MAX+1))
@@ -1384,8 +1338,6 @@ extern "C" {
#define meshtastic_Data_portnum_ENUMTYPE meshtastic_PortNum #define meshtastic_Data_portnum_ENUMTYPE meshtastic_PortNum
#define meshtastic_StoreForwardPlusPlus_sfpp_message_type_ENUMTYPE meshtastic_StoreForwardPlusPlus_SFPP_message_type
#define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority #define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority
@@ -1428,7 +1380,6 @@ extern "C" {
#define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}} #define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}}
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}} #define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}}
#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
@@ -1460,7 +1411,6 @@ extern "C" {
#define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}} #define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}}
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}} #define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}}
#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
@@ -1539,15 +1489,6 @@ extern "C" {
#define meshtastic_KeyVerification_nonce_tag 1 #define meshtastic_KeyVerification_nonce_tag 1
#define meshtastic_KeyVerification_hash1_tag 2 #define meshtastic_KeyVerification_hash1_tag 2
#define meshtastic_KeyVerification_hash2_tag 3 #define meshtastic_KeyVerification_hash2_tag 3
#define meshtastic_StoreForwardPlusPlus_sfpp_message_type_tag 1
#define meshtastic_StoreForwardPlusPlus_message_hash_tag 2
#define meshtastic_StoreForwardPlusPlus_commit_hash_tag 3
#define meshtastic_StoreForwardPlusPlus_root_hash_tag 4
#define meshtastic_StoreForwardPlusPlus_message_tag 5
#define meshtastic_StoreForwardPlusPlus_encapsulated_id_tag 6
#define meshtastic_StoreForwardPlusPlus_encapsulated_to_tag 7
#define meshtastic_StoreForwardPlusPlus_encapsulated_from_tag 8
#define meshtastic_StoreForwardPlusPlus_encapsulated_rxtime_tag 9
#define meshtastic_Waypoint_id_tag 1 #define meshtastic_Waypoint_id_tag 1
#define meshtastic_Waypoint_latitude_i_tag 2 #define meshtastic_Waypoint_latitude_i_tag 2
#define meshtastic_Waypoint_longitude_i_tag 3 #define meshtastic_Waypoint_longitude_i_tag 3
@@ -1764,19 +1705,6 @@ X(a, STATIC, SINGULAR, BYTES, hash2, 3)
#define meshtastic_KeyVerification_CALLBACK NULL #define meshtastic_KeyVerification_CALLBACK NULL
#define meshtastic_KeyVerification_DEFAULT NULL #define meshtastic_KeyVerification_DEFAULT NULL
#define meshtastic_StoreForwardPlusPlus_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, sfpp_message_type, 1) \
X(a, STATIC, SINGULAR, BYTES, message_hash, 2) \
X(a, STATIC, SINGULAR, BYTES, commit_hash, 3) \
X(a, STATIC, SINGULAR, BYTES, root_hash, 4) \
X(a, STATIC, SINGULAR, BYTES, message, 5) \
X(a, STATIC, SINGULAR, UINT32, encapsulated_id, 6) \
X(a, STATIC, SINGULAR, UINT32, encapsulated_to, 7) \
X(a, STATIC, SINGULAR, UINT32, encapsulated_from, 8) \
X(a, STATIC, SINGULAR, UINT32, encapsulated_rxtime, 9)
#define meshtastic_StoreForwardPlusPlus_CALLBACK NULL
#define meshtastic_StoreForwardPlusPlus_DEFAULT NULL
#define meshtastic_Waypoint_FIELDLIST(X, a) \ #define meshtastic_Waypoint_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, id, 1) \ X(a, STATIC, SINGULAR, UINT32, id, 1) \
X(a, STATIC, OPTIONAL, SFIXED32, latitude_i, 2) \ X(a, STATIC, OPTIONAL, SFIXED32, latitude_i, 2) \
@@ -2052,7 +1980,6 @@ extern const pb_msgdesc_t meshtastic_RouteDiscovery_msg;
extern const pb_msgdesc_t meshtastic_Routing_msg; extern const pb_msgdesc_t meshtastic_Routing_msg;
extern const pb_msgdesc_t meshtastic_Data_msg; extern const pb_msgdesc_t meshtastic_Data_msg;
extern const pb_msgdesc_t meshtastic_KeyVerification_msg; extern const pb_msgdesc_t meshtastic_KeyVerification_msg;
extern const pb_msgdesc_t meshtastic_StoreForwardPlusPlus_msg;
extern const pb_msgdesc_t meshtastic_Waypoint_msg; extern const pb_msgdesc_t meshtastic_Waypoint_msg;
extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg; extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg;
extern const pb_msgdesc_t meshtastic_MeshPacket_msg; extern const pb_msgdesc_t meshtastic_MeshPacket_msg;
@@ -2086,7 +2013,6 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_Routing_fields &meshtastic_Routing_msg #define meshtastic_Routing_fields &meshtastic_Routing_msg
#define meshtastic_Data_fields &meshtastic_Data_msg #define meshtastic_Data_fields &meshtastic_Data_msg
#define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg #define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg
#define meshtastic_StoreForwardPlusPlus_fields &meshtastic_StoreForwardPlusPlus_msg
#define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg #define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg
#define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg #define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg
#define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg #define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg
@@ -2143,7 +2069,6 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_QueueStatus_size 23 #define meshtastic_QueueStatus_size 23
#define meshtastic_RouteDiscovery_size 256 #define meshtastic_RouteDiscovery_size 256
#define meshtastic_Routing_size 259 #define meshtastic_Routing_size 259
#define meshtastic_StoreForwardPlusPlus_size 371
#define meshtastic_ToRadio_size 504 #define meshtastic_ToRadio_size 504
#define meshtastic_User_size 115 #define meshtastic_User_size 115
#define meshtastic_Waypoint_size 165 #define meshtastic_Waypoint_size 165

View File

@@ -86,11 +86,6 @@ typedef enum _meshtastic_PortNum {
/* Paxcounter lib included in the firmware /* Paxcounter lib included in the firmware
ENCODING: protobuf */ ENCODING: protobuf */
meshtastic_PortNum_PAXCOUNTER_APP = 34, meshtastic_PortNum_PAXCOUNTER_APP = 34,
/* Store and Forward++ module included in the firmware
ENCODING: protobuf
This module is specifically for Native Linux nodes, and provides a Git-style
chain of messages. */
meshtastic_PortNum_STORE_FORWARD_PLUSPLUS_APP = 35,
/* Provides a hardware serial interface to send and receive from the Meshtastic network. /* Provides a hardware serial interface to send and receive from the Meshtastic network.
Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network. network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.

View File

@@ -170,7 +170,7 @@ bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
} else { } else {
LOG_DEBUG(" Ignoring dummy neighbor info packet (single neighbor with nodeId 0, snr 0)"); LOG_DEBUG(" Ignoring dummy neighbor info packet (single neighbor with nodeId 0, snr 0)");
} }
} else if (mp.hop_start != 0 && mp.hop_start == mp.hop_limit) { } else if (getHopsAway(mp) == 0) {
LOG_DEBUG("Get or create neighbor: %u with snr %f", mp.from, mp.rx_snr); LOG_DEBUG("Get or create neighbor: %u with snr %f", mp.from, mp.rx_snr);
// If the hopLimit is the same as hopStart, then it is a neighbor // If the hopLimit is the same as hopStart, then it is a neighbor
getOrCreateNeighbor(mp.from, mp.from, 0, getOrCreateNeighbor(mp.from, mp.from, 0,

View File

@@ -429,7 +429,9 @@ int32_t PositionModule::runOnce()
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) { if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
if (waitingForFreshPosition) { if (waitingForFreshPosition) {
#ifdef GPS_DEBUG
LOG_DEBUG("Skip initial position send; no fresh position since boot"); LOG_DEBUG("Skip initial position send; no fresh position since boot");
#endif
} else if (nodeDB->hasValidPosition(node)) { } else if (nodeDB->hasValidPosition(node)) {
lastGpsSend = now; lastGpsSend = now;

View File

@@ -58,12 +58,11 @@ void RoutingModule::sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketI
router->sendLocal(p); // we sometimes send directly to the local node router->sendLocal(p); // we sometimes send directly to the local node
} }
uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit) uint8_t RoutingModule::getHopLimitForResponse(const meshtastic_MeshPacket &mp)
{ {
if (hopStart != 0) { const int8_t hopsUsed = getHopsAway(mp);
// Hops used by the request. If somebody in between running modified firmware modified it, ignore it if (hopsUsed >= 0) {
uint8_t hopsUsed = hopStart < hopLimit ? config.lora.hop_limit : hopStart - hopLimit; if (hopsUsed > (int32_t)(config.lora.hop_limit)) {
if (hopsUsed > config.lora.hop_limit) {
// In event mode, we never want to send packets with more than our default 3 hops. // In event mode, we never want to send packets with more than our default 3 hops.
#if !(EVENTMODE) // This falls through to the default. #if !(EVENTMODE) // This falls through to the default.
return hopsUsed; // If the request used more hops than the limit, use the same amount of hops return hopsUsed; // If the request used more hops than the limit, use the same amount of hops

View File

@@ -20,7 +20,7 @@ class RoutingModule : public ProtobufModule<meshtastic_Routing>
uint8_t hopLimit = 0); uint8_t hopLimit = 0);
// Given the hopStart and hopLimit upon reception of a request, return the hop limit to use for the response // Given the hopStart and hopLimit upon reception of a request, return the hop limit to use for the response
uint8_t getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit); uint8_t getHopLimitForResponse(const meshtastic_MeshPacket &mp);
protected: protected:
friend class Router; friend class Router;

View File

@@ -20,7 +20,7 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
switch (arg->getStatusType()) { switch (arg->getStatusType()) {
case STATUS_TYPE_POWER: { case STATUS_TYPE_POWER: {
meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg; meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg;
if (powerStatus->getHasUSB()) { if (powerStatus->getHasUSB() || powerStatus->getIsCharging()) {
power_state = charging; power_state = charging;
if (powerStatus->getBatteryChargePercent() >= 100) { if (powerStatus->getBatteryChargePercent() >= 100) {
power_state = charged; power_state = charged;

View File

@@ -1,5 +1,6 @@
#include "TraceRouteModule.h" #include "TraceRouteModule.h"
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h"
#include "graphics/Screen.h" #include "graphics/Screen.h"
#include "graphics/ScreenFonts.h" #include "graphics/ScreenFonts.h"
#include "graphics/SharedUIDisplay.h" #include "graphics/SharedUIDisplay.h"
@@ -359,10 +360,10 @@ void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_Ro
} }
// Only insert unknown hops if hop_start is valid // Only insert unknown hops if hop_start is valid
if (p.hop_start != 0 && p.hop_limit <= p.hop_start) { const int8_t hopsTaken = getHopsAway(p);
uint8_t hopsTaken = p.hop_start - p.hop_limit; if (hopsTaken >= 0) {
int8_t diff = hopsTaken - *route_count; int8_t diff = hopsTaken - *route_count;
for (uint8_t i = 0; i < diff; i++) { for (int8_t i = 0; i < diff; i++) {
if (*route_count < ROUTE_SIZE) { if (*route_count < ROUTE_SIZE) {
route[*route_count] = NODENUM_BROADCAST; // This will represent an unknown hop route[*route_count] = NODENUM_BROADCAST; // This will represent an unknown hop
*route_count += 1; *route_count += 1;
@@ -370,7 +371,7 @@ void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_Ro
} }
// Add unknown SNR values if necessary // Add unknown SNR values if necessary
diff = *route_count - *snr_count; diff = *route_count - *snr_count;
for (uint8_t i = 0; i < diff; i++) { for (int8_t i = 0; i < diff; i++) {
if (*snr_count < ROUTE_SIZE) { if (*snr_count < ROUTE_SIZE) {
snr_list[*snr_count] = INT8_MIN; // This will represent an unknown SNR snr_list[*snr_count] = INT8_MIN; // This will represent an unknown SNR
*snr_count += 1; *snr_count += 1;

View File

@@ -14,11 +14,11 @@
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#ifdef NIMBLE_TWO
#include "NimBLEAdvertising.h" #include "NimBLEAdvertising.h"
#ifdef CONFIG_BT_NIMBLE_EXT_ADV
#include "NimBLEExtAdvertising.h" #include "NimBLEExtAdvertising.h"
#endif
#include "PowerStatus.h" #include "PowerStatus.h"
#endif
#if defined(CONFIG_NIMBLE_CPP_IDF) #if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_gap.h" #include "host/ble_gap.h"
@@ -26,12 +26,15 @@
#include "nimble/nimble/host/include/host/ble_gap.h" #include "nimble/nimble/host/include/host/ble_gap.h"
#endif #endif
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
namespace namespace
{ {
constexpr uint16_t kPreferredBleMtu = 517; constexpr uint16_t kPreferredBleMtu = 517;
constexpr uint16_t kPreferredBleTxOctets = 251; constexpr uint16_t kPreferredBleTxOctets = 251;
constexpr uint16_t kPreferredBleTxTimeUs = (kPreferredBleTxOctets + 14) * 8; constexpr uint16_t kPreferredBleTxTimeUs = (kPreferredBleTxOctets + 14) * 8;
} // namespace } // namespace
#endif
// Debugging options: careful, they slow things down quite a bit! // Debugging options: careful, they slow things down quite a bit!
// #define DEBUG_NIMBLE_ON_READ_TIMING // uncomment to time onRead duration // #define DEBUG_NIMBLE_ON_READ_TIMING // uncomment to time onRead duration
@@ -310,9 +313,11 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
{ {
PhoneAPI::onNowHasData(fromRadioNum); PhoneAPI::onNowHasData(fromRadioNum);
#ifdef DEBUG_NIMBLE_NOTIFY
int currentNotifyCount = notifyCount.fetch_add(1); int currentNotifyCount = notifyCount.fetch_add(1);
uint8_t cc = bleServer->getConnectedCount(); uint8_t cc = bleServer->getConnectedCount();
#ifdef DEBUG_NIMBLE_NOTIFY
// This logging slows things down when there are lots of packets going to the phone, like initial connection: // This logging slows things down when there are lots of packets going to the phone, like initial connection:
LOG_DEBUG("BLE notify(%d) fromNum: %d connections: %d", currentNotifyCount, fromRadioNum, cc); LOG_DEBUG("BLE notify(%d) fromNum: %d connections: %d", currentNotifyCount, fromRadioNum, cc);
#endif #endif
@@ -321,7 +326,13 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
put_le32(val, fromRadioNum); put_le32(val, fromRadioNum);
fromNumCharacteristic->setValue(val, sizeof(val)); fromNumCharacteristic->setValue(val, sizeof(val));
#ifdef NIMBLE_TWO
// NOTE: I don't have any NIMBLE_TWO devices, but this line makes me suspicious, and I suspect it needs to just be
// notify().
fromNumCharacteristic->notify(val, sizeof(val), BLE_HS_CONN_HANDLE_NONE); fromNumCharacteristic->notify(val, sizeof(val), BLE_HS_CONN_HANDLE_NONE);
#else
fromNumCharacteristic->notify();
#endif
} }
/// Check the current underlying physical link to see if the client is currently connected /// Check the current underlying physical link to see if the client is currently connected
@@ -386,7 +397,12 @@ static uint8_t lastToRadio[MAX_TO_FROM_RADIO_SIZE];
class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
{ {
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &) override #ifdef NIMBLE_TWO
virtual void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo)
#else
virtual void onWrite(NimBLECharacteristic *pCharacteristic)
#endif
{ {
// CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce. // CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce.
// Assumption: onWrite is serialized by NimBLE, so we don't need to lock here against multiple concurrent onWrite calls. // Assumption: onWrite is serialized by NimBLE, so we don't need to lock here against multiple concurrent onWrite calls.
@@ -433,7 +449,11 @@ class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
{ {
void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &) override #ifdef NIMBLE_TWO
virtual void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo)
#else
virtual void onRead(NimBLECharacteristic *pCharacteristic)
#endif
{ {
// CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce. // CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce.
@@ -541,27 +561,32 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
class NimbleBluetoothServerCallback : public NimBLEServerCallbacks class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
{ {
#ifdef NIMBLE_TWO
public: public:
explicit NimbleBluetoothServerCallback(NimbleBluetooth *ble) : ble(ble) {} NimbleBluetoothServerCallback(NimbleBluetooth *ble) { this->ble = ble; }
private: private:
NimbleBluetooth *ble; NimbleBluetooth *ble;
uint32_t onPassKeyDisplay() override virtual uint32_t onPassKeyDisplay()
#else
virtual uint32_t onPassKeyRequest()
#endif
{ {
uint32_t passkey = config.bluetooth.fixed_pin; uint32_t passkey = config.bluetooth.fixed_pin;
if (config.bluetooth.mode == meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN) { if (config.bluetooth.mode == meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN) {
LOG_INFO("Use random passkey"); LOG_INFO("Use random passkey");
// This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
passkey = random(100000, 999999); passkey = random(100000, 999999);
} }
LOG_INFO("*** Enter passkey %06u on the peer side ***", passkey); LOG_INFO("*** Enter passkey %d on the peer side ***", passkey);
powerFSM.trigger(EVENT_BLUETOOTH_PAIR); powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
meshtastic::BluetoothStatus newStatus(std::to_string(passkey)); meshtastic::BluetoothStatus newStatus(std::to_string(passkey));
bluetoothStatus->updateStatus(&newStatus); bluetoothStatus->updateStatus(&newStatus);
#if HAS_SCREEN #if HAS_SCREEN // Todo: migrate this display code back into Screen class, and observe bluetoothStatus
if (screen) { if (screen) {
screen->startAlert([passkey](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void { screen->startAlert([passkey](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
char btPIN[16] = "888888"; char btPIN[16] = "888888";
@@ -590,29 +615,39 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
}); });
} }
#endif #endif
passkeyShowing = true; passkeyShowing = true;
return passkey; return passkey;
} }
void onAuthenticationComplete(NimBLEConnInfo &connInfo) override #ifdef NIMBLE_TWO
virtual void onAuthenticationComplete(NimBLEConnInfo &connInfo)
#else
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc)
#endif
{ {
LOG_INFO("BLE authentication complete"); LOG_INFO("BLE authentication complete");
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::CONNECTED); meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::CONNECTED);
bluetoothStatus->updateStatus(&newStatus); bluetoothStatus->updateStatus(&newStatus);
// Todo: migrate this display code back into Screen class, and observe bluetoothStatus
if (passkeyShowing) { if (passkeyShowing) {
passkeyShowing = false; passkeyShowing = false;
if (screen) { if (screen)
screen->endAlert(); screen->endAlert();
}
} }
// Store the connection handle for future use
#ifdef NIMBLE_TWO
nimbleBluetoothConnHandle = connInfo.getConnHandle(); nimbleBluetoothConnHandle = connInfo.getConnHandle();
#else
nimbleBluetoothConnHandle = desc->conn_handle;
#endif
} }
void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) override #ifdef NIMBLE_TWO
virtual void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo)
{ {
LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str()); LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str());
@@ -637,12 +672,21 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
LOG_INFO("BLE conn %u initial MTU %u (target %u)", connHandle, connInfo.getMTU(), kPreferredBleMtu); LOG_INFO("BLE conn %u initial MTU %u (target %u)", connHandle, connInfo.getMTU(), kPreferredBleMtu);
pServer->updateConnParams(connHandle, 6, 12, 0, 200); pServer->updateConnParams(connHandle, 6, 12, 0, 200);
} }
#endif
void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) override #ifdef NIMBLE_TWO
virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason)
{ {
LOG_INFO("BLE disconnect reason: %d", reason); LOG_INFO("BLE disconnect reason: %d", reason);
#else
virtual void onDisconnect(NimBLEServer *pServer, ble_gap_conn_desc *desc)
{
LOG_INFO("BLE disconnect");
#endif
#ifdef NIMBLE_TWO
if (ble->isDeInit) if (ble->isDeInit)
return; return;
#endif
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED); meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED);
bluetoothStatus->updateStatus(&newStatus); bluetoothStatus->updateStatus(&newStatus);
@@ -666,69 +710,35 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
bluetoothPhoneAPI->writeCount = 0; bluetoothPhoneAPI->writeCount = 0;
} }
// Clear the last ToRadio packet buffer to avoid rejecting first packet from new connection
memset(lastToRadio, 0, sizeof(lastToRadio)); memset(lastToRadio, 0, sizeof(lastToRadio));
nimbleBluetoothConnHandle = BLE_HS_CONN_HANDLE_NONE; nimbleBluetoothConnHandle = BLE_HS_CONN_HANDLE_NONE; // BLE_HS_CONN_HANDLE_NONE means "no connection"
#ifdef NIMBLE_TWO
// Restart Advertising
ble->startAdvertising(); ble->startAdvertising();
#else
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
if (!pAdvertising->start(0)) {
if (pAdvertising->isAdvertising()) {
LOG_DEBUG("BLE advertising already running");
} else {
LOG_ERROR("BLE failed to restart advertising");
}
}
#endif
} }
}; };
static NimbleBluetoothToRadioCallback *toRadioCallbacks; static NimbleBluetoothToRadioCallback *toRadioCallbacks;
static NimbleBluetoothFromRadioCallback *fromRadioCallbacks; static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
void NimbleBluetooth::startAdvertising()
{
#if defined(CONFIG_BT_NIMBLE_EXT_ADV)
NimBLEExtAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
NimBLEExtAdvertisement legacyAdvertising;
legacyAdvertising.setLegacyAdvertising(true);
legacyAdvertising.setScannable(true);
legacyAdvertising.setConnectable(true);
legacyAdvertising.setFlags(BLE_HS_ADV_F_DISC_GEN);
if (powerStatus->getHasBattery() == 1) {
legacyAdvertising.setCompleteServices(NimBLEUUID((uint16_t)0x180f));
}
legacyAdvertising.setCompleteServices(NimBLEUUID(MESH_SERVICE_UUID));
legacyAdvertising.setMinInterval(500);
legacyAdvertising.setMaxInterval(1000);
NimBLEExtAdvertisement legacyScanResponse;
legacyScanResponse.setLegacyAdvertising(true);
legacyScanResponse.setConnectable(true);
legacyScanResponse.setName(getDeviceName());
if (!pAdvertising->setInstanceData(0, legacyAdvertising)) {
LOG_ERROR("BLE failed to set legacyAdvertising");
} else if (!pAdvertising->setScanResponseData(0, legacyScanResponse)) {
LOG_ERROR("BLE failed to set legacyScanResponse");
} else if (!pAdvertising->start(0, 0, 0)) {
LOG_ERROR("BLE failed to start legacyAdvertising");
}
#else
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset();
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
if (powerStatus->getHasBattery() == 1) {
pAdvertising->addServiceUUID(NimBLEUUID((uint16_t)0x180f));
}
NimBLEAdvertisementData scan;
scan.setName(getDeviceName());
pAdvertising->setScanResponseData(scan);
pAdvertising->enableScanResponse(true);
if (!pAdvertising->start(0)) {
LOG_ERROR("BLE failed to start advertising");
}
#endif
LOG_DEBUG("BLE Advertising started");
}
void NimbleBluetooth::shutdown() void NimbleBluetooth::shutdown()
{ {
// No measurable power saving for ESP32 during light-sleep(?)
#ifndef ARCH_ESP32 #ifndef ARCH_ESP32
// Shutdown bluetooth for minimum power draw
LOG_INFO("Disable bluetooth"); LOG_INFO("Disable bluetooth");
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset(); pAdvertising->reset();
@@ -736,6 +746,7 @@ void NimbleBluetooth::shutdown()
#endif #endif
} }
// Proper shutdown for ESP32. Needs reboot to reverse.
void NimbleBluetooth::deinit() void NimbleBluetooth::deinit()
{ {
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
@@ -749,17 +760,21 @@ void NimbleBluetooth::deinit()
digitalWrite(BLE_LED, LOW); digitalWrite(BLE_LED, LOW);
#endif #endif
#endif #endif
#ifndef NIMBLE_TWO
NimBLEDevice::deinit();
#endif
#endif #endif
} }
// Has initial setup been completed
bool NimbleBluetooth::isActive() bool NimbleBluetooth::isActive()
{ {
return bleServer != nullptr; return bleServer;
} }
bool NimbleBluetooth::isConnected() bool NimbleBluetooth::isConnected()
{ {
return bleServer && bleServer->getConnectedCount() > 0; return bleServer->getConnectedCount() > 0;
} }
int NimbleBluetooth::getRssi() int NimbleBluetooth::getRssi()
@@ -803,7 +818,7 @@ void NimbleBluetooth::setup()
LOG_INFO("Init the NimBLE bluetooth module"); LOG_INFO("Init the NimBLE bluetooth module");
NimBLEDevice::init(getDeviceName()); NimBLEDevice::init(getDeviceName());
NimBLEDevice::setPower(9); NimBLEDevice::setPower(ESP_PWR_LVL_P9);
#if NIMBLE_ENABLE_2M_PHY && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)) #if NIMBLE_ENABLE_2M_PHY && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6))
int mtuResult = NimBLEDevice::setMTU(kPreferredBleMtu); int mtuResult = NimBLEDevice::setMTU(kPreferredBleMtu);
@@ -836,7 +851,11 @@ void NimbleBluetooth::setup()
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY); NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
} }
bleServer = NimBLEDevice::createServer(); bleServer = NimBLEDevice::createServer();
auto *serverCallbacks = new NimbleBluetoothServerCallback(this); #ifdef NIMBLE_TWO
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback(this);
#else
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
#endif
bleServer->setCallbacks(serverCallbacks, true); bleServer->setCallbacks(serverCallbacks, true);
setupService(); setupService();
startAdvertising(); startAdvertising();
@@ -881,7 +900,11 @@ void NimbleBluetooth::setupService()
NimBLEService *batteryService = bleServer->createService(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service NimBLEService *batteryService = bleServer->createService(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic) BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic)
(uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1); (uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1);
#ifdef NIMBLE_TWO
NimBLE2904 *batteryLevelDescriptor = BatteryCharacteristic->create2904(); NimBLE2904 *batteryLevelDescriptor = BatteryCharacteristic->create2904();
#else
NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->createDescriptor((uint16_t)0x2904);
#endif
batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8); batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
batteryLevelDescriptor->setNamespace(1); batteryLevelDescriptor->setNamespace(1);
batteryLevelDescriptor->setUnit(0x27ad); batteryLevelDescriptor->setUnit(0x27ad);
@@ -889,12 +912,54 @@ void NimbleBluetooth::setupService()
batteryService->start(); batteryService->start();
} }
void NimbleBluetooth::startAdvertising()
{
#ifdef NIMBLE_TWO
NimBLEExtAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
NimBLEExtAdvertisement legacyAdvertising;
legacyAdvertising.setLegacyAdvertising(true);
legacyAdvertising.setScannable(true);
legacyAdvertising.setConnectable(true);
legacyAdvertising.setFlags(BLE_HS_ADV_F_DISC_GEN);
if (powerStatus->getHasBattery() == 1) {
legacyAdvertising.setCompleteServices(NimBLEUUID((uint16_t)0x180f));
}
legacyAdvertising.setCompleteServices(NimBLEUUID(MESH_SERVICE_UUID));
legacyAdvertising.setMinInterval(500);
legacyAdvertising.setMaxInterval(1000);
NimBLEExtAdvertisement legacyScanResponse;
legacyScanResponse.setLegacyAdvertising(true);
legacyScanResponse.setConnectable(true);
legacyScanResponse.setName(getDeviceName());
if (!pAdvertising->setInstanceData(0, legacyAdvertising)) {
LOG_ERROR("BLE failed to set legacyAdvertising");
} else if (!pAdvertising->setScanResponseData(0, legacyScanResponse)) {
LOG_ERROR("BLE failed to set legacyScanResponse");
} else if (!pAdvertising->start(0, 0, 0)) {
LOG_ERROR("BLE failed to start legacyAdvertising");
}
#else
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset();
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
pAdvertising->addServiceUUID(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
pAdvertising->start(0);
#endif
}
/// Given a level between 0-100, update the BLE attribute /// Given a level between 0-100, update the BLE attribute
void updateBatteryLevel(uint8_t level) void updateBatteryLevel(uint8_t level)
{ {
if ((config.bluetooth.enabled == true) && bleServer && nimbleBluetooth->isConnected()) { if ((config.bluetooth.enabled == true) && bleServer && nimbleBluetooth->isConnected()) {
BatteryCharacteristic->setValue(&level, 1); BatteryCharacteristic->setValue(&level, 1);
#ifdef NIMBLE_TWO
BatteryCharacteristic->notify(&level, 1, BLE_HS_CONN_HANDLE_NONE); BatteryCharacteristic->notify(&level, 1, BLE_HS_CONN_HANDLE_NONE);
#else
BatteryCharacteristic->notify();
#endif
} }
} }
@@ -909,7 +974,11 @@ void NimbleBluetooth::sendLog(const uint8_t *logMessage, size_t length)
if (!bleServer || !isConnected() || length > 512) { if (!bleServer || !isConnected() || length > 512) {
return; return;
} }
#ifdef NIMBLE_TWO
logRadioCharacteristic->notify(logMessage, length, BLE_HS_CONN_HANDLE_NONE); logRadioCharacteristic->notify(logMessage, length, BLE_HS_CONN_HANDLE_NONE);
#else
logRadioCharacteristic->notify(logMessage, length, true);
#endif
} }
void clearNVS() void clearNVS()

View File

@@ -12,11 +12,16 @@ class NimbleBluetooth : BluetoothApi
bool isConnected(); bool isConnected();
int getRssi(); int getRssi();
void sendLog(const uint8_t *logMessage, size_t length); void sendLog(const uint8_t *logMessage, size_t length);
#if defined(NIMBLE_TWO)
void startAdvertising(); void startAdvertising();
#endif
bool isDeInit = false; bool isDeInit = false;
private: private:
void setupService(); void setupService();
#if !defined(NIMBLE_TWO)
void startAdvertising();
#endif
}; };
void setBluetoothEnable(bool enable); void setBluetoothEnable(bool enable);

View File

@@ -279,7 +279,7 @@ void portduinoSetup()
// RAK6421-13300-S1:aabbcc123456:5ba85807d92138b7519cfb60460573af:3061e8d8 // RAK6421-13300-S1:aabbcc123456:5ba85807d92138b7519cfb60460573af:3061e8d8
// <model string>:mac address :<16 random unique bytes in hexidecimal> : crc32 // <model string>:mac address :<16 random unique bytes in hexidecimal> : crc32
// crc32 is calculated on the eeprom string up to but not including the final colon // crc32 is calculated on the eeprom string up to but not including the final colon
if (strlen(autoconf_product) < 6) { if (strlen(autoconf_product) < 6 && portduino_config.i2cdev != "") {
try { try {
char *mac_start = nullptr; char *mac_start = nullptr;
char *devID_start = nullptr; char *devID_start = nullptr;
@@ -867,4 +867,4 @@ void readGPIOFromYaml(YAML::Node sourceNode, pinMapping &destPin, int pinDefault
destPin.line = destPin.pin; destPin.line = destPin.pin;
destPin.gpiochip = portduino_config.lora_default_gpiochip; destPin.gpiochip = portduino_config.lora_default_gpiochip;
} }
} }

View File

@@ -8,9 +8,6 @@
#include <iostream> #include <iostream>
#include <libpinedio-usb.h> #include <libpinedio-usb.h>
#include <unistd.h> #include <unistd.h>
extern "C" {
#include "platform/portduino/ch341a_i2c.h"
}
// include the library for Raspberry GPIO pins // include the library for Raspberry GPIO pins
@@ -50,9 +47,6 @@ class Ch341Hal : public RadioLibHal
std::string s = "Could not open SPI: "; std::string s = "Could not open SPI: ";
throw(s + std::to_string(ret)); throw(s + std::to_string(ret));
} }
// How to read the eeprom
// uint8_t buffer[1024] = {0};
// ch341readEEPROM_param(buffer, 0, 128, 128, 8, 1, 0x50, pinedio.handle);
pinedio_set_option(&pinedio, PINEDIO_OPTION_AUTO_CS, 0); pinedio_set_option(&pinedio, PINEDIO_OPTION_AUTO_CS, 0);
pinedio_set_pin_mode(&pinedio, 3, true); pinedio_set_pin_mode(&pinedio, 3, true);

View File

@@ -1,204 +0,0 @@
//
// ch341eeprom programmer version 0.1 (Beta)
//
// Programming tool for the 24Cxx serial EEPROMs using the Winchiphead CH341A IC
//
// (c) December 2011 asbokid <ballymunboy@gmail.com>
// (c) August 2023 Mikhail Medvedev <e-ink-reader@yandex.ru>
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "ch341a_i2c.h"
// extern struct libusb_device_handle *handle;
unsigned char *readbuf;
uint32_t getnextpkt; // set by the callback function
uint32_t syncackpkt; // synch / ack flag used by BULK OUT cb function
uint32_t byteoffset;
// callback functions for async USB transfers
static void cbBulkIn(struct libusb_transfer *transfer);
static void cbBulkOut(struct libusb_transfer *transfer);
void ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, struct EEPROM *eeprom_info, uint32_t i2c_address)
{
uint8_t *ptr = buffer;
uint8_t msb_addr;
uint32_t size_kb;
*ptr++ = CH341_CMD_I2C_STREAM; // 0
*ptr++ = CH341_CMD_I2C_STM_STA; // 1
// Write address
*ptr++ = CH341_CMD_I2C_STM_OUT | ((*eeprom_info).addr_size + 1); // 2: I2C bus adddress + EEPROM address
if ((*eeprom_info).addr_size >= 2) {
// 24C32 and more
msb_addr = addr >> 16 & (*eeprom_info).i2c_addr_mask;
*ptr++ = (i2c_address | msb_addr) << 1; // 3
*ptr++ = (addr >> 8 & 0xFF); // 4
*ptr++ = (addr >> 0 & 0xFF); // 5
} else {
// 24C16 and less
msb_addr = addr >> 8 & (*eeprom_info).i2c_addr_mask;
*ptr++ = (i2c_address | msb_addr) << 1; // 3
*ptr++ = (addr >> 0 & 0xFF); // 4
}
// Read
*ptr++ = CH341_CMD_I2C_STM_STA; // 6/5
*ptr++ = CH341_CMD_I2C_STM_OUT | 1; // 7/6
*ptr++ = ((i2c_address | msb_addr) << 1) | 1; // 8/7: Read command
// Configuration?
*ptr++ = 0xE0; // 9/8
*ptr++ = 0x00; // 10/9
if ((*eeprom_info).addr_size < 2)
*ptr++ = 0x10; // x/10
memcpy(ptr, "\x00\x06\x04\x00\x00\x00\x00\x00\x00", 9);
ptr += 9; // 10
size_kb = (*eeprom_info).size / 1024;
*ptr++ = size_kb & 0xFF; // 19
*ptr++ = (size_kb >> 8) & 0xFF; // 20
memcpy(ptr, "\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc", 10);
ptr += 10;
// Frame 2
*ptr++ = CH341_CMD_I2C_STREAM;
memcpy(ptr,
"\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00"
"\xd9\x8b\x41\x7e\x00\xe0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e",
31);
ptr += 31;
// Frame 3
*ptr++ = CH341_CMD_I2C_STREAM;
memcpy(ptr,
"\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77"
"\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00",
31);
ptr += 31;
// Finalize
*ptr++ = CH341_CMD_I2C_STREAM; // 0xAA
*ptr++ = 0xDF; // ???
*ptr++ = CH341_CMD_I2C_STM_IN; // 0xC0
*ptr++ = CH341_CMD_I2C_STM_STO; // 0x75
*ptr++ = CH341_CMD_I2C_STM_END; // 0x00
assert(ptr - buffer == CH341_EEPROM_READ_CMD_SZ);
}
// --------------------------------------------------------------------------
// ch341readEEPROM()
// read n bytes from device (in packets of 32 bytes)
int32_t ch341readEEPROM_param(uint8_t *buffer, uint32_t offset, uint32_t bytestoread, uint32_t ic_size, uint32_t block_size,
uint8_t algorithm, uint32_t i2c_address, struct libusb_device_handle *handle)
{
uint8_t ch341outBuffer[EEPROM_READ_BULKOUT_BUF_SZ];
uint8_t ch341inBuffer[IN_BUF_SZ]; // 0x100 bytes
int32_t ret = 0, readpktcount = 0;
struct libusb_transfer *xferBulkIn, *xferBulkOut;
struct timeval tv = {0, 100}; // our async polling interval
struct EEPROM eeprom_info;
eeprom_info.name = "24c01";
eeprom_info.size = ic_size;
eeprom_info.page_size = (uint16_t)block_size;
eeprom_info.addr_size = 0x0f & algorithm;
eeprom_info.i2c_addr_mask = (0xf0 & algorithm) / 16;
xferBulkIn = libusb_alloc_transfer(0);
xferBulkOut = libusb_alloc_transfer(0);
if (!xferBulkIn || !xferBulkOut) {
printf("Couldn't allocate USB transfer structures\n");
return -1;
}
byteoffset = 0;
memset(ch341inBuffer, 0, EEPROM_READ_BULKIN_BUF_SZ);
ch341ReadCmdMarshall(ch341outBuffer, offset, &eeprom_info, i2c_address); // Fill output buffer
libusb_fill_bulk_transfer(xferBulkIn, handle, BULK_READ_ENDPOINT, ch341inBuffer, EEPROM_READ_BULKIN_BUF_SZ, cbBulkIn, NULL,
DEFAULT_TIMEOUT);
libusb_fill_bulk_transfer(xferBulkOut, handle, BULK_WRITE_ENDPOINT, ch341outBuffer, EEPROM_READ_BULKOUT_BUF_SZ, cbBulkOut,
NULL, DEFAULT_TIMEOUT);
libusb_submit_transfer(xferBulkIn);
libusb_submit_transfer(xferBulkOut);
readbuf = buffer;
while (1) {
ret = libusb_handle_events_timeout(NULL, &tv);
if (ret < 0 || getnextpkt == -1) { // indicates an error
printf("ret from libusb_handle_timeout = %d\n", ret);
printf("getnextpkt = %u\n", getnextpkt);
if (ret < 0)
printf("USB read error : %s\n", strerror(-ret));
libusb_free_transfer(xferBulkIn);
libusb_free_transfer(xferBulkOut);
return -1;
}
if (getnextpkt == 1) { // callback function reports a new BULK IN packet received
getnextpkt = 0; // reset the flag
readpktcount++; // increment the read packet counter
byteoffset += EEPROM_READ_BULKIN_BUF_SZ;
if (byteoffset == bytestoread)
break;
libusb_submit_transfer(xferBulkIn); // re-submit request for next BULK IN packet of EEPROM data
if (syncackpkt)
syncackpkt = 0;
// if 4th packet received, we are at end of 0x80 byte data block,
// if it is not the last block, then resubmit request for data
if (readpktcount == 4) {
readpktcount = 0;
ch341ReadCmdMarshall(ch341outBuffer, byteoffset, &eeprom_info, i2c_address); // Fill output buffer
libusb_fill_bulk_transfer(xferBulkOut, handle, BULK_WRITE_ENDPOINT, ch341outBuffer, EEPROM_READ_BULKOUT_BUF_SZ,
cbBulkOut, NULL, DEFAULT_TIMEOUT);
libusb_submit_transfer(xferBulkOut); // update transfer struct (with new EEPROM page offset)
// and re-submit next transfer request to BULK OUT endpoint
}
}
}
libusb_free_transfer(xferBulkIn);
libusb_free_transfer(xferBulkOut);
return 0;
}
// Callback function for async bulk in comms
void cbBulkIn(struct libusb_transfer *transfer)
{
switch (transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
// copy read data to our EEPROM buffer
memcpy(readbuf + byteoffset, transfer->buffer, transfer->actual_length);
getnextpkt = 1;
break;
default:
printf("\ncbBulkIn: error : %d\n", transfer->status);
getnextpkt = -1;
}
return;
}
// Callback function for async bulk out comms
void cbBulkOut(struct libusb_transfer *transfer)
{
syncackpkt = 1;
return;
}

View File

@@ -1,43 +0,0 @@
// libUSB driver for the ch341a in i2c mode
//
// Copyright 2011 asbokid <ballymunboy@gmail.com>
#ifndef __CH341A_I2C_H__
#define __CH341A_I2C_H__
#include <assert.h>
#include <errno.h>
#include <libusb-1.0/libusb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BULK_WRITE_ENDPOINT 0x02 /* bEndpointAddress 0x02 EP 2 OUT (Bulk)*/
#define BULK_READ_ENDPOINT 0x82 /* bEndpointAddress 0x82 EP 2 IN (Bulk)*/
#define DEFAULT_TIMEOUT 300 // 300mS for USB timeouts
#define IN_BUF_SZ 0x100
#define EEPROM_READ_BULKIN_BUF_SZ 0x20
#define EEPROM_READ_BULKOUT_BUF_SZ 0x65
#define CH341_CMD_I2C_STREAM 0xAA
#define CH341_CMD_I2C_STM_STA 0x74
#define CH341_CMD_I2C_STM_STO 0x75
#define CH341_CMD_I2C_STM_OUT 0x80
#define CH341_CMD_I2C_STM_IN 0xC0
#define CH341_CMD_I2C_STM_END 0x00
#define CH341_EEPROM_READ_CMD_SZ 0x65 /* Same size for all 24cXX read setup and next packets*/
struct EEPROM {
char *name;
uint32_t size;
uint16_t page_size;
uint8_t addr_size; // Length of address in bytes
uint8_t i2c_addr_mask;
};
int32_t ch341readEEPROM_param(uint8_t *buffer, uint32_t offset, uint32_t bytestoread, uint32_t ic_size, uint32_t block_size,
uint8_t algorithm, uint32_t i2c_address, struct libusb_device_handle *handle);
#endif /* __CH341A_I2C_H__ */

View File

@@ -418,8 +418,9 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi); jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi);
if (mp->rx_snr != 0) if (mp->rx_snr != 0)
jsonObj["snr"] = new JSONValue((float)mp->rx_snr); jsonObj["snr"] = new JSONValue((float)mp->rx_snr);
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) { const int8_t hopsAway = getHopsAway(*mp);
jsonObj["hops_away"] = new JSONValue((unsigned int)(mp->hop_start - mp->hop_limit)); if (hopsAway >= 0) {
jsonObj["hops_away"] = new JSONValue((unsigned int)(hopsAway));
jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start)); jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start));
} }
@@ -450,8 +451,9 @@ std::string MeshPacketSerializer::JsonSerializeEncrypted(const meshtastic_MeshPa
jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi); jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi);
if (mp->rx_snr != 0) if (mp->rx_snr != 0)
jsonObj["snr"] = new JSONValue((float)mp->rx_snr); jsonObj["snr"] = new JSONValue((float)mp->rx_snr);
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) { const int8_t hopsAway = getHopsAway(*mp);
jsonObj["hops_away"] = new JSONValue((unsigned int)(mp->hop_start - mp->hop_limit)); if (hopsAway >= 0) {
jsonObj["hops_away"] = new JSONValue((unsigned int)(hopsAway));
jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start)); jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start));
} }
jsonObj["size"] = new JSONValue((unsigned int)mp->encrypted.size); jsonObj["size"] = new JSONValue((unsigned int)mp->encrypted.size);

View File

@@ -358,8 +358,9 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
jsonObj["rssi"] = (int)mp->rx_rssi; jsonObj["rssi"] = (int)mp->rx_rssi;
if (mp->rx_snr != 0) if (mp->rx_snr != 0)
jsonObj["snr"] = (float)mp->rx_snr; jsonObj["snr"] = (float)mp->rx_snr;
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) { const int8_t hopsAway = getHopsAway(*mp);
jsonObj["hops_away"] = (unsigned int)(mp->hop_start - mp->hop_limit); if (hopsAway >= 0) {
jsonObj["hops_away"] = (unsigned int)(hopsAway);
jsonObj["hop_start"] = (unsigned int)(mp->hop_start); jsonObj["hop_start"] = (unsigned int)(mp->hop_start);
} }
@@ -393,8 +394,9 @@ std::string MeshPacketSerializer::JsonSerializeEncrypted(const meshtastic_MeshPa
jsonObj["rssi"] = (int)mp->rx_rssi; jsonObj["rssi"] = (int)mp->rx_rssi;
if (mp->rx_snr != 0) if (mp->rx_snr != 0)
jsonObj["snr"] = (float)mp->rx_snr; jsonObj["snr"] = (float)mp->rx_snr;
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) { const int8_t hopsAway = getHopsAway(*mp);
jsonObj["hops_away"] = (unsigned int)(mp->hop_start - mp->hop_limit); if (hopsAway >= 0) {
jsonObj["hops_away"] = (unsigned int)(hopsAway);
jsonObj["hop_start"] = (unsigned int)(mp->hop_start); jsonObj["hop_start"] = (unsigned int)(mp->hop_start);
} }
jsonObj["size"] = (unsigned int)mp->encrypted.size; jsonObj["size"] = (unsigned int)mp->encrypted.size;

View File

@@ -15,5 +15,4 @@ upload_protocol = esptool
upload_speed = 460800 upload_speed = 460800
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel adafruit/Adafruit NeoPixel @ ^1.12.0
adafruit/Adafruit NeoPixel@1.15.2

View File

@@ -13,3 +13,5 @@ board_build.f_cpu = 240000000L
upload_protocol = esptool upload_protocol = esptool
;upload_port = /dev/ttyUSB0 ;upload_port = /dev/ttyUSB0
upload_speed = 460800 upload_speed = 460800
lib_deps =
${esp32_base.lib_deps}

View File

@@ -9,5 +9,4 @@ build_flags =
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX lovyan03/LovyanGFX@^1.2.0
lovyan03/LovyanGFX@1.2.7

View File

@@ -38,7 +38,6 @@ build_flags =
-DAXP_DEBUG_PORT=Serial -DAXP_DEBUG_PORT=Serial
-DCONFIG_BT_NIMBLE_ENABLED -DCONFIG_BT_NIMBLE_ENABLED
-DCONFIG_BT_NIMBLE_MAX_BONDS=6 # default is 3 -DCONFIG_BT_NIMBLE_MAX_BONDS=6 # default is 3
-DCONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2 -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192 -DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192
@@ -54,18 +53,17 @@ build_flags =
lib_deps = lib_deps =
${arduino_base.lib_deps} ${arduino_base.lib_deps}
${networking_base.lib_deps} ${networking_base.lib_deps}
${networking_extra.lib_deps}
${environmental_base.lib_deps} ${environmental_base.lib_deps}
${environmental_extra.lib_deps} ${environmental_extra.lib_deps}
${radiolib_base.lib_deps} ${radiolib_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master # renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
https://github.com/meshtastic/esp32_https_server/archive/3223704846752e6d545139204837bdb2a55459ca.zip https://github.com/meshtastic/esp32_https_server/archive/3223704846752e6d545139204837bdb2a55459ca.zip
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
h2zero/NimBLE-Arduino@^2.3.7 h2zero/NimBLE-Arduino@^1.4.3
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master # renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib # renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib
lewisxhe/XPowersLib@0.3.2 https://github.com/lewisxhe/XPowersLib/archive/v0.3.2.zip
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto

View File

@@ -25,5 +25,4 @@ lib_ignore =
m5stack-core m5stack-core
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX lovyan03/LovyanGFX@^1.2.0
lovyan03/LovyanGFX@1.2.7

View File

@@ -18,10 +18,8 @@ build_flags =
-DM5STACK -DM5STACK
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2 zinggjm/GxEPD2@^1.6.2
zinggjm/GxEPD2@1.6.5 lewisxhe/PCF8563_Library@^1.0.1
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
lib_ignore = lib_ignore =
m5stack-coreink m5stack-coreink
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder

View File

@@ -2,6 +2,8 @@
[env:nano-g1-explorer] [env:nano-g1-explorer]
extends = esp32_base extends = esp32_base
board = ttgo-t-beam board = ttgo-t-beam
lib_deps =
${esp32_base.lib_deps}
build_flags = build_flags =
${esp32_base.build_flags} ${esp32_base.build_flags}
-D NANO_G1_EXPLORER -D NANO_G1_EXPLORER

View File

@@ -2,6 +2,8 @@
[env:nano-g1] [env:nano-g1]
extends = esp32_base extends = esp32_base
board = ttgo-t-beam board = ttgo-t-beam
lib_deps =
${esp32_base.lib_deps}
build_flags = build_flags =
${esp32_base.build_flags} ${esp32_base.build_flags}
-D NANO_G1 -D NANO_G1

View File

@@ -13,5 +13,4 @@ board_build.f_cpu = 240000000L
upload_protocol = esptool upload_protocol = esptool
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=github-tags depName=STK8xxx-Accelerometer packageName=gjelsoe/STK8xxx-Accelerometer
https://github.com/gjelsoe/STK8xxx-Accelerometer/archive/v0.1.1.zip https://github.com/gjelsoe/STK8xxx-Accelerometer/archive/v0.1.1.zip

View File

@@ -15,3 +15,5 @@ build_flags =
-I variants/esp32/radiomaster_900_bandit_nano -I variants/esp32/radiomaster_900_bandit_nano
board_build.f_cpu = 240000000L board_build.f_cpu = 240000000L
upload_protocol = esptool upload_protocol = esptool
lib_deps =
${esp32_base.lib_deps}

View File

@@ -10,3 +10,5 @@ build_flags =
-I variants/esp32/radiomaster_900_bandit_nano -I variants/esp32/radiomaster_900_bandit_nano
board_build.f_cpu = 240000000L board_build.f_cpu = 240000000L
upload_protocol = esptool upload_protocol = esptool
lib_deps =
${esp32_base.lib_deps}

View File

@@ -2,6 +2,8 @@
[env:station-g1] [env:station-g1]
extends = esp32_base extends = esp32_base
board = ttgo-t-beam board = ttgo-t-beam
lib_deps =
${esp32_base.lib_deps}
build_flags = build_flags =
${esp32_base.build_flags} ${esp32_base.build_flags}
-D STATION_G1 -D STATION_G1

View File

@@ -2,8 +2,9 @@
[env:tbeam] [env:tbeam]
extends = esp32_base extends = esp32_base
board = ttgo-t-beam board = ttgo-t-beam
board_level = extra
board_check = true board_check = true
lib_deps = ${esp32_base.lib_deps}
build_flags = ${esp32_base.build_flags} build_flags = ${esp32_base.build_flags}
-D TBEAM_V10 -D TBEAM_V10
-I variants/esp32/tbeam -I variants/esp32/tbeam
@@ -13,14 +14,12 @@ upload_speed = 921600
[env:tbeam-displayshield] [env:tbeam-displayshield]
extends = env:tbeam extends = env:tbeam
board_level = extra
build_flags = build_flags =
${env:tbeam.build_flags} ${env:tbeam.build_flags}
-D USE_ST7796 -D USE_ST7796
lib_deps = lib_deps =
${env:tbeam.lib_deps} ${env:tbeam.lib_deps}
# renovate: datasource=github-tags depName=meshtastic-st7796 packageName=meshtastic/st7796 https://github.com/meshtastic/st7796/archive/refs/tags/1.0.5.zip ; display addon
https://github.com/meshtastic/st7796/archive/1.0.5.zip lewisxhe/SensorLib@0.3.1 ; touchscreen addon
# renovate: datasource=custom.pio depName=lewisxhe-SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/SensorLib@0.3.1

View File

@@ -10,9 +10,6 @@ build_flags =
-I variants/esp32/wiphone -I variants/esp32/wiphone
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX lovyan03/LovyanGFX@^1.2.0
lovyan03/LovyanGFX@1.2.7 sparkfun/SX1509 IO Expander@^3.0.5
# renovate: datasource=custom.pio depName=SX1509 IO Expander packageName=sparkfun/library/SX1509 IO Expander pololu/APA102@^3.0.0
sparkfun/SX1509 IO Expander@3.0.6
# renovate: datasource=custom.pio depName=APA102 packageName=pololu/library/APA102
pololu/APA102@3.0.0

View File

@@ -4,7 +4,7 @@
extends = esp32c3_base extends = esp32c3_base
board = esp32-c3-devkitm-1 board = esp32-c3-devkitm-1
build_flags = build_flags =
${esp32c3_base.build_flags} ${esp32_base.build_flags}
-D PRIVATE_HW -D PRIVATE_HW
-I variants/esp32c3/diy/esp32c3_super_mini -I variants/esp32c3/diy/esp32c3_super_mini
-D ARDUINO_USB_MODE=1 -D ARDUINO_USB_MODE=1

View File

@@ -4,8 +4,3 @@ custom_esp32_kind = esp32c3
monitor_speed = 115200 monitor_speed = 115200
monitor_filters = esp32_c3_exception_decoder monitor_filters = esp32_c3_exception_decoder
build_flags =
${esp32_base.build_flags}
-DCONFIG_BT_NIMBLE_EXT_ADV=1
-DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2

View File

@@ -3,7 +3,7 @@ extends = esp32c3_base
board = esp32-c3-devkitm-1 board = esp32-c3-devkitm-1
board_level = extra board_level = extra
build_flags = build_flags =
${esp32c3_base.build_flags} ${esp32_base.build_flags}
-D PRIVATE_HW -D PRIVATE_HW
-D ARDUINO_USB_MODE=1 -D ARDUINO_USB_MODE=1
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_CDC_ON_BOOT=1

View File

@@ -3,7 +3,7 @@ extends = esp32c3_base
board = esp32-c3-devkitm-1 board = esp32-c3-devkitm-1
board_level = pr board_level = pr
build_flags = build_flags =
${esp32c3_base.build_flags} ${esp32_base.build_flags}
-D HELTEC_HT62 -D HELTEC_HT62
-I variants/esp32c3/heltec_esp32c3 -I variants/esp32c3/heltec_esp32c3
monitor_speed = 115200 monitor_speed = 115200

View File

@@ -2,9 +2,8 @@
extends = esp32c3_base extends = esp32c3_base
board = adafruit_qtpy_esp32c3 board = adafruit_qtpy_esp32c3
build_flags = build_flags =
${esp32c3_base.build_flags} ${esp32_base.build_flags}
-D HELTEC_HRU_3601 -D HELTEC_HRU_3601
-I variants/esp32c3/heltec_hru_3601 -I variants/esp32c3/heltec_hru_3601
lib_deps = ${esp32c3_base.lib_deps} lib_deps = ${esp32c3_base.lib_deps}
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel adafruit/Adafruit NeoPixel @ ^1.12.0
adafruit/Adafruit NeoPixel@1.15.2

View File

@@ -3,7 +3,7 @@ extends = esp32c3_base
board = esp32-c3-devkitm-1 board = esp32-c3-devkitm-1
board_level = extra board_level = extra
build_flags = build_flags =
${esp32c3_base.build_flags} ${esp32_base.build_flags}
-D PRIVATE_HW -D PRIVATE_HW
-I variants/esp32c3/m5stack-stamp-c3 -I variants/esp32c3/m5stack-stamp-c3
monitor_speed = 115200 monitor_speed = 115200

View File

@@ -12,10 +12,8 @@ build_unflags =
-D HAS_WIFI -D HAS_WIFI
lib_deps = lib_deps =
${esp32c6_base.lib_deps} ${esp32c6_base.lib_deps}
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel adafruit/Adafruit NeoPixel@^1.12.3
adafruit/Adafruit NeoPixel@1.15.2 h2zero/NimBLE-Arduino@^2.3.6
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
h2zero/NimBLE-Arduino@2.3.7
build_flags = build_flags =
${esp32c6_base.build_flags} ${esp32c6_base.build_flags}
-D M5STACK_UNITC6L -D M5STACK_UNITC6L
@@ -26,6 +24,7 @@ build_flags =
-D HAS_BLUETOOTH=1 -D HAS_BLUETOOTH=1
-DCONFIG_BT_NIMBLE_EXT_ADV=1 -DCONFIG_BT_NIMBLE_EXT_ADV=1
-DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2 -DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2
-D NIMBLE_TWO
monitor_speed=115200 monitor_speed=115200
lib_ignore = lib_ignore =
NonBlockingRTTTL NonBlockingRTTTL

View File

@@ -16,9 +16,6 @@ build_flags =
-DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. -DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library lewisxhe/PCF8563_Library@^1.0.1
lewisxhe/PCF8563_Library@1.0.1 maxpromer/PCA9557-arduino @ ^1.0.0
# renovate: datasource=custom.pio depName=PCA9557-arduino packageName=maxpromer/library/PCA9557-arduino
maxpromer/PCA9557-arduino@1.0.0

View File

@@ -8,10 +8,9 @@ board_level = extra
upload_protocol = esptool upload_protocol = esptool
;upload_port = /dev/ttyACM2 ;upload_port = /dev/ttyACM2
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=caveman99-ESP32_Codec2 packageName=caveman99/library/ESP32 Codec2 caveman99/ESP32 Codec2@^1.0.1
caveman99/ESP32 Codec2@1.0.1
build_flags = build_flags =
${esp32s3_base.build_flags} ${esp32_base.build_flags}
-D PRIVATE_HW -D PRIVATE_HW
-I variants/esp32s3/bpi_picow_esp32_s3 -I variants/esp32s3/bpi_picow_esp32_s3

View File

@@ -25,7 +25,6 @@ build_flags =
;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
[env:crowpanel-esp32s3-4-epaper] [env:crowpanel-esp32s3-4-epaper]
@@ -55,7 +54,6 @@ build_flags =
;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
[env:crowpanel-esp32s3-2-epaper] [env:crowpanel-esp32s3-2-epaper]
@@ -85,5 +83,4 @@ build_flags =
;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip

View File

@@ -9,16 +9,14 @@ upload_protocol = esptool
;upload_port = /dev/ttyACM1 ;upload_port = /dev/ttyACM1
upload_speed = 921600 upload_speed = 921600
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2 zinggjm/GxEPD2@^1.6.2
zinggjm/GxEPD2@1.6.5 adafruit/Adafruit NeoPixel @ ^1.12.0
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
adafruit/Adafruit NeoPixel@1.15.2
build_unflags = build_unflags =
${esp32s3_base.build_unflags} ${esp32s3_base.build_unflags}
-DARDUINO_USB_MODE=1 -DARDUINO_USB_MODE=1
build_flags = build_flags =
${esp32s3_base.build_flags} ${esp32_base.build_flags}
-D PRIVATE_HW -D PRIVATE_HW
-I variants/esp32s3/diy/my_esp32s3_diy_eink -I variants/esp32s3/diy/my_esp32s3_diy_eink
-Dmy -Dmy

View File

@@ -9,14 +9,13 @@ upload_protocol = esptool
;upload_port = /dev/ttyACM0 ;upload_port = /dev/ttyACM0
upload_speed = 921600 upload_speed = 921600
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel adafruit/Adafruit NeoPixel @ ^1.12.0
adafruit/Adafruit NeoPixel@1.15.2
build_unflags = build_unflags =
${esp32s3_base.build_unflags} ${esp32s3_base.build_unflags}
-DARDUINO_USB_MODE=1 -DARDUINO_USB_MODE=1
build_flags = build_flags =
${esp32s3_base.build_flags} ${esp32_base.build_flags}
-D PRIVATE_HW -D PRIVATE_HW
-I variants/esp32s3/diy/my_esp32s3_diy_oled -I variants/esp32s3/diy/my_esp32s3_diy_oled
-DBOARD_HAS_PSRAM -DBOARD_HAS_PSRAM

View File

@@ -12,10 +12,8 @@ build_flags =
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_CDC_ON_BOOT=1
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=ESP8266Audio packageName=earlephilhower/library/ESP8266Audio earlephilhower/ESP8266Audio@^1.9.9
earlephilhower/ESP8266Audio@1.9.9 earlephilhower/ESP8266SAM@^1.0.1
# renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM
earlephilhower/ESP8266SAM@1.1.0
[env:dreamcatcher-2206] [env:dreamcatcher-2206]
extends = esp32s3_base extends = esp32s3_base

View File

@@ -41,13 +41,9 @@ build_flags = ${esp32s3_base.build_flags} -Os
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
${device-ui_base.lib_deps} ${device-ui_base.lib_deps}
# renovate: datasource=custom.pio depName=ESP8266Audio packageName=earlephilhower/library/ESP8266Audio
earlephilhower/ESP8266Audio@1.9.9 earlephilhower/ESP8266Audio@1.9.9
# renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM
earlephilhower/ESP8266SAM@1.0.1 earlephilhower/ESP8266SAM@1.0.1
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
lovyan03/LovyanGFX@1.2.0 ; note: v1.2.7 breaks the elecrow 7" display functionality lovyan03/LovyanGFX@1.2.0 ; note: v1.2.7 breaks the elecrow 7" display functionality
# renovate: datasource=custom.pio depName=TCA9534 packageName=hideakitai/library/TCA9534
hideakitai/TCA9534@0.1.1 hideakitai/TCA9534@0.1.1
[crowpanel_small_esp32s3_base] ; 2.4, 2.8, 3.5 inch [crowpanel_small_esp32s3_base] ; 2.4, 2.8, 3.5 inch

View File

@@ -22,7 +22,5 @@ build_flags = ${esp32s3_base.build_flags}
-DEINK_HEIGHT=128 -DEINK_HEIGHT=128
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2 zinggjm/GxEPD2@^1.6.2
zinggjm/GxEPD2@1.6.5 adafruit/Adafruit NeoPixel @ ^1.12.0
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
adafruit/Adafruit NeoPixel@1.15.2

View File

@@ -3,8 +3,3 @@ extends = esp32_base
custom_esp32_kind = esp32s3 custom_esp32_kind = esp32s3
monitor_speed = 115200 monitor_speed = 115200
build_flags =
${esp32_base.build_flags}
-DCONFIG_BT_NIMBLE_EXT_ADV=1
-DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2

View File

@@ -12,5 +12,4 @@ build_flags = ${esp32s3_base.build_flags}
-I variants/esp32s3/hackaday-communicator -I variants/esp32s3/hackaday-communicator
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-Arduino_GFX packageName=https://github.com/meshtastic/Arduino_GFX gitBranch=master https://github.com/meshtastic/Arduino_GFX/archive/054e81ffaf23784830a734e3c184346789349406.zip
https://github.com/meshtastic/Arduino_GFX/archive/054e81ffaf23784830a734e3c184346789349406.zip

View File

@@ -9,5 +9,4 @@ build_flags =
-D HELTEC_SENSOR_HUB -D HELTEC_SENSOR_HUB
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel adafruit/Adafruit NeoPixel @ ^1.12.0
adafruit/Adafruit NeoPixel@1.15.2

View File

@@ -7,6 +7,8 @@ build_flags =
${esp32s3_base.build_flags} ${esp32s3_base.build_flags}
-D HELTEC_V4 -D HELTEC_V4
-I variants/esp32s3/heltec_v4 -I variants/esp32s3/heltec_v4
lib_deps =
${esp32s3_base.lib_deps}
[env:heltec-v4] [env:heltec-v4]
@@ -21,6 +23,8 @@ build_flags =
-D I2C_SCL=18 -D I2C_SCL=18
-D I2C_SDA1=4 -D I2C_SDA1=4
-D I2C_SCL1=3 -D I2C_SCL1=3
lib_deps =
${heltec_v4_base.lib_deps}
[env:heltec-v4-tft] [env:heltec-v4-tft]
extends = heltec_v4_base extends = heltec_v4_base
@@ -103,10 +107,6 @@ build_flags =
lib_deps = ${heltec_v4_base.lib_deps} lib_deps = ${heltec_v4_base.lib_deps}
; ${device-ui_base.lib_deps} ; ${device-ui_base.lib_deps}
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
lovyan03/LovyanGFX@1.2.0 lovyan03/LovyanGFX@1.2.0
# renovate: datasource=git-refs depName=Quency-D_chsc6x packageName=https://github.com/Quency-D/chsc6x gitBranch=master
https://github.com/Quency-D/chsc6x/archive/5cbead829d6b432a8d621ed1aafd4eb474fd4f27.zip https://github.com/Quency-D/chsc6x/archive/5cbead829d6b432a8d621ed1aafd4eb474fd4f27.zip
; TODO revert to official device-ui (when merged)
# renovate: datasource=git-refs depName=Quency-D_device-ui packageName=https://github.com/Quency-D/device-ui gitBranch=heltec-v4-tft
https://github.com/Quency-D/device-ui/archive/7c9870b8016641190b059bdd90fe16c1012a39eb.zip https://github.com/Quency-D/device-ui/archive/7c9870b8016641190b059bdd90fe16c1012a39eb.zip

View File

@@ -17,10 +17,8 @@ build_flags =
-DEINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting" -DEINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting"
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library lewisxhe/PCF8563_Library@^1.0.1
lewisxhe/PCF8563_Library@1.0.1
upload_speed = 115200 upload_speed = 115200
[env:heltec-vision-master-e213-inkhud] [env:heltec-vision-master-e213-inkhud]
@@ -29,7 +27,7 @@ board = heltec_vision_master_e213
board_level = pr board_level = pr
board_build.partitions = default_8MB.csv board_build.partitions = default_8MB.csv
build_src_filter = build_src_filter =
${esp32s3_base.build_src_filter} ${esp32_base.build_src_filter}
${inkhud.build_src_filter} ${inkhud.build_src_filter}
build_flags = build_flags =
${esp32s3_base.build_flags} ${esp32s3_base.build_flags}

View File

@@ -20,10 +20,8 @@ build_flags =
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/448c8538129fde3d02a7cb5e6fc81971ad92547f.zip https://github.com/meshtastic/GxEPD2/archive/448c8538129fde3d02a7cb5e6fc81971ad92547f.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library lewisxhe/PCF8563_Library@^1.0.1
lewisxhe/PCF8563_Library@1.0.1
upload_speed = 115200 upload_speed = 115200
[env:heltec-vision-master-e290-inkhud] [env:heltec-vision-master-e290-inkhud]
@@ -31,7 +29,7 @@ extends = esp32s3_base, inkhud
board = heltec_vision_master_e290 board = heltec_vision_master_e290
board_build.partitions = default_8MB.csv board_build.partitions = default_8MB.csv
build_src_filter = build_src_filter =
${esp32s3_base.build_src_filter} ${esp32_base.build_src_filter}
${inkhud.build_src_filter} ${inkhud.build_src_filter}
build_flags = build_flags =
${esp32s3_base.build_flags} ${esp32s3_base.build_flags}

View File

@@ -8,8 +8,6 @@ build_flags =
-D HELTEC_VISION_MASTER_T190 -D HELTEC_VISION_MASTER_T190
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library lewisxhe/PCF8563_Library@^1.0.1
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip
upload_speed = 921600 upload_speed = 921600

Some files were not shown because too many files have changed in this diff Show More