Update RadioLib to V6.0.0
This commit is contained in:
parent
735b55b76b
commit
04f65f1392
166 changed files with 15126 additions and 10136 deletions
30
lib/RadioLib/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
30
lib/RadioLib/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**IMPORTANT: Check the wiki**
|
||||
Before submitting new issue, please check the [Wiki](https://github.com/jgromes/RadioLib/wiki) and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is. When applicable, please include [debug mode output](https://github.com/jgromes/RadioLib/wiki/Debug-mode).
|
||||
|
||||
**To Reproduce**
|
||||
Minimal Arduino sketch to reproduce the behavior. Please use Markdown to style the code to make it readable (see [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)).
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional info (please complete):**
|
||||
- MCU: [e.g. Arduino Uno, ESP8266 etc.]
|
||||
- Link to Arduino core: [e.g. https://github.com/stm32duino/Arduino_Core_STM32 when using official STM32 core. See readme for links to all supported cores]
|
||||
- Wireless module type [e.g. CC1101, SX1268, etc.]
|
||||
- Arduino IDE version [e.g. 1.8.5]
|
||||
- Library version [e.g. 3.0.0]
|
||||
23
lib/RadioLib/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
23
lib/RadioLib/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**IMPORTANT: Check the wiki**
|
||||
Before submitting new issue, please check the [Wiki](https://github.com/jgromes/RadioLib/wiki) and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
34
lib/RadioLib/.github/ISSUE_TEMPLATE/module-not-working.md
vendored
Normal file
34
lib/RadioLib/.github/ISSUE_TEMPLATE/module-not-working.md
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: Module not working
|
||||
about: Template to use when your module isn't working
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**IMPORTANT: Before submitting an issue, please check the following:**
|
||||
1. **Read [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)!** Issues that do not follow this document will be closed/locked/deleted/ignored.
|
||||
2. RadioLib has a [Wiki](https://github.com/jgromes/RadioLib/wiki) and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
3. Make sure you're using the latest release of the library! Releases can be found [here](https://github.com/jgromes/RadioLib/releases).
|
||||
4. Use [Arduino forums](https://forum.arduino.cc/) to ask generic questions about wireless modules, wiring, usage, etc. Only create issues for problems specific to RadioLib!
|
||||
5. Error codes, their meaning and how to fix them can be found on [this page](https://jgromes.github.io/RadioLib/group__status__codes.html).
|
||||
|
||||
**Sketch that is causing the module fail**
|
||||
|
||||
```c++
|
||||
paste the sketch here, even if it is an unmodified example code
|
||||
```
|
||||
|
||||
**Hardware setup**
|
||||
Wiring diagram, schematic, pictures etc.
|
||||
|
||||
**Debug mode output**
|
||||
Enable all [debug levels](https://github.com/jgromes/RadioLib/wiki/Debug-mode) and paste the Serial monitor output here.
|
||||
|
||||
**Additional info (please complete):**
|
||||
- MCU: [e.g. Arduino Uno, ESP8266 etc.]
|
||||
- Link to Arduino core: [e.g. https://github.com/stm32duino/Arduino_Core_STM32 when using official STM32 core. See readme for links to all supported cores]
|
||||
- Wireless module type [e.g. CC1101, SX1268, etc.]
|
||||
- Arduino IDE version [e.g. 1.8.5]
|
||||
- Library version [e.g. 3.0.0]
|
||||
15
lib/RadioLib/.github/ISSUE_TEMPLATE/regular-issue.md
vendored
Normal file
15
lib/RadioLib/.github/ISSUE_TEMPLATE/regular-issue.md
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
name: Regular issue
|
||||
about: Use this template for any other issue
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**IMPORTANT: Before submitting an issue, please check the following:**
|
||||
1. **Read [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)!** Issues that do not follow this document will be closed/locked/deleted/ignored.
|
||||
2. RadioLib has a [Wiki](https://github.com/jgromes/RadioLib/wiki) and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
3. Make sure you're using the latest release of the library! Releases can be found [here](https://github.com/jgromes/RadioLib/releases).
|
||||
4. Use [Arduino forums](https://forum.arduino.cc/) to ask generic questions about wireless modules, wiring, usage, etc. Only create issues for problems specific to RadioLib!
|
||||
5. Error codes, their meaning and how to fix them can be found on [this page](https://jgromes.github.io/RadioLib/group__status__codes.html).
|
||||
66
lib/RadioLib/.github/workflows/codeql-analysis.yml
vendored
Normal file
66
lib/RadioLib/.github/workflows/codeql-analysis.yml
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ['cpp']
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Install arduino-cli
|
||||
run:
|
||||
|
|
||||
mkdir -p ~/.local/bin
|
||||
echo "~/.local/bin" >> $GITHUB_PATH
|
||||
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/.local/bin sh
|
||||
|
||||
- name: Install platform
|
||||
run:
|
||||
|
|
||||
arduino-cli core update-index
|
||||
arduino-cli core install arduino:avr
|
||||
|
||||
- name: Static link
|
||||
run:
|
||||
|
|
||||
# static link fix from https://github.com/github/securitylab/discussions/171
|
||||
for i in ~/.arduino*/packages/arduino/tools/avr-gcc/*/bin/*; do
|
||||
mv "$i" "$i.real";
|
||||
printf '#!/bin/bash\nexec "'"$i"'.real" ${1+"$@"}\n' > "$i";
|
||||
chmod +x "$i";
|
||||
done
|
||||
|
||||
- name: Build example
|
||||
run:
|
||||
arduino-cli compile --libraries /home/runner/work/RadioLib --fqbn arduino:avr:uno $PWD/examples/SX126x/SX126x_Transmit/SX126x_Transmit.ino --warnings=all
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
26
lib/RadioLib/.github/workflows/doxygen.yml
vendored
Normal file
26
lib/RadioLib/.github/workflows/doxygen.yml
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
name: Doxygen
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
doxygen:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Doxygen
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y doxygen
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Generate docs
|
||||
run: doxygen Doxyfile
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: JamesIves/github-pages-deploy-action@releases/v3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BRANCH: gh-pages
|
||||
FOLDER: docs/html
|
||||
208
lib/RadioLib/.github/workflows/main.yml
vendored
Normal file
208
lib/RadioLib/.github/workflows/main.yml
vendored
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
id:
|
||||
description: The ID of the platform on which the build is run
|
||||
required: true
|
||||
default: arduino:avr:uno
|
||||
type: choice
|
||||
options:
|
||||
- all
|
||||
- arduino:avr:uno
|
||||
- arduino:avr:mega
|
||||
- arduino:avr:leonardo
|
||||
- arduino:mbed:nano33ble
|
||||
- arduino:mbed:envie_m4
|
||||
- arduino:megaavr:uno2018
|
||||
- arduino:sam:arduino_due_x
|
||||
- arduino:samd:arduino_zero_native
|
||||
- adafruit:samd:adafruit_feather_m0
|
||||
- adafruit:nrf52:feather52832
|
||||
- esp32:esp32:esp32
|
||||
- esp8266:esp8266:generic
|
||||
- Intel:arc32:arduino_101
|
||||
- SparkFun:apollo3:sfe_artemis
|
||||
- STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC
|
||||
- STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1
|
||||
- stm32duino:STM32F1:mapleMini
|
||||
- MegaCoreX:megaavr:4809
|
||||
- arduino:mbed_rp2040:pico
|
||||
- rp2040:rp2040:rpipico
|
||||
- CubeCell:CubeCell:CubeCell-Board
|
||||
- MegaCore:avr:1281
|
||||
- teensy:avr:teensy41
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
# platform-dependent settings - extra board options, board index URLs, skip patterns etc.
|
||||
include:
|
||||
- id: arduino:avr:uno
|
||||
run: echo "skip-pattern=(STM32WL|SSTV)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:avr:mega
|
||||
run: echo "options=':cpu=atmega2560'" >> $GITHUB_OUTPUT
|
||||
- id: arduino:avr:leonardo
|
||||
- id: arduino:mbed:nano33ble
|
||||
- id: arduino:mbed:envie_m4
|
||||
- id: arduino:megaavr:uno2018
|
||||
run: echo "options=':mode=on'" >> $GITHUB_OUTPUT
|
||||
- id: arduino:sam:arduino_due_x
|
||||
- id: arduino:samd:arduino_zero_native
|
||||
- id: adafruit:samd:adafruit_feather_m0
|
||||
run: |
|
||||
echo "options=':usbstack=arduino,debug=off'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://adafruit.github.io/arduino-board-index/package_adafruit_index.json" >> $GITHUB_OUTPUT
|
||||
- id: adafruit:nrf52:feather52832
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y python3 python3-pip python3-setuptools
|
||||
pip3 install wheel
|
||||
pip3 install --user adafruit-nrfutil
|
||||
echo "/home/runner/.local/bin" >> $GITHUB_PATH
|
||||
echo "options=':softdevice=s132v6,debug=l0'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://adafruit.github.io/arduino-board-index/package_adafruit_index.json" >> $GITHUB_OUTPUT
|
||||
- id: esp32:esp32:esp32
|
||||
run:
|
||||
python -m pip install pyserial
|
||||
echo "index-url=--additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json" >> $GITHUB_OUTPUT
|
||||
- id: esp8266:esp8266:generic
|
||||
run: |
|
||||
echo "options=':xtal=80,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=512K'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls http://arduino.esp8266.com/stable/package_esp8266com_index.json" >> $GITHUB_OUTPUT
|
||||
- id: Intel:arc32:arduino_101
|
||||
- id: SparkFun:apollo3:sfe_artemis
|
||||
run: |
|
||||
echo "warnings='none'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://raw.githubusercontent.com/sparkfun/Arduino_Apollo3/master/package_sparkfun_apollo3_index.json" >> $GITHUB_OUTPUT
|
||||
- id: STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC
|
||||
run: echo "index-url=--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json" >> $GITHUB_OUTPUT
|
||||
- id: STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1
|
||||
run: |
|
||||
# Do *not* skip STM32WL examples
|
||||
echo "skip-pattern=''" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json" >> $GITHUB_OUTPUT
|
||||
- id: stm32duino:STM32F1:mapleMini
|
||||
run: |
|
||||
echo "options=':bootloader_version=original,cpu_speed=speed_72mhz'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls http://dan.drown.org/stm32duino/package_STM32duino_index.json" >> $GITHUB_OUTPUT
|
||||
- id: MegaCoreX:megaavr:4809
|
||||
run: echo "index-url=--additional-urls https://mcudude.github.io/MegaCoreX/package_MCUdude_MegaCoreX_index.json" >> $GITHUB_OUTPUT
|
||||
- id: arduino:mbed_rp2040:pico
|
||||
- id: rp2040:rp2040:rpipico
|
||||
run: echo "index-url=--additional-urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json" >> $GITHUB_OUTPUT
|
||||
- id: CubeCell:CubeCell:CubeCell-Board
|
||||
run: echo "index-url=--additional-urls https://resource.heltec.cn/download/package_CubeCell_index.json" >> $GITHUB_OUTPUT
|
||||
- id: MegaCore:avr:1281
|
||||
run: echo "index-url=--additional-urls https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json" >> $GITHUB_OUTPUT
|
||||
- id: teensy:avr:teensy41
|
||||
run: echo "index-url=--additional-urls https://www.pjrc.com/teensy/td_156/package_teensy_index.json" >> $GITHUB_OUTPUT
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
name: ${{ matrix.id }}
|
||||
env:
|
||||
run-build: ${{ (matrix.id == 'arduino:avr:uno') || contains(github.event.head_commit.message, 'CI_BUILD_ALL') || contains(github.event.head_commit.message, 'Bump version to') || contains(github.event.head_commit.message, format('{0}', matrix.id)) || inputs.id == 'all' || inputs.id == matrix.id }}
|
||||
|
||||
steps:
|
||||
- name: Install arduino-cli
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
run:
|
||||
|
|
||||
mkdir -p ~/.local/bin
|
||||
echo "~/.local/bin" >> $GITHUB_PATH
|
||||
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/.local/bin sh
|
||||
|
||||
- name: Get platform name
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
uses: jungwinter/split@v1
|
||||
id: split
|
||||
with:
|
||||
msg: ${{ matrix.id }}
|
||||
seperator: ':'
|
||||
|
||||
- name: Prepare platform-specific settings
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
id: prep
|
||||
run:
|
||||
|
|
||||
# common settings - no extra options, skip STM32WL examples, all warnings
|
||||
echo "options=''" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=STM32WL" >> $GITHUB_OUTPUT
|
||||
echo "warnings=all" >> $GITHUB_OUTPUT
|
||||
|
||||
# run platform-dependent scripts defined in matrix
|
||||
${{ matrix.run }}
|
||||
|
||||
- name: Install platform
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
run:
|
||||
|
|
||||
arduino-cli core update-index ${{ format('{0}', steps.prep.outputs.index-url) }}
|
||||
arduino-cli core install ${{ format('{0}:{1} {2}', steps.split.outputs._0, steps.split.outputs._1, steps.prep.outputs.index-url) }}
|
||||
|
||||
- name: Checkout repository
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build examples
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
run:
|
||||
|
|
||||
for example in $(find $PWD/examples -name '*.ino' | sort); do
|
||||
# check whether to skip this sketch
|
||||
if [ ! -z '${{ steps.prep.outputs.skip-pattern }}' ] && [[ ${example} =~ ${{ steps.prep.outputs.skip-pattern }} ]]; then
|
||||
# skip sketch
|
||||
echo -e "\n\033[1;33mSkipped ${example##*/} (matched with ${{ steps.prep.outputs.skip-pattern }})\033[0m";
|
||||
else
|
||||
# build sketch
|
||||
echo -e "\n\033[1;33mBuilding ${example##*/} ... \033[0m";
|
||||
arduino-cli compile --libraries /home/runner/work/RadioLib --fqbn ${{ matrix.id }}${{ steps.prep.outputs.options }} $example --warnings=${{ steps.prep.outputs.warnings }}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "\033[1;31m${example##*/} build FAILED\033[0m\n";
|
||||
exit 1;
|
||||
else
|
||||
echo -e "\033[1;32m${example##*/} build PASSED\033[0m\n";
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
rpi-build:
|
||||
runs-on: [self-hosted, ARM64]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y pigpio cmake
|
||||
|
||||
- name: Install the library
|
||||
run: |
|
||||
cd $PWD
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
sudo make install
|
||||
|
||||
- name: Build the example
|
||||
run: |
|
||||
cd $PWD/examples/NonArduino/Raspberry
|
||||
./build.sh
|
||||
|
||||
rpi-test:
|
||||
needs: rpi-build
|
||||
runs-on: [self-hosted, ARM64]
|
||||
steps:
|
||||
- name: SX126x test
|
||||
run: |
|
||||
cd $PWD/extras/test/SX126x
|
||||
./clean.sh
|
||||
./build.sh
|
||||
sudo ./build/rpi-sx1261
|
||||
26
lib/RadioLib/CMakeLists.txt
Normal file
26
lib/RadioLib/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
project(radiolib)
|
||||
|
||||
file(GLOB_RECURSE RADIOLIB_SOURCES
|
||||
"src/*.cpp"
|
||||
)
|
||||
|
||||
add_library(RadioLib ${RADIOLIB_SOURCES})
|
||||
|
||||
target_include_directories(RadioLib
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS RadioLib
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/RadioLib
|
||||
FILES_MATCHING PATTERN "*.h"
|
||||
)
|
||||
|
||||
|
|
@ -2172,7 +2172,8 @@ INCLUDE_FILE_PATTERNS =
|
|||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED = protected=private
|
||||
PREDEFINED = protected=private \
|
||||
DOXYGEN
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# RadioLib 
|
||||
# RadioLib  [](https://registry.platformio.org/libraries/jgromes/RadioLib)
|
||||
|
||||
### _One radio library to rule them all!_
|
||||
|
||||
|
|
@ -9,6 +9,8 @@
|
|||
RadioLib allows its users to integrate all sorts of different wireless communication modules, protocols and even digital modes into a single consistent system.
|
||||
Want to add a Bluetooth interface to your LoRa network? Sure thing! Do you just want to go really old-school and play around with radio teletype, slow-scan TV, or even Hellschreiber using nothing but a cheap radio module? Why not!
|
||||
|
||||
RadioLib natively supports Arduino, but can run in non-Arduino environments as well! See [this Wiki page](https://github.com/jgromes/RadioLib/wiki/Porting-to-non-Arduino-Platforms) and [examples/NonArduino](https://github.com/jgromes/RadioLib/tree/master/examples/NonArduino).
|
||||
|
||||
RadioLib was originally created as a driver for [__RadioShield__](https://github.com/jgromes/RadioShield), but it can be used to control as many different wireless modules as you like - or at least as many as your microcontroller can handle!
|
||||
|
||||
### Supported modules:
|
||||
|
|
@ -19,6 +21,7 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
* __RFM2x__ series FSK modules (RFM22, RM23)
|
||||
* __RFM9x__ series LoRa modules (RFM95, RM96, RFM97, RFM98)
|
||||
* __Si443x__ series FSK modules (Si4430, Si4431, Si4432)
|
||||
* __STM32WL__ integrated microcontroller/LoRa module
|
||||
* __SX126x__ series LoRa modules (SX1261, SX1262, SX1268)
|
||||
* __SX127x__ series LoRa modules (SX1272, SX1273, SX1276, SX1277, SX1278, SX1279)
|
||||
* __SX128x__ series LoRa/GFSK/BLE/FLRC modules (SX1280, SX1281, SX1282)
|
||||
|
|
@ -71,7 +74,8 @@ SX127x, RFM9x, RF69, SX1231, CC1101, nRF24L01, RFM2x and Si443x
|
|||
* [__MegaCore__](https://github.com/MCUdude/MegaCore) - AVR (ATmega1281, ATmega640 etc.)
|
||||
|
||||
* __Raspberry Pi__
|
||||
* [__RP2040__](https://github.com/arduino/ArduinoCore-mbed) - Raspberry Pi Pico and Arduino Nano RP2040 Connect
|
||||
* [__RP2040__ (official core)](https://github.com/arduino/ArduinoCore-mbed) - Raspberry Pi Pico and Arduino Nano RP2040 Connect
|
||||
* [__RP2040__ (unofficial core)](https://github.com/earlephilhower/arduino-pico) - Raspberry Pi Pico/RP2040-based boards
|
||||
* [__Raspberry Pi__](https://github.com/me-no-dev/RasPiArduino) - Arduino framework for RaspberryPI
|
||||
|
||||
* __Heltec__
|
||||
|
|
@ -80,7 +84,7 @@ SX127x, RFM9x, RF69, SX1231, CC1101, nRF24L01, RFM2x and Si443x
|
|||
* __PJRC__
|
||||
* [__Teensy__](https://github.com/PaulStoffregen/cores) - Teensy 2.x, 3.x and 4.x boards
|
||||
|
||||
The list above is by no means exhaustive - RadioLib code is independent of the used platform! Compilation of all examples is tested for all platforms officially supported prior to releasing new version.
|
||||
The list above is by no means exhaustive - RadioLib code is independent of the used platform! Compilation of all examples is tested for all platforms officially supported prior to releasing new version. In addition, RadioLib includes an internal hardware abstracton layer, which allows it to be easily ported even to non-Arduino encironments.
|
||||
|
||||
### In development:
|
||||
* __AX5243__ FSK module
|
||||
|
|
@ -92,6 +96,9 @@ The list above is by no means exhaustive - RadioLib code is independent of the u
|
|||
### Where should I start?
|
||||
First of all, take a look at the [examples](https://github.com/jgromes/RadioLib/tree/master/examples) and the [Wiki](https://github.com/jgromes/RadioLib/wiki) - especially the [Basics](https://github.com/jgromes/RadioLib/wiki/Basics) page. There's a lot of useful information over there. If something isn't working as expected, try searching the [issues](https://github.com/jgromes/RadioLib/issues/).
|
||||
|
||||
### Does RadioLib require Arduino?
|
||||
While RadioLib was originally written with Arduino in mind, it has since evolved and contains its own lightweight hardware abstraction layer. Thanks to this layer, RadioLib can be used on non-Arduino frameworks as well. See [this Wiki page](https://github.com/jgromes/RadioLib/wiki/Porting-to-non-Arduino-Platforms) for details.
|
||||
|
||||
### Help, my module isn't working!
|
||||
The fastest way to get help is by creating an [issue](https://github.com/jgromes/RadioLib/issues/new/choose) using the appropriate template. It is also highly recommended to try running the examples first - their functionality is tested from time to time and they should work. Finally, RadioLib is still under development, which means that sometimes, backwards-incompatible changes might be introduced. Though these are kept at minimum, sometimes it is unavoidable. You can check the [release changelog](https://github.com/jgromes/RadioLib/releases) to find out if there's been such a major change recently.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
RadioLib AFSK External Radio example
|
||||
|
||||
This example shows how to use your Arduino
|
||||
as modulator for an external analogue FM radio.
|
||||
|
||||
The example sends APRS position reports with
|
||||
audio modulated as AFSK at 1200 baud using
|
||||
Bell 202 tones. However, any other AFSK
|
||||
protocol (RTTY, SSTV, etc.) may be used as well.
|
||||
|
||||
DO NOT transmit in APRS bands unless
|
||||
you have a ham radio license!
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// create a dummy radio module
|
||||
ExternalRadio radio;
|
||||
|
||||
// create AFSK client instance using the external radio
|
||||
// pin 5 is connected to the radio sound input
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create AX.25 client instance using the AFSK instance
|
||||
AX25Client ax25(&audio);
|
||||
|
||||
// create APRS client instance using the AX.25 client
|
||||
APRSClient aprs(&ax25);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize AX.25 client
|
||||
Serial.print(F("[AX.25] Initializing ... "));
|
||||
// source station callsign: "N7LEM"
|
||||
// source station SSID: 0
|
||||
// preamble length: 8 bytes
|
||||
int16_t state = ax25.begin("N7LEM");
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// initialize APRS client
|
||||
Serial.print(F("[APRS] Initializing ... "));
|
||||
// symbol: '>' (car)
|
||||
state = aprs.begin('>');
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[APRS] Sending position ... "));
|
||||
|
||||
// send a location without message or timestamp
|
||||
int state = aprs.sendPosition("N0CALL", 0, "4911.67N", "01635.96E");
|
||||
delay(500);
|
||||
|
||||
// send a location with message and without timestamp
|
||||
state |= aprs.sendPosition("N0CALL", 0, "4911.67N", "01635.96E", "I'm here!");
|
||||
delay(500);
|
||||
|
||||
// send a location with message and timestamp
|
||||
state |= aprs.sendPosition("N0CALL", 0, "4911.67N", "01635.96E", "I'm here!", "093045z");
|
||||
delay(500);
|
||||
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// wait one minute before transmitting again
|
||||
delay(60000);
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
- SX1231
|
||||
- CC1101
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -38,6 +39,7 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
void setup() {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
- SX1231
|
||||
- CC1101
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -36,6 +37,7 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
void setup() {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
- CC1101
|
||||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -39,7 +40,14 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create AX.25 client instance using the AFSK instance
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
- CC1101
|
||||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -39,7 +40,14 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create AX.25 client instance using the AFSK instance
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
- CC1101
|
||||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -36,7 +37,14 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create AX.25 client instance using the AFSK instance
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
RadioLib Bell Modem Transmit Example
|
||||
|
||||
This example shows how to transmit binary data
|
||||
using audio Bell 202 tones.
|
||||
|
||||
Other implemented Bell modems
|
||||
- Bell 101
|
||||
- Bell 103
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// create Bell modem instance using the FSK module
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2 (only devices without TCXO!)
|
||||
BellClient bell(&radio, 5);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1278 with default settings
|
||||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
int state = radio.beginFSK();
|
||||
|
||||
// when using one of the non-LoRa modules for AFSK
|
||||
// (RF69, CC1101, Si4432 etc.), use the basic begin() method
|
||||
// int state = radio.begin();
|
||||
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// initialize Bell 202 modem
|
||||
Serial.print(F("[Bell 202] Initializing ... "));
|
||||
state = bell.begin(Bell202);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[Bell 202] Sending data ... "));
|
||||
|
||||
// send out idle condition for 500 ms
|
||||
bell.idle();
|
||||
delay(500);
|
||||
|
||||
// BellClient supports all methods of the Serial class
|
||||
|
||||
// Arduino String class
|
||||
String aStr = "Arduino String";
|
||||
bell.println(aStr);
|
||||
|
||||
// character array (C-String)
|
||||
bell.println("C-String");
|
||||
|
||||
// string saved in flash
|
||||
bell.println(F("Flash String"));
|
||||
|
||||
// character
|
||||
bell.println('c');
|
||||
|
||||
// byte
|
||||
// formatting DEC/HEX/OCT/BIN is supported for
|
||||
// any integer type (byte/int/long)
|
||||
bell.println(255, HEX);
|
||||
|
||||
// integer number
|
||||
int i = 1000;
|
||||
bell.println(i);
|
||||
|
||||
// floating point number
|
||||
float f = -3.1415;
|
||||
bell.println(f, 3);
|
||||
|
||||
// ITA2-encoded string
|
||||
ITA2String str("HELLO WORLD!");
|
||||
bell.print(str);
|
||||
|
||||
// turn the transmitter off
|
||||
bell.standby();
|
||||
|
||||
Serial.println(F("done!"));
|
||||
|
||||
// wait for a second before transmitting again
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ void setup() {
|
|||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setGdo0Action(setFlag);
|
||||
radio.setGdo0Action(setFlag, RISING);
|
||||
|
||||
// start listening for packets
|
||||
Serial.print(F("[CC1101] Starting to listen ... "));
|
||||
|
|
@ -75,9 +75,6 @@ void setup() {
|
|||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -86,11 +83,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
|
@ -98,10 +90,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
|
|
@ -147,10 +135,6 @@ void loop() {
|
|||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ void setup() {
|
|||
// NOTE: Unlike other modules (such as SX127x),
|
||||
// different GDOx pins are used for
|
||||
// transmit and receive interrupts!
|
||||
radio.setGdo2Action(setFlag);
|
||||
radio.setGdo2Action(setFlag, FALLING);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[CC1101] Sending first packet ... "));
|
||||
|
|
@ -71,9 +71,6 @@ void setup() {
|
|||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -82,11 +79,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
|
@ -94,10 +86,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -136,9 +124,5 @@ void loop() {
|
|||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
- SX1231
|
||||
- CC1101
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -36,7 +37,14 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create FSK4 client instance using the AFSK instance
|
||||
|
|
@ -81,7 +89,7 @@ void setup() {
|
|||
// NOTE: Unlike FSK FSK4, AFSK requires no rounding of
|
||||
// the frequency shift.
|
||||
Serial.print(F("[FSK4] Initializing ... "));
|
||||
// low ("space") frequency: 434.0 MHz
|
||||
// lowest ("space") frequency: 400 Hz
|
||||
// frequency shift: 270 Hz
|
||||
// baud rate: 100 baud
|
||||
state = fsk4.begin(400, 270, 100);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
- SX1231
|
||||
- CC1101
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -35,7 +36,14 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create Hellschreiber client instance using the AFSK instance
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
- SX1231
|
||||
- CC1101
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -35,8 +36,15 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
AFSKClient audio(&radio, 10);
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create Morse client instance using the AFSK instance
|
||||
MorseClient morse(&audio);
|
||||
|
|
@ -72,17 +80,6 @@ void setup() {
|
|||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// after that, set mode to OOK
|
||||
Serial.print(F("[SX1278] Switching to OOK ... "));
|
||||
state = radio.setOOK(true);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
|
|||
21
lib/RadioLib/examples/NonArduino/Raspberry/CMakeLists.txt
Normal file
21
lib/RadioLib/examples/NonArduino/Raspberry/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
# create the project
|
||||
project(rpi-sx1261)
|
||||
|
||||
# when using debuggers such as gdb, the following line can be used
|
||||
#set(CMAKE_BUILD_TYPE Debug)
|
||||
|
||||
# if you did not build RadioLib as shared library (see README),
|
||||
# you will have to add it as source directory
|
||||
# the following is just an example, yours will likely be different
|
||||
#add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../RadioLib" "${CMAKE_CURRENT_BINARY_DIR}/RadioLib")
|
||||
|
||||
# add the executable
|
||||
add_executable(${PROJECT_NAME} main.cpp)
|
||||
|
||||
# link both libraries
|
||||
target_link_libraries(${PROJECT_NAME} RadioLib pigpio)
|
||||
|
||||
# you can also specify RadioLib compile-time flags here
|
||||
#target_compile_definitions(${PROJECT_NAME} PUBLIC RADIOLIB_DEBUG RADIOLIB_VERBOSE)
|
||||
153
lib/RadioLib/examples/NonArduino/Raspberry/PiHal.h
Normal file
153
lib/RadioLib/examples/NonArduino/Raspberry/PiHal.h
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#ifndef PI_HAL_H
|
||||
#define PI_HAL_H
|
||||
|
||||
// include RadioLib
|
||||
#include <RadioLib/RadioLib.h>
|
||||
|
||||
// include the library for Raspberry GPIO pins
|
||||
#include "pigpio.h"
|
||||
|
||||
// create a new Raspberry Pi hardware abstraction layer
|
||||
// using the pigpio library
|
||||
// the HAL must inherit from the base RadioLibHal class
|
||||
// and implement all of its virtual methods
|
||||
class PiHal : public RadioLibHal {
|
||||
public:
|
||||
// default constructor - initializes the base HAL and any needed private members
|
||||
PiHal(uint8_t spiChannel, uint32_t spiSpeed = 2000000)
|
||||
: RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, RISING_EDGE, FALLING_EDGE),
|
||||
_spiChannel(spiChannel),
|
||||
_spiSpeed(spiSpeed) {
|
||||
}
|
||||
|
||||
void init() override {
|
||||
// first initialise pigpio library
|
||||
gpioInitialise();
|
||||
|
||||
// now the SPI
|
||||
spiBegin();
|
||||
|
||||
// Waveshare LoRaWAN Hat also needs pin 18 to be pulled high to enable the radio
|
||||
gpioSetMode(18, PI_OUTPUT);
|
||||
gpioWrite(18, PI_HIGH);
|
||||
}
|
||||
|
||||
void term() override {
|
||||
// stop the SPI
|
||||
spiEnd();
|
||||
|
||||
// pull the enable pin low
|
||||
gpioSetMode(18, PI_OUTPUT);
|
||||
gpioWrite(18, PI_LOW);
|
||||
|
||||
// finally, stop the pigpio library
|
||||
gpioTerminate();
|
||||
}
|
||||
|
||||
// GPIO-related methods (pinMode, digitalWrite etc.) should check
|
||||
// RADIOLIB_NC as an alias for non-connected pins
|
||||
void pinMode(uint32_t pin, uint32_t mode) override {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetMode(pin, mode);
|
||||
}
|
||||
|
||||
void digitalWrite(uint32_t pin, uint32_t value) override {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioWrite(pin, value);
|
||||
}
|
||||
|
||||
uint32_t digitalRead(uint32_t pin) override {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(gpioRead(pin));
|
||||
}
|
||||
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetISRFunc(interruptNum, mode, 0, (gpioISRFunc_t)interruptCb);
|
||||
}
|
||||
|
||||
void detachInterrupt(uint32_t interruptNum) override {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetISRFunc(interruptNum, 0, 0, NULL);
|
||||
}
|
||||
|
||||
void delay(unsigned long ms) override {
|
||||
gpioDelay(ms * 1000);
|
||||
}
|
||||
|
||||
void delayMicroseconds(unsigned long us) override {
|
||||
gpioDelay(us);
|
||||
}
|
||||
|
||||
unsigned long millis() override {
|
||||
return(gpioTick() / 1000);
|
||||
}
|
||||
|
||||
unsigned long micros() override {
|
||||
return(gpioTick());
|
||||
}
|
||||
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
gpioSetMode(pin, PI_INPUT);
|
||||
uint32_t start = gpioTick();
|
||||
uint32_t curtick = gpioTick();
|
||||
|
||||
while(gpioRead(pin) == state) {
|
||||
if((gpioTick() - curtick) > timeout) {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
return(gpioTick() - start);
|
||||
}
|
||||
|
||||
void spiBegin() {
|
||||
if(_spiHandle < 0) {
|
||||
_spiHandle = spiOpen(_spiChannel, _spiSpeed, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void spiBeginTransaction() {}
|
||||
|
||||
uint8_t spiTransfer(uint8_t b) {
|
||||
char ret;
|
||||
spiXfer(_spiHandle, (char*)&b, &ret, 1);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void spiEndTransaction() {}
|
||||
|
||||
void spiEnd() {
|
||||
if(_spiHandle >= 0) {
|
||||
spiClose(_spiHandle);
|
||||
_spiHandle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// the HAL can contain any additional private members
|
||||
const unsigned int _spiSpeed;
|
||||
const uint8_t _spiChannel;
|
||||
int _spiHandle = -1;
|
||||
};
|
||||
|
||||
#endif
|
||||
8
lib/RadioLib/examples/NonArduino/Raspberry/build.sh
Normal file
8
lib/RadioLib/examples/NonArduino/Raspberry/build.sh
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -G "CodeBlocks - Unix Makefiles" ..
|
||||
make -j4
|
||||
cd ..
|
||||
3
lib/RadioLib/examples/NonArduino/Raspberry/clean.sh
Normal file
3
lib/RadioLib/examples/NonArduino/Raspberry/clean.sh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -rf ./build
|
||||
66
lib/RadioLib/examples/NonArduino/Raspberry/main.cpp
Normal file
66
lib/RadioLib/examples/NonArduino/Raspberry/main.cpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
RadioLib Non-Arduino Raspberry Pi Example
|
||||
|
||||
This example shows how to use RadioLib without Arduino.
|
||||
In this case, a Raspberry Pi with WaveShare SX1302 LoRaWAN Hat
|
||||
using the pigpio library.
|
||||
|
||||
Can be used as a starting point to port RadioLib to any platform!
|
||||
See this API reference page for details on the RadioLib hardware abstraction
|
||||
https://jgromes.github.io/RadioLib/class_hal.html
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib/RadioLib.h>
|
||||
|
||||
// include the hardware abstraction layer
|
||||
#include "PiHal.h"
|
||||
|
||||
// create a new instance of the HAL class
|
||||
// use SPI channel 1, because on Waveshare LoRaWAN Hat,
|
||||
// the SX1261 CS is connected to CE1
|
||||
PiHal* hal = new PiHal(1);
|
||||
|
||||
// now we can create the radio module
|
||||
// pinout corresponds to the Waveshare LoRaWAN Hat
|
||||
// NSS pin: 7
|
||||
// DIO1 pin: 17
|
||||
// NRST pin: 22
|
||||
// BUSY pin: 4
|
||||
SX1261 radio = new Module(hal, 7, 17, 22, 4);
|
||||
|
||||
// the entry point for the program
|
||||
int main(int argc, char** argv) {
|
||||
// initialize just like with Arduino
|
||||
printf("[SX1261] Initializing ... ");
|
||||
int state = radio.begin();
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
printf("failed, code %d\n", state);
|
||||
return(1);
|
||||
}
|
||||
printf("success!\n");
|
||||
|
||||
// loop forever
|
||||
for(;;) {
|
||||
// send a packet
|
||||
printf("[SX1261] Transmitting packet ... ");
|
||||
state = radio.transmit("Hello World!");
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
printf("success!");
|
||||
|
||||
// wait for a second before transmitting again
|
||||
hal->delay(1000);
|
||||
|
||||
} else {
|
||||
printf("failed, code %d\n", state);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -31,7 +31,15 @@
|
|||
// DIO1 pin: 3
|
||||
SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// DIO2 pin: 5
|
||||
// receiving packets requires connection
|
||||
// to the module direct output pin,
|
||||
// here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
const int pin = 5;
|
||||
|
||||
// create Pager client instance using the FSK module
|
||||
|
|
|
|||
|
|
@ -67,9 +67,6 @@ void setup() {
|
|||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -78,11 +75,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
|
@ -90,10 +82,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
|
|
@ -134,10 +122,5 @@ void loop() {
|
|||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,9 +84,6 @@ void setup() {
|
|||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -95,11 +92,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
|
@ -107,10 +99,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -149,9 +137,5 @@ void loop() {
|
|||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
- SX1231
|
||||
- CC1101
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
@ -33,7 +34,14 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create RTTY client instance using the AFSK instance
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
- SX1231
|
||||
- CC1101
|
||||
- Si443x/RFM2x
|
||||
- SX126x/LLCC68 (only devices without TCXO!)
|
||||
|
||||
NOTE: Some platforms (such as Arduino Uno)
|
||||
might not be fast enough to correctly
|
||||
|
|
@ -42,7 +43,14 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
//SX1278 radio = RadioShield.ModuleA;
|
||||
|
||||
// create AFSK client instance using the FSK module
|
||||
// pin 5 is connected to SX1278 DIO2
|
||||
// this requires connection to the module direct
|
||||
// input pin, here connected to Arduino pin 5
|
||||
// SX127x/RFM9x: DIO2
|
||||
// RF69: DIO2
|
||||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
AFSKClient audio(&radio, 5);
|
||||
|
||||
// create SSTV client instance using the AFSK instance
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
RadioLib STM32WLx Channel Activity Detection Example
|
||||
|
||||
This example uses STM32WLx to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, SX126x/STM32WLx can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// no need to configure pins, signals are routed to the radio internally
|
||||
STM32WLx radio = new STM32WLx_Module();
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize STM32WLx with default settings
|
||||
Serial.print(F("[STM32WLx] Initializing ... "));
|
||||
int state = radio.begin(868.0);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[STM32WLx] Scanning channel for LoRa transmission ... "));
|
||||
|
||||
// start scanning current channel
|
||||
int state = radio.scanChannel();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa preamble was detected
|
||||
Serial.println(F("detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// no preamble was detected, channel is free
|
||||
Serial.println(F("channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait 100 ms before new scan
|
||||
delay(100);
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
RadioLib STM32WLx Channel Activity Detection Example
|
||||
|
||||
This example uses STM32WLx to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, SX126x/STM32WLx can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// no need to configure pins, signals are routed to the radio internally
|
||||
STM32WLx radio = new STM32WLx_Module();
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize STM32WLx with default settings
|
||||
Serial.print(F("[STM32WLx] Initializing ... "));
|
||||
int state = radio.begin(868.0);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa packet or timeout is detected
|
||||
radio.setDio1Action(setFlag);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[STM32WLx] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was detected or CAD timed out
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
void setFlag(void) {
|
||||
// something happened, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// check CAD result
|
||||
int state = radio.getChannelScanResult();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa packet was detected
|
||||
Serial.println(F("[STM32WLx] Packet detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// channel is free
|
||||
Serial.println(F("[STM32WLx] Channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("[STM32WLx] Failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// start scanning the channel again
|
||||
Serial.print(F("[STM32WLx] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
RadioLib STM32WLx Receive Example
|
||||
|
||||
This example listens for LoRa transmissions using STM32WL MCU with
|
||||
integrated (SX126x) LoRa radio.
|
||||
|
||||
To successfully receive data, the following settings have to be the same
|
||||
on both transmitter and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
- preamble length
|
||||
|
||||
This example assumes Nucleo WL55JC1 is used. For other Nucleo boards
|
||||
or standalone STM32WL, some configuration such as TCXO voltage and
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// no need to configure pins, signals are routed to the radio internally
|
||||
STM32WLx radio = new STM32WLx_Module();
|
||||
|
||||
// set RF switch configuration for Nucleo WL55JC1
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||
|
||||
// initialize STM32WL with default settings, except frequency
|
||||
Serial.print(F("[STM32WL] Initializing ... "));
|
||||
int state = radio.begin(868.0);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||
state = radio.setTCXO(1.7);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[STM32WL] Waiting for incoming transmission ... "));
|
||||
|
||||
// you can receive data as an Arduino String
|
||||
// NOTE: receive() is a blocking method!
|
||||
// See example ReceiveInterrupt for details
|
||||
// on non-blocking reception method.
|
||||
String str;
|
||||
int state = radio.receive(str);
|
||||
|
||||
// you can also receive data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the data of the packet
|
||||
Serial.print(F("[STM32WL] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print the RSSI (Received Signal Strength Indicator)
|
||||
// of the last received packet
|
||||
Serial.print(F("[STM32WL] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print the SNR (Signal-to-Noise Ratio)
|
||||
// of the last received packet
|
||||
Serial.print(F("[STM32WL] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
// timeout occurred while waiting for a packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
RadioLib STM32WLx Receive with Interrupts Example
|
||||
|
||||
This example listens for LoRa transmissions and tries to
|
||||
receive them. Once a packet is received, an interrupt is
|
||||
triggered. To successfully receive data, the following
|
||||
settings have to be the same on both transmitter
|
||||
and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
|
||||
This example assumes Nucleo WL55JC1 is used. For other Nucleo boards
|
||||
or standalone STM32WL, some configuration such as TCXO voltage and
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// no need to configure pins, signals are routed to the radio internally
|
||||
STM32WLx radio = new STM32WLx_Module();
|
||||
|
||||
// set RF switch configuration for Nucleo WL55JC1
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||
|
||||
// initialize STM32WL with default settings, except frequency
|
||||
Serial.print(F("[STM32WL] Initializing ... "));
|
||||
int state = radio.begin(868.0);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||
state = radio.setTCXO(1.7);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setDio1Action(setFlag);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[STM32WL] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// if needed, 'listen' mode can be disabled by calling
|
||||
// any of the following methods:
|
||||
//
|
||||
// radio.standby()
|
||||
// radio.sleep()
|
||||
// radio.transmit();
|
||||
// radio.receive();
|
||||
// radio.readData();
|
||||
// radio.scanChannel();
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
void setFlag(void) {
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// you can read received data as an Arduino String
|
||||
String str;
|
||||
int state = radio.readData(str);
|
||||
|
||||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.readData(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("[STM32WL] Received packet!"));
|
||||
|
||||
// print data of the packet
|
||||
Serial.print(F("[STM32WL] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[STM32WL] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[STM32WL] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
RadioLib STM32WLx Transmit Example
|
||||
|
||||
This example transmits packets using STM32WL MCU with integrated
|
||||
(SX126x) LoRa radio.
|
||||
|
||||
Each packet contains up to 256 bytes of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
This example assumes Nucleo WL55JC1 is used. For other Nucleo boards
|
||||
or standalone STM32WL, some configuration such as TCXO voltage and
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// no need to configure pins, signals are routed to the radio internally
|
||||
STM32WLx radio = new STM32WLx_Module();
|
||||
|
||||
// set RF switch configuration for Nucleo WL55JC1
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||
|
||||
// initialize STM32WL with default settings, except frequency
|
||||
Serial.print(F("[STM32WL] Initializing ... "));
|
||||
int state = radio.begin(868.0);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||
state = radio.setTCXO(1.7);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[STM32WL] Transmitting packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
// NOTE: transmit() is a blocking method!
|
||||
// See example STM32WLx_Transmit_Interrupt for details
|
||||
// on non-blocking transmission method.
|
||||
int state = radio.transmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print measured data rate
|
||||
Serial.print(F("[STM32WL] Datarate:\t"));
|
||||
Serial.print(radio.getDataRate());
|
||||
Serial.println(F(" bps"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
// timeout occured while transmitting packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait for a second before transmitting again
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
RadioLib STM32WLx Transmit with Interrupts Example
|
||||
|
||||
This example transmits LoRa packets with one second delays
|
||||
between them. Each packet contains up to 256 bytes
|
||||
of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// no need to configure pins, signals are routed to the radio internally
|
||||
STM32WLx radio = new STM32WLx_Module();
|
||||
|
||||
// set RF switch configuration for Nucleo WL55JC1
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
// save transmission state between loops
|
||||
int transmissionState = RADIOLIB_ERR_NONE;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||
|
||||
// initialize STM32WL with default settings, except frequency
|
||||
Serial.print(F("[STM32WL] Initializing ... "));
|
||||
int state = radio.begin(868.0);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||
state = radio.setTCXO(1.7);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when packet transmission is finished
|
||||
radio.setDio1Action(setFlag);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[STM32WL] Sending first packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
void setFlag(void) {
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
if (transmissionState == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
||||
}
|
||||
|
||||
// clean up after transmission is finished
|
||||
// this will ensure transmitter is disabled,
|
||||
// RF switch is powered down etc.
|
||||
radio.finishTransmit();
|
||||
|
||||
// wait a second before transmitting again
|
||||
delay(1000);
|
||||
|
||||
// send another one
|
||||
Serial.print(F("[STM32WL] Sending another packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -64,9 +64,6 @@ void setup() {
|
|||
// flag to indicate that a packet was detected or CAD timed out
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -75,11 +72,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// something happened, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
|
@ -87,10 +79,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
|
|
@ -121,9 +109,5 @@ void loop() {
|
|||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ int transmissionState = RADIOLIB_ERR_NONE;
|
|||
// flag to indicate transmission or reception state
|
||||
bool transmitFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// flag to indicate that a packet was sent or received
|
||||
volatile bool operationDone = false;
|
||||
|
||||
|
|
@ -46,11 +43,6 @@ volatile bool operationDone = false;
|
|||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent or received a packet, set the flag
|
||||
operationDone = true;
|
||||
}
|
||||
|
|
@ -95,10 +87,6 @@ void setup() {
|
|||
void loop() {
|
||||
// check if the previous operation finished
|
||||
if(operationDone) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
operationDone = false;
|
||||
|
||||
|
|
@ -153,10 +141,6 @@ void loop() {
|
|||
transmissionState = radio.startTransmit("Hello World!");
|
||||
transmitFlag = true;
|
||||
}
|
||||
|
||||
// we're ready to process more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,11 @@ void loop() {
|
|||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[SX1262] Frequency error:\t"));
|
||||
Serial.print(radio.getFrequencyError());
|
||||
Serial.println(F(" Hz"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
// timeout occurred while waiting for a packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
|
|
|||
|
|
@ -74,16 +74,12 @@ void setup() {
|
|||
// radio.sleep()
|
||||
// radio.transmit();
|
||||
// radio.receive();
|
||||
// radio.readData();
|
||||
// radio.scanChannel();
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -92,11 +88,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
|
@ -104,10 +95,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
|
|
@ -139,6 +126,11 @@ void loop() {
|
|||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[SX1262] Frequency error:\t"));
|
||||
Serial.print(radio.getFrequencyError());
|
||||
Serial.println(F(" Hz"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
|
@ -149,13 +141,5 @@ void loop() {
|
|||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ void setup() {
|
|||
// sync word: 0x34 (public network/LoRaWAN)
|
||||
// output power: 2 dBm
|
||||
// preamble length: 20 symbols
|
||||
state = radio2.begin(915.0, 500.0, 6, 5, 0x34, 20);
|
||||
state = radio2.begin(915.0, 500.0, 6, 5, 0x34, 2, 20);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
RadioLib SX126x Spectrum Scan Example
|
||||
|
||||
This example shows how to perform a spectrum power scan using SX126x.
|
||||
The output is in the form of scan lines, each line has 33 power bins.
|
||||
First power bin corresponds to -11 dBm, the second to -15 dBm and so on.
|
||||
Higher number of samples in a bin corresponds to more power received
|
||||
at that level.
|
||||
|
||||
To show the results in a plot, run the Python script
|
||||
RadioLib/extras/SX126x_Spectrum_Scan/SpectrumScan.py
|
||||
|
||||
WARNING: This functionality is experimental and requires a binary patch
|
||||
to be uploaded to the SX126x device. There may be some undocumented
|
||||
side effects!
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// this file contains binary patch for the SX1262
|
||||
#include <modules/SX126x/patches/SX126x_patch_scan.h>
|
||||
|
||||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// initialize SX1262 FSK modem with default settings
|
||||
Serial.print(F("[SX1262] Initializing ... "));
|
||||
int state = radio.beginFSK();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// upload a patch to the SX1262 to enable spectral scan
|
||||
// NOTE: this patch is uploaded into volatile memory,
|
||||
// and must be re-uploaded on every power up
|
||||
Serial.print(F("[SX1262] Uploading patch ... "));
|
||||
state = radio.uploadPatch(sx126x_patch_scan, sizeof(sx126x_patch_scan));
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// configure scan bandwidth to 234.4 kHz
|
||||
// and disable the data shaping
|
||||
Serial.print(F("[SX1262] Setting scan parameters ... "));
|
||||
state = radio.setRxBandwidth(234.3);
|
||||
state |= radio.setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[SX1262] Starting spectral scan ... "));
|
||||
|
||||
// start spectral scan
|
||||
// number of scans in each line is 2048
|
||||
// number of samples: 2048 (fewer samples = better temporal resolution)
|
||||
int state = radio.spectralScanStart(2048);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// wait for spectral scan to finish
|
||||
while(radio.spectralScanGetStatus() != RADIOLIB_ERR_NONE) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// read the results
|
||||
uint16_t results[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE];
|
||||
state = radio.spectralScanGetResult(results);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
// we have some results, print it
|
||||
Serial.print("SCAN ");
|
||||
for(uint8_t i = 0; i < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; i++) {
|
||||
Serial.print(results[i]);
|
||||
Serial.print(',');
|
||||
}
|
||||
Serial.println(" END");
|
||||
}
|
||||
|
||||
// wait a little bit before the next scan
|
||||
delay(5);
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
RadioLib SX126x Spectrum Scan Example
|
||||
|
||||
This example shows how to perform a spectrum power scan using SX126x.
|
||||
The output is in the form of scan lines, each line has 33 power bins.
|
||||
First power bin corresponds to -11 dBm, the second to -15 dBm and so on.
|
||||
Higher number of samples in a bin corresponds to more power received
|
||||
at that level. The example performs frequency sweep over a given range.
|
||||
|
||||
To show the results in a plot, run the Python script
|
||||
RadioLib/extras/SX126x_Spectrum_Scan/SpectrumScan.py
|
||||
|
||||
WARNING: This functionality is experimental and requires a binary patch
|
||||
to be uploaded to the SX126x device. There may be some undocumented
|
||||
side effects!
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// this file contains binary patch for the SX1262
|
||||
#include <modules/SX126x/patches/SX126x_patch_scan.h>
|
||||
|
||||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// frequency range in MHz to scan
|
||||
const float freqStart = 431;
|
||||
const float freqEnd = 435;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// initialize SX1262 FSK modem at the initial frequency
|
||||
Serial.print(F("[SX1262] Initializing ... "));
|
||||
int state = radio.beginFSK(freqStart);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// upload a patch to the SX1262 to enable spectral scan
|
||||
// NOTE: this patch is uploaded into volatile memory,
|
||||
// and must be re-uploaded on every power up
|
||||
Serial.print(F("[SX1262] Uploading patch ... "));
|
||||
state = radio.uploadPatch(sx126x_patch_scan, sizeof(sx126x_patch_scan));
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// configure scan bandwidth to 234.4 kHz
|
||||
// and disable the data shaping
|
||||
Serial.print(F("[SX1262] Setting scan parameters ... "));
|
||||
state = radio.setRxBandwidth(234.3);
|
||||
state |= radio.setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// perform scan over the entire frequency range
|
||||
float freq = freqStart;
|
||||
while(freq <= freqEnd) {
|
||||
Serial.print("FREQ ");
|
||||
Serial.println(freq, 2);
|
||||
|
||||
// start spectral scan
|
||||
// number of samples: 2048 (fewer samples = better temporal resolution)
|
||||
Serial.print(F("[SX1262] Starting spectral scan ... "));
|
||||
int state = radio.spectralScanStart(2048);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// wait for spectral scan to finish
|
||||
while(radio.spectralScanGetStatus() != RADIOLIB_ERR_NONE) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// read the results
|
||||
uint16_t results[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE];
|
||||
state = radio.spectralScanGetResult(results);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
// we have some results, print it
|
||||
Serial.print("SCAN ");
|
||||
for(uint8_t i = 0; i < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; i++) {
|
||||
Serial.print(results[i]);
|
||||
Serial.print(',');
|
||||
}
|
||||
Serial.println(" END");
|
||||
}
|
||||
|
||||
// wait a little bit before the next scan
|
||||
delay(5);
|
||||
|
||||
// set the next frequency
|
||||
// the frequency step should be slightly smaller
|
||||
// or the same as the Rx bandwidth set in setup
|
||||
freq += 0.2;
|
||||
radio.setFrequency(freq);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -73,9 +73,6 @@ void setup() {
|
|||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -84,11 +81,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
|
@ -96,10 +88,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -138,9 +126,5 @@ void loop() {
|
|||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@ void setup() {
|
|||
|
||||
// set the function that will be called
|
||||
// when LoRa preamble is not detected within CAD timeout period
|
||||
radio.setDio0Action(setFlagTimeout);
|
||||
radio.setDio0Action(setFlagTimeout, RISING);
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa preamble is detected
|
||||
radio.setDio1Action(setFlagDetected);
|
||||
radio.setDio1Action(setFlagDetected, RISING);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[SX1278] Starting scan for LoRa preamble ... "));
|
||||
|
|
@ -70,9 +70,6 @@ volatile bool timeoutFlag = false;
|
|||
// flag to indicate that a preamble was detected
|
||||
volatile bool detectedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when no preamble
|
||||
// is detected within timeout period
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -81,11 +78,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlagTimeout(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we timed out, set the flag
|
||||
timeoutFlag = true;
|
||||
}
|
||||
|
|
@ -98,11 +90,6 @@ void setFlagTimeout(void) {
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlagDetected(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a preamble, set the flag
|
||||
detectedFlag = true;
|
||||
}
|
||||
|
|
@ -110,10 +97,6 @@ void setFlagDetected(void) {
|
|||
void loop() {
|
||||
// check if we need to restart channel activity detection
|
||||
if(detectedFlag || timeoutFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// check if we got a preamble
|
||||
if(detectedFlag) {
|
||||
// LoRa preamble was detected
|
||||
|
|
@ -138,10 +121,5 @@ void loop() {
|
|||
// reset flags
|
||||
timeoutFlag = false;
|
||||
detectedFlag = false;
|
||||
|
||||
// enable interrupts again
|
||||
enableInterrupt = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ void setup() {
|
|||
// set the function that will be called
|
||||
// when LoRa preamble is not detected within CAD timeout period
|
||||
// or when a packet is received
|
||||
radio.setDio0Action(setFlagTimeout);
|
||||
radio.setDio0Action(setFlagTimeout, RISING);
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa preamble is detected
|
||||
radio.setDio1Action(setFlagDetected);
|
||||
radio.setDio1Action(setFlagDetected, RISING);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[SX1278] Starting scan for LoRa preamble ... "));
|
||||
|
|
@ -76,9 +76,6 @@ volatile bool timeoutFlag = false;
|
|||
// flag to indicate that a preamble was detected
|
||||
volatile bool detectedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// flag to indicate if we are currently receiving
|
||||
bool receiving = false;
|
||||
|
||||
|
|
@ -90,11 +87,6 @@ bool receiving = false;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlagTimeout(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we timed out, set the flag
|
||||
timeoutFlag = true;
|
||||
}
|
||||
|
|
@ -107,11 +99,6 @@ void setFlagTimeout(void) {
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlagDetected(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a preamble, set the flag
|
||||
detectedFlag = true;
|
||||
}
|
||||
|
|
@ -120,10 +107,6 @@ void loop() {
|
|||
// check if we need to restart channel activity detection
|
||||
if(detectedFlag || timeoutFlag) {
|
||||
int state = RADIOLIB_ERR_NONE;
|
||||
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// check ongoing reception
|
||||
if(receiving) {
|
||||
|
|
@ -217,10 +200,5 @@ void loop() {
|
|||
// reset flags
|
||||
timeoutFlag = false;
|
||||
detectedFlag = false;
|
||||
|
||||
// enable interrupts again
|
||||
enableInterrupt = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ int transmissionState = RADIOLIB_ERR_NONE;
|
|||
// flag to indicate transmission or reception state
|
||||
bool transmitFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// flag to indicate that a packet was sent or received
|
||||
volatile bool operationDone = false;
|
||||
|
||||
|
|
@ -43,11 +40,6 @@ volatile bool operationDone = false;
|
|||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent or received packet, set the flag
|
||||
operationDone = true;
|
||||
}
|
||||
|
|
@ -68,7 +60,7 @@ void setup() {
|
|||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setDio0Action(setFlag);
|
||||
radio.setDio0Action(setFlag, RISING);
|
||||
|
||||
#if defined(INITIATING_NODE)
|
||||
// send the first packet on this node
|
||||
|
|
@ -92,10 +84,6 @@ void setup() {
|
|||
void loop() {
|
||||
// check if the previous operation finished
|
||||
if(operationDone) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
operationDone = false;
|
||||
|
||||
|
|
@ -150,10 +138,5 @@ void loop() {
|
|||
transmissionState = radio.startTransmit("Hello World!");
|
||||
transmitFlag = true;
|
||||
}
|
||||
|
||||
// we're ready to process more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@ void setup() {
|
|||
}
|
||||
|
||||
// set the function to call when reception is finished
|
||||
radio.setDio0Action(setRxFlag);
|
||||
radio.setDio0Action(setRxFlag, RISING);
|
||||
|
||||
// set the function to call when we need to change frequency
|
||||
radio.setDio1Action(setFHSSFlag);
|
||||
radio.setDio1Action(setFHSSFlag, RISING);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[SX1278] Starting to listen ... "));
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ void setup() {
|
|||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setDio0Action(setFlag);
|
||||
radio.setDio0Action(setFlag, RISING);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[SX1278] Starting to listen ... "));
|
||||
|
|
@ -71,16 +71,12 @@ void setup() {
|
|||
// radio.sleep()
|
||||
// radio.transmit();
|
||||
// radio.receive();
|
||||
// radio.readData();
|
||||
// radio.scanChannel();
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -89,11 +85,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
|
@ -101,10 +92,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
|
|
@ -151,13 +138,5 @@ void loop() {
|
|||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,11 +68,11 @@ void setup() {
|
|||
// bandwidth: 500.0 kHz
|
||||
// spreading factor: 6
|
||||
// coding rate: 5
|
||||
// sync word: 0x14
|
||||
// sync word: 0x34
|
||||
// output power: 2 dBm
|
||||
// preamble length: 20 symbols
|
||||
// amplifier gain: 1 (maximum gain)
|
||||
state = radio2.begin(915.0, 500.0, 6, 5, 0x14, 2, 20, 1);
|
||||
state = radio2.begin(915.0, 500.0, 6, 5, 0x34, 2, 20, 1);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -108,10 +108,10 @@ void setup() {
|
|||
}
|
||||
|
||||
// set the function to call when transmission is finished
|
||||
radio.setDio0Action(setTxFlag);
|
||||
radio.setDio0Action(setTxFlag, RISING);
|
||||
|
||||
// set the function to call when we need to change frequency
|
||||
radio.setDio1Action(setFHSSFlag);
|
||||
radio.setDio1Action(setFHSSFlag, RISING);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[SX1278] Sending first packet ... "));
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ void setup() {
|
|||
|
||||
// set the function that will be called
|
||||
// when packet transmission is finished
|
||||
radio.setDio0Action(setFlag);
|
||||
radio.setDio0Action(setFlag, RISING);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[SX1278] Sending first packet ... "));
|
||||
|
|
@ -70,9 +70,6 @@ void setup() {
|
|||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -81,11 +78,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
|
@ -93,10 +85,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -135,9 +123,5 @@ void loop() {
|
|||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
distance between the modules using time-of-flight
|
||||
measurement.
|
||||
|
||||
Only SX1280 and SX1282 support ranging!
|
||||
Only SX1280 and SX1282 without external RF switch support ranging!
|
||||
|
||||
Note that to get accurate ranging results, calibration is needed!
|
||||
The process is described in Semtech SX1280 Application Note AN1200.29
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx128x---lora-modem
|
||||
|
|
@ -57,12 +60,24 @@ void loop() {
|
|||
int state = radio.range(false, 0x12345678);
|
||||
*/
|
||||
|
||||
// if ranging calibration is known, it can be provided
|
||||
// this should improve the accuracy and precision
|
||||
/*
|
||||
uint16_t calibration[3][6] = {
|
||||
{ 10299, 10271, 10244, 10242, 10230, 10246 },
|
||||
{ 11486, 11474, 11453, 11426, 11417, 11401 },
|
||||
{ 13308, 13493, 13528, 13515, 13430, 13376 }
|
||||
};
|
||||
|
||||
int state = radio.range(true, 0x12345678, calibration);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// ranging finished successfully
|
||||
Serial.println(F("success!"));
|
||||
Serial.print(F("[SX1280] Distance:\t\t\t"));
|
||||
Serial.print(radio.getRangingResult());
|
||||
Serial.println(F(" meters"));
|
||||
Serial.println(F(" meters (raw)"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_RANGING_TIMEOUT) {
|
||||
// timed out waiting for ranging packet
|
||||
|
|
|
|||
|
|
@ -78,9 +78,6 @@ void setup() {
|
|||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -89,11 +86,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
|
@ -101,10 +93,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
|
|
@ -155,10 +143,5 @@ void loop() {
|
|||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ void setup() {
|
|||
// bandwidth: 1625.0 kHz
|
||||
// spreading factor: 7
|
||||
// coding rate: 5
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 2 dBm
|
||||
// preamble length: 20 symbols
|
||||
state = radio2.begin(2450.0, 1625.0, 7, 5, 2, 20);
|
||||
state = radio2.begin(2450.0, 1625.0, 7, 5, 0x12, 2, 20);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -70,9 +70,6 @@ void setup() {
|
|||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -81,11 +78,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
|
@ -93,10 +85,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -131,9 +119,5 @@ void loop() {
|
|||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,9 +69,6 @@ void setup() {
|
|||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -80,11 +77,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
|
@ -92,10 +84,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
|
|
@ -130,10 +118,5 @@ void loop() {
|
|||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,9 +68,6 @@ void setup() {
|
|||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -79,11 +76,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
|
@ -91,10 +83,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -129,9 +117,5 @@ void loop() {
|
|||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,9 +86,6 @@ void setup() {
|
|||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// how many bytes are there in total
|
||||
const int totalLength = 512;
|
||||
|
||||
|
|
@ -106,11 +103,6 @@ volatile uint8_t rxBuffer[totalLength + 1];
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void fifoGet(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set the flag when we receive the full packet
|
||||
receivedFlag = radio.fifoGet(rxBuffer, totalLength, &receivedLength);
|
||||
}
|
||||
|
|
@ -118,10 +110,6 @@ void fifoGet(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// packet was successfully received
|
||||
Serial.println(F("[SX1278] Received packet!"));
|
||||
|
||||
|
|
@ -135,10 +123,5 @@ void loop() {
|
|||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,17 +80,17 @@ void setup() {
|
|||
transmissionState = radio.startTransmit(longPacket);
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
// flag to indicate we can keep adding more bytes to FIFO
|
||||
volatile bool fifoEmpty = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
// flag to indicate that a packet was sent
|
||||
bool transmittedFlag = false;
|
||||
|
||||
// how many bytes are there in total
|
||||
volatile int totalLength = longPacket.length();
|
||||
int totalLength = longPacket.length();
|
||||
|
||||
// counter to keep track of how many bytes still need to be sent
|
||||
volatile int remLength = totalLength;
|
||||
int remLength = totalLength;
|
||||
|
||||
// this function is called when the radio transmit buffer
|
||||
// is empty and ready to be refilled
|
||||
|
|
@ -100,23 +100,22 @@ volatile int remLength = totalLength;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void fifoAdd(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add more bytes to the transmit buffer
|
||||
uint8_t* txBuffPtr = (uint8_t*)longPacket.c_str();
|
||||
transmittedFlag = radio.fifoAdd(txBuffPtr, totalLength, &remLength);
|
||||
// we can send more bytes
|
||||
fifoEmpty = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(fifoEmpty) {
|
||||
// reset flag
|
||||
fifoEmpty = false;
|
||||
|
||||
// add more bytes to the transmit buffer
|
||||
uint8_t* txBuffPtr = (uint8_t*)longPacket.c_str();
|
||||
transmittedFlag = radio.fifoAdd(txBuffPtr, totalLength, &remLength);
|
||||
}
|
||||
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -148,9 +147,5 @@ void loop() {
|
|||
// send another one
|
||||
Serial.print(F("[SX1278] Sending another long packet ... "));
|
||||
transmissionState = radio.startTransmit(longPacket);
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,9 +87,6 @@ void setup() {
|
|||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -98,11 +95,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
|
@ -110,10 +102,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
|
|
@ -144,10 +132,5 @@ void loop() {
|
|||
|
||||
// put module back to listen mode
|
||||
radio.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,9 +83,6 @@ void setup() {
|
|||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
|
|
@ -94,11 +91,6 @@ volatile bool enableInterrupt = true;
|
|||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// check if the interrupt is enabled
|
||||
if(!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
|
@ -106,10 +98,6 @@ void setFlag(void) {
|
|||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
|
|
@ -148,9 +136,5 @@ void loop() {
|
|||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
176
lib/RadioLib/extras/SX126x_Spectrum_Scan/SpectrumScan.py
Normal file
176
lib/RadioLib/extras/SX126x_Spectrum_Scan/SpectrumScan.py
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import serial
|
||||
import sys
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from datetime import datetime
|
||||
from argparse import RawTextHelpFormatter
|
||||
|
||||
# number of samples in each scanline
|
||||
SCAN_WIDTH = 33
|
||||
|
||||
# scanline Serial start/end markers
|
||||
SCAN_MARK_START = 'SCAN '
|
||||
SCAN_MARK_FREQ = 'FREQ '
|
||||
SCAN_MARK_END = ' END'
|
||||
|
||||
# output path
|
||||
OUT_PATH = 'out'
|
||||
|
||||
# default settings
|
||||
DEFAULT_BAUDRATE = 115200
|
||||
DEFAULT_COLOR_MAP = 'viridis'
|
||||
DEFAULT_SCAN_LEN = 200
|
||||
DEFAULT_RSSI_OFFSET = -11
|
||||
|
||||
# Print iterations progress
|
||||
# from https://stackoverflow.com/questions/3173320/text-progress-bar-in-terminal-with-block-characters
|
||||
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 50, fill = '█', printEnd = "\r"):
|
||||
"""
|
||||
Call in a loop to create terminal progress bar
|
||||
@params:
|
||||
iteration - Required : current iteration (Int)
|
||||
total - Required : total iterations (Int)
|
||||
prefix - Optional : prefix string (Str)
|
||||
suffix - Optional : suffix string (Str)
|
||||
decimals - Optional : positive number of decimals in percent complete (Int)
|
||||
length - Optional : character length of bar (Int)
|
||||
fill - Optional : bar fill character (Str)
|
||||
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
|
||||
"""
|
||||
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
|
||||
filledLength = int(length * iteration // total)
|
||||
bar = fill * filledLength + '-' * (length - filledLength)
|
||||
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
|
||||
if iteration == total:
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''
|
||||
RadioLib SX126x_Spectrum_Scan plotter script. Displays output from SX126x_Spectrum_Scan example
|
||||
as grayscale and
|
||||
|
||||
Depends on pyserial and matplotlib, install by:
|
||||
'python3 -m pip install pyserial matplotlib'
|
||||
|
||||
Step-by-step guide on how to use the script:
|
||||
1. Upload the SX126x_Spectrum_Scan example to your Arduino board with SX1262 connected.
|
||||
2. Run the script with appropriate arguments.
|
||||
3. Once the scan is complete, output files will be saved to out/
|
||||
''')
|
||||
parser.add_argument('port',
|
||||
type=str,
|
||||
help='COM port to connect to the device')
|
||||
parser.add_argument('--speed',
|
||||
default=DEFAULT_BAUDRATE,
|
||||
type=int,
|
||||
help=f'COM port baudrate (defaults to {DEFAULT_BAUDRATE})')
|
||||
parser.add_argument('--map',
|
||||
default=DEFAULT_COLOR_MAP,
|
||||
type=str,
|
||||
help=f'Matplotlib color map to use for the output (defaults to "{DEFAULT_COLOR_MAP}")')
|
||||
parser.add_argument('--len',
|
||||
default=DEFAULT_SCAN_LEN,
|
||||
type=int,
|
||||
help=f'Number of scanlines to record (defaults to {DEFAULT_SCAN_LEN})')
|
||||
parser.add_argument('--offset',
|
||||
default=DEFAULT_RSSI_OFFSET,
|
||||
type=int,
|
||||
help=f'Default RSSI offset in dBm (defaults to {DEFAULT_RSSI_OFFSET})')
|
||||
parser.add_argument('--freq',
|
||||
default=-1,
|
||||
type=float,
|
||||
help=f'Default starting frequency in MHz')
|
||||
args = parser.parse_args()
|
||||
|
||||
freq_mode = False
|
||||
scan_len = args.len
|
||||
if (args.freq != -1):
|
||||
freq_mode = True
|
||||
scan_len = 1000
|
||||
|
||||
# create the color map and the result array
|
||||
arr = np.zeros((SCAN_WIDTH, scan_len))
|
||||
|
||||
# scanline counter
|
||||
row = 0
|
||||
|
||||
# list of frequencies in frequency mode
|
||||
freq_list = []
|
||||
|
||||
# open the COM port
|
||||
with serial.Serial(args.port, args.speed, timeout=None) as com:
|
||||
while(True):
|
||||
# update the progress bar
|
||||
if not freq_mode:
|
||||
printProgressBar(row, scan_len)
|
||||
|
||||
# read a single line
|
||||
try:
|
||||
line = com.readline().decode('utf-8')
|
||||
except:
|
||||
continue
|
||||
|
||||
if SCAN_MARK_FREQ in line:
|
||||
new_freq = float(line.split(' ')[1])
|
||||
if (len(freq_list) > 1) and (new_freq < freq_list[-1]):
|
||||
break
|
||||
|
||||
freq_list.append(new_freq)
|
||||
print('{:.3f}'.format(new_freq), end = '\r')
|
||||
continue
|
||||
|
||||
# check the markers
|
||||
if (SCAN_MARK_START in line) and (SCAN_MARK_END in line):
|
||||
# get the values
|
||||
scanline = line[len(SCAN_MARK_START):-len(SCAN_MARK_END)].split(',')
|
||||
for col in range(SCAN_WIDTH):
|
||||
arr[col][row] = int(scanline[col])
|
||||
|
||||
# increment the row counter
|
||||
row = row + 1
|
||||
|
||||
# check if we're done
|
||||
if (not freq_mode) and (row >= scan_len):
|
||||
break
|
||||
|
||||
# scale to the number of scans (sum of any given scanline)
|
||||
num_samples = arr.sum(axis=0)[0]
|
||||
arr *= (num_samples/arr.max())
|
||||
|
||||
if freq_mode:
|
||||
scan_len = len(freq_list)
|
||||
|
||||
# create the figure
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
# display the result as heatmap
|
||||
extent = [0, scan_len, -4*(SCAN_WIDTH + 1), args.offset]
|
||||
if freq_mode:
|
||||
extent[0] = freq_list[0]
|
||||
extent[1] = freq_list[-1]
|
||||
im = ax.imshow(arr[:,:scan_len], cmap=args.map, extent=extent)
|
||||
fig.colorbar(im)
|
||||
|
||||
# set some properites and show
|
||||
timestamp = datetime.now().strftime('%y-%m-%d %H-%M-%S')
|
||||
title = f'RadioLib SX126x Spectral Scan {timestamp}'
|
||||
if freq_mode:
|
||||
plt.xlabel("Frequency [Hz]")
|
||||
else:
|
||||
plt.xlabel("Time [sample]")
|
||||
plt.ylabel("RSSI [dBm]")
|
||||
ax.set_aspect('auto')
|
||||
fig.suptitle(title)
|
||||
fig.canvas.manager.set_window_title(title)
|
||||
plt.savefig(f'{OUT_PATH}/{title.replace(" ", "_")}.png', dpi=300)
|
||||
plt.show()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -9,6 +9,8 @@
|
|||
RadioLib KEYWORD1
|
||||
RadioShield KEYWORD1
|
||||
Module KEYWORD1
|
||||
RadioLibHal KEYWORD1
|
||||
ArduinoHal KEYWORD1
|
||||
|
||||
# modules
|
||||
CC1101 KEYWORD1
|
||||
|
|
@ -38,6 +40,8 @@ SX1279 KEYWORD1
|
|||
SX1280 KEYWORD1
|
||||
SX1281 KEYWORD1
|
||||
SX1282 KEYWORD1
|
||||
STM32WLx KEYWORD1
|
||||
STM32WLx_Module KEYWORD1
|
||||
|
||||
# protocols
|
||||
RTTYClient KEYWORD1
|
||||
|
|
@ -50,6 +54,8 @@ AFSKClient KEYWORD1
|
|||
FSK4Client KEYWORD1
|
||||
APRSClient KEYWORD1
|
||||
PagerClient KEYWORD1
|
||||
ExternalRadio KEYWORD1
|
||||
BellClient KEYWORD1
|
||||
|
||||
# SSTV modes
|
||||
Scottie1 KEYWORD1
|
||||
|
|
@ -62,6 +68,11 @@ PasokonP3 KEYWORD1
|
|||
PasokonP5 KEYWORD1
|
||||
PasokonP7 KEYWORD1
|
||||
|
||||
# Bell Modems
|
||||
Bell101 KEYWORD1
|
||||
Bell103 KEYWORD1
|
||||
Bell202 KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
|
@ -69,7 +80,7 @@ PasokonP7 KEYWORD1
|
|||
# RadioLib
|
||||
ModuleA KEYWORD2
|
||||
ModuleB KEYWORD2
|
||||
Module KEYWORD2
|
||||
setRfSwitchTable KEYWORD2
|
||||
|
||||
# SX127x/RFM9x + RF69 + CC1101
|
||||
begin KEYWORD2
|
||||
|
|
@ -191,6 +202,12 @@ setRegulatorDCDC KEYWORD2
|
|||
getCurrentLimit KEYWORD2
|
||||
getIrqStatus KEYWORD2
|
||||
getLastError KEYWORD2
|
||||
setRxBoostedGainMode KEYWORD2
|
||||
uploadPatch KEYWORD2
|
||||
spectralScanStart KEYWORD2
|
||||
spectralScanAbort KEYWORD2
|
||||
spectralScanGetStatus KEYWORD2
|
||||
spectralScanGetResult KEYWORD2
|
||||
|
||||
# nRF24
|
||||
setIrqAction KEYWORD2
|
||||
|
|
@ -249,12 +266,16 @@ dropSync KEYWORD2
|
|||
setTimerFlag KEYWORD2
|
||||
setInterruptSetup KEYWORD2
|
||||
|
||||
# BellModem
|
||||
setModem KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
RADIOLIB_NC LITERAL1
|
||||
RADIOLIB_VERSION LITERAL1
|
||||
RADIOLIB_PIN_TYPE LITERAL1
|
||||
|
||||
RADIOLIB_SHAPING_NONE LITERAL1
|
||||
RADIOLIB_SHAPING_0_3 LITERAL1
|
||||
|
|
|
|||
26
lib/RadioLib/library.json
Normal file
26
lib/RadioLib/library.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "RadioLib",
|
||||
"version": "6.0.0",
|
||||
"description": "Universal wireless communication library. User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.).",
|
||||
"keywords": "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag",
|
||||
"homepage": "https://github.com/jgromes/RadioLib",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/jgromes/RadioLib.git"
|
||||
},
|
||||
"authors":
|
||||
{
|
||||
"name": "Jan Gromeš",
|
||||
"email": "gromes.jan@gmail.com",
|
||||
"maintainer": true
|
||||
},
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
"headers": "RadioLib.h",
|
||||
"build":
|
||||
{
|
||||
"libLDFMode": "chain+"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
name=RadioLib
|
||||
version=5.5.0
|
||||
version=6.0.0
|
||||
author=Jan Gromes <gromes.jan@gmail.com>
|
||||
maintainer=Jan Gromes <gromes.jan@gmail.com>
|
||||
sentence=Universal wireless communication library
|
||||
|
|
|
|||
165
lib/RadioLib/src/ArduinoHal.cpp
Normal file
165
lib/RadioLib/src/ArduinoHal.cpp
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
#include "ArduinoHal.h"
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
|
||||
ArduinoHal::ArduinoHal(): RadioLibHal(INPUT, OUTPUT, LOW, HIGH, RISING, FALLING), spi(&RADIOLIB_DEFAULT_SPI), initInterface(true) {}
|
||||
|
||||
ArduinoHal::ArduinoHal(SPIClass& spi, SPISettings spiSettings): RadioLibHal(INPUT, OUTPUT, LOW, HIGH, RISING, FALLING), spi(&spi), spiSettings(spiSettings) {}
|
||||
|
||||
void ArduinoHal::init() {
|
||||
if(initInterface) {
|
||||
spiBegin();
|
||||
}
|
||||
}
|
||||
|
||||
void ArduinoHal::term() {
|
||||
if(initInterface) {
|
||||
spiEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void inline ArduinoHal::pinMode(uint32_t pin, uint32_t mode) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
::pinMode(pin, RADIOLIB_ARDUINOHAL_PIN_MODE_CAST mode);
|
||||
}
|
||||
|
||||
void inline ArduinoHal::digitalWrite(uint32_t pin, uint32_t value) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
::digitalWrite(pin, RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST value);
|
||||
}
|
||||
|
||||
uint32_t inline ArduinoHal::digitalRead(uint32_t pin) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return 0;
|
||||
}
|
||||
return(::digitalRead(pin));
|
||||
}
|
||||
|
||||
void inline ArduinoHal::attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
::attachInterrupt(interruptNum, interruptCb, RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST mode);
|
||||
}
|
||||
|
||||
void inline ArduinoHal::detachInterrupt(uint32_t interruptNum) {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
::detachInterrupt(interruptNum);
|
||||
}
|
||||
|
||||
void inline ArduinoHal::delay(unsigned long ms) {
|
||||
::delay(ms);
|
||||
}
|
||||
|
||||
void inline ArduinoHal::delayMicroseconds(unsigned long us) {
|
||||
::delayMicroseconds(us);
|
||||
}
|
||||
|
||||
unsigned long inline ArduinoHal::millis() {
|
||||
return(::millis());
|
||||
}
|
||||
|
||||
unsigned long inline ArduinoHal::micros() {
|
||||
return(::micros());
|
||||
}
|
||||
|
||||
long inline ArduinoHal::pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return 0;
|
||||
}
|
||||
return(::pulseIn(pin, state, timeout));
|
||||
}
|
||||
|
||||
void inline ArduinoHal::spiBegin() {
|
||||
spi->begin();
|
||||
}
|
||||
|
||||
void inline ArduinoHal::spiBeginTransaction() {
|
||||
spi->beginTransaction(spiSettings);
|
||||
}
|
||||
|
||||
uint8_t inline ArduinoHal::spiTransfer(uint8_t b) {
|
||||
return(spi->transfer(b));
|
||||
}
|
||||
|
||||
void inline ArduinoHal::spiEndTransaction() {
|
||||
spi->endTransaction();
|
||||
}
|
||||
|
||||
void inline ArduinoHal::spiEnd() {
|
||||
spi->end();
|
||||
}
|
||||
|
||||
void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, unsigned long duration) {
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
::tone(pin, frequency, duration);
|
||||
#elif defined(ESP32)
|
||||
// ESP32 tone() emulation
|
||||
(void)duration;
|
||||
if(prev == -1) {
|
||||
ledcAttachPin(pin, RADIOLIB_TONE_ESP32_CHANNEL);
|
||||
}
|
||||
if(prev != frequency) {
|
||||
ledcWriteTone(RADIOLIB_TONE_ESP32_CHANNEL, frequency);
|
||||
}
|
||||
prev = frequency;
|
||||
#elif defined(RADIOLIB_MBED_TONE_OVERRIDE)
|
||||
// better tone for mbed OS boards
|
||||
(void)duration;
|
||||
if(!pwmPin) {
|
||||
pwmPin = new mbed::PwmOut(digitalPinToPinName(pin));
|
||||
}
|
||||
pwmPin->period(1.0 / frequency);
|
||||
pwmPin->write(0.5);
|
||||
#endif
|
||||
}
|
||||
|
||||
void inline ArduinoHal::noTone(uint32_t pin) {
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED) and defined(ARDUINO_ARCH_STM32)
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
::noTone(pin, false);
|
||||
#elif !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
::noTone(pin);
|
||||
#elif defined(ESP32)
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
// ESP32 tone() emulation
|
||||
ledcDetachPin(pin);
|
||||
ledcWrite(RADIOLIB_TONE_ESP32_CHANNEL, 0);
|
||||
prev = -1;
|
||||
#elif defined(RADIOLIB_MBED_TONE_OVERRIDE)
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
// better tone for mbed OS boards
|
||||
(void)pin;
|
||||
pwmPin->suspend();
|
||||
#endif
|
||||
}
|
||||
|
||||
void inline ArduinoHal::yield() {
|
||||
#if !defined(RADIOLIB_YIELD_UNSUPPORTED)
|
||||
::yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t inline ArduinoHal::pinToInterrupt(uint32_t pin) {
|
||||
return(digitalPinToInterrupt(pin));
|
||||
}
|
||||
|
||||
#endif
|
||||
80
lib/RadioLib/src/ArduinoHal.h
Normal file
80
lib/RadioLib/src/ArduinoHal.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// make sure this is always compiled
|
||||
#include "TypeDef.h"
|
||||
|
||||
#if !defined(_RADIOLIB_ARDUINOHAL_H)
|
||||
#define _RADIOLIB_ARDUINOHAL_H
|
||||
|
||||
// this file only makes sense for Arduino builds
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
|
||||
#if defined(RADIOLIB_MBED_TONE_OVERRIDE)
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
|
||||
#include "Hal.h"
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
/*!
|
||||
\class ArduinoHal
|
||||
\brief Arduino default hardware abstraction library implementation.
|
||||
This class can be extended to support other Arduino platform or change behaviour of the default implementation.
|
||||
*/
|
||||
class ArduinoHal : public RadioLibHal {
|
||||
public:
|
||||
/*!
|
||||
\brief Arduino Hal constructor. Will use the default SPI interface and automatically initialize it.
|
||||
*/
|
||||
ArduinoHal();
|
||||
|
||||
/*!
|
||||
\brief Arduino Hal constructor. Will not attempt SPI interface initialization.
|
||||
\param spi SPI interface to be used, can also use software SPI implementations.
|
||||
\param spiSettings SPI interface settings.
|
||||
*/
|
||||
ArduinoHal(SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
|
||||
// implementations of pure virtual RadioLibHal methods
|
||||
void pinMode(uint32_t pin, uint32_t mode) override;
|
||||
void digitalWrite(uint32_t pin, uint32_t value) override;
|
||||
uint32_t digitalRead(uint32_t pin) override;
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override;
|
||||
void detachInterrupt(uint32_t interruptNum) override;
|
||||
void delay(unsigned long ms) override;
|
||||
void delayMicroseconds(unsigned long us) override;
|
||||
unsigned long millis() override;
|
||||
unsigned long micros() override;
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override;
|
||||
void spiBegin() override;
|
||||
void spiBeginTransaction() override;
|
||||
uint8_t spiTransfer(uint8_t b) override;
|
||||
void spiEndTransaction() override;
|
||||
void spiEnd() override;
|
||||
|
||||
// implementations of virtual RadioLibHal methods
|
||||
void init() override;
|
||||
void term() override;
|
||||
void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0) override;
|
||||
void noTone(uint32_t pin) override;
|
||||
void yield() override;
|
||||
uint32_t pinToInterrupt(uint32_t pin) override;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
SPIClass* spi = NULL;
|
||||
SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS;
|
||||
bool initInterface = false;
|
||||
|
||||
#if defined(RADIOLIB_MBED_TONE_OVERRIDE)
|
||||
mbed::PwmOut *pwmPin = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
int32_t prev = -1;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
11
lib/RadioLib/src/BuildOptUser.h
Normal file
11
lib/RadioLib/src/BuildOptUser.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#if !defined(_RADIOLIB_USER_BUILD_OPTIONS_H)
|
||||
#define _RADIOLIB_USER_BUILD_OPTIONS_H
|
||||
|
||||
// this file can be used to define any user build options
|
||||
// most commonly, RADIOLIB_EXCLUDE_* macros
|
||||
// or enabling debug output
|
||||
|
||||
//#define RADIOLIB_DEBUG
|
||||
//#define RADIOLIB_VERBOSE
|
||||
|
||||
#endif
|
||||
35
lib/RadioLib/src/Hal.cpp
Normal file
35
lib/RadioLib/src/Hal.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#include "Hal.h"
|
||||
|
||||
RadioLibHal::RadioLibHal(const uint32_t input, const uint32_t output, const uint32_t low, const uint32_t high, const uint32_t rising, const uint32_t falling)
|
||||
: GpioModeInput(input),
|
||||
GpioModeOutput(output),
|
||||
GpioLevelLow(low),
|
||||
GpioLevelHigh(high),
|
||||
GpioInterruptRising(rising),
|
||||
GpioInterruptFalling(falling) {}
|
||||
|
||||
void RadioLibHal::init() {
|
||||
|
||||
}
|
||||
|
||||
void RadioLibHal::term() {
|
||||
|
||||
}
|
||||
|
||||
void RadioLibHal::tone(uint32_t pin, unsigned int frequency, unsigned long duration) {
|
||||
(void)pin;
|
||||
(void)frequency;
|
||||
(void)duration;
|
||||
};
|
||||
|
||||
void RadioLibHal::noTone(uint32_t pin) {
|
||||
(void)pin;
|
||||
};
|
||||
|
||||
void RadioLibHal::yield() {
|
||||
|
||||
};
|
||||
|
||||
uint32_t RadioLibHal::pinToInterrupt(uint32_t pin) {
|
||||
return(pin);
|
||||
};
|
||||
209
lib/RadioLib/src/Hal.h
Normal file
209
lib/RadioLib/src/Hal.h
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
#if !defined(_RADIOLIB_HAL_H)
|
||||
#define _RADIOLIB_HAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*!
|
||||
\class Hal
|
||||
\brief Hardware abstraction library base interface.
|
||||
*/
|
||||
class RadioLibHal {
|
||||
public:
|
||||
|
||||
// values for pin modes, levels and change directions
|
||||
// these tell RadioLib how are different logic states represented on a given platform
|
||||
|
||||
/*!
|
||||
\brief Value to be used as the "input" GPIO direction.
|
||||
*/
|
||||
const uint32_t GpioModeInput;
|
||||
|
||||
/*!
|
||||
\brief Value to be used as the "output" GPIO direction.
|
||||
*/
|
||||
const uint32_t GpioModeOutput;
|
||||
|
||||
/*!
|
||||
\brief Value to be used as the "low" GPIO level.
|
||||
*/
|
||||
const uint32_t GpioLevelLow;
|
||||
|
||||
/*!
|
||||
\brief Value to be used as the "high" GPIO level.
|
||||
*/
|
||||
const uint32_t GpioLevelHigh;
|
||||
|
||||
/*!
|
||||
\brief Value to be used as the "rising" GPIO level change direction.
|
||||
*/
|
||||
const uint32_t GpioInterruptRising;
|
||||
|
||||
/*!
|
||||
\brief Value to be used as the "falling" GPIO level change direction.
|
||||
*/
|
||||
const uint32_t GpioInterruptFalling;
|
||||
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param input Value to be used as the "input" GPIO direction.
|
||||
\param output Value to be used as the "output" GPIO direction.
|
||||
\param low Value to be used as the "low" GPIO level.
|
||||
\param high Value to be used as the "high" GPIO level.
|
||||
\param rising Value to be used as the "rising" GPIO level change direction.
|
||||
\param falling Value to be used as the "falling" GPIO level change direction.
|
||||
*/
|
||||
RadioLibHal(const uint32_t input, const uint32_t output, const uint32_t low, const uint32_t high, const uint32_t rising, const uint32_t falling);
|
||||
|
||||
// pure virtual methods - these must be implemented by the hardware abstraction for RadioLib to function
|
||||
|
||||
/*!
|
||||
\brief GPIO pin mode (input/output/...) configuration method.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param pin Pin to be changed (platform-specific).
|
||||
\param mode Mode to be set (platform-specific).
|
||||
*/
|
||||
virtual void pinMode(uint32_t pin, uint32_t mode) = 0;
|
||||
|
||||
/*!
|
||||
\brief Digital write method.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param pin Pin to be changed (platform-specific).
|
||||
\param value Value to set (platform-specific).
|
||||
*/
|
||||
virtual void digitalWrite(uint32_t pin, uint32_t value) = 0;
|
||||
|
||||
/*!
|
||||
\brief Digital read method.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param pin Pin to be changed (platform-specific).
|
||||
\returns Value read on the pin (platform-specific).
|
||||
*/
|
||||
virtual uint32_t digitalRead(uint32_t pin) = 0;
|
||||
|
||||
/*!
|
||||
\brief Method to attach function to an external interrupt.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param interruptNum Interrupt number to attach to (platform-specific).
|
||||
\param interruptCb Interrupt service routine to execute.
|
||||
\param mode Rising/falling mode (platform-specific).
|
||||
*/
|
||||
virtual void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) = 0;
|
||||
|
||||
/*!
|
||||
\brief Method to detach function from an external interrupt.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param interruptNum Interrupt number to detach from (platform-specific).
|
||||
*/
|
||||
virtual void detachInterrupt(uint32_t interruptNum) = 0;
|
||||
|
||||
/*!
|
||||
\brief Blocking wait function.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param ms Number of milliseconds to wait.
|
||||
*/
|
||||
virtual void delay(unsigned long ms) = 0;
|
||||
|
||||
/*!
|
||||
\brief Blocking microsecond wait function.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param us Number of microseconds to wait.
|
||||
*/
|
||||
virtual void delayMicroseconds(unsigned long us) = 0;
|
||||
|
||||
/*!
|
||||
\brief Get number of milliseconds since start.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\returns Number of milliseconds since start.
|
||||
*/
|
||||
virtual unsigned long millis() = 0;
|
||||
|
||||
/*!
|
||||
\brief Get number of microseconds since start.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\returns Number of microseconds since start.
|
||||
*/
|
||||
virtual unsigned long micros() = 0;
|
||||
|
||||
/*!
|
||||
\brief Measure the length of incoming digital pulse in microseconds.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param pin Pin to measure on (platform-specific).
|
||||
\param state Pin level to monitor (platform-specific).
|
||||
\param timeout Timeout in microseconds.
|
||||
\returns Pulse length in microseconds, or 0 if the pulse did not start before timeout.
|
||||
*/
|
||||
virtual long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) = 0;
|
||||
|
||||
/*!
|
||||
\brief SPI initialization method.
|
||||
*/
|
||||
virtual void spiBegin() = 0;
|
||||
|
||||
/*!
|
||||
\brief Method to start SPI transaction.
|
||||
*/
|
||||
virtual void spiBeginTransaction() = 0;
|
||||
|
||||
/*!
|
||||
\brief Method to transfer one byte over SPI.
|
||||
\param b Byte to send.
|
||||
\returns Received byte.
|
||||
*/
|
||||
virtual uint8_t spiTransfer(uint8_t b) = 0;
|
||||
|
||||
/*!
|
||||
\brief Method to end SPI transaction.
|
||||
*/
|
||||
virtual void spiEndTransaction() = 0;
|
||||
|
||||
/*!
|
||||
\brief SPI termination method.
|
||||
*/
|
||||
virtual void spiEnd() = 0;
|
||||
|
||||
// virtual methods - these may or may not exists on a given platform
|
||||
// they exist in this implementation, but do nothing
|
||||
|
||||
/*!
|
||||
\brief Module initialization method.
|
||||
This will be called by all radio modules at the beginning of startup.
|
||||
Can be used to e.g., initalize SPI interface.
|
||||
*/
|
||||
virtual void init();
|
||||
|
||||
/*!
|
||||
\brief Module termination method.
|
||||
This will be called by all radio modules when the desctructor is called.
|
||||
Can be used to e.g., stop SPI interface.
|
||||
*/
|
||||
virtual void term();
|
||||
|
||||
/*!
|
||||
\brief Method to produce a square-wave with 50% duty cycle ("tone") of a given frequency at some pin.
|
||||
\param pin Pin to be used as the output.
|
||||
\param frequency Frequency of the square wave.
|
||||
\param duration Duration of the tone in ms. When set to 0, the tone will be infinite.
|
||||
*/
|
||||
virtual void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0);
|
||||
|
||||
/*!
|
||||
\brief Method to stop producing a tone.
|
||||
\param pin Pin which is currently producing the tone.
|
||||
*/
|
||||
virtual void noTone(uint32_t pin);
|
||||
|
||||
/*!
|
||||
\brief Yield method, called from long loops in multi-threaded environment (to prevent blocking other threads).
|
||||
*/
|
||||
virtual void yield();
|
||||
|
||||
/*!
|
||||
\brief Function to convert from pin number to interrupt number.
|
||||
\param pin Pin to convert from.
|
||||
\returns The interrupt number of a given pin.
|
||||
*/
|
||||
virtual uint32_t pinToInterrupt(uint32_t pin);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,94 +1,31 @@
|
|||
#include "Module.h"
|
||||
|
||||
// the following is probably only needed on non-Arduino builds
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(RADIOLIB_DEBUG)
|
||||
// needed for debug print
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
#include "ArduinoHal.h"
|
||||
|
||||
// we need this to emulate tone() on mbed Arduino boards
|
||||
#if defined(RADIOLIB_MBED_TONE_OVERRIDE)
|
||||
#include "mbed.h"
|
||||
mbed::PwmOut *pwmPin = NULL;
|
||||
Module::Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio) : csPin(cs), irqPin(irq), rstPin(rst), gpioPin(gpio) {
|
||||
this->hal = new ArduinoHal();
|
||||
}
|
||||
|
||||
Module::Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio, SPIClass& spi, SPISettings spiSettings) : csPin(cs), irqPin(irq), rstPin(rst), gpioPin(gpio) {
|
||||
this->hal = new ArduinoHal(spi, spiSettings);
|
||||
}
|
||||
#endif
|
||||
|
||||
Module::Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio):
|
||||
_cs(cs),
|
||||
_irq(irq),
|
||||
_rst(rst),
|
||||
_gpio(gpio)
|
||||
{
|
||||
_spi = &RADIOLIB_DEFAULT_SPI;
|
||||
_initInterface = true;
|
||||
|
||||
// this is Arduino build, pre-set callbacks
|
||||
setCb_pinMode(::pinMode);
|
||||
setCb_digitalRead(::digitalRead);
|
||||
setCb_digitalWrite(::digitalWrite);
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
setCb_tone(::tone);
|
||||
setCb_noTone(::noTone);
|
||||
#endif
|
||||
setCb_attachInterrupt(::attachInterrupt);
|
||||
setCb_detachInterrupt(::detachInterrupt);
|
||||
#if !defined(RADIOLIB_YIELD_UNSUPPORTED)
|
||||
setCb_yield(::yield);
|
||||
#endif
|
||||
setCb_delay(::delay);
|
||||
setCb_delayMicroseconds(::delayMicroseconds);
|
||||
setCb_millis(::millis);
|
||||
setCb_micros(::micros);
|
||||
setCb_pulseIn(::pulseIn);
|
||||
setCb_SPIbegin(&Module::SPIbegin);
|
||||
setCb_SPIbeginTransaction(&Module::beginTransaction);
|
||||
setCb_SPItransfer(&Module::transfer);
|
||||
setCb_SPIendTransaction(&Module::endTransaction);
|
||||
setCb_SPIend(&Module::end);
|
||||
Module::Module(RadioLibHal *hal, uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio) : csPin(cs), irqPin(irq), rstPin(rst), gpioPin(gpio) {
|
||||
this->hal = hal;
|
||||
}
|
||||
|
||||
Module::Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass& spi, SPISettings spiSettings):
|
||||
_cs(cs),
|
||||
_irq(irq),
|
||||
_rst(rst),
|
||||
_gpio(gpio),
|
||||
_spiSettings(spiSettings)
|
||||
{
|
||||
_spi = &spi;
|
||||
_initInterface = false;
|
||||
|
||||
// this is Arduino build, pre-set callbacks
|
||||
setCb_pinMode(::pinMode);
|
||||
setCb_digitalRead(::digitalRead);
|
||||
setCb_digitalWrite(::digitalWrite);
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
setCb_tone(::tone);
|
||||
setCb_noTone(::noTone);
|
||||
#endif
|
||||
setCb_attachInterrupt(::attachInterrupt);
|
||||
setCb_detachInterrupt(::detachInterrupt);
|
||||
#if !defined(RADIOLIB_YIELD_UNSUPPORTED)
|
||||
setCb_yield(::yield);
|
||||
#endif
|
||||
setCb_delay(::delay);
|
||||
setCb_delayMicroseconds(::delayMicroseconds);
|
||||
setCb_millis(::millis);
|
||||
setCb_micros(::micros);
|
||||
setCb_pulseIn(::pulseIn);
|
||||
setCb_SPIbegin(&Module::SPIbegin);
|
||||
setCb_SPIbeginTransaction(&Module::beginTransaction);
|
||||
setCb_SPItransfer(&Module::transfer);
|
||||
setCb_SPIendTransaction(&Module::endTransaction);
|
||||
setCb_SPIend(&Module::end);
|
||||
}
|
||||
#else
|
||||
|
||||
Module::Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio):
|
||||
_cs(cs),
|
||||
_irq(irq),
|
||||
_rst(rst),
|
||||
_gpio(gpio)
|
||||
{
|
||||
// not an Arduino build, it's up to the user to set all callbacks
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Module::Module(const Module& mod) {
|
||||
*this = mod;
|
||||
}
|
||||
|
|
@ -96,38 +33,25 @@ Module::Module(const Module& mod) {
|
|||
Module& Module::operator=(const Module& mod) {
|
||||
this->SPIreadCommand = mod.SPIreadCommand;
|
||||
this->SPIwriteCommand = mod.SPIwriteCommand;
|
||||
this->_cs = mod.getCs();
|
||||
this->_irq = mod.getIrq();
|
||||
this->_rst = mod.getRst();
|
||||
this->_gpio = mod.getGpio();
|
||||
|
||||
this->csPin = mod.csPin;
|
||||
this->irqPin = mod.irqPin;
|
||||
this->rstPin = mod.rstPin;
|
||||
this->gpioPin = mod.gpioPin;
|
||||
return(*this);
|
||||
}
|
||||
|
||||
void Module::init() {
|
||||
this->pinMode(_cs, OUTPUT);
|
||||
this->digitalWrite(_cs, HIGH);
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
if(_initInterface) {
|
||||
(this->*cb_SPIbegin)();
|
||||
}
|
||||
#endif
|
||||
this->hal->init();
|
||||
this->hal->pinMode(csPin, this->hal->GpioModeOutput);
|
||||
this->hal->digitalWrite(csPin, this->hal->GpioLevelHigh);
|
||||
}
|
||||
|
||||
void Module::term() {
|
||||
// stop hardware interfaces (if they were initialized by the library)
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
if(!_initInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(_spi != nullptr) {
|
||||
this->SPIend();
|
||||
}
|
||||
#endif
|
||||
this->hal->term();
|
||||
}
|
||||
|
||||
int16_t Module::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
|
||||
int16_t Module::SPIgetRegValue(uint16_t reg, uint8_t msb, uint8_t lsb) {
|
||||
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
|
||||
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
|
||||
}
|
||||
|
|
@ -137,7 +61,7 @@ int16_t Module::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
|
|||
return(maskedValue);
|
||||
}
|
||||
|
||||
int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
|
||||
int16_t Module::SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
|
||||
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
|
||||
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
|
||||
}
|
||||
|
|
@ -150,9 +74,9 @@ int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
#if defined(RADIOLIB_SPI_PARANOID)
|
||||
// check register value each millisecond until check interval is reached
|
||||
// some registers need a bit of time to process the change (e.g. SX127X_REG_OP_MODE)
|
||||
uint32_t start = this->micros();
|
||||
uint32_t start = this->hal->micros();
|
||||
uint8_t readValue = 0x00;
|
||||
while(this->micros() - start < (checkInterval * 1000)) {
|
||||
while(this->hal->micros() - start < (checkInterval * 1000)) {
|
||||
readValue = SPIreadRegister(reg);
|
||||
if((readValue & checkMask) == (newValue & checkMask)) {
|
||||
// check passed, we can stop the loop
|
||||
|
|
@ -162,23 +86,13 @@ int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
|
||||
// check failed, print debug info
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINT(F("address:\t0x"));
|
||||
RADIOLIB_DEBUG_PRINTLN(reg, HEX);
|
||||
RADIOLIB_DEBUG_PRINT(F("bits:\t\t"));
|
||||
RADIOLIB_DEBUG_PRINT(msb);
|
||||
RADIOLIB_DEBUG_PRINT(' ');
|
||||
RADIOLIB_DEBUG_PRINTLN(lsb);
|
||||
RADIOLIB_DEBUG_PRINT(F("value:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(value, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("current:\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(currentValue, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("mask:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(mask, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("new:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(newValue, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("read:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(readValue, BIN);
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINTLN("address:\t0x%X", reg);
|
||||
RADIOLIB_DEBUG_PRINTLN("bits:\t\t%d %d", msb, lsb);
|
||||
RADIOLIB_DEBUG_PRINT("value:\t\t0x%X", value);
|
||||
RADIOLIB_DEBUG_PRINT("current:\t0x%X", currentValue);
|
||||
RADIOLIB_DEBUG_PRINT("mask:\t\t0x%X", mask);
|
||||
RADIOLIB_DEBUG_PRINT("new:\t\t0x%X", newValue);
|
||||
RADIOLIB_DEBUG_PRINTLN("read:\t\t0x%X", readValue);
|
||||
|
||||
return(RADIOLIB_ERR_SPI_WRITE_FAILED);
|
||||
#else
|
||||
|
|
@ -186,310 +100,278 @@ int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
#endif
|
||||
}
|
||||
|
||||
void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) {
|
||||
SPItransfer(SPIreadCommand, reg, NULL, inBytes, numBytes);
|
||||
void Module::SPIreadRegisterBurst(uint16_t reg, size_t numBytes, uint8_t* inBytes) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIreadCommand, reg, NULL, inBytes, numBytes);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIreadCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, false, NULL, inBytes, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Module::SPIreadRegister(uint8_t reg) {
|
||||
uint8_t Module::SPIreadRegister(uint16_t reg) {
|
||||
uint8_t resp = 0;
|
||||
SPItransfer(SPIreadCommand, reg, NULL, &resp, 1);
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIreadCommand, reg, NULL, &resp, 1);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIreadCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, false, NULL, &resp, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
return(resp);
|
||||
}
|
||||
|
||||
void Module::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes) {
|
||||
SPItransfer(SPIwriteCommand, reg, data, NULL, numBytes);
|
||||
void Module::SPIwriteRegisterBurst(uint16_t reg, uint8_t* data, size_t numBytes) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIwriteCommand, reg, data, NULL, numBytes);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIwriteCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, true, data, NULL, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::SPIwriteRegister(uint8_t reg, uint8_t data) {
|
||||
SPItransfer(SPIwriteCommand, reg, &data, NULL, 1);
|
||||
void Module::SPIwriteRegister(uint16_t reg, uint8_t data) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIwriteCommand, reg, &data, NULL, 1);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIwriteCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, true, &data, NULL, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes) {
|
||||
void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
|
||||
// start SPI transaction
|
||||
this->SPIbeginTransaction();
|
||||
this->hal->spiBeginTransaction();
|
||||
|
||||
// pull CS low
|
||||
this->digitalWrite(_cs, LOW);
|
||||
this->hal->digitalWrite(this->csPin, this->hal->GpioLevelLow);
|
||||
|
||||
// send SPI register address with access command
|
||||
this->SPItransfer(reg | cmd);
|
||||
if(this->SPIaddrWidth <= 8) {
|
||||
this->hal->spiTransfer(reg | cmd);
|
||||
} else {
|
||||
this->hal->spiTransfer((reg >> 8) | cmd);
|
||||
this->hal->spiTransfer(reg & 0xFF);
|
||||
}
|
||||
|
||||
#if defined(RADIOLIB_VERBOSE)
|
||||
if(cmd == SPIwriteCommand) {
|
||||
RADIOLIB_VERBOSE_PRINT('W');
|
||||
RADIOLIB_VERBOSE_PRINT("W");
|
||||
} else if(cmd == SPIreadCommand) {
|
||||
RADIOLIB_VERBOSE_PRINT('R');
|
||||
RADIOLIB_VERBOSE_PRINT("R");
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINT('\t')
|
||||
RADIOLIB_VERBOSE_PRINT(reg, HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT("\t%X\t", reg);
|
||||
#endif
|
||||
|
||||
// send data or get response
|
||||
if(cmd == SPIwriteCommand) {
|
||||
if(dataOut != NULL) {
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
this->SPItransfer(dataOut[n]);
|
||||
RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
this->hal->spiTransfer(dataOut[n]);
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t", dataOut[n]);
|
||||
}
|
||||
}
|
||||
} else if (cmd == SPIreadCommand) {
|
||||
if(dataIn != NULL) {
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
dataIn[n] = this->SPItransfer(0x00);
|
||||
RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
dataIn[n] = this->hal->spiTransfer(0x00);
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t", dataIn[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
|
||||
// release CS
|
||||
this->digitalWrite(_cs, HIGH);
|
||||
this->hal->digitalWrite(this->csPin, this->hal->GpioLevelHigh);
|
||||
|
||||
// end SPI transaction
|
||||
this->SPIendTransaction();
|
||||
this->hal->spiEndTransaction();
|
||||
}
|
||||
|
||||
int16_t Module::SPIreadStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
return(this->SPIreadStream(&cmd, 1, data, numBytes, waitForGpio, verify));
|
||||
}
|
||||
|
||||
int16_t Module::SPIreadStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
// send the command
|
||||
int16_t state = this->SPItransferStream(cmd, cmdLen, false, NULL, data, numBytes, waitForGpio, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check the status
|
||||
if(verify) {
|
||||
state = this->SPIcheckStream();
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t Module::SPIwriteStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
return(this->SPIwriteStream(&cmd, 1, data, numBytes, waitForGpio, verify));
|
||||
}
|
||||
|
||||
int16_t Module::SPIwriteStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
// send the command
|
||||
int16_t state = this->SPItransferStream(cmd, cmdLen, true, data, NULL, numBytes, waitForGpio, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check the status
|
||||
if(verify) {
|
||||
state = this->SPIcheckStream();
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t Module::SPIcheckStream() {
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
|
||||
#if defined(RADIOLIB_SPI_PARANOID)
|
||||
// get the status
|
||||
uint8_t spiStatus = 0;
|
||||
uint8_t cmd = this->SPIstatusCommand;
|
||||
state = this->SPItransferStream(&cmd, 1, false, NULL, &spiStatus, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// translate to RadioLib status code
|
||||
if(this->SPIparseStatusCb != nullptr) {
|
||||
this->SPIstreamError = this->SPIparseStatusCb(spiStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, uint32_t timeout) {
|
||||
#if defined(RADIOLIB_VERBOSE)
|
||||
uint8_t debugBuff[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#endif
|
||||
|
||||
// ensure GPIO is low
|
||||
uint32_t start = this->hal->millis();
|
||||
while(this->hal->digitalRead(this->gpioPin)) {
|
||||
this->hal->yield();
|
||||
if(this->hal->millis() - start >= timeout) {
|
||||
RADIOLIB_DEBUG_PRINTLN("Timed out waiting for GPIO pin, is it connected?");
|
||||
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// pull NSS low
|
||||
this->hal->digitalWrite(this->csPin, this->hal->GpioLevelLow);
|
||||
|
||||
// start transfer
|
||||
this->hal->spiBeginTransaction();
|
||||
|
||||
// send command byte(s)
|
||||
for(uint8_t n = 0; n < cmdLen; n++) {
|
||||
this->hal->spiTransfer(cmd[n]);
|
||||
}
|
||||
|
||||
// variable to save error during SPI transfer
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
|
||||
// send/receive all bytes
|
||||
if(write) {
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
// send byte
|
||||
uint8_t in = this->hal->spiTransfer(dataOut[n]);
|
||||
#if defined(RADIOLIB_VERBOSE)
|
||||
debugBuff[n] = in;
|
||||
#endif
|
||||
|
||||
// check status
|
||||
if(this->SPIparseStatusCb != nullptr) {
|
||||
state = this->SPIparseStatusCb(in);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// skip the first byte for read-type commands (status-only)
|
||||
uint8_t in = this->hal->spiTransfer(this->SPInopCommand);
|
||||
#if defined(RADIOLIB_VERBOSE)
|
||||
debugBuff[0] = in;
|
||||
#endif
|
||||
|
||||
// check status
|
||||
if(this->SPIparseStatusCb != nullptr) {
|
||||
state = this->SPIparseStatusCb(in);
|
||||
} else {
|
||||
state = RADIOLIB_ERR_NONE;
|
||||
}
|
||||
|
||||
// read the data
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
dataIn[n] = this->hal->spiTransfer(this->SPInopCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stop transfer
|
||||
this->hal->spiEndTransaction();
|
||||
this->hal->digitalWrite(this->csPin, this->hal->GpioLevelHigh);
|
||||
|
||||
// wait for GPIO to go high and then low
|
||||
if(waitForGpio) {
|
||||
this->hal->delayMicroseconds(1);
|
||||
uint32_t start = this->hal->millis();
|
||||
while(this->hal->digitalRead(this->gpioPin)) {
|
||||
this->hal->yield();
|
||||
if(this->hal->millis() - start >= timeout) {
|
||||
state = RADIOLIB_ERR_SPI_CMD_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print debug output
|
||||
#if defined(RADIOLIB_VERBOSE)
|
||||
// print command byte(s)
|
||||
RADIOLIB_VERBOSE_PRINT("CMD\t");
|
||||
for(uint8_t n = 0; n < cmdLen; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t", cmd[n]);
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
|
||||
// print data bytes
|
||||
RADIOLIB_VERBOSE_PRINT("DAT");
|
||||
if(write) {
|
||||
RADIOLIB_VERBOSE_PRINT("W\t");
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t%X\t", dataOut[n], debugBuff[n]);
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
} else {
|
||||
RADIOLIB_VERBOSE_PRINT("R\t%X\t%X\t", this->SPInopCommand, debugBuff[0]);
|
||||
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t%X\t", this->SPInopCommand, dataIn[n]);
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
void Module::waitForMicroseconds(uint32_t start, uint32_t len) {
|
||||
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
||||
(void)start;
|
||||
if((this->TimerSetupCb != nullptr) && (len != this->_prevTimingLen)) {
|
||||
if((this->TimerSetupCb != nullptr) && (len != this->prevTimingLen)) {
|
||||
_prevTimingLen = len;
|
||||
this->TimerSetupCb(len);
|
||||
}
|
||||
this->TimerFlag = false;
|
||||
while(!this->TimerFlag) {
|
||||
this->yield();
|
||||
this->hal->yield();
|
||||
}
|
||||
#else
|
||||
while(this->micros() - start < len) {
|
||||
this->yield();
|
||||
while(this->hal->micros() - start < len) {
|
||||
this->hal->yield();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::pinMode(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_MODE mode) {
|
||||
if((pin == RADIOLIB_NC) || (cb_pinMode == nullptr)) {
|
||||
return;
|
||||
}
|
||||
cb_pinMode(pin, mode);
|
||||
}
|
||||
|
||||
void Module::digitalWrite(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_STATUS value) {
|
||||
if((pin == RADIOLIB_NC) || (cb_digitalWrite == nullptr)) {
|
||||
return;
|
||||
}
|
||||
cb_digitalWrite(pin, value);
|
||||
}
|
||||
|
||||
RADIOLIB_PIN_STATUS Module::digitalRead(RADIOLIB_PIN_TYPE pin) {
|
||||
if((pin == RADIOLIB_NC) || (cb_digitalRead == nullptr)) {
|
||||
return((RADIOLIB_PIN_STATUS)0);
|
||||
}
|
||||
return(cb_digitalRead(pin));
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
// we need to cache the previous tone value for emulation on ESP32
|
||||
int32_t prev = -1;
|
||||
#endif
|
||||
|
||||
void Module::tone(RADIOLIB_PIN_TYPE pin, uint16_t value, uint32_t duration) {
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
if((pin == RADIOLIB_NC) || (cb_tone == nullptr)) {
|
||||
return;
|
||||
}
|
||||
cb_tone(pin, value, duration);
|
||||
#else
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
#if defined(ESP32)
|
||||
// ESP32 tone() emulation
|
||||
(void)duration;
|
||||
if(prev == -1) {
|
||||
ledcAttachPin(pin, RADIOLIB_TONE_ESP32_CHANNEL);
|
||||
}
|
||||
if(prev != value) {
|
||||
ledcWriteTone(RADIOLIB_TONE_ESP32_CHANNEL, value);
|
||||
}
|
||||
prev = value;
|
||||
#elif defined(RADIOLIB_MBED_TONE_OVERRIDE)
|
||||
// better tone for mbed OS boards
|
||||
(void)duration;
|
||||
if(!pwmPin) {
|
||||
pwmPin = new mbed::PwmOut(digitalPinToPinName(pin));
|
||||
}
|
||||
pwmPin->period(1.0 / value);
|
||||
pwmPin->write(0.5);
|
||||
#else
|
||||
(void)value;
|
||||
(void)duration;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::noTone(RADIOLIB_PIN_TYPE pin) {
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
if((pin == RADIOLIB_NC) || (cb_noTone == nullptr)) {
|
||||
return;
|
||||
}
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
cb_noTone(pin, false);
|
||||
#else
|
||||
cb_noTone(pin);
|
||||
#endif
|
||||
#else
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
#if defined(ESP32)
|
||||
// ESP32 tone() emulation
|
||||
ledcDetachPin(pin);
|
||||
ledcWrite(RADIOLIB_TONE_ESP32_CHANNEL, 0);
|
||||
prev = -1;
|
||||
#elif defined(RADIOLIB_MBED_TONE_OVERRIDE)
|
||||
// better tone for mbed OS boards
|
||||
(void)pin;
|
||||
pwmPin->suspend();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::attachInterrupt(RADIOLIB_PIN_TYPE interruptNum, void (*userFunc)(void), RADIOLIB_INTERRUPT_STATUS mode) {
|
||||
if((interruptNum == RADIOLIB_NC) || (cb_attachInterrupt == nullptr)) {
|
||||
return;
|
||||
}
|
||||
cb_attachInterrupt(interruptNum, userFunc, mode);
|
||||
}
|
||||
|
||||
void Module::detachInterrupt(RADIOLIB_PIN_TYPE interruptNum) {
|
||||
if((interruptNum == RADIOLIB_NC) || (cb_detachInterrupt == nullptr)) {
|
||||
return;
|
||||
}
|
||||
cb_detachInterrupt(interruptNum);
|
||||
}
|
||||
|
||||
void Module::yield() {
|
||||
if(cb_yield == nullptr) {
|
||||
return;
|
||||
}
|
||||
#if !defined(RADIOLIB_YIELD_UNSUPPORTED)
|
||||
cb_yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::delay(uint32_t ms) {
|
||||
if(cb_delay == nullptr) {
|
||||
return;
|
||||
}
|
||||
cb_delay(ms);
|
||||
}
|
||||
|
||||
void Module::delayMicroseconds(uint32_t us) {
|
||||
if(cb_delayMicroseconds == nullptr) {
|
||||
return;
|
||||
}
|
||||
cb_delayMicroseconds(us);
|
||||
}
|
||||
|
||||
uint32_t Module::millis() {
|
||||
if(cb_millis == nullptr) {
|
||||
return(0);
|
||||
}
|
||||
return(cb_millis());
|
||||
}
|
||||
|
||||
uint32_t Module::micros() {
|
||||
if(cb_micros == nullptr) {
|
||||
return(0);
|
||||
}
|
||||
return(cb_micros());
|
||||
}
|
||||
|
||||
uint32_t Module::pulseIn(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_STATUS state, uint32_t timeout) {
|
||||
if(cb_pulseIn == nullptr) {
|
||||
return(0);
|
||||
}
|
||||
return(cb_pulseIn(pin, state, timeout));
|
||||
}
|
||||
|
||||
void Module::begin() {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
if(cb_SPIbegin == nullptr) {
|
||||
return;
|
||||
}
|
||||
(this->*cb_SPIbegin)();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::beginTransaction() {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
if(cb_SPIbeginTransaction == nullptr) {
|
||||
return;
|
||||
}
|
||||
(this->*cb_SPIbeginTransaction)();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t Module::transfer(uint8_t b) {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
if(cb_SPItransfer == nullptr) {
|
||||
return(0xFF);
|
||||
}
|
||||
return((this->*cb_SPItransfer)(b));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::endTransaction() {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
if(cb_SPIendTransaction == nullptr) {
|
||||
return;
|
||||
}
|
||||
(this->*cb_SPIendTransaction)();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::end() {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
if(cb_SPIend == nullptr) {
|
||||
return;
|
||||
}
|
||||
(this->*cb_SPIend)();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
void Module::SPIbegin() {
|
||||
_spi->begin();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Module::SPIbeginTransaction() {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
_spi->beginTransaction(_spiSettings);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t Module::SPItransfer(uint8_t b) {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
return(_spi->transfer(b));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::SPIendTransaction() {
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
_spi->endTransaction();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
void Module::SPIend() {
|
||||
_spi->end();
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t Module::flipBits(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
|
|
@ -505,17 +387,29 @@ uint16_t Module::flipBits16(uint16_t i) {
|
|||
return i;
|
||||
}
|
||||
|
||||
void Module::hexdump(uint8_t* data, size_t len) {
|
||||
void Module::hexdump(uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
|
||||
size_t rem_len = len;
|
||||
for(size_t i = 0; i < len; i+=16) {
|
||||
char str[80];
|
||||
sprintf(str, "%07x ", i);
|
||||
sprintf(str, "%07" PRIx32 " ", i+offset);
|
||||
size_t line_len = 16;
|
||||
if(rem_len < line_len) {
|
||||
line_len = rem_len;
|
||||
}
|
||||
for(size_t j = 0; j < line_len; j++) {
|
||||
sprintf(&str[8 + j*3], "%02x ", data[i+j]);
|
||||
for(size_t j = 0; j < line_len; j+=width) {
|
||||
if(width > 1) {
|
||||
int m = 0;
|
||||
int step = width/2;
|
||||
if(be) {
|
||||
step *= -1;
|
||||
}
|
||||
for(int32_t k = width - 1; k >= -width + 1; k+=step) {
|
||||
sprintf(&str[8 + (j+m)*3], "%02x ", data[i+j+k+m]);
|
||||
m++;
|
||||
}
|
||||
} else {
|
||||
sprintf(&str[8 + (j)*3], "%02x ", data[i+j]);
|
||||
}
|
||||
}
|
||||
for(size_t j = line_len; j < 16; j++) {
|
||||
sprintf(&str[8 + j*3], " ");
|
||||
|
|
@ -532,39 +426,97 @@ void Module::hexdump(uint8_t* data, size_t len) {
|
|||
for(size_t j = line_len; j < 16; j++) {
|
||||
sprintf(&str[58 + j], " ");
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(str);
|
||||
RADIOLIB_DEBUG_PRINT(str);
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
rem_len -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
void Module::regdump(uint8_t start, uint8_t len) {
|
||||
void Module::regdump(uint16_t start, size_t len) {
|
||||
#if defined(RADIOLIB_STATIC_ONLY)
|
||||
uint8_t buff[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* buff = new uint8_t[len];
|
||||
#endif
|
||||
SPIreadRegisterBurst(start, len, buff);
|
||||
hexdump(buff, len);
|
||||
hexdump(buff, len, start);
|
||||
#if !defined(RADIOLIB_STATIC_ONLY)
|
||||
delete[] buff;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||
_useRfSwitch = true;
|
||||
_rxEn = rxEn;
|
||||
_txEn = txEn;
|
||||
this->pinMode(rxEn, OUTPUT);
|
||||
this->pinMode(txEn, OUTPUT);
|
||||
#if defined(RADIOLIB_DEBUG) and defined(RADIOLIB_BUILD_ARDUINO)
|
||||
// https://github.com/esp8266/Arduino/blob/65579d29081cb8501e4d7f786747bf12e7b37da2/cores/esp8266/Print.cpp#L50
|
||||
size_t Module::serialPrintf(const char* format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
char temp[64];
|
||||
char* buffer = temp;
|
||||
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
|
||||
va_end(arg);
|
||||
if (len > sizeof(temp) - 1) {
|
||||
buffer = new char[len + 1];
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
va_start(arg, format);
|
||||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = RADIOLIB_DEBUG_PORT.write((const uint8_t*)buffer, len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Module::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
|
||||
// This can be on the stack, setRfSwitchTable copies the contents
|
||||
const uint32_t pins[] = {
|
||||
rxEn, txEn, RADIOLIB_NC,
|
||||
};
|
||||
|
||||
// This must be static, since setRfSwitchTable stores a reference.
|
||||
static const RfSwitchMode_t table[] = {
|
||||
{ MODE_IDLE, {this->hal->GpioLevelLow, this->hal->GpioLevelLow} },
|
||||
{ MODE_RX, {this->hal->GpioLevelHigh, this->hal->GpioLevelLow} },
|
||||
{ MODE_TX, {this->hal->GpioLevelLow, this->hal->GpioLevelHigh} },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
setRfSwitchTable(pins, table);
|
||||
}
|
||||
|
||||
void Module::setRfSwitchState(RADIOLIB_PIN_STATUS rxPinState, RADIOLIB_PIN_STATUS txPinState) {
|
||||
// check RF switch control is enabled
|
||||
if(!_useRfSwitch) {
|
||||
void Module::setRfSwitchTable(const uint32_t (&pins)[3], const RfSwitchMode_t table[]) {
|
||||
memcpy(this->rfSwitchPins, pins, sizeof(this->rfSwitchPins));
|
||||
this->rfSwitchTable = table;
|
||||
for(size_t i = 0; i < RFSWITCH_MAX_PINS; i++)
|
||||
this->hal->pinMode(pins[i], this->hal->GpioModeOutput);
|
||||
}
|
||||
|
||||
const Module::RfSwitchMode_t *Module::findRfSwitchMode(uint8_t mode) const {
|
||||
const RfSwitchMode_t *row = this->rfSwitchTable;
|
||||
while (row && row->mode != MODE_END_OF_TABLE) {
|
||||
if (row->mode == mode)
|
||||
return row;
|
||||
++row;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Module::setRfSwitchState(uint8_t mode) {
|
||||
const RfSwitchMode_t *row = findRfSwitchMode(mode);
|
||||
if(!row) {
|
||||
// RF switch control is disabled or does not have this mode
|
||||
return;
|
||||
}
|
||||
|
||||
// set pins
|
||||
this->digitalWrite(_rxEn, rxPinState);
|
||||
this->digitalWrite(_txEn, txPinState);
|
||||
const uint32_t *value = &row->values[0];
|
||||
for(size_t i = 0; i < RFSWITCH_MAX_PINS; i++) {
|
||||
uint32_t pin = this->rfSwitchPins[i];
|
||||
if (pin != RADIOLIB_NC)
|
||||
this->hal->digitalWrite(pin, *value);
|
||||
++value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,84 +2,124 @@
|
|||
#define _RADIOLIB_MODULE_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Hal.h"
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
#if defined(STM32WLxx)
|
||||
#include <SubGhz.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Value to use as the last element in a mode table to indicate the
|
||||
* end of the table.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
*/
|
||||
#define END_OF_MODE_TABLE { Module::MODE_END_OF_TABLE, {} }
|
||||
|
||||
// default timeout for SPI transfers
|
||||
#define RADIOLIB_MODULE_SPI_TIMEOUT (1000)
|
||||
|
||||
/*!
|
||||
\class Module
|
||||
|
||||
\brief Implements all common low-level methods to control the wireless module.
|
||||
Every module class contains one private instance of this class.
|
||||
*/
|
||||
class Module {
|
||||
public:
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
/*!
|
||||
* \brief The maximum number of pins supported by the RF switch
|
||||
* code.
|
||||
*
|
||||
* Note: It is not recommended to use this constant in your sketch
|
||||
* when defining a rfswitch pins array, to prevent issues when this
|
||||
* value is ever increased and such an array gets extra zero
|
||||
* elements (that will be interpreted as pin 0).
|
||||
*/
|
||||
static const size_t RFSWITCH_MAX_PINS = 3;
|
||||
|
||||
/*!
|
||||
\brief Arduino Module constructor. Will use the default SPI interface and automatically initialize it
|
||||
* Description of RF switch pin states for a single mode.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
*/
|
||||
struct RfSwitchMode_t {
|
||||
uint8_t mode;
|
||||
uint32_t values[RFSWITCH_MAX_PINS];
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constants to use in a mode table set be setRfSwitchTable. These
|
||||
* constants work for most radios, but some radios define their own
|
||||
* constants to be used instead.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
*/
|
||||
enum OpMode_t {
|
||||
/*! End of table marker, use \ref END_OF_MODE_TABLE constant
|
||||
* instead. Value is zero to ensure zero-initialized mode ends the
|
||||
* table */
|
||||
MODE_END_OF_TABLE = 0,
|
||||
/*! Idle mode */
|
||||
MODE_IDLE,
|
||||
/*! Receive mode */
|
||||
MODE_RX,
|
||||
/*! Transmission mode */
|
||||
MODE_TX,
|
||||
};
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
/*!
|
||||
\brief Arduino Module constructor. Will use the default SPI interface and automatically initialize it.
|
||||
\param cs Arduino pin to be used as chip select.
|
||||
|
||||
\param irq Arduino pin to be used as interrupt/GPIO.
|
||||
|
||||
\param rst Arduino pin to be used as hardware reset for the module.
|
||||
|
||||
\param gpio Arduino pin to be used as additional interrupt/GPIO.
|
||||
*/
|
||||
Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio = RADIOLIB_NC);
|
||||
Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio = RADIOLIB_NC);
|
||||
|
||||
/*!
|
||||
\brief Arduino Module constructor. Will not attempt SPI interface initialization.
|
||||
|
||||
\param cs Arduino pin to be used as chip select.
|
||||
|
||||
\param irq Arduino pin to be used as interrupt/GPIO.
|
||||
|
||||
\param rst Arduino pin to be used as hardware reset for the module.
|
||||
|
||||
\param gpio Arduino pin to be used as additional interrupt/GPIO.
|
||||
|
||||
\param spi SPI interface to be used, can also use software SPI implementations.
|
||||
|
||||
\param spiSettings SPI interface settings.
|
||||
*/
|
||||
Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param cs Pin to be used as chip select.
|
||||
|
||||
\param irq Pin to be used as interrupt/GPIO.
|
||||
|
||||
\param rst Pin to be used as hardware reset for the module.
|
||||
|
||||
\param gpio Pin to be used as additional interrupt/GPIO.
|
||||
*/
|
||||
Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio = RADIOLIB_NC);
|
||||
|
||||
Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio, SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Copy constructor.
|
||||
\brief Module constructor.
|
||||
\param hal A Hardware abstraction layer instance. An ArduinoHal instance for example.
|
||||
\param cs Pin to be used as chip select.
|
||||
\param irq Pin to be used as interrupt/GPIO.
|
||||
\param rst Pin to be used as hardware reset for the module.
|
||||
\param gpio Pin to be used as additional interrupt/GPIO.
|
||||
*/
|
||||
Module(RadioLibHal *hal, uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio = RADIOLIB_NC);
|
||||
|
||||
/*!
|
||||
\brief Copy constructor.
|
||||
\param mod Module instance to copy.
|
||||
*/
|
||||
Module(const Module& mod);
|
||||
|
||||
/*!
|
||||
\brief Overload for assignment operator.
|
||||
|
||||
\param frame rvalue Module.
|
||||
*/
|
||||
Module& operator=(const Module& mod);
|
||||
|
||||
// public member variables
|
||||
/*!
|
||||
\brief Hardware abstraction layer to be used.
|
||||
*/
|
||||
RadioLibHal* hal = NULL;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI read command. Defaults to 0x00.
|
||||
|
|
@ -91,6 +131,43 @@ class Module {
|
|||
*/
|
||||
uint8_t SPIwriteCommand = 0b10000000;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI no-operation command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPInopCommand = 0x00;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI status read command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPIstatusCommand = 0x00;
|
||||
|
||||
/*!
|
||||
\brief SPI address width. Defaults to 8, currently only supports 8 and 16-bit addresses.
|
||||
*/
|
||||
uint8_t SPIaddrWidth = 8;
|
||||
|
||||
/*!
|
||||
\brief Whether the SPI interface is stream-type (e.g. SX126x) or register-type (e.g. SX127x).
|
||||
Defaults to register-type SPI interfaces.
|
||||
*/
|
||||
bool SPIstreamType = false;
|
||||
|
||||
/*!
|
||||
\brief The last recorded SPI stream error.
|
||||
*/
|
||||
int16_t SPIstreamError = RADIOLIB_ERR_UNKNOWN;
|
||||
|
||||
/*!
|
||||
\brief SPI status parsing callback typedef.
|
||||
*/
|
||||
typedef int16_t (*SPIparseStatusCb_t)(uint8_t in);
|
||||
|
||||
/*!
|
||||
\brief Callback to function that will parse the module-specific status codes to RadioLib status codes.
|
||||
Typically used for modules with SPI stream-type interface (e.g. SX126x/SX128x).
|
||||
*/
|
||||
SPIparseStatusCb_t SPIparseStatusCb = nullptr;
|
||||
|
||||
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
||||
|
||||
/*!
|
||||
|
|
@ -126,281 +203,263 @@ class Module {
|
|||
|
||||
/*!
|
||||
\brief SPI read method that automatically masks unused bits. This method is the preferred SPI read mechanism.
|
||||
|
||||
\param reg Address of SPI register to read.
|
||||
|
||||
\param msb Most significant bit of the register variable. Bits above this one will be masked out.
|
||||
|
||||
\param lsb Least significant bit of the register variable. Bits below this one will be masked out.
|
||||
|
||||
\returns Masked register value or status code.
|
||||
*/
|
||||
int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
int16_t SPIgetRegValue(uint16_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
|
||||
/*!
|
||||
\brief Overwrite-safe SPI write method with verification. This method is the preferred SPI write mechanism.
|
||||
|
||||
\param reg Address of SPI register to write.
|
||||
|
||||
\param value Single byte value that will be written to the SPI register.
|
||||
|
||||
\param msb Most significant bit of the register variable. Bits above this one will not be affected by the write operation.
|
||||
|
||||
\param lsb Least significant bit of the register variable. Bits below this one will not be affected by the write operation.
|
||||
|
||||
\param checkInterval Number of milliseconds between register writing and verification reading. Some registers need up to 10ms to process the change.
|
||||
|
||||
\param checkMask Mask of bits to check, only bits set to 1 will be verified.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
|
||||
int16_t SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
|
||||
|
||||
/*!
|
||||
\brief SPI burst read method.
|
||||
|
||||
\param reg Address of SPI register to read.
|
||||
|
||||
\param numBytes Number of bytes that will be read.
|
||||
|
||||
\param inBytes Pointer to array that will hold the read data.
|
||||
*/
|
||||
void SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes);
|
||||
void SPIreadRegisterBurst(uint16_t reg, size_t numBytes, uint8_t* inBytes);
|
||||
|
||||
/*!
|
||||
\brief SPI basic read method. Use of this method is reserved for special cases, SPIgetRegValue should be used instead.
|
||||
|
||||
\param reg Address of SPI register to read.
|
||||
|
||||
\returns Value that was read from register.
|
||||
*/
|
||||
uint8_t SPIreadRegister(uint8_t reg);
|
||||
uint8_t SPIreadRegister(uint16_t reg);
|
||||
|
||||
/*!
|
||||
\brief SPI burst write method.
|
||||
|
||||
\param reg Address of SPI register to write.
|
||||
|
||||
\param data Pointer to array that holds the data that will be written.
|
||||
|
||||
\param numBytes Number of bytes that will be written.
|
||||
*/
|
||||
void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes);
|
||||
void SPIwriteRegisterBurst(uint16_t reg, uint8_t* data, size_t numBytes);
|
||||
|
||||
/*!
|
||||
\brief SPI basic write method. Use of this method is reserved for special cases, SPIsetRegValue should be used instead.
|
||||
|
||||
\param reg Address of SPI register to write.
|
||||
|
||||
\param data Value that will be written to the register.
|
||||
*/
|
||||
void SPIwriteRegister(uint8_t reg, uint8_t data);
|
||||
void SPIwriteRegister(uint16_t reg, uint8_t data);
|
||||
|
||||
/*!
|
||||
\brief SPI single transfer method.
|
||||
|
||||
\param cmd SPI access command (read/write/burst/...).
|
||||
|
||||
\param reg Address of SPI register to transfer to/from.
|
||||
|
||||
\param dataOut Data that will be transfered from master to slave.
|
||||
|
||||
\param dataIn Data that was transfered from slave to master.
|
||||
|
||||
\param numBytes Number of bytes to transfer.
|
||||
*/
|
||||
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes);
|
||||
void SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
|
||||
|
||||
/*!
|
||||
\brief Method to check the result of last SPI stream transfer.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIcheckStream();
|
||||
|
||||
/*!
|
||||
\brief Method to perform a read transaction with SPI stream.
|
||||
\param cmd SPI operation command.
|
||||
\param data Data that will be transferred from slave to master.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
|
||||
\param verify Whether to verify the result of the transaction after it is finished.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIreadStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Method to perform a read transaction with SPI stream.
|
||||
\param cmd SPI operation command.
|
||||
\param cmdLen SPI command length in bytes.
|
||||
\param data Data that will be transferred from slave to master.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
|
||||
\param verify Whether to verify the result of the transaction after it is finished.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIreadStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Method to perform a write transaction with SPI stream.
|
||||
\param cmd SPI operation command.
|
||||
\param data Data that will be transferred from master to slave.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
|
||||
\param verify Whether to verify the result of the transaction after it is finished.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIwriteStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Method to perform a write transaction with SPI stream.
|
||||
\param cmd SPI operation command.
|
||||
\param cmdLen SPI command length in bytes.
|
||||
\param data Data that will be transferred from master to slave.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
|
||||
\param verify Whether to verify the result of the transaction after it is finished.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIwriteStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief SPI single transfer method for modules with stream-type SPI interface (SX126x, SX128x etc.).
|
||||
\param cmd SPI operation command.
|
||||
\param cmdLen SPI command length in bytes.
|
||||
\param write Set to true for write commands, false for read commands.
|
||||
\param dataOut Data that will be transfered from master to slave.
|
||||
\param dataIn Data that was transfered from slave to master.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
|
||||
\param timeout GPIO wait period timeout in milliseconds.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, uint32_t timeout);
|
||||
|
||||
// pin number access methods
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of SPI chip select.
|
||||
|
||||
\returns Pin number of SPI chip select configured in the constructor.
|
||||
*/
|
||||
RADIOLIB_PIN_TYPE getCs() const { return(_cs); }
|
||||
uint32_t getCs() const { return(csPin); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of interrupt/GPIO.
|
||||
|
||||
\returns Pin number of interrupt/GPIO configured in the constructor.
|
||||
*/
|
||||
RADIOLIB_PIN_TYPE getIrq() const { return(_irq); }
|
||||
uint32_t getIrq() const { return(irqPin); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of hardware reset pin.
|
||||
|
||||
\returns Pin number of hardware reset pin configured in the constructor.
|
||||
*/
|
||||
RADIOLIB_PIN_TYPE getRst() const { return(_rst); }
|
||||
uint32_t getRst() const { return(rstPin); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of second interrupt/GPIO.
|
||||
|
||||
\returns Pin number of second interrupt/GPIO configured in the constructor.
|
||||
*/
|
||||
RADIOLIB_PIN_TYPE getGpio() const { return(_gpio); }
|
||||
uint32_t getGpio() const { return(gpioPin); }
|
||||
|
||||
/*!
|
||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
||||
\brief Some modules contain external RF switch controlled by pins.
|
||||
This function gives RadioLib control over those pins to
|
||||
automatically switch between various modes: When idle both pins
|
||||
will be LOW, during TX the `txEn` pin will be HIGH, during RX the
|
||||
`rxPin` will be HIGH.
|
||||
|
||||
Radiolib will automatically set the pin mode and value of these
|
||||
pins, so do not control them from the sketch.
|
||||
|
||||
When more than two pins or more control over the output values are
|
||||
needed, use the setRfSwitchTable() function.
|
||||
|
||||
\param rxEn RX enable pin.
|
||||
|
||||
\param txEn TX enable pin.
|
||||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
void setRfSwitchPins(uint32_t rxEn, uint32_t txEn);
|
||||
|
||||
/*!
|
||||
\brief Some modules contain external RF switch controlled by pins.
|
||||
This function gives RadioLib control over those pins to
|
||||
automatically switch between various modes.
|
||||
|
||||
Radiolib will automatically set the pin mode and value of these
|
||||
pins, so do not control them from the sketch.
|
||||
|
||||
|
||||
\param pins A reference to an array of pins to control. This
|
||||
should always be an array of 3 elements. If you need less pins,
|
||||
use RADIOLIB_NC for the unused elements.
|
||||
|
||||
\param table A reference to an array of pin values to use for each
|
||||
supported mode. Each element is an RfSwitchMode_T struct that
|
||||
lists the mode for which it applies and the values for each of the
|
||||
pins passed in the pins argument respectively.
|
||||
|
||||
The `pins` array will be copied into the Module object, so the
|
||||
original array can be deallocated after this call. However,
|
||||
a reference to the `table` array will be stored, so that array
|
||||
must remain valid as long RadioLib is being used.
|
||||
|
||||
The `mode` field in each table row should normally use any of the
|
||||
`MODE_*` constants from the Module::OpMode_t enum. However, some
|
||||
radios support additional modes and will define their own OpMode_t
|
||||
enum.
|
||||
|
||||
The length of the table is variable (to support radios that add
|
||||
additional modes), so the table must always be terminated with the
|
||||
special END_OF_MODE_TABLE value.
|
||||
|
||||
Normally all modes should be listed in the table, but for some
|
||||
radios, modes can be omitted to indicate they are not supported
|
||||
(e.g. when a radio has a high power and low power TX mode but
|
||||
external circuitry only supports low power). If applicable, this
|
||||
is documented in the radio class itself.
|
||||
|
||||
#### Example
|
||||
For example, on a board that has an RF switch with an enable pin
|
||||
connected to PA0 and a TX/RX select pin connected to PA1:
|
||||
|
||||
\code
|
||||
// In global scope, define the pin array and mode table
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PA0, PA1, RADIOLIB_NC};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{Module::MODE_IDLE, {LOW, LOW}},
|
||||
{Module::MODE_RX, {HIGH, LOW}},
|
||||
{Module::MODE_TX, {HIGH, HIGH}},
|
||||
Module::END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
...
|
||||
// Then somewhere in setup, pass them to radiolib
|
||||
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
void setRfSwitchTable(const uint32_t (&pins)[RFSWITCH_MAX_PINS], const RfSwitchMode_t table[]);
|
||||
|
||||
/*!
|
||||
\brief Find a mode in the RfSwitchTable.
|
||||
\param The mode to find.
|
||||
\returns A pointer to the RfSwitchMode_t struct in the table that
|
||||
matches the passed mode. Returns nullptr if no rfswitch pins are
|
||||
configured, or the passed mode is not listed in the table.
|
||||
*/
|
||||
const RfSwitchMode_t *findRfSwitchMode(uint8_t mode) const;
|
||||
|
||||
/*!
|
||||
\brief Set RF switch state.
|
||||
|
||||
\param rxPinState Pin state to set on Tx enable pin (usually high to transmit).
|
||||
|
||||
\param txPinState Pin state to set on Rx enable pin (usually high to receive).
|
||||
\param mode The mode to set. This must be one of the MODE_ constants, or a radio-specific constant.
|
||||
*/
|
||||
void setRfSwitchState(RADIOLIB_PIN_STATUS rxPinState, RADIOLIB_PIN_STATUS txPinState);
|
||||
void setRfSwitchState(uint8_t mode);
|
||||
|
||||
/*!
|
||||
\brief Wait for time to elapse, either using the microsecond timer, or the TimerFlag.
|
||||
Note that in interrupt timing mode, it is up to the user to set up the timing interrupt!
|
||||
|
||||
\param start Waiting start timestamp, in microseconds.
|
||||
|
||||
\param len Waiting duration, in microseconds;
|
||||
*/
|
||||
void waitForMicroseconds(uint32_t start, uint32_t len);
|
||||
|
||||
// Arduino core overrides
|
||||
|
||||
/*!
|
||||
\brief Arduino core pinMode override that checks RADIOLIB_NC as alias for unused pin.
|
||||
|
||||
\param pin Pin to change the mode of.
|
||||
|
||||
\param mode Which mode to set.
|
||||
*/
|
||||
void pinMode(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_MODE mode);
|
||||
|
||||
/*!
|
||||
\brief Arduino core digitalWrite override that checks RADIOLIB_NC as alias for unused pin.
|
||||
|
||||
\param pin Pin to write to.
|
||||
|
||||
\param value Whether to set the pin high or low.
|
||||
*/
|
||||
void digitalWrite(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_STATUS value);
|
||||
|
||||
/*!
|
||||
\brief Arduino core digitalWrite override that checks RADIOLIB_NC as alias for unused pin.
|
||||
|
||||
\param pin Pin to read from.
|
||||
|
||||
\returns Pin value.
|
||||
*/
|
||||
RADIOLIB_PIN_STATUS digitalRead(RADIOLIB_PIN_TYPE pin);
|
||||
|
||||
/*!
|
||||
\brief Arduino core tone override that checks RADIOLIB_NC as alias for unused pin and RADIOLIB_TONE_UNSUPPORTED to make sure the platform does support tone.
|
||||
|
||||
\param pin Pin to write to.
|
||||
|
||||
\param value Frequency to output.
|
||||
*/
|
||||
void tone(RADIOLIB_PIN_TYPE pin, uint16_t value, uint32_t duration = 0);
|
||||
|
||||
/*!
|
||||
\brief Arduino core noTone override that checks RADIOLIB_NC as alias for unused pin and RADIOLIB_TONE_UNSUPPORTED to make sure the platform does support tone.
|
||||
|
||||
\param pin Pin to write to.
|
||||
*/
|
||||
void noTone(RADIOLIB_PIN_TYPE pin);
|
||||
|
||||
/*!
|
||||
\brief Arduino core attachInterrupt override.
|
||||
|
||||
\param interruptNum Interrupt number.
|
||||
|
||||
\param userFunc Interrupt service routine.
|
||||
|
||||
\param mode Pin hcange direction.
|
||||
*/
|
||||
void attachInterrupt(RADIOLIB_PIN_TYPE interruptNum, void (*userFunc)(void), RADIOLIB_INTERRUPT_STATUS mode);
|
||||
|
||||
/*!
|
||||
\brief Arduino core detachInterrupt override.
|
||||
|
||||
\param interruptNum Interrupt number.
|
||||
*/
|
||||
void detachInterrupt(RADIOLIB_PIN_TYPE interruptNum);
|
||||
|
||||
/*!
|
||||
\brief Arduino core yield override.
|
||||
*/
|
||||
void yield();
|
||||
|
||||
/*!
|
||||
\brief Arduino core delay override.
|
||||
|
||||
\param ms Delay length in milliseconds.
|
||||
*/
|
||||
void delay(uint32_t ms);
|
||||
|
||||
/*!
|
||||
\brief Arduino core delayMicroseconds override.
|
||||
|
||||
\param us Delay length in microseconds.
|
||||
*/
|
||||
void delayMicroseconds(uint32_t us);
|
||||
|
||||
/*!
|
||||
\brief Arduino core millis override.
|
||||
*/
|
||||
uint32_t millis();
|
||||
|
||||
/*!
|
||||
\brief Arduino core micros override.
|
||||
*/
|
||||
uint32_t micros();
|
||||
|
||||
/*!
|
||||
\brief Arduino core pulseIn override.
|
||||
*/
|
||||
uint32_t pulseIn(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_STATUS state, uint32_t timeout);
|
||||
|
||||
/*!
|
||||
\brief Arduino core SPI begin override.
|
||||
*/
|
||||
void begin();
|
||||
|
||||
/*!
|
||||
\brief Arduino core SPI beginTransaction override.
|
||||
*/
|
||||
void beginTransaction();
|
||||
|
||||
/*!
|
||||
\brief Arduino core SPI transfer override.
|
||||
*/
|
||||
uint8_t transfer(uint8_t b);
|
||||
|
||||
/*!
|
||||
\brief Arduino core SPI endTransaction override.
|
||||
*/
|
||||
void endTransaction();
|
||||
|
||||
/*!
|
||||
\brief Arduino core SPI end override.
|
||||
*/
|
||||
void end();
|
||||
|
||||
// helper functions to set up SPI overrides on Arduino
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
void SPIbegin();
|
||||
void SPIend();
|
||||
#endif
|
||||
virtual void SPIbeginTransaction();
|
||||
virtual uint8_t SPItransfer(uint8_t b);
|
||||
virtual void SPIendTransaction();
|
||||
|
||||
/*!
|
||||
\brief Function to reflect bits within a byte.
|
||||
*/
|
||||
|
|
@ -413,77 +472,38 @@ class Module {
|
|||
|
||||
/*!
|
||||
\brief Function to dump data as hex into the debug port.
|
||||
|
||||
\param data Data to dump.
|
||||
|
||||
\param len Number of bytes to dump.
|
||||
\param width Word width (1 for uint8_t, 2 for uint16_t, 4 for uint32_t).
|
||||
\param be Print multi-byte data as big endian. Defaults to false.
|
||||
*/
|
||||
static void hexdump(uint8_t* data, size_t len);
|
||||
static void hexdump(uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
|
||||
|
||||
/*!
|
||||
\brief Function to dump device registers as hex into the debug port.
|
||||
|
||||
\param start First address to dump.
|
||||
|
||||
\param len Number of bytes to dump.
|
||||
*/
|
||||
void regdump(uint8_t start, uint8_t len);
|
||||
void regdump(uint16_t start, size_t len);
|
||||
|
||||
#if defined(RADIOLIB_DEBUG) and defined(RADIOLIB_BUILD_ARDUINO)
|
||||
static size_t serialPrintf(const char* format, ...);
|
||||
#endif
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
uint32_t csPin = RADIOLIB_NC;
|
||||
uint32_t irqPin = RADIOLIB_NC;
|
||||
uint32_t rstPin = RADIOLIB_NC;
|
||||
uint32_t gpioPin = RADIOLIB_NC;
|
||||
|
||||
// pins
|
||||
RADIOLIB_PIN_TYPE _cs = RADIOLIB_NC;
|
||||
RADIOLIB_PIN_TYPE _irq = RADIOLIB_NC;
|
||||
RADIOLIB_PIN_TYPE _rst = RADIOLIB_NC;
|
||||
RADIOLIB_PIN_TYPE _gpio = RADIOLIB_NC;
|
||||
|
||||
// SPI interface (Arduino only)
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
SPIClass* _spi = NULL;
|
||||
SPISettings _spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS;
|
||||
bool _initInterface = false;
|
||||
#endif
|
||||
|
||||
// RF switch presence and pins
|
||||
bool _useRfSwitch = false;
|
||||
RADIOLIB_PIN_TYPE _rxEn = RADIOLIB_NC;
|
||||
RADIOLIB_PIN_TYPE _txEn = RADIOLIB_NC;
|
||||
// RF switch pins and table
|
||||
uint32_t rfSwitchPins[RFSWITCH_MAX_PINS] = { RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC };
|
||||
const RfSwitchMode_t *rfSwitchTable = nullptr;
|
||||
|
||||
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
||||
uint32_t _prevTimingLen = 0;
|
||||
#endif
|
||||
|
||||
// hardware abstraction layer callbacks
|
||||
// this is placed at the end of Module class because the callback generator macros
|
||||
// screw with the private/public access specifiers
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_PIN_MODE);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_DIGITAL_WRITE);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_DIGITAL_READ);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_TONE);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_NO_TONE);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_ATTACH_INTERRUPT);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_DETACH_INTERRUPT);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_YIELD);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_DELAY);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_DELAY_MICROSECONDS);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_MILLIS);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_MICROS);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_PULSE_IN);
|
||||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
RADIOLIB_GENERATE_CALLBACK_SPI(RADIOLIB_CB_ARGS_SPI_BEGIN);
|
||||
RADIOLIB_GENERATE_CALLBACK_SPI(RADIOLIB_CB_ARGS_SPI_BEGIN_TRANSACTION);
|
||||
RADIOLIB_GENERATE_CALLBACK_SPI(RADIOLIB_CB_ARGS_SPI_TRANSFER);
|
||||
RADIOLIB_GENERATE_CALLBACK_SPI(RADIOLIB_CB_ARGS_SPI_END_TRANSACTION);
|
||||
RADIOLIB_GENERATE_CALLBACK_SPI(RADIOLIB_CB_ARGS_SPI_END);
|
||||
#else
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_SPI_BEGIN);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_SPI_BEGIN_TRANSACTION);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_SPI_TRANSFER);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_SPI_END_TRANSACTION);
|
||||
RADIOLIB_GENERATE_CALLBACK(RADIOLIB_CB_ARGS_SPI_END);
|
||||
uint32_t prevTimingLen = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,12 @@
|
|||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
|
||||
#include "Hal.h"
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
#include "ArduinoHal.h"
|
||||
#endif
|
||||
|
||||
|
||||
// warnings are printed in this file since BuildOpt.h is compiled in multiple places
|
||||
|
||||
// check God mode
|
||||
|
|
@ -78,6 +84,7 @@
|
|||
#include "modules/SX126x/SX1261.h"
|
||||
#include "modules/SX126x/SX1262.h"
|
||||
#include "modules/SX126x/SX1268.h"
|
||||
#include "modules/SX126x/STM32WLx.h"
|
||||
#include "modules/SX127x/SX1272.h"
|
||||
#include "modules/SX127x/SX1273.h"
|
||||
#include "modules/SX127x/SX1276.h"
|
||||
|
|
@ -99,6 +106,9 @@
|
|||
#include "protocols/SSTV/SSTV.h"
|
||||
#include "protocols/FSK4/FSK4.h"
|
||||
#include "protocols/APRS/APRS.h"
|
||||
#include "protocols/ExternalRadio/ExternalRadio.h"
|
||||
#include "protocols/Print/Print.h"
|
||||
#include "protocols/BellModem/BellModem.h"
|
||||
|
||||
// only create Radio class when using RadioShield
|
||||
#if defined(RADIOLIB_RADIOSHIELD)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#if !defined(_RADIOLIB_TYPES_H)
|
||||
#define _RADIOLIB_TYPES_H
|
||||
|
||||
// user build options may override the default
|
||||
#include "BuildOptUser.h"
|
||||
#include "BuildOpt.h"
|
||||
|
||||
/*!
|
||||
|
|
@ -63,6 +65,31 @@
|
|||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup config_standby Standby mode type aliases.
|
||||
|
||||
\{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Default standby used by the module
|
||||
*/
|
||||
#define RADIOLIB_STANDBY_DEFAULT (0x00)
|
||||
|
||||
/*!
|
||||
\brief Warm standby (e.g. crystal left running).
|
||||
*/
|
||||
#define RADIOLIB_STANDBY_WARM (0x01)
|
||||
|
||||
/*!
|
||||
\brief Cold standby (e.g. only internal RC oscillator running).
|
||||
*/
|
||||
#define RADIOLIB_STANDBY_COLD (0x02)
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup status_codes Status Codes
|
||||
|
||||
|
|
@ -287,6 +314,28 @@
|
|||
*/
|
||||
#define RADIOLIB_ERR_MIC_E_TELEMETRY_STATUS (-204)
|
||||
|
||||
// SSDV status codes
|
||||
|
||||
/*!
|
||||
\brief SSDV mode is invalid.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_SSDV_MODE (-301)
|
||||
|
||||
/*!
|
||||
\brief Image size is invalid.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_IMAGE_SIZE (-302)
|
||||
|
||||
/*!
|
||||
\brief Image quality is invalid.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_IMAGE_QUALITY (-303)
|
||||
|
||||
/*!
|
||||
\brief Image subsampling is invalid.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_SUBSAMPLING (-304)
|
||||
|
||||
// RTTY status codes
|
||||
|
||||
/*!
|
||||
|
|
@ -362,6 +411,11 @@
|
|||
|
||||
/*!
|
||||
\brief SX126x failed to execute SPI command.
|
||||
Often this means that the module is trying to use TCXO while
|
||||
XTAL is connected (or vice versa). Make sure your crystal setup
|
||||
(e.g. TCXO reference voltage) matches your hardware by setting
|
||||
"tcxoVoltage" to 0 when using XTAL module, or to appropriate value
|
||||
when using TCXO module.
|
||||
*/
|
||||
#define RADIOLIB_ERR_SPI_CMD_FAILED (-707)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
#include "CC1101.h"
|
||||
#include <math.h>
|
||||
#if !defined(RADIOLIB_EXCLUDE_CC1101)
|
||||
|
||||
CC1101::CC1101(Module* module) : PhysicalLayer(RADIOLIB_CC1101_FREQUENCY_STEP_SIZE, RADIOLIB_CC1101_MAX_PACKET_LENGTH) {
|
||||
_mod = module;
|
||||
this->mod = module;
|
||||
}
|
||||
|
||||
Module* CC1101::getMod() {
|
||||
return(_mod);
|
||||
return(this->mod);
|
||||
}
|
||||
|
||||
int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t preambleLength) {
|
||||
int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
|
||||
// set module properties
|
||||
_mod->SPIreadCommand = RADIOLIB_CC1101_CMD_READ;
|
||||
_mod->SPIwriteCommand = RADIOLIB_CC1101_CMD_WRITE;
|
||||
_mod->init();
|
||||
_mod->pinMode(_mod->getIrq(), INPUT);
|
||||
this->mod->SPIreadCommand = RADIOLIB_CC1101_CMD_READ;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_CC1101_CMD_WRITE;
|
||||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
|
||||
// try to find the CC1101 chip
|
||||
uint8_t i = 0;
|
||||
|
|
@ -24,28 +25,18 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
if((version == RADIOLIB_CC1101_VERSION_CURRENT) || (version == RADIOLIB_CC1101_VERSION_LEGACY) || (version == RADIOLIB_CC1101_VERSION_CLONE)) {
|
||||
flagFound = true;
|
||||
} else {
|
||||
#if defined(RADIOLIB_DEBUG)
|
||||
RADIOLIB_DEBUG_PRINT(F("CC1101 not found! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) RADIOLIB_CC1101_REG_VERSION == "));
|
||||
|
||||
char buffHex[7];
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0004/0x0014"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
_mod->delay(10);
|
||||
RADIOLIB_DEBUG_PRINTLN("CC1101 not found! (%d of 10 tries) RADIOLIB_CC1101_REG_VERSION == 0x%04X, expected 0x0004/0x0014", i + 1, version);
|
||||
this->mod->hal->delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(!flagFound) {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No CC1101 found!"));
|
||||
_mod->term();
|
||||
RADIOLIB_DEBUG_PRINTLN("No CC1101 found!");
|
||||
this->mod->term();
|
||||
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tCC1101"));
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tCC1101");
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
|
|
@ -69,7 +60,7 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default TX output power
|
||||
state = setOutputPower(power);
|
||||
state = setOutputPower(pwr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default packet length mode
|
||||
|
|
@ -77,7 +68,7 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default preamble length
|
||||
state = setPreambleLength(preambleLength);
|
||||
state = setPreambleLength(preambleLength, preambleLength - 4);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default data shaping
|
||||
|
|
@ -94,37 +85,48 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// flush FIFOs
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX | RADIOLIB_CC1101_CMD_READ);
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
void CC1101::reset() {
|
||||
// this is the manual power-on-reset sequence
|
||||
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
|
||||
this->mod->hal->delayMicroseconds(5);
|
||||
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
|
||||
this->mod->hal->delayMicroseconds(40);
|
||||
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
|
||||
this->mod->hal->delay(10);
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_RESET);
|
||||
}
|
||||
|
||||
int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// calculate timeout (5ms + 500 % of expected time-on-air)
|
||||
uint32_t timeout = 5000000 + (uint32_t)((((float)(len * 8)) / (_br * 1000.0)) * 5000000.0);
|
||||
uint32_t timeout = 5000000 + (uint32_t)((((float)(len * 8)) / (this->bitRate * 1000.0)) * 5000000.0);
|
||||
|
||||
// start transmission
|
||||
int16_t state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission start or timeout
|
||||
uint32_t start = _mod->micros();
|
||||
while(!_mod->digitalRead(_mod->getGpio())) {
|
||||
_mod->yield();
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(_mod->micros() - start > timeout) {
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// wait for transmission end or timeout
|
||||
start = _mod->micros();
|
||||
while(_mod->digitalRead(_mod->getGpio())) {
|
||||
_mod->yield();
|
||||
start = this->mod->hal->micros();
|
||||
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(_mod->micros() - start > timeout) {
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
|
|
@ -135,18 +137,18 @@ int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
int16_t CC1101::receive(uint8_t* data, size_t len) {
|
||||
// calculate timeout (500 ms + 400 full max-length packets at current bit rate)
|
||||
uint32_t timeout = 500000 + (1.0/(_br*1000.0))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0);
|
||||
uint32_t timeout = 500000 + (1.0/(this->bitRate*1000.0))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0);
|
||||
|
||||
// start reception
|
||||
int16_t state = startReceive();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet or timeout
|
||||
uint32_t start = _mod->micros();
|
||||
while(!_mod->digitalRead(_mod->getIrq())) {
|
||||
_mod->yield();
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(_mod->micros() - start > timeout) {
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
|
|
@ -162,10 +164,15 @@ int16_t CC1101::standby() {
|
|||
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
||||
|
||||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(LOW, LOW);
|
||||
this->mod->setRfSwitchState(Module::MODE_IDLE);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t CC1101::standby(uint8_t mode) {
|
||||
(void)mode;
|
||||
return(standby());
|
||||
}
|
||||
|
||||
int16_t CC1101::transmitDirect(uint32_t frf) {
|
||||
return transmitDirect(true, frf);
|
||||
}
|
||||
|
|
@ -176,7 +183,7 @@ int16_t CC1101::transmitDirectAsync(uint32_t frf) {
|
|||
|
||||
int16_t CC1101::transmitDirect(bool sync, uint32_t frf) {
|
||||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(LOW, HIGH);
|
||||
this->mod->setRfSwitchState(Module::MODE_TX);
|
||||
|
||||
// user requested to start transmitting immediately (required for RTTY)
|
||||
if(frf != 0) {
|
||||
|
|
@ -206,7 +213,7 @@ int16_t CC1101::receiveDirectAsync() {
|
|||
|
||||
int16_t CC1101::receiveDirect(bool sync) {
|
||||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(HIGH, LOW);
|
||||
this->mod->setRfSwitchState(Module::MODE_RX);
|
||||
|
||||
// activate direct mode
|
||||
int16_t state = directMode(sync);
|
||||
|
|
@ -220,38 +227,38 @@ int16_t CC1101::receiveDirect(bool sync) {
|
|||
int16_t CC1101::packetMode() {
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL1, RADIOLIB_CC1101_CRC_AUTOFLUSH_OFF | RADIOLIB_CC1101_APPEND_STATUS_ON | RADIOLIB_CC1101_ADR_CHK_NONE, 3, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_WHITE_DATA_OFF | RADIOLIB_CC1101_PKT_FORMAT_NORMAL, 6, 4);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_CRC_ON | _packetLengthConfig, 2, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_CRC_ON | this->packetLengthConfig, 2, 0);
|
||||
return(state);
|
||||
}
|
||||
|
||||
void CC1101::setGdo0Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir) {
|
||||
_mod->attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, dir);
|
||||
void CC1101::setGdo0Action(void (*func)(void), uint32_t dir) {
|
||||
this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()), func, dir);
|
||||
}
|
||||
|
||||
void CC1101::clearGdo0Action() {
|
||||
_mod->detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
this->mod->hal->detachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()));
|
||||
}
|
||||
|
||||
void CC1101::setGdo2Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir) {
|
||||
if(_mod->getGpio() == RADIOLIB_NC) {
|
||||
void CC1101::setGdo2Action(void (*func)(void), uint32_t dir) {
|
||||
if(this->mod->getGpio() == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
_mod->pinMode(_mod->getGpio(), INPUT);
|
||||
_mod->attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), func, dir);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getGpio()), func, dir);
|
||||
}
|
||||
|
||||
void CC1101::clearGdo2Action() {
|
||||
if(_mod->getGpio() == RADIOLIB_NC) {
|
||||
if(this->mod->getGpio() == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
_mod->detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()));
|
||||
this->mod->hal->detachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getGpio()));
|
||||
}
|
||||
|
||||
int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// check packet length
|
||||
if(len > RADIOLIB_CC1101_MAX_PACKET_LENGTH) {
|
||||
/*if(len > RADIOLIB_CC1101_MAX_PACKET_LENGTH) {
|
||||
return(RADIOLIB_ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
}*/
|
||||
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
|
@ -260,16 +267,22 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
|
||||
|
||||
// set GDO0 mapping
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED, 5, 0);
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_SYNC_WORD_SENT_OR_PKT_RECEIVED, 5, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
/*int16_t state = RADIOLIB_ERR_NONE;
|
||||
if(len > RADIOLIB_CC1101_MAX_PACKET_LENGTH) {
|
||||
state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_TX_FIFO_ABOVE_THR);
|
||||
} else {
|
||||
state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_SYNC_WORD_SENT_OR_PKT_RECEIVED);
|
||||
}*/
|
||||
|
||||
// data put on FIFO.
|
||||
// data put on FIFO
|
||||
uint8_t dataSent = 0;
|
||||
|
||||
// optionally write packet length
|
||||
if (_packetLengthConfig == RADIOLIB_CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
if (this->packetLengthConfig == RADIOLIB_CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
|
||||
// enforce variable len limit.
|
||||
// enforce variable len limit
|
||||
if (len > RADIOLIB_CC1101_MAX_PACKET_LENGTH - 1) {
|
||||
return (RADIOLIB_ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
|
@ -285,36 +298,47 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
dataSent += 1;
|
||||
}
|
||||
|
||||
// fill the FIFO.
|
||||
// fill the FIFO
|
||||
/*if(len > RADIOLIB_CC1101_MAX_PACKET_LENGTH) {
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_FIFO, data, RADIOLIB_CC1101_FIFO_THRESH_TX);
|
||||
} else {
|
||||
uint8_t initialWrite = min((uint8_t)len, (uint8_t)(RADIOLIB_CC1101_FIFO_SIZE - dataSent));
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_FIFO, data, initialWrite);
|
||||
dataSent += initialWrite;
|
||||
}*/
|
||||
uint8_t initialWrite = min((uint8_t)len, (uint8_t)(RADIOLIB_CC1101_FIFO_SIZE - dataSent));
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_FIFO, data, initialWrite);
|
||||
dataSent += initialWrite;
|
||||
|
||||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(LOW, HIGH);
|
||||
this->mod->setRfSwitchState(Module::MODE_TX);
|
||||
|
||||
// set mode to transmit
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
|
||||
|
||||
// keep feeding the FIFO until the packet is over.
|
||||
if(len > RADIOLIB_CC1101_MAX_PACKET_LENGTH) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// keep feeding the FIFO until the packet is over
|
||||
while (dataSent < len) {
|
||||
// get number of bytes in FIFO.
|
||||
// get number of bytes in FIFO
|
||||
uint8_t bytesInFIFO = SPIgetRegValue(RADIOLIB_CC1101_REG_TXBYTES, 6, 0);
|
||||
|
||||
// if there's room then put other data.
|
||||
// if there's room then put other data
|
||||
if (bytesInFIFO < RADIOLIB_CC1101_FIFO_SIZE) {
|
||||
uint8_t bytesToWrite = min((uint8_t)(RADIOLIB_CC1101_FIFO_SIZE - bytesInFIFO), (uint8_t)(len - dataSent));
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_FIFO, &data[dataSent], bytesToWrite);
|
||||
dataSent += bytesToWrite;
|
||||
} else {
|
||||
// wait for radio to send some data.
|
||||
// wait for radio to send some data
|
||||
/*
|
||||
* Does this work for all rates? If 1 ms is longer than the 1ms delay
|
||||
* then the entire FIFO will be transmitted during that delay.
|
||||
*
|
||||
* TODO: test this on real hardware
|
||||
*/
|
||||
delayMicroseconds(250);
|
||||
this->mod->hal->delayMicroseconds(250);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -324,6 +348,7 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t CC1101::finishTransmit() {
|
||||
// set mode to standby to disable transmitter/RF switch
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// flush Tx FIFO
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
|
||||
|
|
@ -333,18 +358,20 @@ int16_t CC1101::finishTransmit() {
|
|||
|
||||
int16_t CC1101::startReceive() {
|
||||
// set mode to standby
|
||||
standby();
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// flush Rx FIFO
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX | RADIOLIB_CC1101_CMD_READ);
|
||||
|
||||
// set GDO0 mapping: Asserted when RX FIFO > 4 bytes.
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_RX_FIFO_FULL_OR_PKT_END);
|
||||
state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_RX_FIFO_FULL_OR_PKT_END);
|
||||
//state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_SYNC_WORD_SENT_OR_PKT_RECEIVED);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_FIFOTHR, RADIOLIB_CC1101_FIFO_THR_TX_61_RX_4, 3, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(HIGH, LOW);
|
||||
this->mod->setRfSwitchState(Module::MODE_RX);
|
||||
|
||||
// set mode to receive
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
||||
|
|
@ -352,13 +379,30 @@ int16_t CC1101::startReceive() {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len) {
|
||||
(void)timeout;
|
||||
(void)irqFlags;
|
||||
(void)irqMask;
|
||||
(void)len;
|
||||
return(startReceive());
|
||||
}
|
||||
|
||||
int16_t CC1101::readData(uint8_t* data, size_t len) {
|
||||
// get packet length
|
||||
size_t length = getPacketLength();
|
||||
/*RADIOLIB_DEBUG_PRINTLN("length = %d", length);
|
||||
if(length == 0) {
|
||||
this->packetLengthQueried = false;
|
||||
standby();
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}*/
|
||||
if((len != 0) && (len < length)) {
|
||||
// user requested less data than we got, only return what was requested
|
||||
length = len;
|
||||
}
|
||||
//SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE | RADIOLIB_CC1101_CMD_READ);
|
||||
SPIreadRegister(RADIOLIB_CC1101_REG_RXBYTES);
|
||||
|
||||
// check address filtering
|
||||
uint8_t filter = SPIgetRegValue(RADIOLIB_CC1101_REG_PKTCTRL1, 1, 0);
|
||||
|
|
@ -368,17 +412,17 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
|
|||
|
||||
uint8_t bytesInFIFO = SPIgetRegValue(RADIOLIB_CC1101_REG_RXBYTES, 6, 0);
|
||||
size_t readBytes = 0;
|
||||
uint32_t lastPop = millis();
|
||||
uint32_t lastPop = this->mod->hal->millis();
|
||||
|
||||
// keep reading from FIFO until we get all the packet.
|
||||
while (readBytes < length) {
|
||||
if (bytesInFIFO == 0) {
|
||||
if (millis() - lastPop > 5) {
|
||||
if (this->mod->hal->millis() - lastPop > 5) {
|
||||
// readData was required to read a packet longer than the one received.
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No data for more than 5mS. Stop here."));
|
||||
RADIOLIB_DEBUG_PRINTLN("No data for more than 5mS. Stop here.");
|
||||
break;
|
||||
} else {
|
||||
delay(1);
|
||||
this->mod->hal->delay(1);
|
||||
bytesInFIFO = SPIgetRegValue(RADIOLIB_CC1101_REG_RXBYTES, 6, 0);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -388,7 +432,7 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
|
|||
uint8_t bytesToRead = min((uint8_t)(length - readBytes), bytesInFIFO);
|
||||
SPIreadRegisterBurst(RADIOLIB_CC1101_REG_FIFO, bytesToRead, &(data[readBytes]));
|
||||
readBytes += bytesToRead;
|
||||
lastPop = millis();
|
||||
lastPop = this->mod->hal->millis();
|
||||
|
||||
// Get how many bytes are left in FIFO.
|
||||
bytesInFIFO = SPIgetRegValue(RADIOLIB_CC1101_REG_RXBYTES, 6, 0);
|
||||
|
|
@ -398,35 +442,35 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
|
|||
bool isAppendStatus = SPIgetRegValue(RADIOLIB_CC1101_REG_PKTCTRL1, 2, 2) == RADIOLIB_CC1101_APPEND_STATUS_ON;
|
||||
|
||||
// for some reason, we need this delay here to get the correct status bytes
|
||||
delay(3);
|
||||
this->mod->hal->delay(3);
|
||||
|
||||
// If status byte is enabled at least 2 bytes (2 status bytes + any following packet) will remain in FIFO.
|
||||
if (isAppendStatus) {
|
||||
// read RSSI byte
|
||||
_rawRSSI = SPIgetRegValue(RADIOLIB_CC1101_REG_FIFO);
|
||||
this->rawRSSI = SPIgetRegValue(RADIOLIB_CC1101_REG_FIFO);
|
||||
|
||||
// read LQI and CRC byte
|
||||
uint8_t val = SPIgetRegValue(RADIOLIB_CC1101_REG_FIFO);
|
||||
_rawLQI = val & 0x7F;
|
||||
this->rawLQI = val & 0x7F;
|
||||
|
||||
// check CRC
|
||||
if (_crcOn && (val & RADIOLIB_CC1101_CRC_OK) == RADIOLIB_CC1101_CRC_ERROR) {
|
||||
_packetLengthQueried = false;
|
||||
if (this->crcOn && (val & RADIOLIB_CC1101_CRC_OK) == RADIOLIB_CC1101_CRC_ERROR) {
|
||||
this->packetLengthQueried = false;
|
||||
return (RADIOLIB_ERR_CRC_MISMATCH);
|
||||
}
|
||||
}
|
||||
|
||||
// clear internal flag so getPacketLength can return the new packet length
|
||||
_packetLengthQueried = false;
|
||||
this->packetLengthQueried = false;
|
||||
|
||||
// Flush then standby according to RXOFF_MODE (default: RADIOLIB_CC1101_RXOFF_IDLE)
|
||||
if (SPIgetRegValue(RADIOLIB_CC1101_REG_MCSM1, 3, 2) == RADIOLIB_CC1101_RXOFF_IDLE) {
|
||||
|
||||
// flush Rx FIFO
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
||||
// flush Rx FIFO
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX | RADIOLIB_CC1101_CMD_READ);
|
||||
}
|
||||
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
|
@ -451,11 +495,11 @@ int16_t CC1101::setFrequency(float freq) {
|
|||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_FREQ0, FRF & 0x0000FF, 7, 0);
|
||||
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
_freq = freq;
|
||||
this->frequency = freq;
|
||||
}
|
||||
|
||||
// Update the TX power accordingly to new freq. (PA values depend on chosen freq)
|
||||
return(setOutputPower(_power));
|
||||
return(setOutputPower(this->power));
|
||||
}
|
||||
|
||||
int16_t CC1101::setBitRate(float br) {
|
||||
|
|
@ -473,7 +517,7 @@ int16_t CC1101::setBitRate(float br) {
|
|||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG4, e, 3, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG3, m);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
_br = br;
|
||||
this->bitRate = br;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
|
@ -532,7 +576,7 @@ int16_t CC1101::getFrequencyDeviation(float *freqDev) {
|
|||
}
|
||||
|
||||
// if ASK/OOK, deviation makes no sense
|
||||
if (_modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK) {
|
||||
if (this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK) {
|
||||
*freqDev = 0.0;
|
||||
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
|
@ -551,16 +595,16 @@ int16_t CC1101::getFrequencyDeviation(float *freqDev) {
|
|||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t CC1101::setOutputPower(int8_t power) {
|
||||
int16_t CC1101::setOutputPower(int8_t pwr) {
|
||||
// round to the known frequency settings
|
||||
uint8_t f;
|
||||
if(_freq < 374.0) {
|
||||
if(this->frequency < 374.0) {
|
||||
// 315 MHz
|
||||
f = 0;
|
||||
} else if(_freq < 650.5) {
|
||||
} else if(this->frequency < 650.5) {
|
||||
// 434 MHz
|
||||
f = 1;
|
||||
} else if(_freq < 891.5) {
|
||||
} else if(this->frequency < 891.5) {
|
||||
// 868 MHz
|
||||
f = 2;
|
||||
} else {
|
||||
|
|
@ -579,7 +623,7 @@ int16_t CC1101::setOutputPower(int8_t power) {
|
|||
{0xC2, 0xC0, 0xC2, 0xC0}};
|
||||
|
||||
uint8_t powerRaw;
|
||||
switch(power) {
|
||||
switch(pwr) {
|
||||
case -30:
|
||||
powerRaw = paTable[0][f];
|
||||
break;
|
||||
|
|
@ -609,9 +653,9 @@ int16_t CC1101::setOutputPower(int8_t power) {
|
|||
}
|
||||
|
||||
// store the value
|
||||
_power = power;
|
||||
this->power = pwr;
|
||||
|
||||
if(_modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
|
||||
if(this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
|
||||
// Amplitude modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting a 0 (no power)
|
||||
// PA_TABLE[1] is the power to be used when transmitting a 1 (full power)
|
||||
|
|
@ -655,10 +699,10 @@ int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits, bo
|
|||
return(setSyncWord(syncWord, sizeof(syncWord), maxErrBits, requireCarrierSense));
|
||||
}
|
||||
|
||||
int16_t CC1101::setPreambleLength(uint8_t preambleLength) {
|
||||
int16_t CC1101::setPreambleLength(uint8_t preambleLength, uint8_t qualityThreshold) {
|
||||
// check allowed values
|
||||
uint8_t value;
|
||||
switch(preambleLength){
|
||||
switch(preambleLength) {
|
||||
case 16:
|
||||
value = RADIOLIB_CC1101_NUM_PREAMBLE_2;
|
||||
break;
|
||||
|
|
@ -687,7 +731,14 @@ int16_t CC1101::setPreambleLength(uint8_t preambleLength) {
|
|||
return(RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH);
|
||||
}
|
||||
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG1, value, 6, 4));
|
||||
// set preabmble quality threshold and the actual length
|
||||
uint8_t pqt = qualityThreshold/4;
|
||||
if(pqt > 7) {
|
||||
pqt = 7;
|
||||
}
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL1, pqt << 5, 7, 5);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG1, value, 6, 4);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) {
|
||||
|
|
@ -723,7 +774,7 @@ int16_t CC1101::setOOK(bool enableOOK) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update current modulation
|
||||
_modulation = RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK;
|
||||
this->modulation = RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK;
|
||||
} else {
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, RADIOLIB_CC1101_MOD_FORMAT_2_FSK, 6, 4);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
|
@ -733,21 +784,21 @@ int16_t CC1101::setOOK(bool enableOOK) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update current modulation
|
||||
_modulation = RADIOLIB_CC1101_MOD_FORMAT_2_FSK;
|
||||
this->modulation = RADIOLIB_CC1101_MOD_FORMAT_2_FSK;
|
||||
}
|
||||
|
||||
// Update PA_TABLE values according to the new _modulation.
|
||||
return(setOutputPower(_power));
|
||||
// Update PA_TABLE values according to the new this->modulation.
|
||||
return(setOutputPower(this->power));
|
||||
}
|
||||
|
||||
float CC1101::getRSSI() {
|
||||
float rssi;
|
||||
|
||||
if (_directMode) {
|
||||
if(_rawRSSI >= 128) {
|
||||
rssi = (((float)_rawRSSI - 256.0)/2.0) - 74.0;
|
||||
if (this->directModeEnabled) {
|
||||
if(this->rawRSSI >= 128) {
|
||||
rssi = (((float)this->rawRSSI - 256.0)/2.0) - 74.0;
|
||||
} else {
|
||||
rssi = (((float)_rawRSSI)/2.0) - 74.0;
|
||||
rssi = (((float)this->rawRSSI)/2.0) - 74.0;
|
||||
}
|
||||
} else {
|
||||
uint8_t rawRssi = SPIreadRegister(RADIOLIB_CC1101_REG_RSSI);
|
||||
|
|
@ -764,24 +815,38 @@ float CC1101::getRSSI() {
|
|||
}
|
||||
|
||||
uint8_t CC1101::getLQI() const {
|
||||
return(_rawLQI);
|
||||
return(this->rawLQI);
|
||||
}
|
||||
|
||||
size_t CC1101::getPacketLength(bool update) {
|
||||
if(!_packetLengthQueried && update) {
|
||||
if (_packetLengthConfig == RADIOLIB_CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
_packetLength = SPIreadRegister(RADIOLIB_CC1101_REG_FIFO);
|
||||
RADIOLIB_DEBUG_PRINTLN("this->packetLengthQueried=%d", this->packetLengthQueried);
|
||||
RADIOLIB_DEBUG_PRINTLN("update=%d", update);
|
||||
RADIOLIB_DEBUG_PRINTLN("this->packetLengthConfig=%d", this->packetLengthConfig);
|
||||
if(!this->packetLengthQueried && update) {
|
||||
if (this->packetLengthConfig == RADIOLIB_CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
this->packetLength = 0;
|
||||
while(this->packetLength == 0) {
|
||||
this->packetLength = SPIreadRegister(RADIOLIB_CC1101_REG_FIFO);
|
||||
}
|
||||
|
||||
} else {
|
||||
_packetLength = SPIreadRegister(RADIOLIB_CC1101_REG_PKTLEN);
|
||||
this->packetLength = SPIreadRegister(RADIOLIB_CC1101_REG_PKTLEN);
|
||||
}
|
||||
|
||||
_packetLengthQueried = true;
|
||||
this->packetLengthQueried = true;
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN("this->packetLength=%d", this->packetLength);
|
||||
|
||||
return(_packetLength);
|
||||
return(this->packetLength);
|
||||
}
|
||||
|
||||
int16_t CC1101::fixedPacketLengthMode(uint8_t len) {
|
||||
if(len == 0) {
|
||||
// infinite packet mode
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_LENGTH_CONFIG_INFINITE, 1, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
return(setPacketMode(RADIOLIB_CC1101_LENGTH_CONFIG_FIXED, len));
|
||||
}
|
||||
|
||||
|
|
@ -790,52 +855,56 @@ int16_t CC1101::variablePacketLengthMode(uint8_t maxLen) {
|
|||
}
|
||||
|
||||
int16_t CC1101::enableSyncWordFiltering(uint8_t maxErrBits, bool requireCarrierSense) {
|
||||
switch(maxErrBits){
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
|
||||
switch(maxErrBits) {
|
||||
case 0:
|
||||
// in 16 bit sync word, expect all 16 bits
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, (requireCarrierSense ? RADIOLIB_CC1101_SYNC_MODE_16_16_THR : RADIOLIB_CC1101_SYNC_MODE_16_16), 2, 0));
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, (requireCarrierSense ? RADIOLIB_CC1101_SYNC_MODE_16_16_THR : RADIOLIB_CC1101_SYNC_MODE_16_16), 2, 0);
|
||||
break;
|
||||
case 1:
|
||||
// in 16 bit sync word, expect at least 15 bits
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, (requireCarrierSense ? RADIOLIB_CC1101_SYNC_MODE_15_16_THR : RADIOLIB_CC1101_SYNC_MODE_15_16), 2, 0));
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, (requireCarrierSense ? RADIOLIB_CC1101_SYNC_MODE_15_16_THR : RADIOLIB_CC1101_SYNC_MODE_15_16), 2, 0);
|
||||
break;
|
||||
default:
|
||||
return(RADIOLIB_ERR_INVALID_SYNC_WORD);
|
||||
state = RADIOLIB_ERR_INVALID_SYNC_WORD;
|
||||
break;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::disableSyncWordFiltering(bool requireCarrierSense) {
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, (requireCarrierSense ? RADIOLIB_CC1101_SYNC_MODE_NONE_THR : RADIOLIB_CC1101_SYNC_MODE_NONE), 2, 0));
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, (requireCarrierSense ? RADIOLIB_CC1101_SYNC_MODE_NONE_THR : RADIOLIB_CC1101_SYNC_MODE_NONE), 2, 0);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::setCrcFiltering(bool crcOn) {
|
||||
_crcOn = crcOn;
|
||||
int16_t CC1101::setCrcFiltering(bool enable) {
|
||||
this->crcOn = enable;
|
||||
|
||||
if (crcOn == true) {
|
||||
if (this->crcOn == true) {
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_CRC_ON, 2, 2));
|
||||
} else {
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_CRC_OFF, 2, 2));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::setPromiscuousMode(bool promiscuous) {
|
||||
int16_t CC1101::setPromiscuousMode(bool enable) {
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
|
||||
if (_promiscuous == promiscuous) {
|
||||
if(this->promiscuous == enable) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
if (promiscuous == true) {
|
||||
// disable preamble detection and generation
|
||||
state = setPreambleLength(0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
if(enable) {
|
||||
// disable sync word filtering and insertion
|
||||
// this also disables preamble
|
||||
state = disableSyncWordFiltering();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable CRC filtering
|
||||
state = setCrcFiltering(false);
|
||||
} else {
|
||||
state = setPreambleLength(RADIOLIB_CC1101_DEFAULT_PREAMBLELEN);
|
||||
state = setPreambleLength(RADIOLIB_CC1101_DEFAULT_PREAMBLELEN, RADIOLIB_CC1101_DEFAULT_PREAMBLELEN/4);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable sync word filtering and insertion
|
||||
|
|
@ -846,13 +915,13 @@ int16_t CC1101::setPromiscuousMode(bool promiscuous) {
|
|||
state = setCrcFiltering(true);
|
||||
}
|
||||
|
||||
_promiscuous = promiscuous;
|
||||
this->promiscuous = enable;
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
bool CC1101::getPromiscuousMode() {
|
||||
return (_promiscuous);
|
||||
return (this->promiscuous);
|
||||
}
|
||||
|
||||
int16_t CC1101::setDataShaping(uint8_t sh) {
|
||||
|
|
@ -898,17 +967,21 @@ int16_t CC1101::setEncoding(uint8_t encoding) {
|
|||
}
|
||||
}
|
||||
|
||||
void CC1101::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||
_mod->setRfSwitchPins(rxEn, txEn);
|
||||
void CC1101::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
|
||||
this->mod->setRfSwitchPins(rxEn, txEn);
|
||||
}
|
||||
|
||||
void CC1101::setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
|
||||
this->mod->setRfSwitchTable(pins, table);
|
||||
}
|
||||
|
||||
uint8_t CC1101::randomByte() {
|
||||
// set mode to Rx
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
||||
RADIOLIB_DEBUG_PRINTLN("random");
|
||||
RADIOLIB_DEBUG_PRINTLN("CC1101::randomByte");
|
||||
|
||||
// wait a bit for the RSSI reading to stabilise
|
||||
_mod->delay(10);
|
||||
this->mod->hal->delay(10);
|
||||
|
||||
// read RSSI value 8 times, always keep just the least significant bit
|
||||
uint8_t randByte = 0x00;
|
||||
|
|
@ -928,30 +1001,39 @@ int16_t CC1101::getChipVersion() {
|
|||
|
||||
#if !defined(RADIOLIB_EXCLUDE_DIRECT_RECEIVE)
|
||||
void CC1101::setDirectAction(void (*func)(void)) {
|
||||
setGdo0Action(func);
|
||||
setGdo0Action(func, this->mod->hal->GpioInterruptRising);
|
||||
}
|
||||
|
||||
void CC1101::readBit(RADIOLIB_PIN_TYPE pin) {
|
||||
updateDirectBuffer((uint8_t)digitalRead(pin));
|
||||
void CC1101::readBit(uint32_t pin) {
|
||||
updateDirectBuffer((uint8_t)this->mod->hal->digitalRead(pin));
|
||||
}
|
||||
#endif
|
||||
|
||||
int16_t CC1101::setDIOMapping(RADIOLIB_PIN_TYPE pin, uint8_t value) {
|
||||
if (pin > 2)
|
||||
return RADIOLIB_ERR_INVALID_DIO_PIN;
|
||||
int16_t CC1101::setDIOMapping(uint32_t pin, uint32_t value) {
|
||||
if(pin > 2) {
|
||||
return(RADIOLIB_ERR_INVALID_DIO_PIN);
|
||||
}
|
||||
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0 - pin, value));
|
||||
}
|
||||
|
||||
int16_t CC1101::config() {
|
||||
// Reset the radio. Registers may be dirty from previous usage.
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_RESET);
|
||||
reset();
|
||||
|
||||
// Wait a ridiculous amount of time to be sure radio is ready.
|
||||
_mod->delay(150);
|
||||
this->mod->hal->delay(150);
|
||||
|
||||
// enable automatic frequency synthesizer calibration
|
||||
standby();
|
||||
|
||||
// enable automatic frequency synthesizer calibration and disable pin control
|
||||
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_MCSM0, RADIOLIB_CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_MCSM0, RADIOLIB_CC1101_PIN_CTRL_OFF, 1, 1);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set GDOs to Hi-Z so that it doesn't output clock on startup (might confuse GDO0 action)
|
||||
state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_HIGH_Z, 5, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_HIGH_Z, 5, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set packet mode
|
||||
|
|
@ -965,16 +1047,15 @@ int16_t CC1101::directMode(bool sync) {
|
|||
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
||||
|
||||
int16_t state = 0;
|
||||
_directMode = sync;
|
||||
if (sync) {
|
||||
this->directModeEnabled = sync;
|
||||
if(sync) {
|
||||
// set GDO0 and GDO2 mapping
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_SERIAL_CLOCK , 5, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_SERIAL_DATA_SYNC , 5, 0);
|
||||
|
||||
// set continuous mode
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_PKT_FORMAT_SYNCHRONOUS, 5, 4);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// set GDO0 mapping
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_SERIAL_DATA_ASYNC , 5, 0);
|
||||
|
||||
|
|
@ -1027,8 +1108,8 @@ int16_t CC1101::setPacketMode(uint8_t mode, uint16_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update the cached value
|
||||
_packetLength = len;
|
||||
_packetLengthConfig = mode;
|
||||
this->packetLength = len;
|
||||
this->packetLengthConfig = mode;
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
|
@ -1038,7 +1119,7 @@ int16_t CC1101::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
|
|||
reg |= RADIOLIB_CC1101_CMD_ACCESS_STATUS_REG;
|
||||
}
|
||||
|
||||
return(_mod->SPIgetRegValue(reg, msb, lsb));
|
||||
return(this->mod->SPIgetRegValue(reg, msb, lsb));
|
||||
}
|
||||
|
||||
int16_t CC1101::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval) {
|
||||
|
|
@ -1047,11 +1128,11 @@ int16_t CC1101::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
reg |= RADIOLIB_CC1101_CMD_ACCESS_STATUS_REG;
|
||||
}
|
||||
|
||||
return(_mod->SPIsetRegValue(reg, value, msb, lsb, checkInterval));
|
||||
return(this->mod->SPIsetRegValue(reg, value, msb, lsb, checkInterval));
|
||||
}
|
||||
|
||||
void CC1101::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) {
|
||||
_mod->SPIreadRegisterBurst(reg | RADIOLIB_CC1101_CMD_BURST, numBytes, inBytes);
|
||||
this->mod->SPIreadRegisterBurst(reg | RADIOLIB_CC1101_CMD_BURST, numBytes, inBytes);
|
||||
}
|
||||
|
||||
uint8_t CC1101::SPIreadRegister(uint8_t reg) {
|
||||
|
|
@ -1060,7 +1141,7 @@ uint8_t CC1101::SPIreadRegister(uint8_t reg) {
|
|||
reg |= RADIOLIB_CC1101_CMD_ACCESS_STATUS_REG;
|
||||
}
|
||||
|
||||
return(_mod->SPIreadRegister(reg));
|
||||
return(this->mod->SPIreadRegister(reg));
|
||||
}
|
||||
|
||||
void CC1101::SPIwriteRegister(uint8_t reg, uint8_t data) {
|
||||
|
|
@ -1069,26 +1150,28 @@ void CC1101::SPIwriteRegister(uint8_t reg, uint8_t data) {
|
|||
reg |= RADIOLIB_CC1101_CMD_ACCESS_STATUS_REG;
|
||||
}
|
||||
|
||||
return(_mod->SPIwriteRegister(reg, data));
|
||||
return(this->mod->SPIwriteRegister(reg, data));
|
||||
}
|
||||
|
||||
void CC1101::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len) {
|
||||
_mod->SPIwriteRegisterBurst(reg | RADIOLIB_CC1101_CMD_BURST, data, len);
|
||||
this->mod->SPIwriteRegisterBurst(reg | RADIOLIB_CC1101_CMD_BURST, data, len);
|
||||
}
|
||||
|
||||
void CC1101::SPIsendCommand(uint8_t cmd) {
|
||||
// pull NSS low
|
||||
_mod->digitalWrite(_mod->getCs(), LOW);
|
||||
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
|
||||
|
||||
// start transfer
|
||||
_mod->SPIbeginTransaction();
|
||||
this->mod->hal->spiBeginTransaction();
|
||||
|
||||
// send the command byte
|
||||
_mod->SPItransfer(cmd);
|
||||
uint8_t status = this->mod->hal->spiTransfer(cmd);
|
||||
|
||||
// stop transfer
|
||||
_mod->SPIendTransaction();
|
||||
_mod->digitalWrite(_mod->getCs(), HIGH);
|
||||
this->mod->hal->spiEndTransaction();
|
||||
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
|
||||
RADIOLIB_VERBOSE_PRINTLN("CMD\tW\t%02X\t%02X", cmd, status);
|
||||
(void)status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2,10 +2,10 @@
|
|||
#if !defined(RADIOLIB_EXCLUDE_SX126X)
|
||||
|
||||
LLCC68::LLCC68(Module* mod) : SX1262(mod) {
|
||||
|
||||
chipType = RADIOLIB_LLCC68_CHIP_TYPE;
|
||||
}
|
||||
|
||||
int16_t LLCC68::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
int16_t LLCC68::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t pwr, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
// execute common part
|
||||
int16_t state = SX126x::begin(cr, syncWord, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
|
@ -20,7 +20,7 @@ int16_t LLCC68::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
state = setSpreadingFactor(sf);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
state = setOutputPower(pwr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
|
|
@ -35,7 +35,7 @@ int16_t LLCC68::setBandwidth(float bw) {
|
|||
}
|
||||
|
||||
int16_t LLCC68::setSpreadingFactor(uint8_t sf) {
|
||||
switch(SX126x::_bw) {
|
||||
switch(SX126x::bandwidth) {
|
||||
case RADIOLIB_SX126X_LORA_BW_125_0:
|
||||
RADIOLIB_CHECK_RANGE(sf, 5, 9, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -8,59 +8,48 @@
|
|||
#include "../../Module.h"
|
||||
#include "../SX126x/SX1262.h"
|
||||
|
||||
//RADIOLIB_SX126X_REG_VERSION_STRING
|
||||
#define RADIOLIB_LLCC68_CHIP_TYPE "LLCC68"
|
||||
|
||||
/*!
|
||||
\class LLCC68
|
||||
|
||||
\brief Derived class for %LLCC68 modules.
|
||||
*/
|
||||
class LLCC68: public SX1262 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LLCC68(Module* mod);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LoRa modem.
|
||||
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
|
||||
\param bw LoRa bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
|
||||
\param sf LoRa spreading factor. Defaults to 9.
|
||||
|
||||
\param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
|
||||
|
||||
\param syncWord 2-byte LoRa sync word. Defaults to RADIOLIB_SX126X_SYNC_WORD_PRIVATE (0x12).
|
||||
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
|
||||
\param syncWord 1-byte LoRa sync word. Defaults to RADIOLIB_SX126X_SYNC_WORD_PRIVATE (0x12).
|
||||
\param pwr Output power in dBm. Defaults to 10 dBm.
|
||||
\param preambleLength LoRa preamble length in symbols. Defaults to 8 symbols.
|
||||
|
||||
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
|
||||
|
||||
\param useRegulatorLDO Whether to use only LDO regulator (true) or DC-DC regulator (false). Defaults to false.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t pwr = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\brief Sets LoRa bandwidth. Allowed values are 125.0, 250.0 and 500.0 kHz.
|
||||
|
||||
\param bw LoRa bandwidth to be set in kHz.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setBandwidth(float bw);
|
||||
|
||||
/*!
|
||||
\brief Sets LoRa spreading factor. Allowed values range from 5 to 11, depending on currently set spreading factor.
|
||||
|
||||
\param sf LoRa spreading factor to be set.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
/*!
|
||||
\class RFM22
|
||||
|
||||
\brief Only exists as alias for Si4432, since there seems to be no difference between %RFM22 and %Si4432 modules.
|
||||
*/
|
||||
RADIOLIB_TYPE_ALIAS(Si4432, RFM22);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
/*!
|
||||
\class RFM23
|
||||
|
||||
\brief Only exists as alias for Si4431, since there seems to be no difference between %RFM23 and %Si4431 modules.
|
||||
*/
|
||||
RADIOLIB_TYPE_ALIAS(Si4431, RFM23);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ int16_t RFM95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
// some other error
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1278"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRFM95"));
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tSX1278");
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tRFM95");
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setBandwidth(bw);
|
||||
|
|
@ -42,17 +42,17 @@ int16_t RFM95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
|
||||
int16_t RFM95::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL, br, freqDev, rxBw, preambleLength, enableOOK);
|
||||
int16_t state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL, freqDev, rxBw, preambleLength, enableOOK);
|
||||
if(state == RADIOLIB_ERR_CHIP_NOT_FOUND) {
|
||||
// SX127X_REG_VERSION might be set 0x12
|
||||
state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL, br, freqDev, rxBw, preambleLength, enableOOK);
|
||||
state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL, freqDev, rxBw, preambleLength, enableOOK);
|
||||
RADIOLIB_ASSERT(state);
|
||||
} else if(state != RADIOLIB_ERR_NONE) {
|
||||
// some other error
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1278"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRFM95"));
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tSX1278");
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tRFM95");
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = configFSK();
|
||||
|
|
@ -62,6 +62,9 @@ int16_t RFM95::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
|
|||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBitRate(br);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
|
|
@ -82,7 +85,7 @@ int16_t RFM95::setFrequency(float freq) {
|
|||
// set frequency and if successful, save the new setting
|
||||
int16_t state = SX127x::setFrequencyRaw(freq);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
SX127x::_freq = freq;
|
||||
SX127x::frequency = freq;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,11 @@
|
|||
#include "../SX127x/SX1278.h"
|
||||
|
||||
// SX127X_REG_VERSION
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL 0x11
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL 0x12 // according to datasheet, only 0x11 should be possible, but some modules seem to have 0x12
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL 0x11
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL 0x12 // according to datasheet, only 0x11 should be possible, but some modules seem to have 0x12
|
||||
|
||||
/*!
|
||||
\class RFM95
|
||||
|
||||
\brief Derived class for %RFM95 modules. Overrides some methods from SX1278 due to different parameter ranges.
|
||||
*/
|
||||
class RFM95: public SX1278 {
|
||||
|
|
@ -25,7 +24,6 @@ class RFM95: public SX1278 {
|
|||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
RFM95(Module* mod);
|
||||
|
|
@ -34,47 +32,30 @@ class RFM95: public SX1278 {
|
|||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 868.0 MHz to 915.0 MHz.
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
/*!
|
||||
\brief FSK modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 525.0 MHz.
|
||||
|
||||
\param br Bit rate of the FSK transmission in kbps (kilobits per second). Allowed values range from 1.2 to 300.0 kbps.
|
||||
|
||||
\param freqDev Frequency deviation of the FSK transmission in kHz. Allowed values range from 0.6 to 200.0 kHz.
|
||||
Note that the allowed range changes based on bit rate setting, so that the condition FreqDev + BitRate/2 <= 250 kHz is always met.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Allowed values are 2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6, 20.8, 25, 31.3, 41.7, 50, 62.5, 83.3, 100, 125, 166.7, 200 and 250 kHz.
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param preambleLength Length of FSK preamble in bits.
|
||||
|
||||
\param enableOOK Use OOK modulation instead of FSK.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
|
||||
|
|
@ -83,9 +64,7 @@ class RFM95: public SX1278 {
|
|||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values range from 868.0 MHz to 915.0 MHz.
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ int16_t RFM96::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
// some other error
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1278"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRFM96"));
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tSX1278");
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tRFM96");
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setBandwidth(bw);
|
||||
|
|
@ -43,17 +43,17 @@ int16_t RFM96::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
|
||||
int16_t RFM96::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL, br, freqDev, rxBw, preambleLength, enableOOK);
|
||||
int16_t state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL, freqDev, rxBw, preambleLength, enableOOK);
|
||||
if(state == RADIOLIB_ERR_CHIP_NOT_FOUND) {
|
||||
// SX127X_REG_VERSION might be set 0x12
|
||||
state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL, br, freqDev, rxBw, preambleLength, enableOOK);
|
||||
state = SX127x::beginFSK(RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL, freqDev, rxBw, preambleLength, enableOOK);
|
||||
RADIOLIB_ASSERT(state);
|
||||
} else if(state != RADIOLIB_ERR_NONE) {
|
||||
// some other error
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1278"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRFM96"));
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tSX1278");
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tRFM96");
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = configFSK();
|
||||
|
|
@ -63,6 +63,9 @@ int16_t RFM96::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
|
|||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBitRate(br);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
|
|
@ -83,7 +86,7 @@ int16_t RFM96::setFrequency(float freq) {
|
|||
// set frequency and if successful, save the new setting
|
||||
int16_t state = SX127x::setFrequencyRaw(freq);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
SX127x::_freq = freq;
|
||||
SX127x::frequency = freq;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,11 @@
|
|||
#include "../SX127x/SX1278.h"
|
||||
|
||||
// SX127X_REG_VERSION
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL 0x11
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL 0x12 // according to datasheet, only 0x11 should be possible, but some modules seem to have 0x12
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_OFFICIAL 0x11
|
||||
#define RADIOLIB_RFM9X_CHIP_VERSION_UNOFFICIAL 0x12 // according to datasheet, only 0x11 should be possible, but some modules seem to have 0x12
|
||||
|
||||
/*!
|
||||
\class RFM96
|
||||
|
||||
\brief Derived class for %RFM96 modules. Overrides some methods from SX1278 due to different parameter ranges.
|
||||
*/
|
||||
class RFM96: public SX1278 {
|
||||
|
|
@ -25,7 +24,6 @@ class RFM96: public SX1278 {
|
|||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
RFM96(Module* mod);
|
||||
|
|
@ -34,47 +32,32 @@ class RFM96: public SX1278 {
|
|||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 433.0 MHz to 470.0 MHz.
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks.
|
||||
Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols
|
||||
longer than the set number. Allowed values range from 6 to 65535.
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6
|
||||
where 1 is the highest gain. Set to 0 to enable automatic gain control (recommended).
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
/*!
|
||||
\brief FSK modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 525.0 MHz.
|
||||
|
||||
\param br Bit rate of the FSK transmission in kbps (kilobits per second). Allowed values range from 1.2 to 300.0 kbps.
|
||||
|
||||
\param freqDev Frequency deviation of the FSK transmission in kHz. Allowed values range from 0.6 to 200.0 kHz.
|
||||
Note that the allowed range changes based on bit rate setting, so that the condition FreqDev + BitRate/2 <= 250 kHz is always met.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Allowed values are 2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6, 20.8, 25, 31.3, 41.7, 50, 62.5, 83.3, 100, 125, 166.7, 200 and 250 kHz.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Allowed values are 2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6, 20.8, 25,
|
||||
31.3, 41.7, 50, 62.5, 83.3, 100, 125, 166.7, 200 and 250 kHz.
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param preambleLength Length of FSK preamble in bits.
|
||||
|
||||
\param enableOOK Use OOK modulation instead of FSK.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
|
||||
|
|
@ -83,9 +66,7 @@ class RFM96: public SX1278 {
|
|||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values range from 433.0 MHz to 470.0 MHz.
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
|
@ -98,7 +79,6 @@ class RFM96: public SX1278 {
|
|||
|
||||
/*!
|
||||
\class RFM98
|
||||
|
||||
\brief Only exists as alias for RFM96, since there seems to be no difference between %RFM96 and %RFM98 modules.
|
||||
*/
|
||||
RADIOLIB_TYPE_ALIAS(RFM96, RFM98);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ int16_t RFM97::setSpreadingFactor(uint8_t sf) {
|
|||
// set spreading factor and if successful, save the new setting
|
||||
int16_t state = SX1278::setSpreadingFactorRaw(newSpreadingFactor);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
SX127x::_sf = sf;
|
||||
SX127x::spreadingFactor = sf;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
/*!
|
||||
\class RFM97
|
||||
|
||||
\brief Derived class for %RFM97 modules. Overrides some methods from RFM95 due to different parameter ranges.
|
||||
*/
|
||||
class RFM97: public RFM95 {
|
||||
|
|
@ -22,7 +21,6 @@ class RFM97: public RFM95 {
|
|||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
RFM97(Module* mod);
|
||||
|
|
@ -31,9 +29,7 @@ class RFM97: public RFM95 {
|
|||
|
||||
/*!
|
||||
\brief Sets %LoRa link spreading factor. Allowed values range from 6 to 9. Only available in %LoRa mode.
|
||||
|
||||
\param sf %LoRa link spreading factor to be set.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ SX1231::SX1231(Module* mod) : RF69(mod) {
|
|||
|
||||
int16_t SX1231::begin(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t preambleLen) {
|
||||
// set module properties
|
||||
_mod->init();
|
||||
_mod->pinMode(_mod->getIrq(), INPUT);
|
||||
_mod->pinMode(_mod->getRst(), OUTPUT);
|
||||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getRst(), this->mod->hal->GpioModeOutput);
|
||||
|
||||
// try to find the SX1231 chip
|
||||
uint8_t i = 0;
|
||||
|
|
@ -18,42 +18,32 @@ int16_t SX1231::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
int16_t version = getChipVersion();
|
||||
if((version == 0x21) || (version == 0x22) || (version == 0x23)) {
|
||||
flagFound = true;
|
||||
_chipRevision = version;
|
||||
this->chipRevision = version;
|
||||
} else {
|
||||
#if defined(RADIOLIB_DEBUG)
|
||||
RADIOLIB_DEBUG_PRINT(F("SX1231 not found! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) RF69_REG_VERSION == "));
|
||||
|
||||
char buffHex[12];
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0021 / 0x0022 / 0x0023"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
_mod->delay(10);
|
||||
RADIOLIB_DEBUG_PRINTLN("SX1231 not found! (%d of 10 tries) RF69_REG_VERSION == 0x%04X, expected 0x0021 / 0x0022 / 0x0023", i + 1, version);
|
||||
this->mod->hal->delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(!flagFound) {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No SX1231 found!"));
|
||||
_mod->term();
|
||||
RADIOLIB_DEBUG_PRINTLN("No SX1231 found!");
|
||||
this->mod->term();
|
||||
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1231"));
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tSX1231");
|
||||
|
||||
// configure settings not accessible by API
|
||||
int16_t state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRF69"));
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tRF69");
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure bitrate
|
||||
_rxBw = 125.0;
|
||||
this->rxBandwidth = 125.0;
|
||||
state = setBitRate(br);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
|
|
@ -85,13 +75,13 @@ int16_t SX1231::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
}
|
||||
|
||||
// SX1231 V2a only
|
||||
if(_chipRevision == RADIOLIB_SX1231_CHIP_REVISION_2_A) {
|
||||
if(this->chipRevision == RADIOLIB_SX1231_CHIP_REVISION_2_A) {
|
||||
// modify default OOK threshold value
|
||||
state = _mod->SPIsetRegValue(RADIOLIB_SX1231_REG_TEST_OOK, RADIOLIB_SX1231_OOK_DELTA_THRESHOLD);
|
||||
state = this->mod->SPIsetRegValue(RADIOLIB_SX1231_REG_TEST_OOK, RADIOLIB_SX1231_OOK_DELTA_THRESHOLD);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable OCP with 95 mA limit
|
||||
state = _mod->SPIsetRegValue(RADIOLIB_RF69_REG_OCP, RADIOLIB_RF69_OCP_ON | RADIOLIB_RF69_OCP_TRIM, 4, 0);
|
||||
state = this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_OCP, RADIOLIB_RF69_OCP_ON | RADIOLIB_RF69_OCP_TRIM, 4, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,113 +8,104 @@
|
|||
#include "../../Module.h"
|
||||
#include "../RF69/RF69.h"
|
||||
|
||||
#define RADIOLIB_SX1231_CHIP_REVISION_2_A 0x21
|
||||
#define RADIOLIB_SX1231_CHIP_REVISION_2_B 0x22
|
||||
#define RADIOLIB_SX1231_CHIP_REVISION_2_C 0x23
|
||||
#define RADIOLIB_SX1231_CHIP_REVISION_2_A 0x21
|
||||
#define RADIOLIB_SX1231_CHIP_REVISION_2_B 0x22
|
||||
#define RADIOLIB_SX1231_CHIP_REVISION_2_C 0x23
|
||||
|
||||
//SX1231 specific register map
|
||||
#define RADIOLIB_SX1231_REG_TEST_OOK 0x6E
|
||||
// RADIOLIB_SX1231 specific register map
|
||||
#define RADIOLIB_SX1231_REG_TEST_OOK 0x6E
|
||||
|
||||
//SX1231_REG_TEST_OOK
|
||||
#define RADIOLIB_SX1231_OOK_DELTA_THRESHOLD 0x0C
|
||||
// RADIOLIB_SX1231_REG_TEST_OOK
|
||||
#define RADIOLIB_SX1231_OOK_DELTA_THRESHOLD 0x0C
|
||||
|
||||
// SX1231_REG_DIO_MAPPING_1
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_MODE_READY 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_PLL_LOCK 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_SYNC_ADDRESS 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_TIMEOUT 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_RSSI 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_MODE_READY 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_PLL_LOCK 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_CRC_OK 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_PAYLOAD_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_SYNC_ADDRESS 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_RSSI 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_PACKET_SENT 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_LOW_BAT 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_PLL_LOCK 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_DCLK 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_RX_READY 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_SYNC_ADDRESS 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_TX_READY 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_FIFO_LEVEL 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_FIFO_FULL 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_FIFO_NOT_EMPTY 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_PLL_LOCK 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_TIMEOUT 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO2_CONT_DATA 0b00000000 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_FIFO_NOT_EMPTY 0b00000000 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_LOW_BAT 0b00001000 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_AUTO_MODE 0b00001100 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_DATA 0b00000100 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_AUTO_MODE 0b00000010 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_RSSI 0b00000000 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_RX_READY 0b00000001 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_TIMEOUT 0b00000011 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_TX_READY 0b00000001 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_FIFO_FULL 0b00000000 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_LOW_BAT 0b00000010 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_PLL_LOCK 0b00000011 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_RSSI 0b00000001 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_SYNC_ADDRESSS 0b00000010 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_TX_READY 0b00000001 // 0 1
|
||||
// RADIOLIB_SX1231_REG_DIO_MAPPING_1
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_MODE_READY 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_PLL_LOCK 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_SYNC_ADDRESS 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_TIMEOUT 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_RSSI 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_MODE_READY 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_CONT_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_PLL_LOCK 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_CRC_OK 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_PAYLOAD_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_SYNC_ADDRESS 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_RSSI 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_PACKET_SENT 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO0_PACK_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_LOW_BAT 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_PLL_LOCK 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_DCLK 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_RX_READY 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_SYNC_ADDRESS 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_CONT_TX_READY 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_FIFO_LEVEL 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_FIFO_FULL 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_FIFO_NOT_EMPTY 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_PLL_LOCK 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO1_PACK_TIMEOUT 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO2_CONT_DATA 0b00000000 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_FIFO_NOT_EMPTY 0b00000000 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_LOW_BAT 0b00001000 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_AUTO_MODE 0b00001100 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO2_PACK_DATA 0b00000100 // 3 2
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_AUTO_MODE 0b00000010 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_RSSI 0b00000000 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_RX_READY 0b00000001 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_TIMEOUT 0b00000011 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_CONT_TX_READY 0b00000001 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_FIFO_FULL 0b00000000 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_LOW_BAT 0b00000010 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_PLL_LOCK 0b00000011 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_RSSI 0b00000001 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_SYNC_ADDRESSS 0b00000010 // 0 1
|
||||
#define RADIOLIB_SX1231_DIO3_PACK_TX_READY 0b00000001 // 0 1
|
||||
|
||||
// SX1231_REG_DIO_MAPPING_2
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_PLL_LOCK 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_TIMEOUT 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_RX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_SYNC_ADDRESS 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_PLL_LOCK 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_TIMEOUT 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_RSSI 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_RX_READY 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_MODE_READY 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_LOW_BAT 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_MODE_READY 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_CLK_OUT 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_RSSI 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_LOW_BAT 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_MODE_READY 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_CLK_OUT 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_DATA 0b00010000 // 5 4
|
||||
// RADIOLIB_SX1231_REG_DIO_MAPPING_2
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_PLL_LOCK 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_TIMEOUT 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_RX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_SYNC_ADDRESS 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_CONT_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_LOW_BAT 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_PLL_LOCK 0b11000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_TIMEOUT 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_RSSI 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_RX_READY 0b10000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_MODE_READY 0b00000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO4_PACK_TX_READY 0b01000000 // 7 6
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_LOW_BAT 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_MODE_READY 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_CLK_OUT 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_CONT_RSSI 0b00010000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_LOW_BAT 0b00100000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_MODE_READY 0b00110000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_CLK_OUT 0b00000000 // 5 4
|
||||
#define RADIOLIB_SX1231_DIO5_PACK_DATA 0b00010000 // 5 4
|
||||
|
||||
/*!
|
||||
\class SX1231
|
||||
|
||||
\brief Control class for %SX1231 module. Overrides some methods from RF69 due to different register values.
|
||||
*/
|
||||
class SX1231: public RF69 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1231(Module* mod);
|
||||
|
||||
/*!
|
||||
\brief Initialization method.
|
||||
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
|
||||
\param br Bit rate to be used in kbps. Defaults to 4.8 kbps.
|
||||
|
||||
\param freqDev Frequency deviation from carrier frequency in kHz Defaults to 5.0 kHz.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
|
||||
\param preambleLen Preamble Length in bits. Defaults to 16 bits.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint8_t preambleLen = 16);
|
||||
|
|
@ -122,7 +113,7 @@ class SX1231: public RF69 {
|
|||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
uint8_t _chipRevision = 0;
|
||||
uint8_t chipRevision = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
102
lib/RadioLib/src/modules/SX126x/STM32WLx.cpp
Normal file
102
lib/RadioLib/src/modules/SX126x/STM32WLx.cpp
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Copyright (c) 2018 Jan Gromeš
|
||||
Copyright (c) 2022 STMicroelectronics
|
||||
|
||||
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "STM32WLx.h"
|
||||
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
|
||||
STM32WLx::STM32WLx(STM32WLx_Module* mod) : SX1262(mod) { }
|
||||
|
||||
int16_t STM32WLx::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
// Execute common part
|
||||
int16_t state = SX1262::begin(freq, bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// This overrides the value in SX126x::begin()
|
||||
// On STM32WL, DIO2 is hardwired to the radio IRQ on the MCU, so it
|
||||
// should really not be used as RfSwitch control output.
|
||||
state = setDio2AsRfSwitch(false);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t STM32WLx::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
// Execute common part
|
||||
int16_t state = SX1262::beginFSK(freq, br, freqDev, rxBw, power, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// This overrides the value in SX126x::beginFSK()
|
||||
// On STM32WL, DIO2 is hardwired to the radio IRQ on the MCU, so it
|
||||
// should really not be used as RfSwitch control output.
|
||||
state = setDio2AsRfSwitch(false);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t STM32WLx::setOutputPower(int8_t power) {
|
||||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// Use HP only if available and needed for the requested power
|
||||
bool hp_supported = this->mod->findRfSwitchMode(MODE_TX_HP);
|
||||
bool use_hp = power > 14 && hp_supported;
|
||||
|
||||
// set PA config.
|
||||
if(use_hp) {
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
state = SX126x::setPaConfig(0x04, 0x00, 0x07); // HP output up to 22dBm
|
||||
this->txMode = MODE_TX_HP;
|
||||
} else {
|
||||
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
state = SX126x::setPaConfig(0x04, 0x01, 0x00); // LP output up to 14dBm
|
||||
this->txMode = MODE_TX_LP;
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// Apply workaround for HP only
|
||||
state = SX126x::fixPaClamping(use_hp);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
/// \todo power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
||||
int16_t STM32WLx::clearIrqStatus(uint16_t clearIrqParams) {
|
||||
int16_t res = SX126x::clearIrqStatus(clearIrqParams);
|
||||
// The NVIC interrupt is level-sensitive, so clear away any pending
|
||||
// flag that is only set because the radio IRQ status was not cleared
|
||||
// in the interrupt (to prevent each IRQ triggering twice and allow
|
||||
// reading the irq status through the pending flag).
|
||||
SubGhz.clearPendingInterrupt();
|
||||
if(SubGhz.hasInterrupt())
|
||||
SubGhz.enableInterrupt();
|
||||
return(res);
|
||||
}
|
||||
|
||||
void STM32WLx::setDio1Action(void (*func)(void)) {
|
||||
SubGhz.attachInterrupt([func]() {
|
||||
// Because the interrupt is level-triggered, we disable it in the
|
||||
// NVIC (otherwise we would need an SPI command to clear the IRQ in
|
||||
// the radio, or it would trigger over and over again).
|
||||
SubGhz.disableInterrupt();
|
||||
func();
|
||||
});
|
||||
}
|
||||
|
||||
void STM32WLx::clearDio1Action() {
|
||||
SubGhz.detachInterrupt();
|
||||
}
|
||||
|
||||
#endif // !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
134
lib/RadioLib/src/modules/SX126x/STM32WLx.h
Normal file
134
lib/RadioLib/src/modules/SX126x/STM32WLx.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
Copyright (c) 2018 Jan Gromeš
|
||||
Copyright (c) 2022 STMicroelectronics
|
||||
|
||||
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#if !defined(_RADIOLIB_STM32WLx_H)
|
||||
#define _RADIOLIB_STM32WLx_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
|
||||
#include "../../Module.h"
|
||||
#include "SX1262.h"
|
||||
#include "STM32WLx_Module.h"
|
||||
|
||||
/*!
|
||||
\class STM32WLx
|
||||
|
||||
\brief Derived class for STM32WL modules.
|
||||
|
||||
The radio integrated into these modules is essentially the same as the
|
||||
Semtech %SX126x external radio chips, so most of the documentation for
|
||||
those also applies here.
|
||||
|
||||
One notable difference with the %SX126x radios is that this radio
|
||||
essentially combines the %SX1261 and %SX1262 by integrating both the
|
||||
low-power (LP) and high-power (HP) amplifier. See setOutputPower() and
|
||||
setRfSwitchTable() for details on how this is handled.
|
||||
*/
|
||||
class STM32WLx : public SX1262 {
|
||||
// NOTE: This class could not be named STM32WL (or STM32WLxx), since
|
||||
// those are macros defined by
|
||||
// system/Drivers/CMSIS/Device/ST/STM32WLxxx/Include/stm32wlxx.h
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of STM32WLx_Module that will be used to communicate with the radio.
|
||||
*/
|
||||
STM32WLx(STM32WLx_Module* mod);
|
||||
|
||||
/*!
|
||||
\brief Custom operation modes for STMWLx.
|
||||
|
||||
This splits the TX mode into two modes: Low-power and high-power.
|
||||
These constants can be used with the setRfSwitchTable() method,
|
||||
instead of the Module::OpMode_t constants.
|
||||
*/
|
||||
enum OpMode_t {
|
||||
/*! End of table marker, use \ref END_OF_MODE_TABLE constant instead */
|
||||
MODE_END_OF_TABLE = Module::MODE_END_OF_TABLE,
|
||||
/*! Idle mode */
|
||||
MODE_IDLE = Module::MODE_IDLE,
|
||||
/*! Receive mode */
|
||||
MODE_RX = Module::MODE_RX,
|
||||
/*! Low power transmission mode */
|
||||
MODE_TX_LP = Module::MODE_TX,
|
||||
/*! High power transmission mode */
|
||||
MODE_TX_HP,
|
||||
};
|
||||
|
||||
// basic methods
|
||||
|
||||
/*!
|
||||
\copydoc SX1262::begin
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
|
||||
/*!
|
||||
\copydoc SX1262::beginFSK
|
||||
*/
|
||||
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -17 to 22 dBm.
|
||||
|
||||
This automatically switches between the low-power (LP) and high-power (HP) amplifier.
|
||||
|
||||
LP is preferred and supports -17 to +14dBm. When a higher power is
|
||||
requested (or the LP amplifier is marked as unvailable using
|
||||
setRfSwitchTable()), HP is used, which supports -9 to +22dBm.
|
||||
|
||||
\param power Output power to be set in dBm.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
virtual int16_t setOutputPower(int8_t power) override;
|
||||
|
||||
/*!
|
||||
\copybrief Module::setRfSwitchTable
|
||||
|
||||
This method works like Module::setRfSwitchTable(), except that you
|
||||
should use STM32WLx::OpMode_t constants for modes, which
|
||||
distinguishes between a low-power (LP) and high-power (HP) TX mode.
|
||||
|
||||
For boards that do not support both modes, just omit the
|
||||
unsupported mode from the table and it will not be used (and the
|
||||
valid power range is adjusted by setOutputPower() accordingly).
|
||||
|
||||
Note that the setRfSwitchTable() method should be called *before* the
|
||||
begin() method, to ensure the radio knows which modes are supported
|
||||
during initialization.
|
||||
*/
|
||||
// Note: This explicitly inherits this method only to override docs
|
||||
using SX126x::setRfSwitchTable;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when DIO1/2/3 activates.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setDio1Action(void (*func)(void));
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when DIO1/2/3 activates.
|
||||
*/
|
||||
void clearDio1Action();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
virtual int16_t clearIrqStatus(uint16_t clearIrqParams) override;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // !defined(RADIOLIB_EXCLUDE_SX126X)
|
||||
|
||||
#endif // _RADIOLIB_STM32WLX_MODULE_H
|
||||
106
lib/RadioLib/src/modules/SX126x/STM32WLx_Module.cpp
Normal file
106
lib/RadioLib/src/modules/SX126x/STM32WLx_Module.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2022 STMicroelectronics
|
||||
|
||||
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "STM32WLx_Module.h"
|
||||
|
||||
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
|
||||
#include "../../ArduinoHal.h"
|
||||
|
||||
// This defines some dummy pin numbers (starting at NUM_DIGITAL_PINS to
|
||||
// guarantee these are not valid regular pin numbers) that can be passed
|
||||
// to the parent Module class, to be stored here and then passed back to
|
||||
// the overridden callbacks when these are used.
|
||||
enum {
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS = NUM_DIGITAL_PINS,
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY,
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ,
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET,
|
||||
};
|
||||
|
||||
class Stm32wlxHal : public ArduinoHal {
|
||||
public:
|
||||
Stm32wlxHal(): ArduinoHal(SubGhz.SPI, SubGhz.spi_settings) {}
|
||||
|
||||
void pinMode(uint32_t dwPin, uint32_t dwMode) {
|
||||
switch(dwPin) {
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY:
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ:
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET:
|
||||
// Nothing to do
|
||||
break;
|
||||
default:
|
||||
::pinMode(dwPin, dwMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(uint32_t dwPin, uint32_t dwVal) {
|
||||
switch (dwPin) {
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||
SubGhz.setNssActive(dwVal == LOW);
|
||||
break;
|
||||
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET:
|
||||
SubGhz.setResetActive(dwVal == LOW);
|
||||
break;
|
||||
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY:
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ:
|
||||
// Should not (and cannot) be written, just ignore
|
||||
break;
|
||||
|
||||
default:
|
||||
::digitalWrite(dwPin, dwVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t digitalRead(uint32_t ulPin) {
|
||||
switch (ulPin) {
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY:
|
||||
return(SubGhz.isBusy() ? HIGH : LOW);
|
||||
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ:
|
||||
// We cannot use the radio IRQ output directly, but since:
|
||||
// - the pending flag will be set whenever the IRQ output is set,
|
||||
// and
|
||||
// - the pending flag will be cleared (by
|
||||
// STM32WLx::clearIrqStatus()) whenever the radio IRQ output is
|
||||
// cleared,
|
||||
// the pending flag should always reflect the current radio IRQ
|
||||
// output. There is one exception: when the ISR starts the pending
|
||||
// flag is cleared by hardware and not set again until after the
|
||||
// ISR finishes, so the value is incorrect *inside* the ISR, but
|
||||
// running RadioLib code inside the ISR (especially code that
|
||||
// polls the IRQ flag) is not supported and probably broken in
|
||||
// other ways too.
|
||||
return(SubGhz.isInterruptPending() ? HIGH : LOW);
|
||||
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||
return(SubGhz.isNssActive() ? LOW : HIGH);
|
||||
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET:
|
||||
return(SubGhz.isResetActive() ? LOW : HIGH);
|
||||
|
||||
default:
|
||||
return(::digitalRead(ulPin));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
STM32WLx_Module::STM32WLx_Module():
|
||||
Module(
|
||||
new Stm32wlxHal,
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS,
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ,
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET,
|
||||
RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY
|
||||
) {}
|
||||
|
||||
#endif // !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
38
lib/RadioLib/src/modules/SX126x/STM32WLx_Module.h
Normal file
38
lib/RadioLib/src/modules/SX126x/STM32WLx_Module.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2022 STMicroelectronics
|
||||
|
||||
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#if !defined(_RADIOLIB_STM32WLX_MODULE_H)
|
||||
#define _RADIOLIB_STM32WLX_MODULE_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
|
||||
#include "../../Module.h"
|
||||
|
||||
/*!
|
||||
* \class STM32WLx_Module
|
||||
*
|
||||
* This is a subclass of Module to be used with the STM32WLx driver.
|
||||
*
|
||||
* It is used to override some callbacks, allowing access to some of the
|
||||
* radio control signals that are wired to internal registers instead of
|
||||
* actual GPIO pins.
|
||||
*/
|
||||
class STM32WLx_Module : public Module {
|
||||
// Note: We cannot easily override any methods here, since most calls
|
||||
// are non-virtual and made through a Module*, so they would not be
|
||||
// calling any overridden methods. This means this class works by
|
||||
// overriding some of the callbacks in its constructor.
|
||||
|
||||
public:
|
||||
STM32WLx_Module();
|
||||
};
|
||||
|
||||
#endif // !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
|
||||
#endif // _RADIOLIB_STM32WLX_MODULE_H
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#if !defined(RADIOLIB_EXCLUDE_SX126X)
|
||||
|
||||
SX1261::SX1261(Module* mod): SX1262(mod) {
|
||||
|
||||
chipType = RADIOLIB_SX1261_CHIP_TYPE;
|
||||
}
|
||||
|
||||
int16_t SX1261::setOutputPower(int8_t power) {
|
||||
|
|
|
|||
|
|
@ -10,27 +10,26 @@
|
|||
#include "SX1262.h"
|
||||
|
||||
//RADIOLIB_SX126X_CMD_SET_PA_CONFIG
|
||||
#define RADIOLIB_SX126X_PA_CONFIG_SX1261 0x01
|
||||
#define RADIOLIB_SX126X_PA_CONFIG_SX1261 0x01
|
||||
|
||||
//RADIOLIB_SX126X_REG_VERSION_STRING
|
||||
#define RADIOLIB_SX1261_CHIP_TYPE "SX1261"
|
||||
|
||||
/*!
|
||||
\class SX1261
|
||||
|
||||
\brief Derived class for %SX1261 modules.
|
||||
*/
|
||||
class SX1261 : public SX1262 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1261(Module* mod);
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -17 to 14 dBm.
|
||||
|
||||
\param power Output power to be set in dBm.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue