mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-23 19:20:41 +00:00
Merge branch 'master' into XEdDSA
This commit is contained in:
238
.github/workflows/pr_tests.yml
vendored
Normal file
238
.github/workflows/pr_tests.yml
vendored
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
# DISABLED: Changed from automatic PR triggers to manual only
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
reason:
|
||||||
|
description: "Reason for manual test run"
|
||||||
|
required: false
|
||||||
|
default: "Manual test execution"
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: tests-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
checks: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
native-tests:
|
||||||
|
name: "🧪 Native Tests"
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
|
uses: ./.github/workflows/test_native.yml
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
checks: write
|
||||||
|
|
||||||
|
test-summary:
|
||||||
|
name: "📊 Test Results"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [native-tests]
|
||||||
|
if: always()
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
checks: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
|
||||||
|
- name: Download test artifacts
|
||||||
|
if: needs.native-tests.result != 'skipped'
|
||||||
|
uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Parse test results and create detailed summary
|
||||||
|
id: test-results
|
||||||
|
run: |
|
||||||
|
echo "## 🧪 Test Results Summary" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# Check overall job status first
|
||||||
|
if [[ "${{ needs.native-tests.result }}" == "success" ]]; then
|
||||||
|
echo "✅ **Overall Status**: PASSED" >> $GITHUB_STEP_SUMMARY
|
||||||
|
elif [[ "${{ needs.native-tests.result }}" == "failure" ]]; then
|
||||||
|
echo "❌ **Overall Status**: FAILED" >> $GITHUB_STEP_SUMMARY
|
||||||
|
elif [[ "${{ needs.native-tests.result }}" == "cancelled" ]]; then
|
||||||
|
echo "⏸️ **Overall Status**: CANCELLED" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "Tests were cancelled before completion." >> $GITHUB_STEP_SUMMARY
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "⚠️ **Overall Status**: SKIPPED" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "Tests were skipped." >> $GITHUB_STEP_SUMMARY
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# Parse detailed test results if available
|
||||||
|
if [ -f "testreport.xml" ]; then
|
||||||
|
echo "### 🔍 Individual Test Results" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
python3 << 'EOF'
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import os
|
||||||
|
|
||||||
|
try:
|
||||||
|
tree = ET.parse('testreport.xml')
|
||||||
|
root = tree.getroot()
|
||||||
|
|
||||||
|
total_tests = 0
|
||||||
|
passed_tests = 0
|
||||||
|
failed_tests = 0
|
||||||
|
skipped_tests = 0
|
||||||
|
|
||||||
|
# Parse testsuite elements
|
||||||
|
for testsuite in root.findall('.//testsuite'):
|
||||||
|
suite_name = testsuite.get('name', 'Unknown')
|
||||||
|
suite_tests = int(testsuite.get('tests', '0'))
|
||||||
|
suite_failures = int(testsuite.get('failures', '0'))
|
||||||
|
suite_errors = int(testsuite.get('errors', '0'))
|
||||||
|
suite_skipped = int(testsuite.get('skipped', '0'))
|
||||||
|
|
||||||
|
total_tests += suite_tests
|
||||||
|
failed_tests += suite_failures + suite_errors
|
||||||
|
skipped_tests += suite_skipped
|
||||||
|
passed_tests += suite_tests - suite_failures - suite_errors - suite_skipped
|
||||||
|
|
||||||
|
if suite_tests > 0:
|
||||||
|
status = "✅" if (suite_failures + suite_errors) == 0 else "❌"
|
||||||
|
print(f"**{status} Test Suite: {suite_name}**")
|
||||||
|
print(f"- Total: {suite_tests}")
|
||||||
|
print(f"- Passed: ✅ {suite_tests - suite_failures - suite_errors - suite_skipped}")
|
||||||
|
print(f"- Failed: ❌ {suite_failures + suite_errors}")
|
||||||
|
if suite_skipped > 0:
|
||||||
|
print(f"- Skipped: ⏭️ {suite_skipped}")
|
||||||
|
print("")
|
||||||
|
|
||||||
|
# Show individual test results for failed suites
|
||||||
|
if suite_failures + suite_errors > 0:
|
||||||
|
print("**Failed Tests:**")
|
||||||
|
for testcase in testsuite.findall('testcase'):
|
||||||
|
test_name = testcase.get('name', 'Unknown')
|
||||||
|
failure = testcase.find('failure')
|
||||||
|
error = testcase.find('error')
|
||||||
|
|
||||||
|
if failure is not None:
|
||||||
|
msg = failure.get('message', 'Unknown error')[:100]
|
||||||
|
print(f"- ❌ `{test_name}`: {msg}")
|
||||||
|
elif error is not None:
|
||||||
|
msg = error.get('message', 'Unknown error')[:100]
|
||||||
|
print(f"- ❌ `{test_name}`: ERROR - {msg}")
|
||||||
|
print("")
|
||||||
|
else:
|
||||||
|
# Show passed tests for successful suites
|
||||||
|
passed_count = 0
|
||||||
|
for testcase in testsuite.findall('testcase'):
|
||||||
|
if testcase.find('failure') is None and testcase.find('error') is None:
|
||||||
|
if passed_count < 5: # Limit to first 5 to avoid spam
|
||||||
|
test_name = testcase.get('name', 'Unknown')
|
||||||
|
print(f"- ✅ `{test_name}`: PASSED")
|
||||||
|
passed_count += 1
|
||||||
|
if passed_count > 5:
|
||||||
|
print(f"- ... and {passed_count - 5} more tests passed")
|
||||||
|
print("")
|
||||||
|
|
||||||
|
# Summary statistics
|
||||||
|
print("### 📊 Test Statistics")
|
||||||
|
print(f"- **Total Tests**: {total_tests}")
|
||||||
|
print(f"- **Passed**: ✅ {passed_tests}")
|
||||||
|
print(f"- **Failed**: ❌ {failed_tests}")
|
||||||
|
if skipped_tests > 0:
|
||||||
|
print(f"- **Skipped**: ⏭️ {skipped_tests}")
|
||||||
|
|
||||||
|
if failed_tests > 0:
|
||||||
|
print(f"\n❌ **{failed_tests} tests failed out of {total_tests} total**")
|
||||||
|
else:
|
||||||
|
print(f"\n✅ **All {total_tests} tests passed!**")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error parsing test results: {e}")
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
echo "⚠️ **No detailed test report available**" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "Test artifacts may not have been generated properly." >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "---" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "View detailed logs in the [Actions tab](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
- name: Comment test results on PR
|
||||||
|
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
// Read the step summary to use as PR comment
|
||||||
|
let testSummary = "## 🧪 Test Results Summary\n\n";
|
||||||
|
|
||||||
|
if ("${{ needs.native-tests.result }}" === "success") {
|
||||||
|
testSummary += "✅ **All tests passed!**\n\n";
|
||||||
|
} else if ("${{ needs.native-tests.result }}" === "failure") {
|
||||||
|
testSummary += "❌ **Some tests failed.**\n\n";
|
||||||
|
} else {
|
||||||
|
testSummary += "⚠️ **Tests did not complete normally.**\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
testSummary += `View detailed results: [Actions Run](${context.payload.repository.html_url}/actions/runs/${context.runId})\n\n`;
|
||||||
|
testSummary += "---\n";
|
||||||
|
testSummary += "*This comment will be automatically updated when new commits are pushed.*";
|
||||||
|
|
||||||
|
// Find existing comment
|
||||||
|
const comments = await github.rest.issues.listComments({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number
|
||||||
|
});
|
||||||
|
|
||||||
|
const botComment = comments.data.find(comment =>
|
||||||
|
comment.user.type === 'Bot' &&
|
||||||
|
comment.body.includes('🧪 Test Results Summary')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (botComment) {
|
||||||
|
// Update existing comment
|
||||||
|
await github.rest.issues.updateComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: botComment.id,
|
||||||
|
body: testSummary
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Create new comment
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
body: testSummary
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Set overall status
|
||||||
|
run: |
|
||||||
|
if [[ "${{ needs.native-tests.result }}" == "success" ]]; then
|
||||||
|
echo "All tests passed! ✅"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Some tests failed! ❌"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -9,9 +9,9 @@ plugins:
|
|||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- checkov@3.2.461
|
- checkov@3.2.461
|
||||||
- renovate@41.63.0
|
- renovate@41.74.0
|
||||||
- prettier@3.6.2
|
- prettier@3.6.2
|
||||||
- trufflehog@3.90.3
|
- trufflehog@3.90.5
|
||||||
- yamllint@1.37.1
|
- yamllint@1.37.1
|
||||||
- bandit@1.8.6
|
- bandit@1.8.6
|
||||||
- trivy@0.64.1
|
- trivy@0.64.1
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ RUN apt-get update && apt-get --no-install-recommends -y install \
|
|||||||
|
|
||||||
# Fetch compiled binary from the builder
|
# Fetch compiled binary from the builder
|
||||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
|
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
|
||||||
COPY --from=builder /tmp/web /usr/share/meshtasticd/
|
COPY --from=builder /tmp/web /usr/share/meshtasticd/web/
|
||||||
# Copy config templates
|
# Copy config templates
|
||||||
COPY ./bin/config.d /etc/meshtasticd/available.d
|
COPY ./bin/config.d /etc/meshtasticd/available.d
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ build_flags =
|
|||||||
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
|
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp> -<serialization/>
|
||||||
|
|
||||||
lib_deps=
|
lib_deps=
|
||||||
${arduino_base.lib_deps}
|
${arduino_base.lib_deps}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
[portduino_base]
|
[portduino_base]
|
||||||
platform =
|
platform =
|
||||||
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
||||||
https://github.com/meshtastic/platform-native/archive/6cb7a455b440dd0738e8ed74a18136ed5cf7ea63.zip
|
https://github.com/meshtastic/platform-native/archive/37d986499ce24511952d7146db72d667c6bdaff7.zip
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ 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/0119501e9983bd894830b02f545c377ee08d66fe.zip
|
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/9573abb64dc9c94f3051348f2bf4fc5cedf03c22.zip
|
||||||
# renovate: datasource=custom.pio depName=OneButton packageName=mathertel/library/OneButton
|
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
|
||||||
mathertel/OneButton@2.6.1
|
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
|
||||||
https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip
|
https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip
|
||||||
# renovate: datasource=git-refs depName=meshtastic-TinyGPSPlus packageName=https://github.com/meshtastic/TinyGPSPlus gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic-TinyGPSPlus packageName=https://github.com/meshtastic/TinyGPSPlus gitBranch=master
|
||||||
@@ -102,6 +102,14 @@ 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
|
||||||
@@ -110,7 +118,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/0cd108ff783539e41ef38258ba2784ab3b1bdc97.zip
|
https://github.com/meshtastic/device-ui/archive/8f5094b248c15ea2f9acf19cedfef6d2248fc1ff.zip
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
|
|||||||
Submodule protobufs updated: e2c0831aa3...be51376980
@@ -89,14 +89,22 @@ class BluetoothStatus : public Status
|
|||||||
case ConnectionState::CONNECTED:
|
case ConnectionState::CONNECTED:
|
||||||
LOG_DEBUG("BluetoothStatus CONNECTED");
|
LOG_DEBUG("BluetoothStatus CONNECTED");
|
||||||
#ifdef BLE_LED
|
#ifdef BLE_LED
|
||||||
|
#ifdef BLE_LED_INVERTED
|
||||||
|
digitalWrite(BLE_LED, LOW);
|
||||||
|
#else
|
||||||
digitalWrite(BLE_LED, HIGH);
|
digitalWrite(BLE_LED, HIGH);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConnectionState::DISCONNECTED:
|
case ConnectionState::DISCONNECTED:
|
||||||
LOG_DEBUG("BluetoothStatus DISCONNECTED");
|
LOG_DEBUG("BluetoothStatus DISCONNECTED");
|
||||||
#ifdef BLE_LED
|
#ifdef BLE_LED
|
||||||
|
#ifdef BLE_LED_INVERTED
|
||||||
|
digitalWrite(BLE_LED, HIGH);
|
||||||
|
#else
|
||||||
digitalWrite(BLE_LED, LOW);
|
digitalWrite(BLE_LED, LOW);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,10 @@ bool playNextLeadUpNote()
|
|||||||
playTones(¬e, 1); // Play single note using existing playTones function
|
playTones(¬e, 1); // Play single note using existing playTones function
|
||||||
|
|
||||||
leadUpNoteIndex++;
|
leadUpNoteIndex++;
|
||||||
|
|
||||||
|
if (leadUpNoteIndex >= leadUpNotesCount) {
|
||||||
|
return false; // this was the final note
|
||||||
|
}
|
||||||
return true; // Note was played (playTones handles buzzer availability internally)
|
return true; // Note was played (playTones handles buzzer availability internally)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,13 +140,13 @@ bool EInkDisplay::connect()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1)
|
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE)
|
||||||
{
|
{
|
||||||
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
|
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
|
||||||
|
|
||||||
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||||
adafruitDisplay->init();
|
adafruitDisplay->init();
|
||||||
#ifdef ELECROW_ThinkNode_M1
|
#if defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE)
|
||||||
adafruitDisplay->setRotation(4);
|
adafruitDisplay->setRotation(4);
|
||||||
#else
|
#else
|
||||||
adafruitDisplay->setRotation(3);
|
adafruitDisplay->setRotation(3);
|
||||||
|
|||||||
@@ -365,9 +365,6 @@ void Screen::doDeepSleep()
|
|||||||
{
|
{
|
||||||
#ifdef USE_EINK
|
#ifdef USE_EINK
|
||||||
setOn(false, graphics::UIRenderer::drawDeepSleepFrame);
|
setOn(false, graphics::UIRenderer::drawDeepSleepFrame);
|
||||||
#ifdef PIN_EINK_EN
|
|
||||||
digitalWrite(PIN_EINK_EN, LOW); // power off backlight
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
// Without E-Ink display:
|
// Without E-Ink display:
|
||||||
setOn(false);
|
setOn(false);
|
||||||
@@ -391,7 +388,11 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
|
|||||||
dispdev->displayOn();
|
dispdev->displayOn();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ELECROW_ThinkNode_M5
|
#ifdef PIN_EINK_EN
|
||||||
|
if (uiconfig.screen_brightness == 1)
|
||||||
|
digitalWrite(PIN_EINK_EN, HIGH);
|
||||||
|
#elif defined(PCA_PIN_EINK_EN)
|
||||||
|
if (uiconfig.screen_brightness == 1)
|
||||||
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
|
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -424,13 +425,10 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
|
|||||||
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead
|
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead
|
||||||
setScreensaverFrames(einkScreensaver);
|
setScreensaverFrames(einkScreensaver);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ELECROW_ThinkNode_M1
|
|
||||||
if (digitalRead(PIN_EINK_EN) == HIGH) {
|
|
||||||
digitalWrite(PIN_EINK_EN, LOW);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ELECROW_ThinkNode_M5
|
#ifdef PIN_EINK_EN
|
||||||
|
digitalWrite(PIN_EINK_EN, LOW);
|
||||||
|
#elif defined(PCA_PIN_EINK_EN)
|
||||||
io.digitalWrite(PCA_PIN_EINK_EN, LOW);
|
io.digitalWrite(PCA_PIN_EINK_EN, LOW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -694,7 +692,7 @@ int32_t Screen::runOnce()
|
|||||||
|
|
||||||
#ifndef DISABLE_WELCOME_UNSET
|
#ifndef DISABLE_WELCOME_UNSET
|
||||||
if (!NotificationRenderer::isOverlayBannerShowing() && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
if (!NotificationRenderer::isOverlayBannerShowing() && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
||||||
menuHandler::LoraRegionPicker(0);
|
menuHandler::OnboardMessage();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0) {
|
if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0) {
|
||||||
|
|||||||
@@ -849,9 +849,29 @@ static LGFX *tft = nullptr;
|
|||||||
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
|
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
|
||||||
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
|
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
|
||||||
|
|
||||||
|
class PanelInit_ST7701 : public lgfx::Panel_ST7701
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const uint8_t *getInitCommands(uint8_t listno) const override
|
||||||
|
{
|
||||||
|
// 180 degree hw rotation: vertical flip, horizontal flip
|
||||||
|
static constexpr const uint8_t list1[] = {0x36, 1, 0x10, // MADCTL for vertical flip
|
||||||
|
0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x10, // Command2 BK0 SEL
|
||||||
|
0xC7, 1, 0x04, // SDIR: X-direction Control (Horizontal Flip)
|
||||||
|
0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x00, // Command2 BK0 DIS
|
||||||
|
0xFF, 0xFF};
|
||||||
|
switch (listno) {
|
||||||
|
case 1:
|
||||||
|
return list1;
|
||||||
|
default:
|
||||||
|
return lgfx::Panel_ST7701::getInitCommands(listno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LGFX : public lgfx::LGFX_Device
|
class LGFX : public lgfx::LGFX_Device
|
||||||
{
|
{
|
||||||
lgfx::Panel_ST7701 _panel_instance;
|
PanelInit_ST7701 _panel_instance;
|
||||||
lgfx::Bus_RGB _bus_instance;
|
lgfx::Bus_RGB _bus_instance;
|
||||||
lgfx::Light_PWM _light_instance;
|
lgfx::Light_PWM _light_instance;
|
||||||
lgfx::Touch_FT5x06 _touch_instance;
|
lgfx::Touch_FT5x06 _touch_instance;
|
||||||
@@ -1184,9 +1204,9 @@ bool TFTDisplay::connect()
|
|||||||
attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING);
|
attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING);
|
||||||
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
|
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
|
||||||
tft->setRotation(1); // T-Deck has the TFT in landscape
|
tft->setRotation(1); // T-Deck has the TFT in landscape
|
||||||
#elif defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
|
#elif defined(T_WATCH_S3)
|
||||||
tft->setRotation(2); // T-Watch S3 left-handed orientation
|
tft->setRotation(2); // T-Watch S3 left-handed orientation
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO || defined(SENSECAP_INDICATOR)
|
||||||
tft->setRotation(0); // use config.yaml to set rotation
|
tft->setRotation(0); // use config.yaml to set rotation
|
||||||
#else
|
#else
|
||||||
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
|
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
|
||||||
|
|||||||
@@ -26,6 +26,27 @@ menuHandler::screenMenus menuHandler::menuQueue = menu_none;
|
|||||||
bool test_enabled = false;
|
bool test_enabled = false;
|
||||||
uint8_t test_count = 0;
|
uint8_t test_count = 0;
|
||||||
|
|
||||||
|
void menuHandler::OnboardMessage()
|
||||||
|
{
|
||||||
|
static const char *optionsArray[] = {"OK", "Got it!"};
|
||||||
|
enum optionsNumbers { OK, got };
|
||||||
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if HAS_TFT
|
||||||
|
bannerOptions.message = "Welcome to Meshtastic!\nSwipe to navigate and\nlong press to select\nor open a menu.";
|
||||||
|
#elif defined(BUTTON_PIN)
|
||||||
|
bannerOptions.message = "Welcome to Meshtastic!\nClick to navigate and\nlong press to select\nor open a menu.";
|
||||||
|
#else
|
||||||
|
bannerOptions.message = "Welcome to Meshtastic!\nUse the Select button\nto open menus\nand make selections.";
|
||||||
|
#endif
|
||||||
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
|
bannerOptions.optionsCount = 2;
|
||||||
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
|
menuHandler::menuQueue = menuHandler::no_timeout_lora_picker;
|
||||||
|
screen->runNow();
|
||||||
|
};
|
||||||
|
screen->showOverlayBanner(bannerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
void menuHandler::LoraRegionPicker(uint32_t duration)
|
void menuHandler::LoraRegionPicker(uint32_t duration)
|
||||||
{
|
{
|
||||||
static const char *optionsArray[] = {"Back",
|
static const char *optionsArray[] = {"Back",
|
||||||
@@ -301,7 +322,7 @@ void menuHandler::homeBaseMenu()
|
|||||||
static int optionsEnumArray[enumEnd] = {Back};
|
static int optionsEnumArray[enumEnd] = {Back};
|
||||||
int options = 1;
|
int options = 1;
|
||||||
|
|
||||||
#ifdef PIN_EINK_EN
|
#if defined(PIN_EINK_EN) || defined(PCA_PIN_EINK_EN)
|
||||||
optionsArray[options] = "Toggle Backlight";
|
optionsArray[options] = "Toggle Backlight";
|
||||||
optionsEnumArray[options++] = Backlight;
|
optionsEnumArray[options++] = Backlight;
|
||||||
#else
|
#else
|
||||||
@@ -325,12 +346,24 @@ void menuHandler::homeBaseMenu()
|
|||||||
bannerOptions.optionsCount = options;
|
bannerOptions.optionsCount = options;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected == Backlight) {
|
if (selected == Backlight) {
|
||||||
#ifdef PIN_EINK_EN
|
#if defined(PIN_EINK_EN)
|
||||||
if (digitalRead(PIN_EINK_EN) == HIGH) {
|
if (uiconfig.screen_brightness == 1) {
|
||||||
|
uiconfig.screen_brightness = 0;
|
||||||
digitalWrite(PIN_EINK_EN, LOW);
|
digitalWrite(PIN_EINK_EN, LOW);
|
||||||
} else {
|
} else {
|
||||||
|
uiconfig.screen_brightness = 1;
|
||||||
digitalWrite(PIN_EINK_EN, HIGH);
|
digitalWrite(PIN_EINK_EN, HIGH);
|
||||||
}
|
}
|
||||||
|
saveUIConfig();
|
||||||
|
#elif defined(PCA_PIN_EINK_EN)
|
||||||
|
if (uiconfig.screen_brightness == 1) {
|
||||||
|
uiconfig.screen_brightness = 0;
|
||||||
|
io.digitalWrite(PCA_PIN_EINK_EN, LOW);
|
||||||
|
} else {
|
||||||
|
uiconfig.screen_brightness = 1;
|
||||||
|
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
|
||||||
|
}
|
||||||
|
saveUIConfig();
|
||||||
#endif
|
#endif
|
||||||
} else if (selected == Sleep) {
|
} else if (selected == Sleep) {
|
||||||
screen->setOn(false);
|
screen->setOn(false);
|
||||||
@@ -1103,6 +1136,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
|||||||
case lora_picker:
|
case lora_picker:
|
||||||
LoraRegionPicker();
|
LoraRegionPicker();
|
||||||
break;
|
break;
|
||||||
|
case no_timeout_lora_picker:
|
||||||
|
LoraRegionPicker(0);
|
||||||
|
break;
|
||||||
case TZ_picker:
|
case TZ_picker:
|
||||||
TZPicker();
|
TZPicker();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class menuHandler
|
|||||||
enum screenMenus {
|
enum screenMenus {
|
||||||
menu_none,
|
menu_none,
|
||||||
lora_picker,
|
lora_picker,
|
||||||
|
no_timeout_lora_picker,
|
||||||
TZ_picker,
|
TZ_picker,
|
||||||
twelve_hour_picker,
|
twelve_hour_picker,
|
||||||
clock_face_picker,
|
clock_face_picker,
|
||||||
@@ -41,6 +42,7 @@ class menuHandler
|
|||||||
};
|
};
|
||||||
static screenMenus menuQueue;
|
static screenMenus menuQueue;
|
||||||
|
|
||||||
|
static void OnboardMessage();
|
||||||
static void LoraRegionPicker(uint32_t duration = 30000);
|
static void LoraRegionPicker(uint32_t duration = 30000);
|
||||||
static void handleMenuSwitch(OLEDDisplay *display);
|
static void handleMenuSwitch(OLEDDisplay *display);
|
||||||
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
|
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
|
||||||
|
|||||||
@@ -383,7 +383,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
|
|||||||
|
|
||||||
uint8_t firstOptionToShow = 0;
|
uint8_t firstOptionToShow = 0;
|
||||||
if (alertBannerOptions > 0) {
|
if (alertBannerOptions > 0) {
|
||||||
if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) {
|
if (visibleTotalLines - lineCount == 1) {
|
||||||
|
firstOptionToShow = curSelected;
|
||||||
|
} else if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) {
|
||||||
if (curSelected > alertBannerOptions - visibleTotalLines + lineCount)
|
if (curSelected > alertBannerOptions - visibleTotalLines + lineCount)
|
||||||
firstOptionToShow = alertBannerOptions - visibleTotalLines + lineCount;
|
firstOptionToShow = alertBannerOptions - visibleTotalLines + lineCount;
|
||||||
else
|
else
|
||||||
@@ -392,6 +394,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
|
|||||||
firstOptionToShow = 0;
|
firstOptionToShow = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Useful log line for troubleshooting:
|
||||||
|
/* LOG_WARN("alertBannerOptions: %u, curSelected: %u, visibleTotalLines: %u, lineCount: %u, firstOptionToShow: %u",
|
||||||
|
alertBannerOptions, curSelected, visibleTotalLines, lineCount, firstOptionToShow); */
|
||||||
|
|
||||||
for (int i = firstOptionToShow; i < alertBannerOptions && linesShown < visibleTotalLines; i++, linesShown++) {
|
for (int i = firstOptionToShow; i < alertBannerOptions && linesShown < visibleTotalLines; i++, linesShown++) {
|
||||||
if (i == curSelected) {
|
if (i == curSelected) {
|
||||||
|
|||||||
@@ -92,8 +92,11 @@ bool ButtonThread::initButton(const ButtonConfig &config)
|
|||||||
if (config.shortLong != INPUT_BROKER_NONE) {
|
if (config.shortLong != INPUT_BROKER_NONE) {
|
||||||
_shortLong = config.shortLong;
|
_shortLong = config.shortLong;
|
||||||
}
|
}
|
||||||
|
#ifdef USE_EINK
|
||||||
|
userButton.setDebounceMs(0);
|
||||||
|
#else
|
||||||
userButton.setDebounceMs(1);
|
userButton.setDebounceMs(1);
|
||||||
|
#endif
|
||||||
userButton.setPressMs(_longPressTime);
|
userButton.setPressMs(_longPressTime);
|
||||||
|
|
||||||
if (screen) {
|
if (screen) {
|
||||||
@@ -137,8 +140,7 @@ int32_t ButtonThread::runOnce()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Progressive lead-up sound system
|
// Progressive lead-up sound system
|
||||||
if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS &&
|
if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS) {
|
||||||
(millis() - buttonPressStartTime) < _longLongPressTime) {
|
|
||||||
|
|
||||||
// Start the progressive sequence if not already active
|
// Start the progressive sequence if not already active
|
||||||
if (!leadUpSequenceActive) {
|
if (!leadUpSequenceActive) {
|
||||||
@@ -150,13 +152,14 @@ int32_t ButtonThread::runOnce()
|
|||||||
else if ((millis() - lastLeadUpNoteTime) >= 400) { // 400ms interval between notes
|
else if ((millis() - lastLeadUpNoteTime) >= 400) { // 400ms interval between notes
|
||||||
if (playNextLeadUpNote()) {
|
if (playNextLeadUpNote()) {
|
||||||
lastLeadUpNoteTime = millis();
|
lastLeadUpNoteTime = millis();
|
||||||
|
} else {
|
||||||
|
leadUpPlayed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset when button is released
|
// Reset when button is released
|
||||||
if (!buttonCurrentlyPressed && buttonWasPressed) {
|
if (!buttonCurrentlyPressed && buttonWasPressed) {
|
||||||
leadUpPlayed = false;
|
|
||||||
leadUpSequenceActive = false;
|
leadUpSequenceActive = false;
|
||||||
resetLeadUpSequence();
|
resetLeadUpSequence();
|
||||||
}
|
}
|
||||||
@@ -253,12 +256,13 @@ int32_t ButtonThread::runOnce()
|
|||||||
|
|
||||||
LOG_INFO("LONG PRESS RELEASE AFTER %u MILLIS", millis() - buttonPressStartTime);
|
LOG_INFO("LONG PRESS RELEASE AFTER %u MILLIS", millis() - buttonPressStartTime);
|
||||||
if (millis() > 30000 && _longLongPress != INPUT_BROKER_NONE &&
|
if (millis() > 30000 && _longLongPress != INPUT_BROKER_NONE &&
|
||||||
(millis() - buttonPressStartTime) >= _longLongPressTime) {
|
(millis() - buttonPressStartTime) >= _longLongPressTime && leadUpPlayed) {
|
||||||
evt.inputEvent = _longLongPress;
|
evt.inputEvent = _longLongPress;
|
||||||
this->notifyObservers(&evt);
|
this->notifyObservers(&evt);
|
||||||
}
|
}
|
||||||
// Reset combination tracking
|
// Reset combination tracking
|
||||||
waitingForLongPress = false;
|
waitingForLongPress = false;
|
||||||
|
leadUpPlayed = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class ButtonThread : public Observable<const InputEvent *>, public concurrency::
|
|||||||
|
|
||||||
voidFuncPtr _intRoutine = nullptr;
|
voidFuncPtr _intRoutine = nullptr;
|
||||||
uint16_t _longPressTime = 500;
|
uint16_t _longPressTime = 500;
|
||||||
uint16_t _longLongPressTime = 5000;
|
uint16_t _longLongPressTime = 3900;
|
||||||
int _pinNum = 0;
|
int _pinNum = 0;
|
||||||
bool _activeLow = true;
|
bool _activeLow = true;
|
||||||
bool _touchQuirk = false;
|
bool _touchQuirk = false;
|
||||||
|
|||||||
@@ -304,7 +304,6 @@ void setup()
|
|||||||
Wire.begin(48, 47);
|
Wire.begin(48, 47);
|
||||||
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
|
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
|
||||||
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
|
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
|
||||||
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
|
|
||||||
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
|
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
|
||||||
// io.pinMode(C2_PIN, OUTPUT);
|
// io.pinMode(C2_PIN, OUTPUT);
|
||||||
#endif
|
#endif
|
||||||
@@ -326,8 +325,12 @@ void setup()
|
|||||||
|
|
||||||
#ifdef BLE_LED
|
#ifdef BLE_LED
|
||||||
pinMode(BLE_LED, OUTPUT);
|
pinMode(BLE_LED, OUTPUT);
|
||||||
|
#ifdef BLE_LED_INVERTED
|
||||||
|
digitalWrite(BLE_LED, HIGH);
|
||||||
|
#else
|
||||||
digitalWrite(BLE_LED, LOW);
|
digitalWrite(BLE_LED, LOW);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(T_DECK)
|
#if defined(T_DECK)
|
||||||
// GPIO10 manages all peripheral power supplies
|
// GPIO10 manages all peripheral power supplies
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#include "mesh/NodeDB.h"
|
#include "mesh/NodeDB.h"
|
||||||
#ifdef LR11X0_DIO_AS_RF_SWITCH
|
#ifdef LR11X0_DIO_AS_RF_SWITCH
|
||||||
#include "rfswitch.h"
|
#include "rfswitch.h"
|
||||||
|
#elif ARCH_PORTDUINO
|
||||||
|
#include "PortduinoGlue.h"
|
||||||
|
#define rfswitch_dio_pins portduino_config.rfswitch_dio_pins
|
||||||
|
#define rfswitch_table portduino_config.rfswitch_table
|
||||||
#else
|
#else
|
||||||
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
|
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
|
||||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||||
@@ -14,10 +18,6 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_PORTDUINO
|
|
||||||
#include "PortduinoGlue.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
|
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
|
||||||
// specified (may be dangerous if using external PA and LR11x0 power config forgotten)
|
// specified (may be dangerous if using external PA and LR11x0 power config forgotten)
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
@@ -117,17 +117,14 @@ template <typename T> bool LR11x0Interface<T>::init()
|
|||||||
#ifdef LR11X0_DIO_AS_RF_SWITCH
|
#ifdef LR11X0_DIO_AS_RF_SWITCH
|
||||||
bool dioAsRfSwitch = true;
|
bool dioAsRfSwitch = true;
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
bool dioAsRfSwitch = false;
|
bool dioAsRfSwitch = portduino_config.has_rfswitch_table;
|
||||||
if (settingsMap[dio2_as_rf_switch]) {
|
|
||||||
dioAsRfSwitch = true;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
bool dioAsRfSwitch = false;
|
bool dioAsRfSwitch = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dioAsRfSwitch) {
|
if (dioAsRfSwitch) {
|
||||||
lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||||
LOG_DEBUG("Set DIO RF switch", res);
|
LOG_DEBUG("Set DIO RF switch");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == RADIOLIB_ERR_NONE) {
|
if (res == RADIOLIB_ERR_NONE) {
|
||||||
|
|||||||
@@ -1616,9 +1616,11 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
|||||||
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
||||||
|
|
||||||
// Alert the user if a remote node is advertising public key that matches our own
|
// Alert the user if a remote node is advertising public key that matches our own
|
||||||
if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0 && !duplicateWarned) {
|
if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0) {
|
||||||
|
if (!duplicateWarned) {
|
||||||
duplicateWarned = true;
|
duplicateWarned = true;
|
||||||
char warning[] = "Remote device %s has advertised your public key. This may indicate a compromised key. You may need "
|
char warning[] =
|
||||||
|
"Remote device %s has advertised your public key. This may indicate a compromised key. You may need "
|
||||||
"to regenerate your public keys.";
|
"to regenerate your public keys.";
|
||||||
LOG_WARN(warning, p.long_name);
|
LOG_WARN(warning, p.long_name);
|
||||||
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
|
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
|
||||||
@@ -1627,13 +1629,20 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
|||||||
sprintf(cn->message, warning, p.long_name);
|
sprintf(cn->message, warning, p.long_name);
|
||||||
service->sendClientNotification(cn);
|
service->sendClientNotification(cn);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (info->user.public_key.size == 32) { // if we have a key for this user already, don't overwrite with a new one
|
||||||
|
// if the key doesn't match, don't update nodeDB at all.
|
||||||
|
if (p.public_key.size != 32 || (memcmp(p.public_key.bytes, info->user.public_key.bytes, 32) != 0)) {
|
||||||
|
LOG_WARN("Public Key mismatch, dropping NodeInfo");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
|
|
||||||
LOG_INFO("Public Key set for node, not updating!");
|
LOG_INFO("Public Key set for node, not updating!");
|
||||||
// we copy the key into the incoming packet, to prevent overwrite
|
// we copy the key into the incoming packet, to prevent overwrite
|
||||||
p.public_key.size = 32;
|
p.public_key.size = 32;
|
||||||
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
|
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
|
||||||
} else if (p.public_key.size > 0) {
|
} else if (p.public_key.size == 32) {
|
||||||
LOG_INFO("Update Node Pubkey!");
|
LOG_INFO("Update Node Pubkey!");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -192,12 +192,6 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
|||||||
|
|
||||||
size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||||
{
|
{
|
||||||
if (!available()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// In case we send a FromRadio packet
|
|
||||||
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
|
||||||
|
|
||||||
// Respond to heartbeat by sending queue status
|
// Respond to heartbeat by sending queue status
|
||||||
if (heartbeatReceived) {
|
if (heartbeatReceived) {
|
||||||
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
||||||
@@ -209,6 +203,12 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
return numbytes;
|
return numbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!available()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// In case we send a FromRadio packet
|
||||||
|
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
||||||
|
|
||||||
// Advance states as needed
|
// Advance states as needed
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_SEND_NOTHING:
|
case STATE_SEND_NOTHING:
|
||||||
|
|||||||
@@ -548,8 +548,10 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
|
|||||||
// is not in the local nodedb
|
// is not in the local nodedb
|
||||||
// First, only PKC encrypt packets we are originating
|
// First, only PKC encrypt packets we are originating
|
||||||
if (isFromUs(p) &&
|
if (isFromUs(p) &&
|
||||||
// Don't use PKC with simulator
|
#if ARCH_PORTDUINO
|
||||||
radioType != SIM_RADIO &&
|
// Sim radio via the cli flag skips PKC
|
||||||
|
!portduino_config.force_simradio &&
|
||||||
|
#endif
|
||||||
// Don't use PKC with Ham mode
|
// Don't use PKC with Ham mode
|
||||||
!owner.is_licensed &&
|
!owner.is_licensed &&
|
||||||
// Don't use PKC if it's not explicitly requested and a non-primary channel is requested
|
// Don't use PKC if it's not explicitly requested and a non-primary channel is requested
|
||||||
|
|||||||
@@ -270,6 +270,8 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
/* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
|
/* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
|
||||||
https://heltec.org/project/meshsolar/ */
|
https://heltec.org/project/meshsolar/ */
|
||||||
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
|
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
|
||||||
|
/* Lilygo T-Echo Lite */
|
||||||
|
meshtastic_HardwareModel_T_ECHO_LITE = 109,
|
||||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
|||||||
@@ -99,7 +99,9 @@ typedef enum _meshtastic_TelemetrySensorType {
|
|||||||
/* Sensirion SFA30 Formaldehyde sensor */
|
/* Sensirion SFA30 Formaldehyde sensor */
|
||||||
meshtastic_TelemetrySensorType_SFA30 = 42,
|
meshtastic_TelemetrySensorType_SFA30 = 42,
|
||||||
/* SEN5X PM SENSORS */
|
/* SEN5X PM SENSORS */
|
||||||
meshtastic_TelemetrySensorType_SEN5X = 43
|
meshtastic_TelemetrySensorType_SEN5X = 43,
|
||||||
|
/* TSL2561 light sensor */
|
||||||
|
meshtastic_TelemetrySensorType_TSL2561 = 44
|
||||||
} meshtastic_TelemetrySensorType;
|
} meshtastic_TelemetrySensorType;
|
||||||
|
|
||||||
/* Struct definitions */
|
/* Struct definitions */
|
||||||
@@ -434,8 +436,8 @@ extern "C" {
|
|||||||
|
|
||||||
/* Helper constants for enums */
|
/* Helper constants for enums */
|
||||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SEN5X
|
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_TSL2561
|
||||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SEN5X+1))
|
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_TSL2561+1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
SerialModule *serialModule;
|
SerialModule *serialModule;
|
||||||
SerialModuleRadio *serialModuleRadio;
|
SerialModuleRadio *serialModuleRadio;
|
||||||
|
|
||||||
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
|
#if defined(TTGO_T_ECHO) || defined(T_ECHO_LITE) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
|
||||||
defined(ELECROW_ThinkNode_M5)
|
defined(ELECROW_ThinkNode_M5)
|
||||||
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
|
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
|
||||||
static Print *serialPrint = &Serial;
|
static Print *serialPrint = &Serial;
|
||||||
@@ -179,8 +179,8 @@ int32_t SerialModule::runOnce()
|
|||||||
Serial.begin(baud);
|
Serial.begin(baud);
|
||||||
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
|
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
|
||||||
}
|
}
|
||||||
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
|
#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
||||||
!defined(ELECROW_ThinkNode_M5)
|
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
||||||
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
||||||
#ifdef ARCH_RP2040
|
#ifdef ARCH_RP2040
|
||||||
Serial2.setFIFOSize(RX_BUFFER);
|
Serial2.setFIFOSize(RX_BUFFER);
|
||||||
@@ -236,8 +236,8 @@ int32_t SerialModule::runOnce()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
|
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
||||||
!defined(ELECROW_ThinkNode_M5)
|
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
||||||
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
|
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
|
||||||
processWXSerial();
|
processWXSerial();
|
||||||
|
|
||||||
@@ -496,8 +496,8 @@ ParsedLine parseLine(const char *line)
|
|||||||
*/
|
*/
|
||||||
void SerialModule::processWXSerial()
|
void SerialModule::processWXSerial()
|
||||||
{
|
{
|
||||||
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \
|
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
|
||||||
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
||||||
static unsigned int lastAveraged = 0;
|
static unsigned int lastAveraged = 0;
|
||||||
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
|
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
|
||||||
static double dir_sum_sin = 0;
|
static double dir_sum_sin = 0;
|
||||||
|
|||||||
@@ -223,9 +223,12 @@ void NimbleBluetooth::deinit()
|
|||||||
LOG_INFO("Disable bluetooth until reboot");
|
LOG_INFO("Disable bluetooth until reboot");
|
||||||
|
|
||||||
#ifdef BLE_LED
|
#ifdef BLE_LED
|
||||||
|
#ifdef BLE_LED_INVERTED
|
||||||
|
digitalWrite(BLE_LED, HIGH);
|
||||||
|
#else
|
||||||
digitalWrite(BLE_LED, LOW);
|
digitalWrite(BLE_LED, LOW);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
NimBLEDevice::deinit();
|
NimBLEDevice::deinit();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,8 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
|
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
|
||||||
#elif defined(TTGO_T_ECHO)
|
#elif defined(TTGO_T_ECHO)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
|
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
|
||||||
|
#elif defined(T_ECHO_LITE)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE
|
||||||
#elif defined(ELECROW_ThinkNode_M1)
|
#elif defined(ELECROW_ThinkNode_M1)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
|
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
|
||||||
#elif defined(NANO_G2_ULTRA)
|
#elif defined(NANO_G2_ULTRA)
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
|
|
||||||
std::map<configNames, int> settingsMap;
|
std::map<configNames, int> settingsMap;
|
||||||
std::map<configNames, std::string> settingsStrings;
|
std::map<configNames, std::string> settingsStrings;
|
||||||
|
portduino_config_struct portduino_config;
|
||||||
std::ofstream traceFile;
|
std::ofstream traceFile;
|
||||||
Ch341Hal *ch341Hal = nullptr;
|
Ch341Hal *ch341Hal = nullptr;
|
||||||
char *configPath = nullptr;
|
char *configPath = nullptr;
|
||||||
char *optionMac = nullptr;
|
char *optionMac = nullptr;
|
||||||
bool forceSimulated = false;
|
|
||||||
bool verboseEnabled = false;
|
bool verboseEnabled = false;
|
||||||
|
|
||||||
const char *argp_program_version = optstr(APP_VERSION);
|
const char *argp_program_version = optstr(APP_VERSION);
|
||||||
@@ -66,7 +66,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
|||||||
configPath = arg;
|
configPath = arg;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
forceSimulated = true;
|
portduino_config.force_simradio = true;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
optionMac = arg;
|
optionMac = arg;
|
||||||
@@ -189,7 +189,7 @@ void portduinoSetup()
|
|||||||
|
|
||||||
YAML::Node yamlConfig;
|
YAML::Node yamlConfig;
|
||||||
|
|
||||||
if (forceSimulated == true) {
|
if (portduino_config.force_simradio == true) {
|
||||||
settingsMap[use_simradio] = true;
|
settingsMap[use_simradio] = true;
|
||||||
} else if (configPath != nullptr) {
|
} else if (configPath != nullptr) {
|
||||||
if (loadConfig(configPath)) {
|
if (loadConfig(configPath)) {
|
||||||
@@ -553,6 +553,48 @@ bool loadConfig(const char *configPath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]) {
|
||||||
|
portduino_config.has_rfswitch_table = true;
|
||||||
|
portduino_config.rfswitch_table[0].mode = LR11x0::MODE_STBY;
|
||||||
|
portduino_config.rfswitch_table[1].mode = LR11x0::MODE_RX;
|
||||||
|
portduino_config.rfswitch_table[2].mode = LR11x0::MODE_TX;
|
||||||
|
portduino_config.rfswitch_table[3].mode = LR11x0::MODE_TX_HP;
|
||||||
|
portduino_config.rfswitch_table[4].mode = LR11x0::MODE_TX_HF;
|
||||||
|
portduino_config.rfswitch_table[5].mode = LR11x0::MODE_GNSS;
|
||||||
|
portduino_config.rfswitch_table[6].mode = LR11x0::MODE_WIFI;
|
||||||
|
portduino_config.rfswitch_table[7] = END_OF_MODE_TABLE;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
|
||||||
|
// set up the pin array first
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO5")
|
||||||
|
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO5;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO6")
|
||||||
|
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO6;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO7")
|
||||||
|
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO7;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO8")
|
||||||
|
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO8;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO10")
|
||||||
|
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO10;
|
||||||
|
|
||||||
|
// now fill in the table
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_STBY"][i].as<std::string>("") == "HIGH")
|
||||||
|
portduino_config.rfswitch_table[0].values[i] = HIGH;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_RX"][i].as<std::string>("") == "HIGH")
|
||||||
|
portduino_config.rfswitch_table[1].values[i] = HIGH;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX"][i].as<std::string>("") == "HIGH")
|
||||||
|
portduino_config.rfswitch_table[2].values[i] = HIGH;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HP"][i].as<std::string>("") == "HIGH")
|
||||||
|
portduino_config.rfswitch_table[3].values[i] = HIGH;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HF"][i].as<std::string>("") == "HIGH")
|
||||||
|
portduino_config.rfswitch_table[4].values[i] = HIGH;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_GNSS"][i].as<std::string>("") == "HIGH")
|
||||||
|
portduino_config.rfswitch_table[5].values[i] = HIGH;
|
||||||
|
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_WIFI"][i].as<std::string>("") == "HIGH")
|
||||||
|
portduino_config.rfswitch_table[6].values[i] = HIGH;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["GPIO"]) {
|
if (yamlConfig["GPIO"]) {
|
||||||
settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
|
settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "LR11x0Interface.h"
|
||||||
|
#include "Module.h"
|
||||||
#include "platform/portduino/USBHal.h"
|
#include "platform/portduino/USBHal.h"
|
||||||
|
|
||||||
// Product strings for auto-configuration
|
// Product strings for auto-configuration
|
||||||
@@ -127,3 +129,10 @@ static bool ends_with(std::string_view str, std::string_view suffix);
|
|||||||
void getMacAddr(uint8_t *dmac);
|
void getMacAddr(uint8_t *dmac);
|
||||||
bool MAC_from_string(std::string mac_str, uint8_t *dmac);
|
bool MAC_from_string(std::string mac_str, uint8_t *dmac);
|
||||||
std::string exec(const char *cmd);
|
std::string exec(const char *cmd);
|
||||||
|
|
||||||
|
extern struct portduino_config_struct {
|
||||||
|
bool has_rfswitch_table = false;
|
||||||
|
uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
|
||||||
|
Module::RfSwitchMode_t rfswitch_table[8];
|
||||||
|
bool force_simradio = false;
|
||||||
|
} portduino_config;
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
#define LORA_DIO1 SX126X_DIO1
|
#define LORA_DIO1 SX126X_DIO1
|
||||||
|
|
||||||
#define USE_EINK
|
#define USE_EINK
|
||||||
#define PIN_EINK_EN -1 // Note: this is really just backlight power
|
// Note: this is really just backlight power
|
||||||
#define PCA_PIN_EINK_EN 5 // This is the pin number on the GPIO expander
|
#define PCA_PIN_EINK_EN 5 // This is the pin number on the GPIO expander
|
||||||
#define PIN_EINK_CS 39
|
#define PIN_EINK_CS 39
|
||||||
#define PIN_EINK_BUSY 42
|
#define PIN_EINK_BUSY 42
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ build_flags = ${nrf52840_base.build_flags}
|
|||||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||||
-DHAS_RAKPROT=1 ; Define if RAk OneWireSerial is used (disables GPS)
|
-DHAS_RAKPROT=1 ; Define if RAk OneWireSerial is used (disables GPS)
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> +<mesh/api/> +<mqtt/>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> +<mesh/api/> +<mqtt/> +<serialization/>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
${networking_base.lib_deps}
|
${nrf52_networking_base.lib_deps}
|
||||||
melopero/Melopero RV3028@^1.1.0
|
melopero/Melopero RV3028@^1.1.0
|
||||||
https://github.com/beegee-tokyo/RAK-OneWireSerial/archive/0.0.2.zip
|
https://github.com/beegee-tokyo/RAK-OneWireSerial/archive/0.0.2.zip
|
||||||
debug_tool = jlink
|
debug_tool = jlink
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ build_flags = ${nrf52840_base.build_flags}
|
|||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631> +<mesh/eth/> +<mesh/api/> +<mqtt/>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631> +<mesh/eth/> +<mesh/api/> +<mqtt/>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
${networking_base.lib_deps}
|
${nrf52_networking_base.lib_deps}
|
||||||
melopero/Melopero RV3028@^1.1.0
|
melopero/Melopero RV3028@^1.1.0
|
||||||
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
|
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
|
||||||
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
|
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ build_flags = ${nrf52840_base.build_flags}
|
|||||||
-DMESHTASTIC_EXCLUDE_STOREFORWARD=1
|
-DMESHTASTIC_EXCLUDE_STOREFORWARD=1
|
||||||
-DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
|
-DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
|
||||||
-DMESHTASTIC_EXCLUDE_WAYPOINT=1
|
-DMESHTASTIC_EXCLUDE_WAYPOINT=1
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_eth_gw> +<mesh/eth/> +<mesh/api/> +<mqtt/>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_eth_gw> +<mesh/eth/> +<mesh/api/> +<mqtt/> +<serialization/>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
${networking_base.lib_deps}
|
${networking_base.lib_deps}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ build_flags = ${nrf52840_base.build_flags}
|
|||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak_wismeshtap> +<mesh/eth/> +<mesh/api/> +<mqtt/>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak_wismeshtap> +<mesh/eth/> +<mesh/api/> +<mqtt/>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
${networking_base.lib_deps}
|
${nrf52_networking_base.lib_deps}
|
||||||
melopero/Melopero RV3028@^1.1.0
|
melopero/Melopero RV3028@^1.1.0
|
||||||
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
|
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
|
||||||
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
|
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
|
||||||
|
|||||||
25
variants/nrf52840/t-echo-lite/platformio.ini
Normal file
25
variants/nrf52840/t-echo-lite/platformio.ini
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
; Using original screen class
|
||||||
|
[env:t-echo-lite]
|
||||||
|
extends = nrf52840_base
|
||||||
|
board = t-echo
|
||||||
|
board_check = true
|
||||||
|
debug_tool = jlink
|
||||||
|
|
||||||
|
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
|
||||||
|
build_flags = ${nrf52840_base.build_flags}
|
||||||
|
-Ivariants/nrf52840/t-echo-lite
|
||||||
|
-D T_ECHO_LITE
|
||||||
|
-D GPS_POWER_TOGGLE
|
||||||
|
-D EINK_DISPLAY_MODEL=GxEPD2_122_T61
|
||||||
|
-D EINK_WIDTH=192
|
||||||
|
-D EINK_HEIGHT=176
|
||||||
|
-D USE_EINK
|
||||||
|
-D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
|
||||||
|
-D EINK_LIMIT_FASTREFRESH=20 ; How many consecutive fast-refreshes are permitted
|
||||||
|
-D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
|
||||||
|
|
||||||
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/t-echo-lite>
|
||||||
|
lib_deps =
|
||||||
|
${nrf52840_base.lib_deps}
|
||||||
|
https://github.com/meshtastic/GxEPD2/archive/a05c11c02862624266b61599b0d6ba93e33c6f24.zip
|
||||||
|
;upload_protocol = fs
|
||||||
44
variants/nrf52840/t-echo-lite/variant.cpp
Normal file
44
variants/nrf52840/t-echo-lite/variant.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||||
|
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||||
|
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "variant.h"
|
||||||
|
#include "nrf.h"
|
||||||
|
#include "wiring_constants.h"
|
||||||
|
#include "wiring_digital.h"
|
||||||
|
|
||||||
|
const uint32_t g_ADigitalPinMap[] = {
|
||||||
|
// P0 - pins 0 and 1 are hardwired for xtal and should never be enabled
|
||||||
|
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
|
|
||||||
|
// P1
|
||||||
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||||
|
|
||||||
|
void initVariant()
|
||||||
|
{
|
||||||
|
// LED1 & LED2
|
||||||
|
pinMode(PIN_LED1, OUTPUT);
|
||||||
|
ledOff(PIN_LED1);
|
||||||
|
|
||||||
|
pinMode(PIN_LED2, OUTPUT);
|
||||||
|
ledOff(PIN_LED2);
|
||||||
|
|
||||||
|
pinMode(PIN_LED3, OUTPUT);
|
||||||
|
ledOff(PIN_LED3);
|
||||||
|
}
|
||||||
207
variants/nrf52840/t-echo-lite/variant.h
Normal file
207
variants/nrf52840/t-echo-lite/variant.h
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||||
|
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||||
|
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
This library 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 Lesser General Public License for more details.
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _VARIANT_TTGO_EINK_V1_0_
|
||||||
|
#define _VARIANT_TTGO_EINK_V1_0_
|
||||||
|
|
||||||
|
/** Master clock frequency */
|
||||||
|
#define VARIANT_MCK (64000000ul)
|
||||||
|
|
||||||
|
#define USE_LFXO // Board uses 32khz crystal for LF
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Headers
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "WVariant.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
// Number of pins defined in PinDescription array
|
||||||
|
#define PINS_COUNT (48)
|
||||||
|
#define NUM_DIGITAL_PINS (48)
|
||||||
|
#define NUM_ANALOG_INPUTS (1)
|
||||||
|
#define NUM_ANALOG_OUTPUTS (0)
|
||||||
|
|
||||||
|
// LEDs
|
||||||
|
#define PIN_LED1 (32 + 7) // Green LED
|
||||||
|
#define PIN_LED2 (32 + 5) // Blue LED
|
||||||
|
// Unused(by firmware) LEDs:
|
||||||
|
#define PIN_LED3 (32 + 14) // Red LED inside, under the display.
|
||||||
|
|
||||||
|
#define LED_RED PIN_LED3
|
||||||
|
#define LED_BLUE PIN_LED2
|
||||||
|
#define LED_GREEN PIN_LED1
|
||||||
|
|
||||||
|
#define BLE_LED LED_BLUE
|
||||||
|
#define BLE_LED_INVERTED 1
|
||||||
|
#define LED_BUILTIN LED_GREEN
|
||||||
|
#define LED_CONN LED_GREEN
|
||||||
|
#define LED_STATE_ON 0 // State when LED is lit
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
#define PIN_BUTTON1 (0 + 24)
|
||||||
|
#define PIN_BUTTON2 (0 + 18) // 0.18 is labeled on the board as RESET but we configure it in the bootloader as a regular GPIO
|
||||||
|
|
||||||
|
#define BUTTON_CLICK_MS 400
|
||||||
|
|
||||||
|
// Analog pins
|
||||||
|
#define PIN_A0 (0 + 2) // Battery ADC
|
||||||
|
|
||||||
|
#define BATTERY_PIN PIN_A0
|
||||||
|
|
||||||
|
static const uint8_t A0 = PIN_A0;
|
||||||
|
|
||||||
|
#define ADC_RESOLUTION 14
|
||||||
|
|
||||||
|
#define ADC_CTRL (0 + 31)
|
||||||
|
#define ADC_CTRL_ENABLED HIGH
|
||||||
|
|
||||||
|
// NFC
|
||||||
|
#define PIN_NFC1 (9)
|
||||||
|
#define PIN_NFC2 (10)
|
||||||
|
|
||||||
|
// Wire Interfaces
|
||||||
|
#define WIRE_INTERFACES_COUNT 1
|
||||||
|
|
||||||
|
#define PIN_WIRE_SDA (32 + 4)
|
||||||
|
#define PIN_WIRE_SCL (32 + 2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Internal, PCB PAD interrupt PIN. Currently not used. (Not built in my device)
|
||||||
|
*/
|
||||||
|
// #define PIN_IMU_INT (0 + 16) // Interrupt from the IMU, macro name correct?!
|
||||||
|
|
||||||
|
// External serial flash ZD25WQ32CEIGR
|
||||||
|
// QSPI Pins
|
||||||
|
#define PIN_QSPI_SCK (0 + 4)
|
||||||
|
#define PIN_QSPI_CS (0 + 12)
|
||||||
|
#define PIN_QSPI_IO0 (0 + 6) // MOSI if using two bit interface
|
||||||
|
#define PIN_QSPI_IO1 (0 + 8) // MISO if using two bit interface
|
||||||
|
#define PIN_QSPI_IO2 (32 + 9) // WP if using two bit interface (i.e. not used)
|
||||||
|
#define PIN_QSPI_IO3 (0 + 26) // HOLD if using two bit interface (i.e. not used)
|
||||||
|
|
||||||
|
// On-board QSPI Flash
|
||||||
|
#define EXTERNAL_FLASH_DEVICES ZD25WQ32CEIGR
|
||||||
|
#define EXTERNAL_FLASH_USE_QSPI
|
||||||
|
|
||||||
|
// Lora radio
|
||||||
|
|
||||||
|
#define USE_SX1262
|
||||||
|
// #define USE_SX1268 // currently only available with XS1262.
|
||||||
|
#define SX126X_CS (0 + 11)
|
||||||
|
#define SX126X_DIO1 (32 + 8)
|
||||||
|
#define SX126X_DIO2 (0 + 5)
|
||||||
|
#define SX126X_BUSY (0 + 14)
|
||||||
|
#define SX126X_RESET (0 + 7)
|
||||||
|
#define SX126X_RXEN (32 + 1)
|
||||||
|
#define SX126X_TXEN (0 + 27)
|
||||||
|
// #define TCXO_OPTIONAL
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
|
|
||||||
|
// eink display pins
|
||||||
|
#define VEXT_ENABLE (32 + 12)
|
||||||
|
#define VEXT_ON_VALUE LOW
|
||||||
|
#define PIN_EINK_CS (0 + 22)
|
||||||
|
#define PIN_EINK_BUSY (0 + 3)
|
||||||
|
#define PIN_EINK_DC (0 + 21)
|
||||||
|
#define PIN_EINK_RES (0 + 28)
|
||||||
|
#define PIN_EINK_SCLK (0 + 19)
|
||||||
|
#define PIN_EINK_MOSI (0 + 20)
|
||||||
|
|
||||||
|
// Controls power 3V3 for all peripherals (eink + GPS + LoRa + Sensor)
|
||||||
|
#define PIN_POWER_EN (0 + 30) // 3V3 POWER Enable
|
||||||
|
|
||||||
|
#define PIN_SPI1_MISO (-1) // The display does not use MISO.
|
||||||
|
#define PIN_SPI1_MOSI PIN_EINK_MOSI
|
||||||
|
#define PIN_SPI1_SCK PIN_EINK_SCLK
|
||||||
|
|
||||||
|
// GPS pins
|
||||||
|
// #define GPS_DEBUG
|
||||||
|
#define GPS_L76K
|
||||||
|
#define GPS_BAUDRATE 9600
|
||||||
|
#define HAS_GPS 1
|
||||||
|
// #define PIN_GPS_REINIT (32 + 5) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
|
||||||
|
|
||||||
|
#define PIN_GPS_STANDBY (32 + 10) // An output to wake GPS, low means allow sleep, high means force wake
|
||||||
|
// Seems to be missing on this new board
|
||||||
|
#define PIN_GPS_PPS (0 + 29) // Pulse per second input from the GPS
|
||||||
|
#define GPS_TX_PIN (32 + 15) // This is for bits going TOWARDS the CPU
|
||||||
|
#define GPS_RX_PIN (32 + 13) // This is for bits going TOWARDS the GPS
|
||||||
|
|
||||||
|
#define GPS_THREAD_INTERVAL 50
|
||||||
|
|
||||||
|
#define PIN_SERIAL1_RX GPS_TX_PIN
|
||||||
|
#define PIN_SERIAL1_TX GPS_RX_PIN
|
||||||
|
|
||||||
|
// SPI Interfaces
|
||||||
|
#define SPI_INTERFACES_COUNT 2
|
||||||
|
|
||||||
|
// For LORA, SPI 0
|
||||||
|
#define PIN_SPI_MISO (0 + 17)
|
||||||
|
#define PIN_SPI_MOSI (0 + 15)
|
||||||
|
#define PIN_SPI_SCK (0 + 13)
|
||||||
|
|
||||||
|
// Battery
|
||||||
|
// The battery sense is hooked to pin A0 (2)
|
||||||
|
// it is defined in the analogue pin section of this file
|
||||||
|
// and has 12 bit resolution
|
||||||
|
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||||
|
#define BATTERY_SENSE_RESOLUTION 4096.0
|
||||||
|
#undef AREF_VOLTAGE
|
||||||
|
#define AREF_VOLTAGE 3.0
|
||||||
|
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||||
|
#define ADC_MULTIPLIER (2.0F)
|
||||||
|
|
||||||
|
// #define NO_EXT_GPIO 1
|
||||||
|
// PINs back side
|
||||||
|
// Batt & solar connector left up corner
|
||||||
|
/*
|
||||||
|
-------------------------------
|
||||||
|
| VDDH, VBAT, 0.23, SCL , 1.06 |
|
||||||
|
| GND , SDA , 0.09, 0.10, 0.25 |
|
||||||
|
-------------------------------
|
||||||
|
--------
|
||||||
|
| VDDH |
|
||||||
|
| GND |
|
||||||
|
| 1.13 | - Wake Up/standby
|
||||||
|
| 1.15 | - PPS
|
||||||
|
| 0.29 | - TX
|
||||||
|
| 1.10 | - RX
|
||||||
|
| 1.11 | - EN
|
||||||
|
--------
|
||||||
|
-------------------------------
|
||||||
|
| 3V3 , GND , 0.16, 1.03, G_WU | 0.16 internal solder pad interrupt PIN,
|
||||||
|
| G_EN, G_RX, G_TX, GND , PPS |
|
||||||
|
-------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||||
|
// #define USE_SEGGER
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Arduino objects - C++ only
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user