Compare commits

..

37 Commits

Author SHA1 Message Date
Kevin Hester
80e4bc6289 fix nrf52 build 2021-05-03 15:58:35 +08:00
Kevin Hester
19ee911022 turn off simulator build for now, because (ugh) it is accidentally looking for gpiod hardware 2021-05-03 15:54:26 +08:00
Kevin Hester
cb4d5d580a add gpiod libs 2021-05-03 15:51:33 +08:00
Kevin Hester
7b3d59569e Merge remote-tracking branch 'root/master' into pinelora 2021-05-03 15:46:26 +08:00
Kevin Hester
3bc0aaabe4 disable platformio caching for now 2021-05-03 15:46:13 +08:00
Kevin Hester
2418fee444 Merge pull request #799 from geeksville/pinelora
Pinelora
2021-05-03 15:42:21 +08:00
Kevin Hester
b56c5df6e1 1.2.30 2021-05-03 15:38:14 +08:00
Kevin Hester
bc76c79e1e oops my latest change busted android connection detection 2021-05-03 15:37:37 +08:00
Kevin Hester
d179bda728 serious bug: connection to phones not being properly tracked 2021-05-03 14:46:30 +08:00
Kevin Hester
e60ef655cb fix serious bug! plugin was incorrectly stopping packet processing 2021-05-03 10:53:24 +08:00
Kevin Hester
c15204fed1 better debug output 2021-05-03 10:53:06 +08:00
Kevin Hester
1f2dc82035 don't cache platformio for now 2021-05-03 10:36:44 +08:00
Kevin Hester
218d841511 use short version string on bootscreen 2021-05-03 09:50:06 +08:00
Kevin Hester
f40c6f21d4 fix portduino rtc 2021-05-03 09:30:03 +08:00
Kevin Hester
6dc4471bec fix serious bug! don't send NO-RESPONSE NAKs for messages sent by local node 2021-05-03 08:45:32 +08:00
Kevin Hester
4c1b7d4840 pinelora WIP 2021-05-01 11:27:37 +08:00
Kevin Hester
8ec73e653b apparently regen-docs is removed now ;-) 2021-05-01 11:26:36 +08:00
Kevin Hester
babc1b3613 include file/lineno in critical error logs 2021-04-29 09:52:15 +08:00
Kevin Hester
c27d479a9f t-echo: add hwmodel 2021-04-29 09:51:10 +08:00
Kevin Hester
14224088aa don't checkin workspace files 2021-04-28 15:33:08 +08:00
Kevin Hester
b95baadb9a fix USB power detection for analog battery sensors (t-echo and possibly heltec/t-lora32) 2021-04-28 15:30:02 +08:00
Kevin Hester
c940d22a98 t-echo: enable nrfupload 2021-04-28 15:25:54 +08:00
Kevin Hester
28b7bd347a Fix nrf52 USB (don't call delay() in loop() if connected via usb) 2021-04-28 15:11:55 +08:00
Kevin Hester
a42bb80cf4 pinelora wip 2021-04-28 14:47:29 +08:00
Kevin Hester
2a9b2d3b29 official name for t-echo board 2021-04-27 10:21:54 +08:00
Kevin Hester
9c94a324e5 use real gpios for pinelora 2021-04-27 10:04:02 +08:00
Sacha Weatherstone
f07f3ae94b Merge pull request #798 from kylegordon/patch-1
Fix Development Documents link
2021-04-26 23:22:12 +10:00
Kyle Gordon
b6c2cd6caa Fix Development Documents link 2021-04-26 13:47:21 +01:00
Kevin Hester
a66ad8a9d9 pinelora WIP 2021-04-22 17:48:20 +08:00
Kevin Hester
8e3281a658 pinelora WIP 2021-04-22 14:28:56 +08:00
Kevin Hester
6e27856daa pinelora WIP 2021-04-22 08:49:05 +08:00
Kevin Hester
ce2d603def Merge pull request #796 from geeksville/codespacedev
Codespacedev
2021-04-21 21:14:41 +08:00
Kevin Hester
fa00e21f49 make github codespaces work 2021-04-21 13:13:38 +00:00
Kevin Hester
c4878671e3 add codespace support 2021-04-21 18:00:34 +08:00
Kevin Hester
57ef3b499f look for v1 versions only 2021-04-17 09:28:36 +08:00
Kevin Hester
6c956591f8 disambig github action names 2021-04-16 15:31:53 +08:00
Kevin Hester
640cc82103 1.2.29 get ready for automated releases 2021-04-16 15:29:33 +08:00
60 changed files with 463 additions and 365 deletions

11
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,11 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/ubuntu/.devcontainer/base.Dockerfile
# [Choice] Ubuntu version: bionic, focal
ARG VARIANT="focal"
FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
# [Optional] Uncomment this section to install additional OS packages.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install python3-distutils python3-pip
RUN pip3 install platformio meshtastic adafruit-nrfutil
RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.8/protoc-3.15.8-linux-x86_64.zip -O /tmp/protoc.zip && cd /tmp && unzip protoc.zip && chmod a+x bin/protoc && cp bin/protoc /usr/local/bin

View File

@@ -0,0 +1,32 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/ubuntu
{
"name": "Ubuntu",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick an Ubuntu version: focal, bionic
"args": { "VARIANT": "focal" }
},
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"platformio.platformio-ide",
"xaver.clang-format"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "uname -a",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"postCreateCommand": "git submodule update --init"
}

View File

@@ -24,12 +24,13 @@ runs:
python -m pip install --upgrade pip
pip install -U platformio meshtastic adafruit-nrfutil
- name: Cache platformio
uses: actions/cache@v1
id: cache-platformio # needed in if test
with:
path: ~/.platformio
key: ${{ runner.os }}-platformio
# Don't cache for now because I want to be lazy with portuino updates githashes
# - name: Cache platformio
# uses: actions/cache@v1
# id: cache-platformio # needed in if test
# with:
# path: ~/.platformio
# key: ${{ runner.os }}-platformio
- name: Upgrade platformio
run: |

View File

@@ -14,7 +14,7 @@ jobs:
# - name: Startup
# run: echo "No action setup currently needed, skipping..."
build:
ci-build:
# needs: setup
runs-on: ubuntu-latest
steps:
@@ -36,6 +36,10 @@ jobs:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
#- name: Install linux apt packages
# run: |
# sudo apt-get install -y libgpiod-dev
- name: Upgrade python tools
# We actually want to run this every time
# if: steps.cache-pip.outputs.cache-hit != 'true'
@@ -43,26 +47,26 @@ jobs:
python -m pip install --upgrade pip
pip install -U platformio meshtastic adafruit-nrfutil
- name: Cache platformio
uses: actions/cache@v1
id: cache-platformio # needed in if test
with:
path: ~/.platformio
key: ${{ runner.os }}-platformio
# - name: Cache platformio
# uses: actions/cache@v1
# id: cache-platformio # needed in if test
# with:
# path: ~/.platformio
# key: ${{ runner.os }}-platformio
- name: Upgrade platformio
run: |
pio upgrade
# We now run integration test before other build steps (to quickly see runtime failures)
- name: Build for native
run: platformio run -e native
- name: Integration test
run: |
.pio/build/native/program &
sleep 20 # 5 seconds was not enough
echo "Simulator started, launching python test..."
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
#- name: Build for native
# run: platformio run -e native
#- name: Integration test
# run: |
# .pio/build/native/program &
# sleep 20 # 5 seconds was not enough
# echo "Simulator started, launching python test..."
# python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
# - name: Build for tbeam
# run: platformio run -e tbeam

View File

@@ -9,10 +9,10 @@ on:
branches:
- "!*"
tags:
- "v*"
- "v1*"
jobs:
build:
release-build:
runs-on: ubuntu-latest
steps:

5
.gitignore vendored
View File

@@ -9,6 +9,8 @@ main/credentials.h
!.vscode/extensions.json
*.code-workspace
.idea/workspace.xml
.DS_Store
Thumbs.db
.autotools
@@ -19,4 +21,5 @@ Thumbs.db
nanopb*
flash.uf2
cmake-build*
__pycache__
__pycache__

162
.idea/workspace.xml generated
View File

@@ -1,162 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated>
<config projectName="meshtastic-esp32" targetName="Debug" />
<config projectName="meshtastic-esp32" targetName="Production" />
<config projectName="meshtastic-esp32" targetName="Z_DUMMY_TARGET" />
</generated>
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="native" CONFIG_NAME="native" ENABLED="true" />
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="58922733-b05b-4b90-9655-b9b18914977a" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectId" id="1pmWHw2wau2TbdKvXvmQUB0EUE9" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="ASKED_ADD_EXTERNAL_FILES" value="true" />
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.advertisement.text.overridden" value="true" />
<property name="cf.first.check.clang-format" value="false" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="settings.editor.selected.configurable" value="CMakeSettings" />
</component>
<component name="RunManager" selected="GDB Remote Debug.gdbremote-localhost-2345">
<configuration default="true" type="CLion_Remote" version="1" remoteCommand="tcp:localhost:2345" symbolFile="" sysroot="">
<debugger kind="GDB" isBundled="true" />
<method v="2" />
</configuration>
<configuration name="gdbremote-localhost-2345" type="CLion_Remote" version="1" remoteCommand="tcp:localhost:2345" symbolFile="" sysroot="">
<debugger kind="GDB" isBundled="true" />
<method v="2" />
</configuration>
<configuration name="Z_DUMMY_TARGET" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="meshtastic-esp32" TARGET_NAME="Z_DUMMY_TARGET" CONFIG_NAME="native" RUN_TARGET_PROJECT_NAME="meshtastic-esp32" RUN_TARGET_NAME="Z_DUMMY_TARGET">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration default="true" type="GradleAppRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="com.jetbrains.cidr.cpp.gradle.execution.GradleNativeBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="PlatformIO Debug" type="platformio" factoryName="PlatformIO Debug" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="meshtastic-esp32" TARGET_NAME="Debug" CONFIG_NAME="native" RUN_TARGET_PROJECT_NAME="meshtastic-esp32" RUN_TARGET_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="PlatformIO Upload" type="platformio" factoryName="PlatformIO Upload" REDIRECT_INPUT="false" ELEVATE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="meshtastic-esp32" TARGET_NAME="Production" CONFIG_NAME="native" RUN_TARGET_PROJECT_NAME="meshtastic-esp32" RUN_TARGET_NAME="Production">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<list>
<item itemvalue="CMake Application.Z_DUMMY_TARGET" />
<item itemvalue="GDB Remote Debug.gdbremote-localhost-2345" />
<item itemvalue="PlatformIO.PlatformIO Debug" />
<item itemvalue="PlatformIO.PlatformIO Upload" />
</list>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="58922733-b05b-4b90-9655-b9b18914977a" name="Default Changelist" comment="" />
<created>1615788661896</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1615788661896</updated>
<workItem from="1615788663210" duration="6661000" />
<workItem from="1615938346019" duration="1208000" />
<workItem from="1615971126983" duration="5945000" />
<workItem from="1617115374907" duration="357000" />
<workItem from="1617115747078" duration="1391000" />
<workItem from="1617117632667" duration="307000" />
<workItem from="1617160691713" duration="1016000" />
<workItem from="1617279002260" duration="1626000" />
<workItem from="1617425689081" duration="1896000" />
<workItem from="1617437366919" duration="1182000" />
<workItem from="1618544034975" duration="1185000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
<url>file://$PROJECT_DIR$/src/mesh/wifi/WiFiServerAPI.cpp</url>
<line>53</line>
<option name="timeStamp" value="6" />
</line-breakpoint>
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
<url>file://$PROJECT_DIR$/src/mesh/wifi/WiFiServerAPI.cpp</url>
<line>37</line>
<option name="timeStamp" value="7" />
</line-breakpoint>
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
<url>file://$PROJECT_DIR$/src/mqtt/MQTT.cpp</url>
<line>166</line>
<option name="timeStamp" value="10" />
</line-breakpoint>
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
<url>file://$PROJECT_DIR$/.pio/libdeps/native/PubSubClient/src/PubSubClient.cpp</url>
<line>468</line>
<option name="timeStamp" value="11" />
</line-breakpoint>
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
<url>file://$PROJECT_DIR$/src/mesh/mesh-pb-constants.cpp</url>
<line>20</line>
<option name="timeStamp" value="12" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
<watches-manager>
<configuration name="CLion_Remote">
<watch expression="radioConfig" language="ObjectiveC" />
<watch expression="fromRadioScratch" language="ObjectiveC" />
</configuration>
</watches-manager>
</component>
<component name="XSLT-Support.FileAssociations.UIState">
<expand />
<select />
</component>
</project>

View File

@@ -77,6 +77,5 @@
"--java_out=/tmp",
"-I=/home/kevinh/development/meshtastic/meshtastic-esp32/proto"
]
},
"editor.formatOnSave": true
}
}

View File

@@ -195,7 +195,7 @@ We offer a [python API](https://github.com/meshtastic/Meshtastic-python) that ma
# Development
We'd love to have you join us on this merry little project. Please see our [development documents](./docs/software/sw-design.md) and [join us in our discussion forum](https://meshtastic.discourse.group/).
We'd love to have you join us on this merry little project. Please see our [development documents](https://meshtastic.org/docs/software/other/sw-design) and [join us in our discussion forum](https://meshtastic.discourse.group/).
# Credits

View File

@@ -8,7 +8,7 @@ BOARDS_ESP32="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec tbeam0.7"
#BOARDS_ESP32=tbeam
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
BOARDS_NRF52="rak4631"
BOARDS_NRF52="rak4631 t-echo"
OUTDIR=release/latest

View File

@@ -3,5 +3,5 @@ import configparser
from readprops import readProps
verStr = readProps('version.properties')
print(f"{verStr}")
verObj = readProps('version.properties')
print(f"{verObj['long']}")

View File

@@ -9,11 +9,12 @@ from readprops import readProps
Import("projenv")
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
verStr = readProps(prefsLoc)
print("Using meshtastic platform-custom.py, firmare version " + verStr)
verObj = readProps(prefsLoc)
print("Using meshtastic platform-custom.py, firmare version " + verObj['long'])
# print("path is" + ','.join(sys.path))
# General options that are passed to the C and C++ compilers
projenv.Append(CCFLAGS=[
"-DAPP_VERSION=" + verStr
"-DAPP_VERSION=" + verObj['long'],
"-DAPP_VERSION_SHORT=" + verObj['short']
])

9
bin/promote-release.sh Executable file
View File

@@ -0,0 +1,9 @@
echo "This script is only for developers who are publishing new builds on github. Most users don't need it"
VERSION=`bin/buildinfo.py`
# Must have a V prefix to trigger github
git tag "v${VERSION}"
git push root "v${VERSION}" # push the tag
echo "Tag ${VERSION} pushed to github, github actions should now be building the draft release. If it seems good, click to publish it"

View File

@@ -12,6 +12,8 @@ def readProps(prefsLoc):
config = configparser.RawConfigParser()
config.read(prefsLoc)
version = dict(config.items('VERSION'))
verObj = dict(short = "{}.{}.{}".format(version["major"], version["minor"], version["build"]),
long = "unset")
# Try to find current build SHA if if the workspace is clean. This could fail if git is not installed
try:
@@ -23,14 +25,13 @@ def readProps(prefsLoc):
if isDirty:
# short for 'dirty', we want to keep our verstrings source for protobuf reasons
suffix = sha + "-d"
verStr = "{}.{}.{}.{}".format(
verObj['long'] = "{}.{}.{}.{}".format(
version["major"], version["minor"], version["build"], suffix)
except:
# print("Unexpected error:", sys.exc_info()[0])
# traceback.print_exc()
verStr = "{}.{}.{}".format(
version["major"], version["minor"], version["build"])
verObj['long'] = verObj['short']
# print("firmare version " + verStr)
return verStr
return verObj
# print("path is" + ','.join(sys.path))

View File

@@ -10,6 +10,6 @@ echo "prebuilt binaries for your computer into nanopb-0.4.4"
cd proto
../nanopb-0.4.4/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../proto *.proto
echo "Regenerating protobuf documentation - if you see an error message"
echo "you can ignore it unless doing a new protobuf release to github."
bin/regen-docs.sh
#echo "Regenerating protobuf documentation - if you see an error message"
#echo "you can ignore it unless doing a new protobuf release to github."
#bin/regen-docs.sh

View File

@@ -1,5 +1,5 @@
set -e
echo "Converting to uf2 for NRF52 Adafruit bootloader"
bin/uf2conv.py .pio/build/rak4631/firmware.hex -f 0xADA52840
bin/uf2conv.py .pio/build/t-echo/firmware.hex -f 0xADA52840
cp flash.uf2 /media/kevinh/FTH*BOOT/

5
bin/upload-to-rak4631.sh Executable file
View File

@@ -0,0 +1,5 @@
set -e
echo "Converting to uf2 for NRF52 Adafruit bootloader"
bin/uf2conv.py .pio/build/rak4631/firmware.hex -f 0xADA52840
cp flash.uf2 /media/kevinh/FTH*BOOT/

View File

@@ -15,7 +15,7 @@
],
"usb_product": "TTGO_eink",
"mcu": "nrf52840",
"variant": "eink",
"variant": "t-echo",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"
@@ -44,17 +44,20 @@
"arduino"
],
"name": "TTGO eink (Adafruit BSP)",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"require_upload_port": true,
"speed": 115200,
"protocol": "jlink",
"protocols": [
"jlink",
"nrfjprog",
"stlink"
]
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "FIXME",
"vendor": "TTGO"

View File

@@ -4,10 +4,11 @@ You probably don't care about this section - skip to the next one.
## before next release
* @havealoha fixedposition not working
* turn on setTx(timeout) and state = setDioIrqParams(SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT, SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT); in sx1262 code
* pine64 lora module
* merge https://meshtastic.discourse.group/t/spanish-translation-update/2986/5
* nrf52 USB is unreliable while sleeping?
* @havealoha fixedposition not working
* merge https://meshtastic.discourse.group/t/spanish-translation-update/2986/5
* @luxonn reports that after a while the android app stops showing new messages
* nrf52 shows as "sleeping" in android app? (but led is blinking)
* ask for vercel access

View File

@@ -0,0 +1,51 @@
# Notes on the pine64 lora board
like before but sx1262 based?
Since both DIO3 and DIO2 not apply to PINE64 LoRa situation, I will wire SX1262 INT [DIO1] pin, contact to CS341F pin 7 INT# and pin 5.
FIX ch341 GPIO access from linux
RF95 packet RX seems busted FIX FIRST
USE ch341 devboard if needed
SX1262 BUSY seems to come out on pin 15 of the RFM90 HOPE module. The 'footprint' seems rotated on the pine64 board schematic and that becomes pin 7 on U4 which is "DIO5" on that schematic. Which goes to pin 8 on the CH341F, which that datasheet calls "IN3"
FIXME - see if possible to read BUSY from "IN3"?
on a ch341a
* - Pin 15 (D0/CS0 ) as input/output/CS (CH341_PIN_MODE_IN/CH341_PIN_MODE_OUT/CH341_PIN_MODE_CS) (confirm hooked to CS)
* - Pin 16 (D1/CS1 ) as input/output/CS (CH341_PIN_MODE_IN/CH341_PIN_MODE_OUT/CH341_PIN_MODE_CS)
* - Pin 17 (D2/CS2 ) as input/output/CS (CH341_PIN_MODE_IN/CH341_PIN_MODE_OUT/CH341_PIN_MODE_CS)
* - Pin 19 (D4/DOUT2) as input/output (CH341_PIN_MODE_IN/CH341_PIN_MODE_OUT) / gpio4 in linux driver / (FIXME: confirm hooked to IRQ also?)
* - Pin 21 (D6/DIN2 ) as input (CH341_PIN_MODE_IN) / called RTS when in UART mode
## ch341-driver
driver busted in 5.11 kernels (rf95 init fails). 5.8.0 is okay, 5.8.18 is okay. fails on 5.10.31, 5.9.16 is okay. Therefore breakage happened in 5.10 kernels! Possibly not really breakage, possibly just sloppy caching or something that is more easily caught with modern threading.
cs_change is not being set on the way into the driver!
## gpio
the new GPIO interface https://embeddedbits.org/new-linux-kernel-gpio-user-space-interface/
~/development/meshtastic/meshtastic-esp32$ gpiodetect
gpiochip0 [INT34BB:00] (312 lines)
gpiochip1 [ch341] (2 lines)
~/development/meshtastic/meshtastic-esp32$ gpioinfo 1
gpiochip1 - 2 lines:
line 0: "gpio4" unused input active-high
line 1: "gpio5" unused input active-high
gpiofind gpio4
gpiochip1 0
DO NOT "apt install libgpiod-dev" It doesn't work with kernels newer than about 5.8. Instead build and install from source: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/
## Send in patch
Fix drivers/spi/spi.c transfer_once
read about spi: https://elinux.org/images/2/20/Whats_going_on_with_SPI--mark_brown.pdf
https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

View File

@@ -16,7 +16,7 @@ default_envs = tbeam
;default_envs = tlora_v1_3
;default_envs = tlora-v2
;default_envs = lora-relay-v1 # nrf board
;default_envs = eink
;default_envs = t-echo
;default_envs = nrf52840dk-geeksville
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
;default_envs = rak4631
@@ -72,7 +72,7 @@ lib_deps =
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
https://github.com/meshtastic/arduino-fsm.git#829e967b8a95c094f73c60ef8dacfe66eae38940
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
https://github.com/meshtastic/RadioLib.git#07de964e929238949035fb0d5887026a3058df1a
https://github.com/meshtastic/RadioLib.git#80ed10d689a0568782c5bd152906b0f97d2bce93
https://github.com/meshtastic/TinyGPSPlus.git#f0f47067ef2f67c856475933188251c1ef615e79
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
Wire ; explicitly needed here because the AXP202 library forgets to add it
@@ -88,7 +88,8 @@ framework = arduino
lib_deps =
${env.lib_deps}
build_flags = ${env.build_flags} -Os
build_flags = ${env.build_flags} -Os
# -DRADIOLIB_GODMODE
src_filter = ${env.src_filter} -<portduino/>
@@ -211,7 +212,7 @@ lib_ignore =
monitor_port = /dev/ttyACM1
# we pass in options to jlink so it can understand freertos (note: we don't use "jlink" as the tool)
debug_tool = jlink
;debug_tool = jlink
debug_port = :2331
# Note: the ARGUMENTS MUST BE on multiple lines. Otherwise platformio/commands/debug/helpers.py misparses everything into the "executable"
# attribute and leaves "arguments" empty
@@ -340,32 +341,33 @@ lib_deps =
${arduino_base.lib_deps}
; First prototype eink/nrf52840/sx1262 device
[env:eink]
[env:t-echo]
extends = nrf52840_base
board = eink
board = t-echo
# add our variants files to the include and src paths
# define build flags for the TFT_eSPI library
build_flags = ${nrf52_base.build_flags} -Ivariants/eink
build_flags = ${nrf52_base.build_flags} -Ivariants/t-echo
-DBUSY_PIN=3 -DRST_PIN=2 -DDC_PIN=28 -DCS_PIN=30
src_filter = ${nrf52_base.src_filter} +<../variants/eink>
src_filter = ${nrf52_base.src_filter} +<../variants/t-echo>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/geeksville/EPD_Libraries.git
TFT_eSPI
;upload_protocol = fs
; First prototype eink/nrf52840/sx1262 device
[env:eink0.1]
extends = nrf52840_base
board = eink0.1
# add our variants files to the include and src paths
# define build flags for the TFT_eSPI library
build_flags = ${nrf52_base.build_flags} -Ivariants/eink0.1
-DBUSY_PIN=3 -DRST_PIN=2 -DDC_PIN=28 -DCS_PIN=30
src_filter = ${nrf52_base.src_filter} +<../variants/eink0.1>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/geeksville/EPD_Libraries.git
TFT_eSPI
; First prototype eink/nrf52840/sx1262 device (removed from build because didn't ship in quantity)
;[env:eink0.1]
;extends = nrf52840_base
;board = eink0.1
;# add our variants files to the include and src paths
;# define build flags for the TFT_eSPI library
;build_flags = ${nrf52_base.build_flags} -Ivariants/eink0.1
; -DBUSY_PIN=3 -DRST_PIN=2 -DDC_PIN=28 -DCS_PIN=30
;src_filter = ${nrf52_base.src_filter} +<../variants/eink0.1>
;lib_deps =
; ${nrf52840_base.lib_deps}
; https://github.com/geeksville/EPD_Libraries.git
; TFT_eSPI
; The https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay board by @BigCorvus
[env:lora-relay-v1]
@@ -417,7 +419,7 @@ lib_deps =
[env:native]
platform = https://github.com/geeksville/platform-native.git
src_filter = ${env.src_filter} -<esp32/> -<nimble/> -<nrf52/> -<mesh/http/> -<plugins/esp32>
build_flags = ${arduino_base.build_flags} -O0
build_flags = ${arduino_base.build_flags} -O0 -lgpiod
framework = arduino
board = native
lib_deps =

2
proto

Submodule proto updated: 157f9891dd...5be5307c90

View File

@@ -120,7 +120,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
virtual bool isVBUSPlug() { return getBattVoltage() > 1000 * chargingVolt; }
virtual bool isVBUSPlug() { return getBattVoltage() > chargingVolt; }
/// Assume charging if we have a battery and external power is connected.
/// we can't be smart enough to say 'full'?

View File

@@ -32,6 +32,13 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
emitRebooted();
}
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
bool SerialConsole::checkIsConnected()
{
uint32_t now = millis();
return (now - lastContactMsec) < getPref_phone_timeout_secs() * 1000UL;
}
/**
* we override this to notice when we've received a protobuf over the serial
* stream. Then we shunt off debug serial output.
@@ -46,14 +53,3 @@ bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
return StreamAPI::handleToRadio(buf, len);
}
/// Hookable to find out when connection changes
void SerialConsole::onConnectionChanged(bool connected)
{
if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
} else {
// FIXME, we get no notice of serial going away, we should instead automatically generate this event if we haven't
// received a packet in a while
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
}
}

View File

@@ -25,8 +25,9 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
}
protected:
/// Hookable to find out when connection changes
virtual void onConnectionChanged(bool connected);
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected();
};
// A simple wrapper to allow non class aware code write to the console

View File

@@ -413,6 +413,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define HW_VENDOR HardwareModel_RAK4631
#elif defined(TTGO_T_ECHO)
#define HW_VENDOR HardwareModel_T_ECHO
#elif NRF52_SERIES
#define HW_VENDOR HardwareModel_NRF52_UNKNOWN
@@ -423,11 +427,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define USE_SIM_RADIO
#define USE_RF95
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET RADIOLIB_NC
#define LORA_DIO1 33 // Not really used
#define LORA_DIO2 32 // Not really used
// Pine64 uses a common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
// not found then probe for SX1262. Currently the RF95 code is disabled because I think the RF95 module won't need to ship.
// #define USE_RF95
#define USE_SX1262
// Fake SPI device selections
#define RF95_SCK 5
@@ -435,6 +438,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define RF95_MOSI 27
#define RF95_NSS RADIOLIB_NC // the ch341f spi controller does CS for us
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET 14
#define LORA_DIO1 33 // SX1262 IRQ, called DIO0 on pinelora schematic, pin 7 on ch341f "ack" - FIXME, enable hwints in linux
#define LORA_DIO2 32 // SX1262 BUSY, actually connected to "DIO5" on pinelora schematic, pin 8 on ch341f "slct"
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
#ifdef USE_SX1262
#define SX1262_CS 20 // CS0 on pinelora schematic, hooked to gpio D0 on ch341f
#define SX1262_DIO1 LORA_DIO1
#define SX1262_BUSY LORA_DIO2
#define SX1262_RESET LORA_RESET
// HOPE RFM90 does not have a TCXO therefore not SX1262_E22
#endif
#endif
// DEBUG LED

View File

@@ -4,5 +4,8 @@
#include "mesh/generated/mesh.pb.h" // For CriticalErrorCode
/// A macro that include filename and line
#define RECORD_CRITICALERROR(code) recordCriticalError(code, __LINE__, __FILE__)
/// Record an error that should be reported via analytics
void recordCriticalError(CriticalErrorCode code = CriticalErrorCode_Unspecified, uint32_t address = 0);
void recordCriticalError(CriticalErrorCode code = CriticalErrorCode_Unspecified, uint32_t address = 0, const char *filename = NULL);

View File

@@ -48,14 +48,22 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
shouldSet = false;
if (shouldSet) {
lastSetMsec = now;
#ifndef NO_ESP32
settimeofday(tv, NULL);
readFromRTC();
#else
lastSetMsec = now;
// This delta value works on all platforms
timeStartMsec = now;
zeroOffsetSecs = tv->tv_sec;
// If this platform has a setable RTC, set it
#ifndef NO_ESP32
settimeofday(tv, NULL);
#endif
// nrf52 doesn't have a readable RTC (yet - software not written)
#if defined(PORTDUINO) || !defined(NO_ESP32)
readFromRTC();
#endif
return true;
} else {
return false;
@@ -84,7 +92,7 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
uint32_t getTime()
{
return ((millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
return (((uint32_t) millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
}
uint32_t getValidTime(RTCQuality minQuality)

View File

@@ -43,7 +43,7 @@ bool UBloxGPS::setupGPS()
DEBUG_MSG("Connected to UBLOX GPS successfully\n");
if (!setUBXMode())
recordCriticalError(CriticalErrorCode_UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug
RECORD_CRITICALERROR(CriticalErrorCode_UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug
return true;
} else {

View File

@@ -130,7 +130,7 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
// Draw version in upper right
char buf[16];
snprintf(buf, sizeof(buf), "%s",
xstr(APP_VERSION)); // Note: we don't bother printing region or now, it makes the string too long
xstr(APP_VERSION_SHORT)); // Note: we don't bother printing region or now, it makes the string too long
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
screen->forceDisplay();

View File

@@ -299,6 +299,13 @@ uint32_t ButtonThread::longPressTime = 0;
RadioInterface *rIf = NULL;
/**
* Some platforms (nrf52) might provide an alterate version that supresses calling delay from sleep.
*/
__attribute__ ((weak, noinline)) bool loopCanSleep() {
return true;
}
void setup()
{
concurrency::hasBeenSetup = true;
@@ -459,7 +466,7 @@ void setup()
// Do this after service.init (because that clears error_code)
#ifdef AXP192_SLAVE_ADDRESS
if (!axp192_found)
recordCriticalError(CriticalErrorCode_NoAXP192); // Record a hardware fault for missing hardware
RECORD_CRITICALERROR(CriticalErrorCode_NoAXP192); // Record a hardware fault for missing hardware
#endif
// Don't call screen setup until after nodedb is setup (because we need
@@ -499,7 +506,7 @@ void setup()
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("Radio init succeeded, using RF95 radio\n");
DEBUG_MSG("RF95 Radio init succeeded, using RF95 radio\n");
}
}
#endif
@@ -512,7 +519,7 @@ void setup()
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("Radio init succeeded, using SX1262 radio\n");
DEBUG_MSG("SX1262 Radio init succeeded, using SX1262 radio\n");
}
}
#endif
@@ -550,7 +557,7 @@ void setup()
airTime = new AirTime();
if (!rIf)
recordCriticalError(CriticalErrorCode_NoRadio);
RECORD_CRITICALERROR(CriticalErrorCode_NoRadio);
else
router->addInterface(rIf);
@@ -640,7 +647,7 @@ void loop()
mainController.nextThread->tillRun(millis())); */
// We want to sleep as long as possible here - because it saves power
if (!runASAP)
if (!runASAP && loopCanSleep())
mainDelay.delay(delayMsec);
// if (didWake) DEBUG_MSG("wake!\n");
}

View File

@@ -86,10 +86,11 @@ void MeshPlugin::callPlugins(const MeshPacket &mp)
/// We only call plugins that are interested in the packet (and the message is destined to us or we are promiscious)
bool wantsPacket = (isDecoded || pi.encryptedOk) && (pi.isPromiscuous || toUs) && pi.wantPacket(&mp);
DEBUG_MSG("Plugin %s wantsPacket=%d\n", pi.name, wantsPacket);
assert(!pi.myReply); // If it is !null it means we have a bug, because it should have been sent the previous time
if (wantsPacket) {
DEBUG_MSG("Plugin %s wantsPacket=%d\n", pi.name, wantsPacket);
pluginFound = true;
/// received channel (or NULL if not decoded)
@@ -97,17 +98,21 @@ void MeshPlugin::callPlugins(const MeshPacket &mp)
/// Is the channel this packet arrived on acceptable? (security check)
/// Note: we can't know channel names for encrypted packets, so those are NEVER sent to boundChannel plugins
bool rxChannelOk = !pi.boundChannel || (ch && ((mp.from == 0) || (strcmp(ch->settings.name, pi.boundChannel) == 0)));
/// Also: if a packet comes in on the local PC interface, we don't check for bound channels, because it is TRUSTED and it needs to
/// to be able to fetch the initial admin packets without yet knowing any channels.
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (ch && (strcmp(ch->settings.name, pi.boundChannel) == 0));
if (!rxChannelOk) {
// no one should have already replied!
assert(!currentReply);
if (mp.decoded.want_response) {
DEBUG_MSG("packet on wrong channel, returning error\n");
printPacket("packet on wrong channel, returning error", &mp);
currentReply = pi.allocErrorResponse(Routing_Error_NOT_AUTHORIZED, &mp);
} else
DEBUG_MSG("packet on wrong channel, but client didn't want response\n");
printPacket("packet on wrong channel, but can't respond", &mp);
} else {
bool handled = pi.handleReceived(mp);
@@ -149,7 +154,9 @@ void MeshPlugin::callPlugins(const MeshPacket &mp)
printPacket("Sending response", currentReply);
service.sendToMesh(currentReply);
currentReply = NULL;
} else {
} else if(mp.from != ourNodeNum) {
// Note: if the message started with the local node we don't want to send a no response reply
// No one wanted to reply to this requst, tell the requster that happened
DEBUG_MSG("No one responded, send a nak\n");

View File

@@ -541,15 +541,24 @@ NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
}
/// Record an error that should be reported via analytics
void recordCriticalError(CriticalErrorCode code, uint32_t address)
void recordCriticalError(CriticalErrorCode code, uint32_t address, const char *filename)
{
// Print error to screen and serial port
String lcd = String("Critical error ") + code + "!\n";
screen->print(lcd.c_str());
DEBUG_MSG("NOTE! Recording critical error %d, address=%lx\n", code, address);
if(filename)
DEBUG_MSG("NOTE! Recording critical error %d at %s:%lx\n", code, filename, address);
else
DEBUG_MSG("NOTE! Recording critical error %d, address=%lx\n", code, address);
// Record error to DB
myNodeInfo.error_code = code;
myNodeInfo.error_address = address;
myNodeInfo.error_count++;
// Currently portuino is mostly used for simulation. Make sue the user notices something really bad happend
#ifdef PORTDUINO
DEBUG_MSG("A critical failure occurred, portduino is exiting...");
exit(2);
#endif
}

View File

@@ -27,7 +27,7 @@ bool PacketHistory::wasSeenRecently(const MeshPacket *p, bool withUpdate)
recentPackets.erase(recentPackets.begin() + i); // delete old record
} else {
if (r.id == p->id && r.sender == getFrom(p)) {
DEBUG_MSG("Found existing packet record for fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
DEBUG_MSG("Found existing packet record for fr=0x%x,to=0x%x,id=0x%x\n", p->from, p->to, p->id);
// Update the time on this record to now
if (withUpdate)

View File

@@ -27,6 +27,7 @@ PhoneAPI::~PhoneAPI()
void PhoneAPI::handleStartConfig()
{
// Must be before setting state (because state is how we know !connected)
if (!isConnected()) {
onConnectionChanged(true);
observe(&service.fromNumChanged);
@@ -35,7 +36,7 @@ void PhoneAPI::handleStartConfig()
// even if we were already connected - restart our state machine
state = STATE_SEND_MY_INFO;
DEBUG_MSG("Reset nodeinfo read pointer\n");
DEBUG_MSG("Starting API client config\n");
nodeInfoForPhone = NULL; // Don't keep returning old nodeinfos
nodeDB.resetReadPointer(); // FIXME, this read pointer should be moved out of nodeDB and into this class - because
// this will break once we have multiple instances of PhoneAPI running independently
@@ -56,10 +57,9 @@ void PhoneAPI::close()
void PhoneAPI::checkConnectionTimeout()
{
if (isConnected()) {
uint32_t now = millis();
bool newContact = (now - lastContactMsec) < getPref_phone_timeout_secs() * 1000UL;
bool newContact = checkIsConnected();
if (!newContact) {
DEBUG_MSG("Timed out on phone contact, dropping phone connection\n");
DEBUG_MSG("Lost phone connection\n");
close();
}
}
@@ -93,7 +93,8 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
break;
default:
DEBUG_MSG("Error: unexpected ToRadio variant\n");
// Ignore nop messages
// DEBUG_MSG("Error: unexpected ToRadio variant\n");
break;
}
} else {

View File

@@ -50,9 +50,6 @@ class PhoneAPI
/// Use to ensure that clients don't get confused about old messages from the radio
uint32_t config_nonce = 0;
/** the last msec we heard from the client on the other side of this link */
uint32_t lastContactMsec = 0;
public:
PhoneAPI();
@@ -88,12 +85,18 @@ class PhoneAPI
/// Our fromradio packet while it is being assembled
FromRadio fromRadioScratch;
/** the last msec we heard from the client on the other side of this link */
uint32_t lastContactMsec = 0;
/// Hookable to find out when connection changes
virtual void onConnectionChanged(bool connected) {}
/// If we haven't heard from the other side in a while then say not connected
void checkConnectionTimeout();
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() = 0;
/**
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
*/

View File

@@ -94,15 +94,15 @@ bool RF95Interface::reconfigure()
// configure publicly accessible settings
int err = lora->setSpreadingFactor(sf);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
err = lora->setBandwidth(bw);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
err = lora->setCodingRate(cr);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
err = lora->setSyncWord(syncWord);
assert(err == ERR_NONE);
@@ -115,13 +115,13 @@ bool RF95Interface::reconfigure()
err = lora->setFrequency(freq);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
if (power > MAX_POWER) // This chip has lower power limits than some
power = MAX_POWER;
err = lora->setOutputPower(power);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
startReceive(); // restart receiving

View File

@@ -14,7 +14,6 @@ class RF95Interface : public RadioLibInterface
public:
RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi);
/// Some boards (Pinetab Lora module) have broken IRQ wires, so we need to poll via i2c registers
bool isIRQPending() { return lora->getPendingIRQ(); }
/// Initialise the Driver transport hardware and software.

View File

@@ -151,6 +151,9 @@ class RadioInterface
*/
float getFreq();
/// Some boards (1st gen Pinetab Lora module) have broken IRQ wires, so we need to poll via i2c registers
virtual bool isIRQPending() { return false; }
protected:
int8_t power = 17; // Set by applyModemConfig()

View File

@@ -75,7 +75,7 @@ bool RadioLibInterface::canSendImmediately()
// TX IRQ from the radio, the radio is probably broken.
if (busyTx && (millis() - lastTxStart > 60000)) {
DEBUG_MSG("Hardware Failure! busyTx for more than 60s\n");
recordCriticalError(CriticalErrorCode_TransmitFailed);
RECORD_CRITICALERROR(CriticalErrorCode_TransmitFailed);
#ifndef NO_ESP32
if (busyTx && (millis() - lastTxStart > 65000)) // After 5s more, reboot
ESP.restart();
@@ -312,7 +312,13 @@ void RadioLibInterface::startSend(MeshPacket *txp)
size_t numbytes = beginSending(txp);
int res = iface->startTransmit(radiobuf, numbytes);
assert(res == ERR_NONE);
if(res != ERR_NONE) {
RECORD_CRITICALERROR(CriticalErrorCode_RadioSpiBug);
// This send failed, but make sure to 'complete' it properly
completeSending();
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
}
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrTxLevel0);

View File

@@ -49,6 +49,9 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
stopRetransmission(key);
}
else {
DEBUG_MSG("didn't find pending packet\n");
}
}
return FloodingRouter::shouldFilterReceived(p);

View File

@@ -59,6 +59,30 @@ bool SX1262Interface::init()
res = lora.setDio2AsRfSwitch(false);
#endif
#if 0
// Read/write a register we are not using (only used for FSK mode) to test SPI comms
uint8_t crcLSB = 0;
int err = lora.readRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
//if(crcLSB != 0x0f)
// RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
crcLSB = 0x5a;
err = lora.writeRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
err = lora.readRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
if(crcLSB != 0x5a)
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
// If we got this far register accesses (and therefore SPI comms) are good
#endif
if (res == ERR_NONE)
res = lora.setCRC(SX126X_LORA_CRC_ON);
@@ -78,15 +102,15 @@ bool SX1262Interface::reconfigure()
// configure publicly accessible settings
int err = lora.setSpreadingFactor(sf);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
err = lora.setBandwidth(bw);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
err = lora.setCodingRate(cr);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
err = lora.setRxGain(true);
@@ -103,7 +127,7 @@ bool SX1262Interface::reconfigure()
err = lora.setFrequency(freq);
if (err != ERR_NONE)
recordCriticalError(CriticalErrorCode_InvalidRadioSetting);
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
if (power > 22) // This chip has lower power limits than some
power = 22;

View File

@@ -25,6 +25,8 @@ class SX1262Interface : public RadioLibInterface
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep();
bool isIRQPending() { return lora.getIrqStatus() != 0; }
protected:
/**
* Glue functions called from ISR land

View File

@@ -1,4 +1,5 @@
#include "StreamAPI.h"
#include "PowerFSM.h"
#include "configuration.h"
#define START1 0x94
@@ -28,37 +29,42 @@ int32_t StreamAPI::readStream()
uint8_t c = stream->read();
// Use the read pointer for a little state machine, first look for framing, then length bytes, then payload
size_t ptr = rxPtr++; // assume we will probably advance the rxPtr
size_t ptr = rxPtr;
rxPtr++; // assume we will probably advance the rxPtr
rxBuf[ptr] = c; // store all bytes (including framing)
// console->printf("rxPtr %d ptr=%d c=0x%x\n", rxPtr, ptr, c);
if (ptr == 0) { // looking for START1
if (c != START1)
rxPtr = 0; // failed to find framing
} else if (ptr == 1) { // looking for START2
if (c != START2)
rxPtr = 0; // failed to find framing
} else if (ptr >= HEADER_LEN) { // we have at least read our 4 byte framing
} else if (ptr >= HEADER_LEN - 1) { // we have at least read our 4 byte framing
uint32_t len = (rxBuf[2] << 8) + rxBuf[3]; // big endian 16 bit length follows framing
if (ptr == HEADER_LEN) {
console->printf("len %d\n", len);
if (ptr == HEADER_LEN - 1) {
// we _just_ finished our 4 byte header, validate length now (note: a length of zero is a valid
// protobuf also)
if (len > MAX_TO_FROM_RADIO_SIZE)
rxPtr = 0; // length is bogus, restart search for framing
}
if (rxPtr != 0 && ptr + 1 == len + HEADER_LEN) {
rxPtr = 0; // start over again on the next packet
if (rxPtr != 0) // Is packet still considered 'good'?
if (ptr + 1 >= len + HEADER_LEN) { // have we received all of the payload?
rxPtr = 0; // start over again on the next packet
// If we didn't just fail the packet and we now have the right # of bytes, parse it
if (handleToRadio(rxBuf + HEADER_LEN, len))
return 0; // we want to be called again ASAP because we still have more work to do
}
// If we didn't just fail the packet and we now have the right # of bytes, parse it
handleToRadio(rxBuf + HEADER_LEN, len);
}
}
}
// we had packets available this time, so assume we might have them next time also
// we had bytes available this time, so assume we might have them next time also
lastRxMsec = now;
return 0;
}
@@ -109,4 +115,18 @@ void StreamAPI::emitRebooted()
// DEBUG_MSG("Emitting reboot packet for serial shell\n");
emitTxBuffer(pb_encode_to_bytes(txBuf + HEADER_LEN, FromRadio_size, FromRadio_fields, &fromRadioScratch));
}
/// Hookable to find out when connection changes
void StreamAPI::onConnectionChanged(bool connected)
{
// FIXME do reference counting instead
if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
} else {
// FIXME, we get no notice of serial going away, we should instead automatically generate this event if we haven't
// received a packet in a while
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
}
}

View File

@@ -67,6 +67,11 @@ class StreamAPI : public PhoneAPI, protected concurrency::OSThread
*/
void emitRebooted();
virtual void onConnectionChanged(bool connected);
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() = 0;
/**
* Send the current txBuffer over our stream
*/

View File

@@ -46,7 +46,9 @@ typedef enum _CriticalErrorCode {
CriticalErrorCode_NoAXP192 = 6,
CriticalErrorCode_InvalidRadioSetting = 7,
CriticalErrorCode_TransmitFailed = 8,
CriticalErrorCode_Brownout = 9
CriticalErrorCode_Brownout = 9,
CriticalErrorCode_SX1262Failure = 10,
CriticalErrorCode_RadioSpiBug = 11
} CriticalErrorCode;
typedef enum _Routing_Error {
@@ -216,8 +218,8 @@ typedef struct _ToRadio {
#define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1))
#define _CriticalErrorCode_MIN CriticalErrorCode_None
#define _CriticalErrorCode_MAX CriticalErrorCode_Brownout
#define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_Brownout+1))
#define _CriticalErrorCode_MAX CriticalErrorCode_RadioSpiBug
#define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_RadioSpiBug+1))
#define _Routing_Error_MIN Routing_Error_NONE
#define _Routing_Error_MAX Routing_Error_NOT_AUTHORIZED

View File

@@ -40,7 +40,9 @@ class HttpAPI : public PhoneAPI
// Nothing here yet
protected:
// Nothing here yet
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() { return true; } // FIXME, be smarter about this
};

View File

@@ -1,5 +1,4 @@
#include "WiFiServerAPI.h"
#include "PowerFSM.h"
#include "configuration.h"
#include <Arduino.h>
@@ -26,18 +25,7 @@ WiFiServerAPI::~WiFiServerAPI()
// FIXME - delete this if the client dropps the connection!
}
/// Hookable to find out when connection changes
void WiFiServerAPI::onConnectionChanged(bool connected)
{
// FIXME - we really should be doing global reference counting to see if anyone is currently using serial or wifi and if so,
// block sleep
if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
} else {
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
}
}
/// override close to also shutdown the TCP link
void WiFiServerAPI::close()
@@ -46,6 +34,12 @@ void WiFiServerAPI::close()
StreamAPI::close();
}
/// Check the current underlying physical link to see if the client is currently connected
bool WiFiServerAPI::checkIsConnected()
{
return client.connected();
}
int32_t WiFiServerAPI::runOnce()
{
if (client.connected()) {

View File

@@ -21,10 +21,11 @@ class WiFiServerAPI : public StreamAPI
virtual void close();
protected:
/// Hookable to find out when connection changes
virtual void onConnectionChanged(bool connected);
virtual int32_t runOnce(); // Check for dropped client connections
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected();
};
/**

View File

@@ -31,6 +31,10 @@ void BluetoothPhoneAPI::onNowHasData(uint32_t fromRadioNum)
}
}
bool BluetoothPhoneAPI::checkIsConnected() {
return curConnectionHandle >= 0;
}
int toradio_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
{
auto om = ctxt->om;

View File

@@ -6,10 +6,14 @@ extern uint16_t fromNumValHandle;
class BluetoothPhoneAPI : public PhoneAPI
{
protected:
/**
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
*/
virtual void onNowHasData(uint32_t fromRadioNum);
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected();
};
extern PhoneAPI *bluetoothPhoneAPI;

View File

@@ -21,6 +21,8 @@ static BLEDfu bledfu; // DFU software update helper service
static uint8_t fromRadioBytes[FromRadio_size];
static uint8_t toRadioBytes[ToRadio_size];
static bool bleConnected;
class BluetoothPhoneAPI : public PhoneAPI
{
/**
@@ -33,6 +35,11 @@ class BluetoothPhoneAPI : public PhoneAPI
DEBUG_MSG("BLE notify fromNum\n");
fromNum.notify32(fromRadioNum);
}
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() {
return bleConnected;
}
};
static BluetoothPhoneAPI *bluetoothPhoneAPI;
@@ -46,6 +53,7 @@ void connect_callback(uint16_t conn_handle)
connection->getPeerName(central_name, sizeof(central_name));
DEBUG_MSG("BLE Connected to %s\n", central_name);
bleConnected = true;
}
/**
@@ -55,7 +63,8 @@ void connect_callback(uint16_t conn_handle)
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void)conn_handle;
// FIXME - we currently assume only one active connection
bleConnected = false;
DEBUG_MSG("BLE Disconnected, reason = 0x%x\n", reason);
}

View File

@@ -19,6 +19,10 @@ static inline void debugger_break(void)
"mov pc, lr\n\t");
}
bool loopCanSleep() {
return !tud_cdc_connected();
}
// handle standard gcc assert failures
void __attribute__((noreturn)) __assert_func(const char *file, int line, const char *func, const char *failedexpr)
{
@@ -104,7 +108,7 @@ void checkSDEvents()
while (NRF_SUCCESS == sd_evt_get(&evt)) {
switch (evt) {
case NRF_EVT_POWER_FAILURE_WARNING:
recordCriticalError(CriticalErrorCode_Brownout);
RECORD_CRITICALERROR(CriticalErrorCode_Brownout);
break;
default:
@@ -114,7 +118,7 @@ void checkSDEvents()
}
} else {
if (NRF_POWER->EVENTS_POFWARN)
recordCriticalError(CriticalErrorCode_Brownout);
RECORD_CRITICALERROR(CriticalErrorCode_Brownout);
}
}

View File

@@ -30,10 +30,11 @@ void AdminPlugin::handleGetRadio(const MeshPacket &req)
AdminMessage r = AdminMessage_init_default;
r.get_radio_response = radioConfig;
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
// NOTE: The phone app needs to know the ls_secs & phone_timeout value so it can properly expect sleep behavior.
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
// using to the app (so that even old phone apps work with new device loads).
r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
r.get_radio_response.preferences.phone_timeout_secs = getPref_phone_timeout_secs();
r.which_variant = AdminMessage_get_radio_response_tag;
myReply = allocDataProtobuf(r);

View File

@@ -176,5 +176,5 @@ bool ExternalNotificationPlugin::handleReceived(const MeshPacket &mp)
#endif
return true; // Let others look at this message also if they want
return false; // Very important to never return TRUE here. TRUE means we handled the packet and we will stop letting other plugins see it
}

View File

@@ -6,6 +6,7 @@
#include <Utility.h>
#include <assert.h>
#include <linux/gpio/LinuxGPIOPin.h>
// FIXME - move setBluetoothEnable into a HALPlatform class
@@ -21,33 +22,14 @@ void cpuDeepSleep(uint64_t msecs)
void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel");
/** Dear pinetab hardware geeks!
*
* The current pinetab lora module has a slight bug. The ch341 part only provides ISR assertions on edges.
* This makes sense because USB interrupts happen through fast/repeated special irq urbs that are constantly
* chattering on the USB bus.
*
* But this isn't sufficient for level triggered ISR sources like the sx127x radios. The common way that seems to
* be addressed by cs341 users is to **always** connect the INT# (pin 26 on the ch341f) signal to one of the GPIO signals
* on the part. I'd recommend connecting that LORA_DIO0/INT# line to pin 19 (data 4) on the pinetab board. This would
* provide an efficent mechanism so that the (kernel) code in the cs341 driver that I've slightly hacked up to see the
* current state of LORA_DIO0. Without that access, I can't know if the interrupt is still pending - which would create
* race conditions in packet handling.
*
* My workaround is to poll the status register internally to the sx127x. Which is expensive because it involves a number of
* i2c transactions and many trips back and forth between kernel and my userspace app. I think shipping the current version
* of the pinetab lora device would be fine because I can poll slowly (because lora is slow). But if you ever have cause to
* rev this board. I highly encourage this small change.
*
* Btw - your little "USB lora dongle" is really neat. I encourage you to sell it, because even non pinetab customers could
* use it to easily add lora to rasberry pi, desktop pcs etc...
*
/** a simulated pin for busted IRQ hardware
* Porduino helper class to do this i2c based polling:
*/
class R595PolledIrqPin : public GPIOPin
class PolledIrqPin : public GPIOPin
{
public:
R595PolledIrqPin() : GPIOPin(LORA_DIO0, "LORA_DIO0") {}
PolledIrqPin() : GPIOPin(LORA_DIO1, "loraIRQ") {}
/// Read the low level hardware for this pin
virtual PinStatus readPinHardware()
@@ -58,14 +40,16 @@ class R595PolledIrqPin : public GPIOPin
extern RadioInterface *rIf; // FIXME, temporary hack until we know if we need to keep this
assert(rIf);
RF95Interface *rIf95 = static_cast<RF95Interface *>(rIf);
RadioLibInterface *rIf95 = static_cast<RadioLibInterface *>(rIf);
bool p = rIf95->isIRQPending();
// log(SysGPIO, LogDebug, "R595PolledIrqPin::readPinHardware(%s, %d, %d)", getName(), getPinNum(), p);
log(SysGPIO, LogDebug, "PolledIrqPin::readPinHardware(%s, %d, %d)", getName(), getPinNum(), p);
return p ? HIGH : LOW;
}
}
};
GPIOPin *loraIrq;
/** apps run under portduino can optionally define a portduinoSetup() to
* use portduino specific init code (such as gpioBind) to setup portduino on their host machine,
* before running 'arduino' code.
@@ -74,8 +58,26 @@ void portduinoSetup()
{
printf("Setting up Meshtastic on Porduino...\n");
// FIXME: disable while not testing with real hardware
// gpioBind(new R595PolledIrqPin());
// FIXME: remove this hack once interrupts are confirmed to work on new pine64 board
// loraIrq = new PolledIrqPin();
loraIrq = new LinuxGPIOPin(LORA_DIO1, "ch341", "int", "loraIrq"); // or "err"?
loraIrq->setSilent();
gpioBind(loraIrq);
// BUSY hw was busted on current board - just use the simulated pin (which will read low)
auto busy = new LinuxGPIOPin(SX1262_BUSY, "ch341", "slct", "loraBusy");
busy->setSilent();
gpioBind(busy);
//auto fakeBusy = new SimGPIOPin(SX1262_BUSY, "fakeBusy");
//fakeBusy->writePin(LOW);
//fakeBusy->setSilent(true);
//gpioBind(fakeBusy);
gpioBind(new LinuxGPIOPin(SX1262_RESET, "ch341", "ini", "loraReset"));
auto loraCs = new LinuxGPIOPin(SX1262_CS, "ch341", "cs0", "loraCs");
loraCs->setSilent();
gpioBind(loraCs);
// gpioBind((new SimGPIOPin(LORA_RESET, "LORA_RESET")));
// gpioBind((new SimGPIOPin(RF95_NSS, "RF95_NSS"))->setSilent());

View File

@@ -127,7 +127,7 @@ static void waitEnterSleep()
delay(100); // Kinda yucky - wait until radio says say we can shutdown (finished in process sends/receives)
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
recordCriticalError(CriticalErrorCode_SleepEnterWait);
RECORD_CRITICALERROR(CriticalErrorCode_SleepEnterWait);
assert(0); // FIXME - for now we just restart, need to fix bug #167
break;
}

View File

@@ -92,6 +92,8 @@ Note: Turning off EINK PWR_ON produces no noticeable power savings over just put
extern "C" {
#endif // __cplusplus
#define TTGO_T_ECHO
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
@@ -231,8 +233,6 @@ External serial flash WP25R1635FZUIL0
#define PIN_GPS_TX (32 + 9) // This is for bits going TOWARDS the CPU
#define PIN_GPS_RX (32 + 8) // This is for bits going TOWARDS the GPS
#define HAS_AIR530_GPS
#define PIN_SERIAL1_RX PIN_GPS_TX
#define PIN_SERIAL1_TX PIN_GPS_RX

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 1
minor = 2
build = 28
build = 30