Merge remote-tracking branch 'upstream/master'
* upstream/master: (249 commits) [SX127x] OOK functions style cleanup [RF69] OOK functions style cleanup styles and syntax changes added RF69::setOokThresholdType added RF69::setLnaTestBoost doc fix SX1278::getRSSI() modified for OOK so it wont require an activation SX127x::setOokPeakThresholdDecrement ignore jetbrain .idea SX1278::setGain() added support for FSK_OOK modes SX127x::setOokFixedOrFloorThreshold SX1278::setOokThresholdType() RF69::setOOK [SX127x] Fixed shaping in OOK (#268) [SX127x] Added FSK CRC mode configuration (#266) Bump version to 4.3.0 [nRF24] Added low-level access macro [XBee] Added low-level access macro [Si443x] Added low-level access macro [SX128x] Added low-level access macro ...
This commit is contained in:
commit
4d2764edb2
89 changed files with 2210 additions and 1023 deletions
66
.github/workflows/codeql-analysis.yml
vendored
Normal file
66
.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
.github/workflows/doxygen.yml
vendored
Normal file
26
.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
|
162
.github/workflows/main.yml
vendored
Normal file
162
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
board:
|
||||
- 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
|
||||
- STM32:stm32:GenF3
|
||||
- stm32duino:STM32F1:mapleMini
|
||||
- MegaCoreX:megaavr:4809
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
name: ${{ matrix.board }}
|
||||
env:
|
||||
run-build: ${{ (matrix.board == '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.board)) }}
|
||||
|
||||
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.board }}
|
||||
seperator: ':'
|
||||
|
||||
- name: Prepare platform-specific settings
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
id: prep
|
||||
run:
|
||||
|
|
||||
# common settings - no extra options, skip nothing, all warnings
|
||||
echo "::set-output name=options::"
|
||||
echo "::set-output name=skip-pattern::''"
|
||||
echo "::set-output name=warnings::'all'"
|
||||
|
||||
# platform-dependent settings - extra board options, board index URLs, skip patterns etc.
|
||||
if [[ "${{ contains(matrix.board, 'arduino:avr:mega') }}" == "true" ]]; then
|
||||
# Arduino Mega
|
||||
echo "::set-output name=options:::cpu=atmega2560"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'arduino:mbed') }}" == "true" ]]; then
|
||||
# Arduino Nano 33 BLE
|
||||
echo "::set-output name=skip-pattern::(HTTP|MQTT).*ino"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'arduino-beta:mbed') }}" == "true" ]]; then
|
||||
# Arduino Portenta H7
|
||||
echo "::set-output name=skip-pattern::(HTTP|MQTT).*ino"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'arduino:megaavr:uno2018') }}" == "true" ]]; then
|
||||
# Arduino Uno WiFi
|
||||
echo "::set-output name=options:::mode=on"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'adafruit:samd') }}" == "true" ]]; then
|
||||
# Adafruit SAMD
|
||||
echo "::set-output name=options:::usbstack=arduino,debug=off"
|
||||
echo "::set-output name=index-url::--additional-urls https://www.adafruit.com/package_adafruit_index.json"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'adafruit:nrf52') }}" == "true" ]]; then
|
||||
# Adafruit Feather nRF52
|
||||
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 "::set-output name=options:::softdevice=s132v6,debug=l0"
|
||||
echo "::set-output name=index-url::--additional-urls https://www.adafruit.com/package_adafruit_index.json"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'esp32:esp32') }}" == "true" ]]; then
|
||||
# ESP32
|
||||
python -m pip install pyserial
|
||||
echo "::set-output name=index-url::--additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'esp8266:esp8266') }}" == "true" ]]; then
|
||||
# ESP8266
|
||||
echo "::set-output name=options:::xtal=80,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=512K"
|
||||
echo "::set-output name=index-url::--additional-urls http://arduino.esp8266.com/stable/package_esp8266com_index.json"
|
||||
echo "::set-output name=skip-pattern::(HTTP|MQTT).*ino"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'SparkFun:apollo3') }}" == "true" ]]; then
|
||||
# SparkFun Apollo
|
||||
echo "::set-output name=index-url::--additional-urls https://raw.githubusercontent.com/sparkfun/Arduino_Apollo3/master/package_sparkfun_apollo3_index.json"
|
||||
echo "::set-output name=warnings::'none'"
|
||||
echo "::set-output name=skip-pattern::(HTTP|MQTT).*ino"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'STM32:stm32') }}" == "true" ]]; then
|
||||
# STM32 (official core)
|
||||
echo "::set-output name=options:::pnum=BLACKPILL_F303CC"
|
||||
echo "::set-output name=index-url::--additional-urls https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'stm32duino:STM32F1') }}" == "true" ]]; then
|
||||
# STM32 (unofficial core)
|
||||
echo "::set-output name=options:::bootloader_version=original,cpu_speed=speed_72mhz"
|
||||
echo "::set-output name=index-url::--additional-urls http://dan.drown.org/stm32duino/package_STM32duino_index.json"
|
||||
|
||||
elif [[ "${{ contains(matrix.board, 'MegaCoreX:megaavr') }}" == "true" ]]; then
|
||||
# MegaCoreX
|
||||
echo "::set-output name=index-url::--additional-urls https://mcudude.github.io/MegaCoreX/package_MCUdude_MegaCoreX_index.json"
|
||||
|
||||
fi
|
||||
|
||||
- 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.board }}${{ 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
|
46
.gitignore
vendored
46
.gitignore
vendored
|
@ -1,42 +1,16 @@
|
|||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Arduino Library Development file
|
||||
.development
|
||||
|
||||
# Arduino testing sketches
|
||||
examples/test/
|
||||
|
||||
# Atom
|
||||
*.tags
|
||||
*.tags1
|
||||
|
||||
# Jetbrain IDEs
|
||||
.idea
|
||||
|
||||
# Debug decoder
|
||||
extras/decoder/log.txt
|
||||
extras/decoder/out.txt
|
||||
|
||||
# PlatformIO
|
||||
.pio*
|
195
.travis.yml
195
.travis.yml
|
@ -1,195 +0,0 @@
|
|||
env:
|
||||
global:
|
||||
matrix:
|
||||
# see https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc#options
|
||||
# and https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#boardstxt
|
||||
- BOARD="arduino:avr:uno"
|
||||
- BOARD="arduino:avr:mega:cpu=atmega2560"
|
||||
- BOARD="arduino:avr:leonardo"
|
||||
- BOARD="esp8266:esp8266:generic:xtal=80,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=512K"
|
||||
- BOARD="esp32:esp32:esp32"
|
||||
- BOARD="STM32:stm32:GenF3:pnum=BLACKPILL_F303CC"
|
||||
- BOARD="arduino:samd:arduino_zero_native"
|
||||
- BOARD="arduino:sam:arduino_due_x"
|
||||
- BOARD="adafruit:nrf52:feather52832:softdevice=s132v6,debug=l0"
|
||||
- BOARD="Intel:arc32:arduino_101"
|
||||
- BOARD="arduino:megaavr:uno2018:mode=on"
|
||||
- BOARD="SparkFun:apollo3:amap3redboard"
|
||||
- BOARD="arduino:mbed:nano33ble"
|
||||
- BOARD="stm32duino:STM32F1:mapleMini:bootloader_version=original,cpu_speed=speed_72mhz"
|
||||
- BOARD="adafruit:samd:adafruit_feather_m0:usbstack=arduino,debug=off"
|
||||
- BOARD="arduino-beta:mbed:envie_m4"
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# required for Adafruit nRF52 (adafruit-nrfutil package)
|
||||
- python3
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
|
||||
before_install:
|
||||
# install Arduino CLI
|
||||
- curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
|
||||
- export PATH=$PATH:$PWD/bin
|
||||
|
||||
# check every board in matrix and install 3rd party definitions
|
||||
- |
|
||||
if [[ "$BOARD" =~ "arduino:avr:uno" ]]; then
|
||||
export BUILD_EXAMPLES=true;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino:avr;
|
||||
|
||||
elif [[ "$BOARD" =~ "arduino:avr:mega" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino:avr;
|
||||
|
||||
elif [[ "$BOARD" =~ "arduino:avr:leonardo" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino:avr;
|
||||
|
||||
elif [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index --additional-urls http://arduino.esp8266.com/stable/package_esp8266com_index.json;
|
||||
arduino-cli core install esp8266:esp8266 --additional-urls http://arduino.esp8266.com/stable/package_esp8266com_index.json;
|
||||
export SKIP_PAT='(HTTP|MQTT).*ino';
|
||||
|
||||
elif [[ "$BOARD" =~ "esp32:esp32:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json;
|
||||
arduino-cli core install esp32:esp32 --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json;
|
||||
|
||||
elif [[ "$BOARD" =~ "STM32:stm32:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index --additional-urls https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json;
|
||||
arduino-cli core install STM32:stm32 --additional-urls https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json;
|
||||
|
||||
elif [[ "$BOARD" =~ "arduino:samd:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino:samd;
|
||||
|
||||
elif [[ "$BOARD" =~ "arduino:sam:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino:sam;
|
||||
|
||||
elif [[ "$BOARD" =~ "adafruit:nrf52:" ]]; then
|
||||
pip3 install --user adafruit-nrfutil;
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index --additional-urls https://www.adafruit.com/package_adafruit_index.json;
|
||||
arduino-cli core install adafruit:nrf52 --additional-urls https://www.adafruit.com/package_adafruit_index.json;
|
||||
|
||||
elif [[ "$BOARD" =~ "Intel:arc32:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install Intel:arc32;
|
||||
|
||||
elif [[ "$BOARD" =~ "arduino:megaavr:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino:megaavr;
|
||||
|
||||
elif [[ "$BOARD" =~ "SparkFun:apollo3:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=none;
|
||||
arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json;
|
||||
arduino-cli core install SparkFun:apollo3 --additional-urls https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json;
|
||||
|
||||
elif [[ "$BOARD" =~ "arduino:mbed:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino:mbed;
|
||||
export SKIP_PAT='(HTTP|MQTT).*ino';
|
||||
|
||||
elif [[ "$BOARD" =~ "stm32duino:STM32F1:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index --additional-urls http://dan.drown.org/stm32duino/package_STM32duino_index.json;
|
||||
arduino-cli core install stm32duino:STM32F1 --additional-urls http://dan.drown.org/stm32duino/package_STM32duino_index.json;
|
||||
|
||||
elif [[ "$BOARD" =~ "adafruit:samd:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index --additional-urls https://www.adafruit.com/package_adafruit_index.json
|
||||
arduino-cli core install adafruit:samd --additional-urls https://www.adafruit.com/package_adafruit_index.json
|
||||
|
||||
elif [[ "$BOARD" =~ "arduino-beta:mbed:" ]]; then
|
||||
export BUILD_EXAMPLES=false;
|
||||
export WARNINGS=all;
|
||||
arduino-cli core update-index;
|
||||
arduino-cli core install arduino-beta:mbed;
|
||||
export SKIP_PAT='(HTTP|MQTT).*ino';
|
||||
|
||||
fi
|
||||
|
||||
# check if this release commit (or forced build) and if so, build for every board
|
||||
- if [[ "$TRAVIS_COMMIT_MESSAGE" =~ "Bump version to" || "$TRAVIS_COMMIT_MESSAGE" =~ "TRAVIS_FORCE_BUILD" ]]; then
|
||||
export BUILD_EXAMPLES=true;
|
||||
fi
|
||||
|
||||
# create directory to save the library and create symbolic link
|
||||
install:
|
||||
- mkdir -p $HOME/Arduino/libraries
|
||||
- ln -s $PWD $HOME/Arduino/libraries/RadioLib
|
||||
|
||||
# only build the master branch
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
script:
|
||||
# build all example sketches
|
||||
- |
|
||||
if [ ! -z "$BUILD_EXAMPLES" ] && [ "$BUILD_EXAMPLES" = true ] ; then
|
||||
for example in $(find $PWD/examples -name '*.ino' | sort); do
|
||||
# check whether to skip this sketch
|
||||
if [ ! -z "$SKIP_PAT" ] && [[ ${example} =~ $SKIP_PAT ]]; then
|
||||
# skip sketch
|
||||
echo -e "\n\033[1;33mSkipped ${example##*/} (matched with $SKIP_PAT)\033[0m";
|
||||
else
|
||||
# build sketch
|
||||
echo -e "\n\033[1;33mBuilding ${example##*/} ... \033[0m";
|
||||
arduino-cli compile --fqbn $BOARD $example --warnings=$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
|
||||
else
|
||||
echo -e "\n\033[1;33mExample builds skipped for $BOARD\033[0m";
|
||||
fi
|
||||
|
||||
# generate Doxygen documentation (only for Arduino UNO)
|
||||
- if [ $BOARD = "arduino:avr:uno" ]; then
|
||||
sudo apt-get update;
|
||||
sudo apt-get install -y doxygen;
|
||||
doxygen Doxyfile;
|
||||
fi
|
||||
|
||||
# deploy Doxygen docs on master branch and only when building for Arduino UNO
|
||||
deploy:
|
||||
provider: pages
|
||||
skip_cleanup: true
|
||||
local_dir: docs/html
|
||||
github_token: $GH_REPO_TOKEN
|
||||
on:
|
||||
branch: master
|
||||
condition: $BOARD = "arduino:avr:uno"
|
3
CODE_OF_CONDUCT.md
Normal file
3
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Code of Conduct
|
||||
|
||||
Don't be an a*shole.
|
|
@ -1,4 +1,4 @@
|
|||
# RadioLib [](https://travis-ci.org/jgromes/RadioLib)
|
||||
# RadioLib 
|
||||
|
||||
### _One radio library to rule them all!_
|
||||
|
||||
|
@ -69,6 +69,9 @@ SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
|||
* [__STM32__ (official core)](https://github.com/stm32duino/Arduino_Core_STM32) - STM32 Nucleo, Discovery, Maple, BluePill, BlackPill etc.
|
||||
* [__STM32__ (unofficial core)](https://github.com/rogerclarkmelbourne/Arduino_STM32) - STM32F1 and STM32F4-based boards
|
||||
|
||||
* __MCUdude__
|
||||
* [__MegaCoreX__](https://github.com/MCUdude/MegaCoreX) - megaAVR-0 series (ATmega4809, ATmega3209 etc.)
|
||||
|
||||
The list above is by no means exhaustive. Most of RadioLib code is independent of the used platform, so as long as your board is running some Arduino-compatible core, RadioLib should work. Compilation of all examples is tested for all platforms prior to releasing new version.
|
||||
|
||||
### In development:
|
||||
|
@ -83,7 +86,7 @@ The list above is by no means exhaustive. Most of RadioLib code is independent o
|
|||
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/).
|
||||
|
||||
### Help, my module isn't working!
|
||||
The fastest way to get help is by creating an [issue](https://github.com/jgromes/RadioLib/issues/new?assignees=&labels=&template=bug_report.md&title=) 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.
|
||||
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.
|
||||
|
||||
### RadioLib doesn't support my module! What should I do?
|
||||
Start by creating new issue (if it doesn't exist yet). If you have some experience with Arduino and C/C++ in general, you can try to add the support yourself! Use the template files in `/extras/` folder to get started. This is by far the fastest way to implement new modules into RadioLib, since I can't be working on everything all the time. If you don't trust your programming skills enough to have a go at it yourself, don't worry. I will try to implement all requested modules, but it will take me a while.
|
||||
|
|
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
RadioLib is provided as-is without any warranty, and is not intended to be used in security-critical applications. However, if you discover a vulnerability within the library code, please report it to gromes.jan@gmail.com.
|
|
@ -58,6 +58,17 @@ void setup() {
|
|||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// initialize AFSK client
|
||||
Serial.print(F("[AFSK] Initializing ... "));
|
||||
state = audio.begin();
|
||||
if(state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
|
@ -46,7 +46,7 @@ void setup() {
|
|||
int state = radio.beginFSK();
|
||||
|
||||
// when using one of the non-LoRa modules for AFSK
|
||||
// (RF69, CC1101,, Si4432 etc.), use the basic begin() method
|
||||
// (RF69, CC1101, Si4432 etc.), use the basic begin() method
|
||||
// int state = radio.begin();
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
|
@ -56,17 +56,30 @@ void setup() {
|
|||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// initialize AFSK client
|
||||
Serial.print(F("[AFSK] Initializing ... "));
|
||||
state = audio.begin();
|
||||
if(state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// AFSKClient can be used to transmit tones,
|
||||
// same as Arduino tone() function
|
||||
|
||||
|
||||
// 400 Hz tone
|
||||
Serial.print(F("[AFSK] 400 Hz tone ... "));
|
||||
audio.tone(400);
|
||||
delay(1000);
|
||||
|
||||
// silence
|
||||
Serial.println(F("done!"));
|
||||
audio.noTone();
|
||||
delay(1000);
|
||||
|
||||
|
|
|
@ -44,8 +44,7 @@ void setup() {
|
|||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 1.2 kbps (1200 baud 2-FSK AX.25)
|
||||
// frequency deviation: 0.5 kHz (1200 baud 2-FSK AX.25)
|
||||
int state = radio.beginFSK(434.0, 1.2, 0.5);
|
||||
int state = radio.beginFSK(434.0, 1.2);
|
||||
|
||||
// when using one of the non-LoRa modules for AX.25
|
||||
// (RF69, CC1101,, Si4432 etc.), use the basic begin() method
|
||||
|
|
|
@ -111,6 +111,11 @@ void loop() {
|
|||
|
||||
}
|
||||
|
||||
// NOTE: in FSK mode, SX127x will not automatically
|
||||
// turn transmitter off after sending a packet
|
||||
// set mode to standby to ensure we don't jam others
|
||||
//radio.standby()
|
||||
|
||||
// wait a second before transmitting again
|
||||
delay(1000);
|
||||
|
||||
|
|
112
extras/decoder/DebugDecoder.py
Normal file
112
extras/decoder/DebugDecoder.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
import re, sys, argparse
|
||||
from pathlib import Path
|
||||
from argparse import RawTextHelpFormatter
|
||||
|
||||
|
||||
'''
|
||||
TODO list:
|
||||
1. Parse macro values (the names of bits in all registers in header file)
|
||||
2. Failed SPI write handling
|
||||
3. SX126x/SX128x handling
|
||||
4. AT handling
|
||||
'''
|
||||
|
||||
|
||||
def get_macro_name(value, macros):
|
||||
for macro in macros:
|
||||
if macro[1] == value:
|
||||
return macro[0]
|
||||
return 'UNKNOWN_VALUE'
|
||||
|
||||
|
||||
def get_macro_value(value):
|
||||
return ' 0x{0:02X}\n'.format(int(value, 16))
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''
|
||||
RadioLib debug output decoder script. Turns RadioLib Serial dumps into readable text.
|
||||
|
||||
Step-by-step guid on how to use the decoder:
|
||||
1. Uncomment lines 312 (#define RADIOLIB_DEBUG) and 313 (#define RADIOLIB_VERBOSE) in RadioLib/src/BuildOpt.h
|
||||
2. Recompile and upload the failing Arduino sketch
|
||||
3. Open Arduino IDE Serial Monitor and enable timestamps
|
||||
4. Copy the Serial output and save it into a .txt file
|
||||
5. Run this script
|
||||
|
||||
Output will be saved in the file specified by --out and printed to the terminal
|
||||
''')
|
||||
parser.add_argument('file', metavar='file', type=str, help='Text file of the debug output')
|
||||
parser.add_argument('--out', metavar='out', default='./out.txt', type=str, help='Where to save the decoded file (defaults to ./out.txt)')
|
||||
args = parser.parse_args()
|
||||
|
||||
# open the log file
|
||||
log = open(args.file, 'r').readlines()
|
||||
|
||||
# find modules that are in use
|
||||
used_modules = []
|
||||
pattern_module = re.compile('(([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?.[0-9]{3} -> )?M\t')
|
||||
for entry in log:
|
||||
m = pattern_module.search(entry)
|
||||
if m != None:
|
||||
used_modules.append(entry[m.end():].rstrip())
|
||||
|
||||
# get paths to all relevant header files
|
||||
header_files = []
|
||||
for path in Path('../../src').rglob('*.h'):
|
||||
for module in used_modules:
|
||||
if module in path.name:
|
||||
header_files.append(path)
|
||||
|
||||
# extract names of address macros from the header files
|
||||
macro_addresses = []
|
||||
pattern_define = re.compile('#define \w* +\w*(\n| +\/\/){1}')
|
||||
for path in header_files:
|
||||
file = open(path, 'r').readlines()
|
||||
for line in file:
|
||||
m = pattern_define.search(line)
|
||||
if m != None:
|
||||
s = re.split(' +', m.group().rstrip())
|
||||
if (s.__len__() > 1) and ('_REG' in s[1]):
|
||||
macro_addresses.append([s[1], int(s[2], 0)])
|
||||
|
||||
'''
|
||||
# extract names of value macros for each adddress macro
|
||||
macro_values = []
|
||||
for path in header_files:
|
||||
file = open(path, 'r').readlines()
|
||||
for line in file:
|
||||
for module in used_modules:
|
||||
pattern_addr_macro = re.compile('\/\/ SI443X_REG_\w+'.format(module.capitalize()))
|
||||
'''
|
||||
|
||||
# parse every line in the log file
|
||||
out = []
|
||||
pattern_debug = re.compile('(([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?.[0-9]{3} -> )?[RWM]\t.+')
|
||||
for entry in log:
|
||||
m = pattern_debug.search(entry)
|
||||
if m != None:
|
||||
s = re.split('( |\t)+', entry.rstrip())
|
||||
cmd_len = int((s.__len__() - 7)/2)
|
||||
new_entry = s[0] + s[1] + s[2] + s[3]
|
||||
if s[4] == 'W':
|
||||
macro_address = int(s[6], 16)
|
||||
new_entry += 'write {0:>2} 0x{1:02X} {2}\n'.format(cmd_len, macro_address, get_macro_name(macro_address, macro_addresses))
|
||||
for i in range(cmd_len):
|
||||
new_entry += get_macro_value(s[8 + 2*i]);
|
||||
elif s[4] == 'R':
|
||||
macro_address = int(s[6], 16)
|
||||
new_entry += 'read {0:>2} 0x{1:02X} {2}\n'.format(cmd_len, macro_address, get_macro_name(macro_address, macro_addresses))
|
||||
for i in range(cmd_len):
|
||||
new_entry += get_macro_value(s[8 + 2*i]);
|
||||
elif s[4] == 'M':
|
||||
new_entry += 'module {}\n'.format(s[6])
|
||||
out.append(new_entry)
|
||||
else:
|
||||
out.append(entry)
|
||||
|
||||
# write the output file
|
||||
out_file = open(args.out, 'w')
|
||||
for line in out:
|
||||
print(line, end='')
|
||||
out_file.write(line)
|
||||
out_file.close()
|
|
@ -130,6 +130,11 @@ getTempRaw KEYWORD2
|
|||
setRfSwitchPins KEYWORD2
|
||||
forceLDRO KEYWORD2
|
||||
autoLDRO KEYWORD2
|
||||
getChipVersion KEYWORD2
|
||||
invertIQ KEYWORD2
|
||||
setOokThresholdType KEYWORD2
|
||||
setOokPeakThresholdDecrement KEYWORD2
|
||||
setOokFixedOrFloorThreshold KEYWORD2
|
||||
|
||||
# RF69-specific
|
||||
setAESKey KEYWORD2
|
||||
|
@ -137,6 +142,7 @@ enableAES KEYWORD2
|
|||
disableAES KEYWORD2
|
||||
getTemperature KEYWORD2
|
||||
setAmbientTemperature KEYWORD2
|
||||
setLnaTestBoost KEYWORD2
|
||||
|
||||
# CC1101-specific
|
||||
getLQI KEYWORD2
|
||||
|
@ -144,6 +150,7 @@ setGdo0Action KEYWORD2
|
|||
setGdo2Action KEYWORD2
|
||||
clearGdo0Action KEYWORD2
|
||||
clearGdo2Action KEYWORD2
|
||||
setCrcFiltering KEYWORD2
|
||||
|
||||
# SX126x-specific
|
||||
setTCXO KEYWORD2
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=RadioLib
|
||||
version=4.0.1
|
||||
version=4.3.0
|
||||
author=Jan Gromes <gromes.jan@gmail.com>
|
||||
maintainer=Jan Gromes <gromes.jan@gmail.com>
|
||||
sentence=Universal wireless communication library for Arduino
|
||||
|
|
145
src/BuildOpt.h
145
src/BuildOpt.h
|
@ -1,4 +1,4 @@
|
|||
#ifndef _RADIOLIB_BUILD_OPTIONS_H
|
||||
#if !defined(_RADIOLIB_BUILD_OPTIONS_H)
|
||||
#define _RADIOLIB_BUILD_OPTIONS_H
|
||||
|
||||
#if ARDUINO >= 100
|
||||
|
@ -10,13 +10,16 @@
|
|||
/*
|
||||
* Platform-specific configuration.
|
||||
*
|
||||
* RADIOLIB_PLATFORM - platform name, used in debugging to quickly check the correct platform is detected,
|
||||
* RADIOLIB_PLATFORM - platform name, used in debugging to quickly check the correct platform is detected.
|
||||
* RADIOLIB_PIN_TYPE - which type should be used for pin numbers in functions like digitalRead().
|
||||
* RADIOLIB_PIN_MODE - which type should be used for pin modes in functions like pinMode().
|
||||
* RADIOLIB_PIN_STATUS - which type should be used for pin values in functions like digitalWrite().
|
||||
* RADIOLIB_DIGITAL_PIN_TO_INTERRUPT - function to be used to convert digital pin number to interrupt pin number.
|
||||
* RADIOLIB_INTERRUPT_STATUS - which type should be used for pin changes in functions like attachInterrupt().
|
||||
* RADIOLIB_DIGITAL_PIN_TO_INTERRUPT - function/macro to be used to convert digital pin number to interrupt pin number.
|
||||
* RADIOLIB_NC - alias for unused pin, usually the largest possible value of RADIOLIB_PIN_TYPE.
|
||||
* RADIOLIB_DEFAULT_SPI - default SPIClass instance to use.
|
||||
* RADIOLIB_PROGMEM - macro to place variable into program storage (usually Flash).
|
||||
* RADIOLIB_PROGMEM_READ_BYTE - function/macro to read variables saved in program storage (usually Flash).
|
||||
* RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED - defined if the specific platform does not support SoftwareSerial.
|
||||
* RADIOLIB_HARDWARE_SERIAL_PORT - which hardware serial port should be used on platform that do not have SoftwareSerial support.
|
||||
* RADIOLIB_TONE_UNSUPPORTED - some platforms do not have tone()/noTone(), which is required for AFSK.
|
||||
|
@ -43,6 +46,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
// the following must be defined if the Arduino core does not support SoftwareSerial library
|
||||
//#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
|
@ -51,6 +56,11 @@
|
|||
// the following must be defined if the Arduino core does not support tone function
|
||||
//#define RADIOLIB_TONE_UNSUPPORTED
|
||||
|
||||
// some platforms seem to have issues with SPI modules that use a command interface
|
||||
// this can be mitigated by adding delays into SPI communication
|
||||
// (see https://github.com/jgromes/RadioLib/issues/158 for details)
|
||||
//#define RADIOLIB_SPI_SLOWDOWN
|
||||
|
||||
// some of RadioLib drivers may be excluded, to prevent collisions with platforms (or to speed up build process)
|
||||
// the following is a complete list of all possible exclusion macros, uncomment any of them to disable that driver
|
||||
// NOTE: Some of the exclusion macros are dependent on each other. For example, it is not possible to exclude RF69
|
||||
|
@ -80,7 +90,7 @@
|
|||
//#define RADIOLIB_EXCLUDE_SSTV
|
||||
|
||||
#else
|
||||
#if defined(__AVR__) && !(defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY))
|
||||
#if defined(__AVR__) && !(defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY) || defined(ARDUINO_ARCH_MEGAAVR))
|
||||
// Arduino AVR boards (except for megaAVR) - Uno, Mega etc.
|
||||
#define RADIOLIB_PLATFORM "Arduino AVR"
|
||||
#define RADIOLIB_PIN_TYPE uint8_t
|
||||
|
@ -90,6 +100,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
#elif defined(ESP8266)
|
||||
// ESP8266 boards
|
||||
|
@ -101,6 +113,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
// RadioLib has ESP8266 driver, this must be disabled to use ESP8266 as platform
|
||||
#define RADIOLIB_EXCLUDE_ESP8266
|
||||
|
@ -115,9 +129,14 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
|
||||
// ESP32 doesn't support tone(), but it can be emulated via LED control peripheral
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
#define RADIOLIB_TONE_ESP32_CHANNEL (1)
|
||||
|
||||
#elif defined(ARDUINO_ARCH_STM32)
|
||||
// official STM32 Arduino core (https://github.com/stm32duino/Arduino_Core_STM32)
|
||||
|
@ -126,15 +145,20 @@
|
|||
#define RADIOLIB_PIN_MODE uint32_t
|
||||
#define RADIOLIB_PIN_STATUS uint32_t
|
||||
#define RADIOLIB_INTERRUPT_STATUS RADIOLIB_PIN_STATUS
|
||||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(digitalPinToPinName(p))
|
||||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFFFFFFFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
|
||||
// slow down SX126x/8x SPI on this platform
|
||||
#define RADIOLIB_SPI_SLOWDOWN
|
||||
|
||||
#elif defined(SAMD_SERIES)
|
||||
// Arduino SAMD (Zero, MKR, etc.) and Adafruit SAMD boards (M0 and M4)
|
||||
#define RADIOLIB_PLATFORM "Arduino/Adafruit SAMD"
|
||||
// Adafruit SAMD boards (M0 and M4)
|
||||
#define RADIOLIB_PLATFORM "Adafruit SAMD"
|
||||
#define RADIOLIB_PIN_TYPE uint32_t
|
||||
#define RADIOLIB_PIN_MODE uint32_t
|
||||
#define RADIOLIB_PIN_STATUS uint32_t
|
||||
|
@ -142,6 +166,26 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFFFFFFFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
|
||||
// slow down SX126x/8x SPI on this platform
|
||||
#define RADIOLIB_SPI_SLOWDOWN
|
||||
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
// Arduino SAMD (Zero, MKR, etc.)
|
||||
#define RADIOLIB_PLATFORM "Arduino SAMD"
|
||||
#define RADIOLIB_PIN_TYPE pin_size_t
|
||||
#define RADIOLIB_PIN_MODE PinMode
|
||||
#define RADIOLIB_PIN_STATUS PinStatus
|
||||
#define RADIOLIB_INTERRUPT_STATUS RADIOLIB_PIN_STATUS
|
||||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
|
||||
|
@ -155,6 +199,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFFFFFFFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
|
@ -169,6 +215,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFFFFFFFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
#elif defined(ARDUINO_ARC32_TOOLS)
|
||||
// Intel Curie
|
||||
|
@ -180,6 +228,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
#elif defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY)
|
||||
// Arduino megaAVR boards - Uno Wifi Rev.2, Nano Every
|
||||
|
@ -191,20 +241,29 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
#elif defined(AM_PART_APOLLO3)
|
||||
// Sparkfun Artemis boards
|
||||
#define RADIOLIB_PLATFORM "Sparkfun Artemis"
|
||||
#define RADIOLIB_PIN_TYPE uint8_t
|
||||
#define RADIOLIB_PIN_MODE uint8_t
|
||||
#define RADIOLIB_PIN_STATUS uint8_t
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3)
|
||||
// Sparkfun Apollo3 boards
|
||||
#define RADIOLIB_PLATFORM "Sparkfun Apollo3"
|
||||
#define RADIOLIB_PIN_TYPE pin_size_t
|
||||
#define RADIOLIB_PIN_MODE Arduino_PinMode
|
||||
#define RADIOLIB_PIN_STATUS PinStatus
|
||||
#define RADIOLIB_INTERRUPT_STATUS RADIOLIB_PIN_STATUS
|
||||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
|
||||
// Apollo3 uses mbed libraries, which already contain ESP8266 driver
|
||||
#define RADIOLIB_EXCLUDE_ESP8266
|
||||
|
||||
// slow down SX126x/8x SPI on this platform
|
||||
#define RADIOLIB_SPI_SLOWDOWN
|
||||
|
||||
#elif defined(ARDUINO_ARDUINO_NANO33BLE)
|
||||
// Arduino Nano 33 BLE
|
||||
|
@ -216,6 +275,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
|
||||
|
@ -232,6 +293,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
|
||||
|
@ -248,9 +311,23 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#define RADIOLIB_HARDWARE_SERIAL_PORT Serial1
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
|
||||
#elif defined(ARDUINO_ARCH_MEGAAVR)
|
||||
// MegaCoreX by MCUdude (https://github.com/MCUdude/MegaCoreX)
|
||||
#define RADIOLIB_PLATFORM "MegaCoreX"
|
||||
#define RADIOLIB_PIN_TYPE uint8_t
|
||||
#define RADIOLIB_PIN_MODE uint8_t
|
||||
#define RADIOLIB_PIN_STATUS uint8_t
|
||||
#define RADIOLIB_INTERRUPT_STATUS RADIOLIB_PIN_STATUS
|
||||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
#else
|
||||
// other platforms not covered by the above list - this may or may not work
|
||||
|
@ -263,6 +340,8 @@
|
|||
#define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p)
|
||||
#define RADIOLIB_NC (0xFF)
|
||||
#define RADIOLIB_DEFAULT_SPI SPI
|
||||
#define RADIOLIB_PROGMEM PROGMEM
|
||||
#define RADIOLIB_PROGMEM_READ_BYTE(addr) pgm_read_byte(addr)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -297,6 +376,23 @@
|
|||
#define RADIOLIB_VERBOSE_PRINTLN(...) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uncomment to enable "paranoid" SPI mode
|
||||
* Every write to an SPI register using SPI set function will be verified by a subsequent read operation.
|
||||
* This improves reliablility, but slightly slows down communication.
|
||||
* Note: Enabled by default.
|
||||
*/
|
||||
#define RADIOLIB_SPI_PARANOID
|
||||
|
||||
/*
|
||||
* Uncomment to enable parameter range checking
|
||||
* RadioLib will check provided parameters (such as frequency) against limits determined by the device manufacturer.
|
||||
* It is highly advised to keep this macro defined, removing it will allow invalid values to be set,
|
||||
* possibly leading to bricked module and/or program crashing.
|
||||
* Note: Enabled by default.
|
||||
*/
|
||||
#define RADIOLIB_CHECK_PARAMS
|
||||
|
||||
/*
|
||||
* Uncomment to enable god mode - all methods and member variables in all classes will be made public, thus making them accessible from Arduino code.
|
||||
* Warning: Come on, it's called GOD mode - obviously only use this if you know what you're doing.
|
||||
|
@ -304,6 +400,13 @@
|
|||
*/
|
||||
//#define RADIOLIB_GODMODE
|
||||
|
||||
/*
|
||||
* Uncomment to enable low-level hardware access
|
||||
* This will make some hardware methods like SPI get/set accessible from the user sketch - think of it as "god mode lite"
|
||||
* Warning: RadioLib won't stop you from writing invalid stuff into your device, so it's quite easy to brick your module with this.
|
||||
*/
|
||||
//#define RADIOLIB_LOW_LEVEL
|
||||
|
||||
/*
|
||||
* Uncomment to enable pre-defined modules when using RadioShield.
|
||||
*/
|
||||
|
@ -313,7 +416,6 @@
|
|||
* Uncomment to enable static-only memory management: no dynamic allocation will be performed.
|
||||
* Warning: Large static arrays will be created in some methods. It is not advised to send large packets in this mode.
|
||||
*/
|
||||
|
||||
//#define RADIOLIB_STATIC_ONLY
|
||||
|
||||
// set the size of static arrays to use
|
||||
|
@ -327,15 +429,18 @@
|
|||
#define RADIOLIB_ASSERT(STATEVAR) { if((STATEVAR) != ERR_NONE) { return(STATEVAR); } }
|
||||
|
||||
/*!
|
||||
\brief Macro to check variable is within constraints - this is commonly used to check parameter ranges.
|
||||
\brief Macro to check variable is within constraints - this is commonly used to check parameter ranges. Requires RADIOLIB_CHECK_RANGE to be enabled
|
||||
*/
|
||||
#if defined(RADIOLIB_CHECK_PARAMS)
|
||||
#define RADIOLIB_CHECK_RANGE(VAR, MIN, MAX, ERR) { if(!(((VAR) >= (MIN)) && ((VAR) <= (MAX)))) { return(ERR); } }
|
||||
|
||||
#else
|
||||
#define RADIOLIB_CHECK_RANGE(VAR, MIN, MAX, ERR) {}
|
||||
#endif
|
||||
|
||||
// version definitions
|
||||
#define RADIOLIB_VERSION_MAJOR (0x04)
|
||||
#define RADIOLIB_VERSION_MINOR (0x00)
|
||||
#define RADIOLIB_VERSION_PATCH (0x01)
|
||||
#define RADIOLIB_VERSION_MINOR (0x03)
|
||||
#define RADIOLIB_VERSION_PATCH (0x00)
|
||||
#define RADIOLIB_VERSION_EXTRA (0x00)
|
||||
|
||||
#define RADIOLIB_VERSION ((RADIOLIB_VERSION_MAJOR << 24) | (RADIOLIB_VERSION_MINOR << 16) | (RADIOLIB_VERSION_PATCH << 8) | (RADIOLIB_VERSION_EXTRA))
|
||||
|
|
|
@ -33,28 +33,11 @@ void ISerial::flush() {
|
|||
_mod->ModuleSerial->flush();
|
||||
}
|
||||
|
||||
// SoftwareSerial-only methods
|
||||
#if !defined(RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED)
|
||||
bool ISerial::listen() {
|
||||
return(_mod->ModuleSerial->listen());
|
||||
}
|
||||
|
||||
bool ISerial::isListening() {
|
||||
return(_mod->ModuleSerial->isListening());
|
||||
}
|
||||
|
||||
bool ISerial::stopListening() {
|
||||
return(_mod->ModuleSerial->stopListening());
|
||||
}
|
||||
|
||||
bool ISerial::overflow() {
|
||||
return(_mod->ModuleSerial->overflow());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_ARCH_MEGAAVR
|
||||
size_t ISerial::print(const __FlashStringHelper *ifsh) {
|
||||
return(_mod->ModuleSerial->print(ifsh));
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t ISerial::print(const String &s) {
|
||||
return(_mod->ModuleSerial->print(s));
|
||||
|
@ -96,9 +79,11 @@ size_t ISerial::print(const Printable& x) {
|
|||
return(_mod->ModuleSerial->print(x));
|
||||
}
|
||||
|
||||
#ifndef ARDUINO_ARCH_MEGAAVR
|
||||
size_t ISerial::println(const __FlashStringHelper *ifsh) {
|
||||
return(_mod->ModuleSerial->println(ifsh));
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t ISerial::println(const String &s) {
|
||||
return(_mod->ModuleSerial->println(s));
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#ifndef _RADIOLIB_ISERIAL_H
|
||||
#if !defined(_RADIOLIB_ISERIAL_H)
|
||||
#define _RADIOLIB_ISERIAL_H
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "WString.h"
|
||||
#include "Printable.h"
|
||||
|
||||
/*!
|
||||
\class ISerial
|
||||
|
||||
|
@ -25,15 +20,9 @@ class ISerial {
|
|||
int available();
|
||||
void flush();
|
||||
|
||||
// SoftwareSerial-only methods
|
||||
#if !defined(RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED)
|
||||
bool listen();
|
||||
bool isListening();
|
||||
bool stopListening();
|
||||
bool overflow();
|
||||
#endif
|
||||
|
||||
#if !defined(ARDUINO_ARCH_MEGAAVR)
|
||||
size_t print(const __FlashStringHelper *);
|
||||
#endif
|
||||
size_t print(const String &);
|
||||
size_t print(const char[]);
|
||||
size_t print(char);
|
||||
|
@ -45,7 +34,9 @@ class ISerial {
|
|||
size_t print(double, int = 2);
|
||||
size_t print(const Printable&);
|
||||
|
||||
#if !defined(ARDUINO_ARCH_MEGAAVR)
|
||||
size_t println(const __FlashStringHelper *);
|
||||
#endif
|
||||
size_t println(const String &s);
|
||||
size_t println(const char[]);
|
||||
size_t println(char);
|
||||
|
@ -58,7 +49,7 @@ class ISerial {
|
|||
size_t println(const Printable&);
|
||||
size_t println(void);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !(defined(RADIOLIB_LOW_LEVEL) || defined(RADIOLIB_GODMODE))
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
|
125
src/Module.cpp
125
src/Module.cpp
|
@ -175,8 +175,8 @@ bool Module::ATsendData(uint8_t* data, uint32_t len) {
|
|||
bool Module::ATgetResponse() {
|
||||
char data[128];
|
||||
char* dataPtr = data;
|
||||
uint32_t start = millis();
|
||||
while(millis() - start < _ATtimeout) {
|
||||
uint32_t start = Module::millis();
|
||||
while(Module::millis() - start < _ATtimeout) {
|
||||
while(ModuleSerial->available() > 0) {
|
||||
char c = ModuleSerial->read();
|
||||
RADIOLIB_VERBOSE_PRINT(c);
|
||||
|
@ -216,39 +216,43 @@ int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
uint8_t newValue = (currentValue & ~mask) | (value & mask);
|
||||
SPIwriteRegister(reg, newValue);
|
||||
|
||||
// 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 = micros();
|
||||
uint8_t readValue;
|
||||
while(micros() - start < (checkInterval * 1000)) {
|
||||
readValue = SPIreadRegister(reg);
|
||||
if(readValue == newValue) {
|
||||
// check passed, we can stop the loop
|
||||
return(ERR_NONE);
|
||||
#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 = Module::micros();
|
||||
uint8_t readValue = 0x00;
|
||||
while(Module::micros() - start < (checkInterval * 1000)) {
|
||||
readValue = SPIreadRegister(reg);
|
||||
if(readValue == newValue) {
|
||||
// check passed, we can stop the loop
|
||||
return(ERR_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
// 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();
|
||||
|
||||
return(ERR_SPI_WRITE_FAILED);
|
||||
return(ERR_SPI_WRITE_FAILED);
|
||||
#else
|
||||
return(ERR_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) {
|
||||
|
@ -336,21 +340,62 @@ RADIOLIB_PIN_STATUS Module::digitalRead(RADIOLIB_PIN_TYPE pin) {
|
|||
}
|
||||
|
||||
void Module::tone(RADIOLIB_PIN_TYPE pin, uint16_t value) {
|
||||
/// \todo Add tone support for platforms without tone()
|
||||
#ifndef RADIOLIB_TONE_UNSUPPORTED
|
||||
if(pin != RADIOLIB_NC) {
|
||||
::tone(pin, value);
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
::tone(pin, value);
|
||||
#else
|
||||
#if defined(ESP32)
|
||||
// ESP32 tone() emulation
|
||||
ledcAttachPin(pin, RADIOLIB_TONE_ESP32_CHANNEL);
|
||||
ledcWriteTone(RADIOLIB_TONE_ESP32_CHANNEL, value);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::noTone(RADIOLIB_PIN_TYPE pin) {
|
||||
/// \todo Add tone support for platforms without tone()
|
||||
#ifndef RADIOLIB_TONE_UNSUPPORTED
|
||||
if(pin != RADIOLIB_NC) {
|
||||
::noTone(pin);
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
::noTone(pin);
|
||||
#else
|
||||
#if defined(ESP32)
|
||||
ledcDetachPin(pin);
|
||||
ledcWrite(RADIOLIB_TONE_ESP32_CHANNEL, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void Module::attachInterrupt(RADIOLIB_PIN_TYPE interruptNum, void (*userFunc)(void), RADIOLIB_INTERRUPT_STATUS mode) {
|
||||
::attachInterrupt(interruptNum, userFunc, mode);
|
||||
}
|
||||
|
||||
void Module::detachInterrupt(RADIOLIB_PIN_TYPE interruptNum) {
|
||||
::detachInterrupt(interruptNum);
|
||||
}
|
||||
|
||||
void Module::yield() {
|
||||
::yield();
|
||||
}
|
||||
|
||||
void Module::delay(uint32_t ms) {
|
||||
::delay(ms);
|
||||
}
|
||||
|
||||
void Module::delayMicroseconds(uint32_t us) {
|
||||
::delayMicroseconds(us);
|
||||
}
|
||||
|
||||
uint32_t Module::millis() {
|
||||
return(::millis());
|
||||
}
|
||||
|
||||
uint32_t Module::micros() {
|
||||
return(::micros());
|
||||
}
|
||||
|
||||
void Module::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||
|
|
74
src/Module.h
74
src/Module.h
|
@ -4,7 +4,6 @@
|
|||
#include "TypeDef.h"
|
||||
|
||||
#include <SPI.h>
|
||||
//#include <Wire.h>
|
||||
#ifndef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#include <SoftwareSerial.h>
|
||||
#endif
|
||||
|
@ -87,9 +86,9 @@ class Module {
|
|||
|
||||
\param spi SPI interface to be used, can also use software SPI implementations.
|
||||
|
||||
\param spiSettings SPI interface settings.
|
||||
\param spiSettings SPI interface settings. Defaults to 2 MHz clock, MSB first, mode 0.
|
||||
*/
|
||||
Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass& spi, SPISettings spiSettings);
|
||||
Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass& spi, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
/*!
|
||||
\brief Generic module constructor.
|
||||
|
@ -356,6 +355,27 @@ class Module {
|
|||
*/
|
||||
SPISettings getSpiSettings() const { return(_spiSettings); }
|
||||
|
||||
/*!
|
||||
\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!
|
||||
|
||||
\param rxEn RX enable pin.
|
||||
|
||||
\param txEn TX enable pin.
|
||||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
|
||||
/*!
|
||||
\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).
|
||||
*/
|
||||
void setRfSwitchState(RADIOLIB_PIN_STATUS rxPinState, RADIOLIB_PIN_STATUS txPinState);
|
||||
|
||||
// Arduino core overrides
|
||||
|
||||
/*!
|
||||
\brief Arduino core pinMode override that checks RADIOLIB_NC as alias for unused pin.
|
||||
|
||||
|
@ -400,23 +420,51 @@ class Module {
|
|||
static void noTone(RADIOLIB_PIN_TYPE pin);
|
||||
|
||||
/*!
|
||||
\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 Arduino core attachInterrupt override.
|
||||
|
||||
\param rxEn RX enable pin.
|
||||
\param interruptNum Interrupt number.
|
||||
|
||||
\param txEn TX enable pin.
|
||||
\param userFunc Interrupt service routine.
|
||||
|
||||
\param mode Pin hcange direction.
|
||||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
static void attachInterrupt(RADIOLIB_PIN_TYPE interruptNum, void (*userFunc)(void), RADIOLIB_INTERRUPT_STATUS mode);
|
||||
|
||||
/*!
|
||||
\brief Set RF switch state.
|
||||
\brief Arduino core detachInterrupt override.
|
||||
|
||||
\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 interruptNum Interrupt number.
|
||||
*/
|
||||
void setRfSwitchState(RADIOLIB_PIN_STATUS rxPinState, RADIOLIB_PIN_STATUS txPinState);
|
||||
static void detachInterrupt(RADIOLIB_PIN_TYPE interruptNum);
|
||||
|
||||
/*!
|
||||
\brief Arduino core yield override.
|
||||
*/
|
||||
static void yield();
|
||||
|
||||
/*!
|
||||
\brief Arduino core delay override.
|
||||
|
||||
\param ms Delay length in milliseconds.
|
||||
*/
|
||||
static void delay(uint32_t ms);
|
||||
|
||||
/*!
|
||||
\brief Arduino core delayMicroseconds override.
|
||||
|
||||
\param us Delay length in microseconds.
|
||||
*/
|
||||
static void delayMicroseconds(uint32_t us);
|
||||
|
||||
/*!
|
||||
\brief Arduino core millis override.
|
||||
*/
|
||||
static uint32_t millis();
|
||||
|
||||
/*!
|
||||
\brief Arduino core micros override.
|
||||
*/
|
||||
static uint32_t micros();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef _RADIOLIB_H
|
||||
#if !defined(_RADIOLIB_H)
|
||||
#define _RADIOLIB_H
|
||||
|
||||
/*!
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef _RADIOLIB_TYPES_H
|
||||
#if !defined(_RADIOLIB_TYPES_H)
|
||||
#define _RADIOLIB_TYPES_H
|
||||
|
||||
#include "BuildOpt.h"
|
||||
|
@ -283,6 +283,11 @@
|
|||
*/
|
||||
#define ERR_INVALID_ENCODING -23
|
||||
|
||||
/*!
|
||||
\brief LoRa packet header has been damaged.
|
||||
*/
|
||||
#define ERR_LORA_HEADER_DAMAGED -24
|
||||
|
||||
// RF69-specific status codes
|
||||
|
||||
/*!
|
||||
|
@ -320,6 +325,11 @@
|
|||
*/
|
||||
#define ERR_INVALID_MODULATION -107
|
||||
|
||||
/*!
|
||||
\brief Supplied Peak type is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_OOK_RSSI_PEAK_TYPE -108
|
||||
|
||||
// ESP8266 status codes
|
||||
|
||||
/*!
|
||||
|
|
|
@ -16,8 +16,8 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
uint8_t i = 0;
|
||||
bool flagFound = false;
|
||||
while((i < 10) && !flagFound) {
|
||||
uint8_t version = SPIreadRegister(CC1101_REG_VERSION);
|
||||
if(version == 0x14) {
|
||||
int16_t version = getChipVersion();
|
||||
if((version == CC1101_VERSION_CURRENT) || (version == CC1101_VERSION_LEGACY)) {
|
||||
flagFound = true;
|
||||
} else {
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
|
@ -28,10 +28,10 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
char buffHex[7];
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0014"));
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0004/0x0014"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
_mod->term(RADIOLIB_USE_SPI);
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found CC1101! (match by CC1101_REG_VERSION == 0x14)"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tCC1101"));
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
|
@ -96,18 +96,35 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
// start transmission
|
||||
int16_t state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission start
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
// wait for transmission start or timeout
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_TX);
|
||||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// wait for transmission end
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
// wait for transmission end or timeout
|
||||
start = Module::micros();
|
||||
while(Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_TX);
|
||||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
|
@ -120,13 +137,35 @@ 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))*(CC1101_MAX_PACKET_LENGTH*400.0);
|
||||
|
||||
// start reception
|
||||
int16_t state = startReceive();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for rx queue to exceed threshold.
|
||||
while (!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
// wait for sync word or timeout
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_TX);
|
||||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// wait for packet end or timeout
|
||||
start = Module::micros();
|
||||
while(Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_TX);
|
||||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// read packet data
|
||||
|
@ -185,11 +224,11 @@ int16_t CC1101::packetMode() {
|
|||
}
|
||||
|
||||
void CC1101::setGdo0Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir) {
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, dir);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, dir);
|
||||
}
|
||||
|
||||
void CC1101::clearGdo0Action() {
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
}
|
||||
|
||||
void CC1101::setGdo2Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir) {
|
||||
|
@ -197,14 +236,14 @@ void CC1101::setGdo2Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir) {
|
|||
return;
|
||||
}
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), func, dir);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), func, dir);
|
||||
}
|
||||
|
||||
void CC1101::clearGdo2Action() {
|
||||
if(_mod->getGpio() != RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()));
|
||||
}
|
||||
|
||||
int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -414,12 +453,10 @@ int16_t CC1101::setBitRate(float br) {
|
|||
// set bit rate value
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_MDMCFG4, e, 3, 0);
|
||||
state |= SPIsetRegValue(CC1101_REG_MDMCFG3, m);
|
||||
|
||||
if (state == ERR_NONE) {
|
||||
_br = br;
|
||||
if(state == ERR_NONE) {
|
||||
CC1101::_br = br;
|
||||
}
|
||||
|
||||
return (state);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::setRxBandwidth(float rxBw) {
|
||||
|
@ -443,14 +480,13 @@ int16_t CC1101::setRxBandwidth(float rxBw) {
|
|||
}
|
||||
|
||||
int16_t CC1101::setFrequencyDeviation(float freqDev) {
|
||||
// set frequency deviation to lowest available setting (required for RTTY)
|
||||
if(freqDev == 0.0) {
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_DEVIATN, 0, 6, 4);
|
||||
state |= SPIsetRegValue(CC1101_REG_DEVIATN, 0, 2, 0);
|
||||
return(state);
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
if(freqDev < 0.0) {
|
||||
newFreqDev = 1.587;
|
||||
}
|
||||
|
||||
RADIOLIB_CHECK_RANGE(freqDev, 1.587, 380.8, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
RADIOLIB_CHECK_RANGE(newFreqDev, 1.587, 380.8, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
|
||||
// set mode to standby
|
||||
SPIsendCommand(CC1101_CMD_IDLE);
|
||||
|
@ -458,7 +494,7 @@ int16_t CC1101::setFrequencyDeviation(float freqDev) {
|
|||
// calculate exponent and mantissa values
|
||||
uint8_t e = 0;
|
||||
uint8_t m = 0;
|
||||
getExpMant(freqDev * 1000.0, 8, 17, 7, e, m);
|
||||
getExpMant(newFreqDev * 1000.0, 8, 17, 7, e, m);
|
||||
|
||||
// set frequency deviation value
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_DEVIATN, (e << 4), 6, 4);
|
||||
|
@ -622,7 +658,7 @@ int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) {
|
|||
|
||||
int16_t CC1101::disableAddressFiltering() {
|
||||
// disable address filtering
|
||||
int16_t state = _mod->SPIsetRegValue(CC1101_REG_PKTCTRL1, CC1101_ADR_CHK_NONE, 1, 0);
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_PKTCTRL1, CC1101_ADR_CHK_NONE, 1, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set node address to default (0x00)
|
||||
|
@ -678,9 +714,9 @@ uint8_t CC1101::getLQI() const {
|
|||
size_t CC1101::getPacketLength(bool update) {
|
||||
if(!_packetLengthQueried && update) {
|
||||
if (_packetLengthConfig == CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
_packetLength = _mod->SPIreadRegister(CC1101_REG_FIFO);
|
||||
_packetLength = SPIreadRegister(CC1101_REG_FIFO);
|
||||
} else {
|
||||
_packetLength = _mod->SPIreadRegister(CC1101_REG_PKTLEN);
|
||||
_packetLength = SPIreadRegister(CC1101_REG_PKTLEN);
|
||||
}
|
||||
|
||||
_packetLengthQueried = true;
|
||||
|
@ -698,23 +734,20 @@ int16_t CC1101::variablePacketLengthMode(uint8_t maxLen) {
|
|||
}
|
||||
|
||||
int16_t CC1101::enableSyncWordFiltering(uint8_t maxErrBits, bool requireCarrierSense) {
|
||||
switch (maxErrBits){
|
||||
switch(maxErrBits){
|
||||
case 0:
|
||||
// in 16 bit sync word, expect all 16 bits
|
||||
return (SPIsetRegValue(CC1101_REG_MDMCFG2,
|
||||
requireCarrierSense ? CC1101_SYNC_MODE_16_16_THR : CC1101_SYNC_MODE_16_16, 2, 0));
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, (requireCarrierSense ? CC1101_SYNC_MODE_16_16_THR : CC1101_SYNC_MODE_16_16), 2, 0));
|
||||
case 1:
|
||||
// in 16 bit sync word, expect at least 15 bits
|
||||
return (SPIsetRegValue(CC1101_REG_MDMCFG2,
|
||||
requireCarrierSense ? CC1101_SYNC_MODE_15_16_THR : CC1101_SYNC_MODE_15_16, 2, 0));
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, (requireCarrierSense ? CC1101_SYNC_MODE_15_16_THR : CC1101_SYNC_MODE_15_16), 2, 0));
|
||||
default:
|
||||
return (ERR_INVALID_SYNC_WORD);
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::disableSyncWordFiltering(bool requireCarrierSense) {
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2,
|
||||
requireCarrierSense ? CC1101_SYNC_MODE_NONE_THR : CC1101_SYNC_MODE_NONE, 2, 0));
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, (requireCarrierSense ? CC1101_SYNC_MODE_NONE_THR : CC1101_SYNC_MODE_NONE), 2, 0));
|
||||
}
|
||||
|
||||
int16_t CC1101::setCrcFiltering(bool crcOn) {
|
||||
|
@ -761,10 +794,10 @@ int16_t CC1101::setDataShaping(uint8_t sh) {
|
|||
// set data shaping
|
||||
switch(sh) {
|
||||
case RADIOLIB_SHAPING_NONE:
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_2_FSK, 6, 4);
|
||||
state = SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_2_FSK, 6, 4);
|
||||
break;
|
||||
case RADIOLIB_SHAPING_0_5:
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_GFSK, 6, 4);
|
||||
state = SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_GFSK, 6, 4);
|
||||
break;
|
||||
default:
|
||||
return(ERR_INVALID_DATA_SHAPING);
|
||||
|
@ -780,17 +813,17 @@ int16_t CC1101::setEncoding(uint8_t encoding) {
|
|||
// set encoding
|
||||
switch(encoding) {
|
||||
case RADIOLIB_ENCODING_NRZ:
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MANCHESTER_EN_OFF, 3, 3);
|
||||
state = SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MANCHESTER_EN_OFF, 3, 3);
|
||||
RADIOLIB_ASSERT(state);
|
||||
return(_mod->SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_OFF, 6, 6));
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_OFF, 6, 6));
|
||||
case RADIOLIB_ENCODING_MANCHESTER:
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MANCHESTER_EN_ON, 3, 3);
|
||||
state = SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MANCHESTER_EN_ON, 3, 3);
|
||||
RADIOLIB_ASSERT(state);
|
||||
return(_mod->SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_OFF, 6, 6));
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_OFF, 6, 6));
|
||||
case RADIOLIB_ENCODING_WHITENING:
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MANCHESTER_EN_OFF, 3, 3);
|
||||
state = SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MANCHESTER_EN_OFF, 3, 3);
|
||||
RADIOLIB_ASSERT(state);
|
||||
return(_mod->SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_ON, 6, 6));
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_ON, 6, 6));
|
||||
default:
|
||||
return(ERR_INVALID_ENCODING);
|
||||
}
|
||||
|
@ -800,12 +833,36 @@ void CC1101::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
|||
_mod->setRfSwitchPins(rxEn, txEn);
|
||||
}
|
||||
|
||||
uint8_t CC1101::random() {
|
||||
// set mode to Rx
|
||||
SPIsendCommand(CC1101_CMD_RX);
|
||||
|
||||
// wait a bit for the RSSI reading to stabilise
|
||||
Module::delay(10);
|
||||
|
||||
// read RSSI value 8 times, always keep just the least significant bit
|
||||
uint8_t randByte = 0x00;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
randByte |= ((SPIreadRegister(CC1101_REG_RSSI) & 0x01) << i);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
SPIsendCommand(CC1101_CMD_IDLE);
|
||||
|
||||
return(randByte);
|
||||
}
|
||||
|
||||
|
||||
int16_t CC1101::getChipVersion() {
|
||||
return(SPIgetRegValue(CC1101_REG_VERSION));
|
||||
}
|
||||
|
||||
int16_t CC1101::config() {
|
||||
// Reset the radio. Registers may be dirty from previous usage.
|
||||
SPIsendCommand(CC1101_CMD_RESET);
|
||||
|
||||
// Wait a ridiculous amount of time to be sure radio is ready.
|
||||
delay(150);
|
||||
Module::delay(150);
|
||||
|
||||
// enable automatic frequency synthesizer calibration
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4);
|
||||
|
@ -863,11 +920,11 @@ int16_t CC1101::setPacketMode(uint8_t mode, uint8_t len) {
|
|||
}
|
||||
|
||||
// set PKTCTRL0.LENGTH_CONFIG
|
||||
int16_t state = _mod->SPIsetRegValue(CC1101_REG_PKTCTRL0, mode, 1, 0);
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_PKTCTRL0, mode, 1, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_PKTLEN, len);
|
||||
state = SPIsetRegValue(CC1101_REG_PKTLEN, len);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update the cached value
|
||||
|
@ -921,10 +978,21 @@ void CC1101::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len) {
|
|||
}
|
||||
|
||||
void CC1101::SPIsendCommand(uint8_t cmd) {
|
||||
// get pointer to used SPI interface and the settings
|
||||
SPIClass* spi = _mod->getSpi();
|
||||
SPISettings spiSettings = _mod->getSpiSettings();
|
||||
|
||||
// pull NSS low
|
||||
Module::digitalWrite(_mod->getCs(), LOW);
|
||||
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
SPI.transfer(cmd);
|
||||
SPI.endTransaction();
|
||||
|
||||
// start transfer
|
||||
spi->beginTransaction(spiSettings);
|
||||
|
||||
// send the command byte
|
||||
spi->transfer(cmd);
|
||||
|
||||
// stop transfer
|
||||
spi->endTransaction();
|
||||
Module::digitalWrite(_mod->getCs(), HIGH);
|
||||
}
|
||||
|
||||
|
|
|
@ -456,7 +456,8 @@
|
|||
#define CC1101_PARTNUM 0x00
|
||||
|
||||
// CC1101_REG_VERSION
|
||||
#define CC1101_VERSION 0x14
|
||||
#define CC1101_VERSION_CURRENT 0x14
|
||||
#define CC1101_VERSION_LEGACY 0x04
|
||||
|
||||
// CC1101_REG_MARCSTATE
|
||||
#define CC1101_MARC_STATE_SLEEP 0x00 // 4 0 main radio control state: sleep
|
||||
|
@ -528,7 +529,7 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\param freqDev Frequency deviation from carrier frequency in kHz Defaults to 48.0 kHz.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 135.0 kHz.
|
||||
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
|
||||
|
@ -875,12 +876,41 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
Module* _mod;
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t random();
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return CC1101_VERSION_LEGACY (0x04) or CC1101_VERSION_CURRENT (0x14) if CC1101 is connected and working.
|
||||
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
int16_t getChipVersion();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
// SPI read overrides to set bit for burst write and status registers access
|
||||
int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
int16_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2);
|
||||
void SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes);
|
||||
uint8_t SPIreadRegister(uint8_t reg);
|
||||
void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len);
|
||||
void SPIwriteRegister(uint8_t reg, uint8_t data);
|
||||
|
||||
void SPIsendCommand(uint8_t cmd);
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
float _freq = 0;
|
||||
float _br = 0;
|
||||
uint8_t _rawRSSI = 0;
|
||||
uint8_t _rawLQI = 0;
|
||||
uint8_t _modulation = CC1101_MOD_FORMAT_2_FSK;
|
||||
|
@ -899,16 +929,6 @@ class CC1101: public PhysicalLayer {
|
|||
int16_t directMode();
|
||||
static void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant);
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
||||
// SPI read overrides to set bit for burst write and status registers access
|
||||
int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
int16_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2);
|
||||
void SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes);
|
||||
uint8_t SPIreadRegister(uint8_t reg);
|
||||
void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len);
|
||||
void SPIwriteRegister(uint8_t reg, uint8_t data);
|
||||
|
||||
void SPIsendCommand(uint8_t cmd);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,13 +30,13 @@ int16_t ESP8266::reset() {
|
|||
}
|
||||
|
||||
// wait for the module to start
|
||||
delay(2000);
|
||||
Module::delay(2000);
|
||||
|
||||
// test AT setup
|
||||
uint32_t start = millis();
|
||||
while (millis() - start < 3000) {
|
||||
uint32_t start = Module::millis();
|
||||
while (Module::millis() - start < 3000) {
|
||||
if(!_mod->ATsendCommand("AT")) {
|
||||
delay(100);
|
||||
Module::delay(100);
|
||||
} else {
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
@ -192,11 +192,11 @@ int16_t ESP8266::send(uint8_t* data, size_t len) {
|
|||
|
||||
size_t ESP8266::receive(uint8_t* data, size_t len, uint32_t timeout) {
|
||||
size_t i = 0;
|
||||
uint32_t start = millis();
|
||||
uint32_t start = Module::millis();
|
||||
|
||||
// wait until the required number of bytes is received or until timeout
|
||||
while((millis() - start < timeout) && (i < len)) {
|
||||
yield();
|
||||
while((Module::millis() - start < timeout) && (i < len)) {
|
||||
Module::yield();
|
||||
while(_mod->ModuleSerial->available() > 0) {
|
||||
uint8_t b = _mod->ModuleSerial->read();
|
||||
RADIOLIB_DEBUG_PRINT(b);
|
||||
|
@ -209,10 +209,10 @@ size_t ESP8266::receive(uint8_t* data, size_t len, uint32_t timeout) {
|
|||
|
||||
size_t ESP8266::getNumBytes(uint32_t timeout, size_t minBytes) {
|
||||
// wait for available data
|
||||
uint32_t start = millis();
|
||||
uint32_t start = Module::millis();
|
||||
while(_mod->ModuleSerial->available() < (int16_t)minBytes) {
|
||||
yield();
|
||||
if(millis() - start >= timeout) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start >= timeout) {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
@ -220,16 +220,16 @@ size_t ESP8266::getNumBytes(uint32_t timeout, size_t minBytes) {
|
|||
// read response
|
||||
char rawStr[20];
|
||||
uint8_t i = 0;
|
||||
start = millis();
|
||||
start = Module::millis();
|
||||
while(_mod->ModuleSerial->available() > 0) {
|
||||
yield();
|
||||
Module::yield();
|
||||
char c = _mod->ModuleSerial->read();
|
||||
rawStr[i++] = c;
|
||||
if(c == ':') {
|
||||
rawStr[i++] = 0;
|
||||
break;
|
||||
}
|
||||
if(millis() - start >= timeout) {
|
||||
if(Module::millis() - start >= timeout) {
|
||||
rawStr[i++] = 0;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -55,10 +55,14 @@ class ESP8266: public TransportLayer {
|
|||
size_t receive(uint8_t* data, size_t len, uint32_t timeout = 10000) override;
|
||||
size_t getNumBytes(uint32_t timeout = 10000, size_t minBytes = 10) override;
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,8 +18,8 @@ int16_t RF69::begin(float freq, float br, float freqDev, float rxBw, int8_t powe
|
|||
reset();
|
||||
|
||||
// check version register
|
||||
uint8_t version = _mod->SPIreadRegister(RF69_REG_VERSION);
|
||||
if(version == 0x24) {
|
||||
int16_t version = getChipVersion();
|
||||
if(version == RF69_CHIP_VERSION) {
|
||||
flagFound = true;
|
||||
} else {
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
|
@ -33,7 +33,7 @@ int16_t RF69::begin(float freq, float br, float freqDev, float rxBw, int8_t powe
|
|||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0024"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ int16_t RF69::begin(float freq, float br, float freqDev, float rxBw, int8_t powe
|
|||
_mod->term(RADIOLIB_USE_SPI);
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found RF69! (match by RF69_REG_VERSION == 0x24)"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRF69"));
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
|
@ -102,9 +102,9 @@ int16_t RF69::begin(float freq, float br, float freqDev, float rxBw, int8_t powe
|
|||
void RF69::reset() {
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
}
|
||||
|
||||
int16_t RF69::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -116,11 +116,11 @@ int16_t RF69::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission end or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
if(micros() - start > timeout) {
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
clearIRQFlags();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
|
@ -145,11 +145,11 @@ int16_t RF69::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
if(micros() - start > timeout) {
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
clearIRQFlags();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
|
@ -267,26 +267,26 @@ int16_t RF69::startReceive() {
|
|||
}
|
||||
|
||||
void RF69::setDio0Action(void (*func)(void)) {
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
}
|
||||
|
||||
void RF69::clearDio0Action() {
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
}
|
||||
|
||||
void RF69::setDio1Action(void (*func)(void)) {
|
||||
if(_mod->getGpio() != RADIOLIB_NC) {
|
||||
if(_mod->getGpio() == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), func, RISING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), func, RISING);
|
||||
}
|
||||
|
||||
void RF69::clearDio1Action() {
|
||||
if(_mod->getGpio() != RADIOLIB_NC) {
|
||||
if(_mod->getGpio() == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()));
|
||||
}
|
||||
|
||||
int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -369,23 +369,26 @@ int16_t RF69::readData(uint8_t* data, size_t len) {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t CC1101::setOOK(bool enableOOK) {
|
||||
// Change modulation
|
||||
int16_t RF69::setOOK(bool enableOOK) {
|
||||
// set OOK and if successful, save the new setting
|
||||
int16_t state = ERR_NONE;
|
||||
if(enableOOK) {
|
||||
int16_t state = SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_OOK, 4, 3);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update current modulation
|
||||
_modulation = CC1101_MOD_FORMAT_ASK_OOK;
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_OOK, 4, 3, 5);
|
||||
} else {
|
||||
int16_t state = SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_FSK, 4, 3);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update current modulation
|
||||
_modulation = CC1101_MOD_FORMAT_2_FSK;
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_FSK, 4, 3, 5);
|
||||
}
|
||||
if(state == ERR_NONE) {
|
||||
_ook = enableOOK;
|
||||
}
|
||||
|
||||
return(setOutputPower(_power));
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::setOokThresholdType(uint8_t type) {
|
||||
if((type != RF69_OOK_THRESH_FIXED) && (type != RF69_OOK_THRESH_PEAK) && (type != RF69_OOK_THRESH_AVERAGE)) {
|
||||
return(ERR_INVALID_OOK_RSSI_PEAK_TYPE);
|
||||
}
|
||||
return(_mod->SPIsetRegValue(RF69_REG_OOK_PEAK, type, 7, 3, 5));
|
||||
}
|
||||
|
||||
int16_t RF69::setFrequency(float freq) {
|
||||
|
@ -401,11 +404,10 @@ int16_t RF69::setFrequency(float freq) {
|
|||
|
||||
//set carrier frequency
|
||||
uint32_t FRF = (freq * (uint32_t(1) << RF69_DIV_EXPONENT)) / RF69_CRYSTAL_FREQ;
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_FRF_MSB, (FRF & 0xFF0000) >> 16, 7, 0);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_FRF_MID, (FRF & 0x00FF00) >> 8, 7, 0);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_FRF_LSB, FRF & 0x0000FF, 7, 0);
|
||||
|
||||
return(state);
|
||||
_mod->SPIwriteRegister(RF69_REG_FRF_MSB, (FRF & 0xFF0000) >> 16);
|
||||
_mod->SPIwriteRegister(RF69_REG_FRF_MID, (FRF & 0x00FF00) >> 8);
|
||||
_mod->SPIwriteRegister(RF69_REG_FRF_LSB, FRF & 0x0000FF);
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t RF69::setBitRate(float br) {
|
||||
|
@ -525,8 +527,14 @@ int16_t RF69::setRxBandwidth(float rxBw) {
|
|||
}
|
||||
|
||||
int16_t RF69::setFrequencyDeviation(float freqDev) {
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
if(freqDev < 0.0) {
|
||||
newFreqDev = 0.6;
|
||||
}
|
||||
|
||||
// check frequency deviation range
|
||||
if(!((freqDev + _br/2 <= 500))) {
|
||||
if(!((newFreqDev + _br/2 <= 500))) {
|
||||
return(ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
}
|
||||
|
||||
|
@ -535,7 +543,7 @@ int16_t RF69::setFrequencyDeviation(float freqDev) {
|
|||
|
||||
// set frequency deviation from carrier frequency
|
||||
uint32_t base = 1;
|
||||
uint32_t fdev = (freqDev * (base << 19)) / 32000;
|
||||
uint32_t fdev = (newFreqDev * (base << 19)) / 32000;
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_FDEV_MSB, (fdev & 0xFF00) >> 8, 5, 0);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_FDEV_LSB, fdev & 0x00FF, 7, 0);
|
||||
|
||||
|
@ -659,7 +667,7 @@ int16_t RF69::getTemperature() {
|
|||
// wait until measurement is finished
|
||||
while(_mod->SPIgetRegValue(RF69_REG_TEMP_1, 2, 2) == RF69_TEMP_MEAS_RUNNING) {
|
||||
// check every 10 us
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
}
|
||||
int8_t rawTemp = _mod->SPIgetRegValue(RF69_REG_TEMP_2);
|
||||
|
||||
|
@ -776,6 +784,14 @@ int16_t RF69::setEncoding(uint8_t encoding) {
|
|||
}
|
||||
}
|
||||
|
||||
int16_t RF69::setLnaTestBoost(bool value) {
|
||||
if(value) {
|
||||
return (_mod->SPIsetRegValue(RF69_REG_TEST_LNA, RF69_TEST_LNA_BOOST_HIGH, 7, 0));
|
||||
}
|
||||
|
||||
return(_mod->SPIsetRegValue(RF69_TEST_LNA_BOOST_NORMAL, RF69_TEST_LNA_BOOST_HIGH, 7, 0));
|
||||
}
|
||||
|
||||
float RF69::getRSSI() {
|
||||
return(-1.0 * (_mod->SPIgetRegValue(RF69_REG_RSSI_VALUE)/2.0));
|
||||
}
|
||||
|
@ -784,6 +800,29 @@ void RF69::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
|||
_mod->setRfSwitchPins(rxEn, txEn);
|
||||
}
|
||||
|
||||
uint8_t RF69::random() {
|
||||
// set mode to Rx
|
||||
setMode(RF69_RX);
|
||||
|
||||
// wait a bit for the RSSI reading to stabilise
|
||||
Module::delay(10);
|
||||
|
||||
// read RSSI value 8 times, always keep just the least significant bit
|
||||
uint8_t randByte = 0x00;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
randByte |= ((_mod->SPIreadRegister(RF69_REG_RSSI_VALUE) & 0x01) << i);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
setMode(RF69_STANDBY);
|
||||
|
||||
return(randByte);
|
||||
}
|
||||
|
||||
int16_t RF69::getChipVersion() {
|
||||
return(_mod->SPIgetRegValue(RF69_REG_VERSION));
|
||||
}
|
||||
|
||||
int16_t RF69::config() {
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#define RF69_REG_AES_KEY_16 0x4D
|
||||
#define RF69_REG_TEMP_1 0x4E
|
||||
#define RF69_REG_TEMP_2 0x4F
|
||||
#define RF69_REG_TEST_LNA 0x58
|
||||
#define RF69_REG_TEST_PA1 0x5A
|
||||
#define RF69_REG_TEST_PA2 0x5C
|
||||
#define RF69_REG_TEST_DAGC 0x6F
|
||||
|
@ -162,6 +163,9 @@
|
|||
// RF69_REG_LISTEN_3
|
||||
#define RF69_LISTEN_COEF_RX 0x20 // 7 0 duration of Rx phase in Listen mode
|
||||
|
||||
// RF69_REG_VERSION
|
||||
#define RF69_CHIP_VERSION 0x24 // 7 0
|
||||
|
||||
// RF69_REG_PA_LEVEL
|
||||
#define RF69_PA0_OFF 0b00000000 // 7 7 PA0 disabled
|
||||
#define RF69_PA0_ON 0b10000000 // 7 7 PA0 enabled (default)
|
||||
|
@ -406,6 +410,10 @@
|
|||
#define RF69_AES_OFF 0b00000000 // 0 0 AES encryption disabled (default)
|
||||
#define RF69_AES_ON 0b00000001 // 0 0 AES encryption enabled, payload size limited to 66 bytes
|
||||
|
||||
// RF69_REG_TEST_LNA
|
||||
#define RF69_TEST_LNA_BOOST_NORMAL 0x1B // 7 0
|
||||
#define RF69_TEST_LNA_BOOST_HIGH 0x2D // 7 0
|
||||
|
||||
// RF69_REG_TEMP_1
|
||||
#define RF69_TEMP_MEAS_START 0b00001000 // 3 3 trigger temperature measurement
|
||||
#define RF69_TEMP_MEAS_RUNNING 0b00000100 // 2 2 temperature measurement status: on-going
|
||||
|
@ -740,6 +748,24 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
size_t getPacketLength(bool update = true) override;
|
||||
|
||||
/*!
|
||||
\brief Enables/disables OOK modulation instead of FSK.
|
||||
|
||||
\param enableOOK Enable (true) or disable (false) OOK.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOOK(bool enableOOK);
|
||||
|
||||
/*!
|
||||
\brief Selects the type of threshold in the OOK data slicer
|
||||
|
||||
\param type Threshold type: RF69_OOK_THRESH_PEAK(default), RF69_OOK_THRESH_FIXED or RF69_OOK_THRESH_AVERAGE
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOokThresholdType(uint8_t type);
|
||||
|
||||
/*!
|
||||
\brief Set modem in fixed packet length mode.
|
||||
|
||||
|
@ -777,7 +803,7 @@ class RF69: public PhysicalLayer {
|
|||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
||||
\param crcOn Set or unset promiscuous mode.
|
||||
\param crcOn Set or unset CRC filtering.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
|
@ -812,6 +838,15 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setEncoding(uint8_t encoding) override;
|
||||
|
||||
/*!
|
||||
\brief Enable/disable LNA Boost mode (disabled by default).
|
||||
|
||||
\param value True to enable, false to disable.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setLnaTestBoost(bool value);
|
||||
|
||||
/*!
|
||||
\brief Gets RSSI (Recorded Signal Strength Indicator) of the last received packet.
|
||||
|
||||
|
@ -829,13 +864,32 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t random();
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return RF69_CHIP_VERSION (0x24) if SX127x is connected and working.
|
||||
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
int16_t getChipVersion();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
float _br = 0;
|
||||
float _rxBw = 0;
|
||||
bool _ook = false;
|
||||
int16_t _tempOffset = 0;
|
||||
int8_t _power = 0;
|
||||
|
||||
|
@ -851,7 +905,7 @@ class RF69: public PhysicalLayer {
|
|||
int16_t directMode();
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
int16_t setMode(uint8_t mode);
|
||||
|
|
|
@ -16,16 +16,14 @@ int16_t RFM95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
// some other error
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1278"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRFM95"));
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
@ -45,8 +43,12 @@ int16_t RFM95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
int16_t RFM95::setFrequency(float freq) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 862.0, 1020.0, ERR_INVALID_FREQUENCY);
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
// set frequency and if successful, save the new setting
|
||||
int16_t state = SX127x::setFrequencyRaw(freq);
|
||||
if(state == ERR_NONE) {
|
||||
SX127x::_freq = freq;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,7 +68,7 @@ class RFM95: public SX1278 {
|
|||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,16 +16,14 @@ int16_t RFM96::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
// some other error
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1278"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRFM96"));
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
@ -46,8 +44,12 @@ int16_t RFM96::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncW
|
|||
int16_t RFM96::setFrequency(float freq) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 410.0, 525.0, ERR_INVALID_FREQUENCY);
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
// set frequency and if successful, save the new setting
|
||||
int16_t state = SX127x::setFrequencyRaw(freq);
|
||||
if(state == ERR_NONE) {
|
||||
SX127x::_freq = freq;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,7 +68,7 @@ class RFM96: public SX1278 {
|
|||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class RFM97: public RFM95 {
|
|||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
uint8_t i = 0;
|
||||
bool flagFound = false;
|
||||
while((i < 10) && !flagFound) {
|
||||
uint8_t version = _mod->SPIreadRegister(RF69_REG_VERSION);
|
||||
int16_t version = getChipVersion();
|
||||
if((version == 0x21) || (version == 0x22) || (version == 0x23)) {
|
||||
flagFound = true;
|
||||
_chipRevision = version;
|
||||
|
@ -25,13 +25,13 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) RF69_REG_VERSION == "));
|
||||
|
||||
char buffHex[7];
|
||||
char buffHex[12];
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0021 / 0x0022 / 0x0023"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -40,13 +40,13 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
RADIOLIB_DEBUG_PRINTLN(F("No SX1231 found!"));
|
||||
_mod->term(RADIOLIB_USE_SPI);
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found SX1231!"));
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX1231"));
|
||||
|
||||
// configure settings not accessible by API
|
||||
int16_t state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tRF69"));
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
|
|
|
@ -51,7 +51,7 @@ class SX1231: public RF69 {
|
|||
*/
|
||||
int16_t begin(float freq = 434.0, float br = 48.0, float rxBw = 125.0, float freqDev = 50.0, int8_t power = 10, uint8_t preambleLen = 16);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
uint8_t _chipRevision = 0;
|
||||
|
|
|
@ -35,7 +35,7 @@ class SX1261 : public SX1262 {
|
|||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ class SX1262: public SX126x {
|
|||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ class SX1268: public SX126x {
|
|||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ int16_t SX126x::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16
|
|||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX126x"));
|
||||
|
||||
// BW in kHz and SF are required in order to calculate LDRO for setModulationParams
|
||||
_bwKhz = bw;
|
||||
|
@ -80,6 +81,7 @@ int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, uint16_t preambleL
|
|||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX126x"));
|
||||
|
||||
// initialize configuration variables (will be overwritten during public settings configuration)
|
||||
_br = 21333; // 48.0 kbps
|
||||
|
@ -159,7 +161,7 @@ int16_t SX126x::reset(bool verify) {
|
|||
// run the reset sequence
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
|
||||
// return immediately when verification is disabled
|
||||
|
@ -168,7 +170,7 @@ int16_t SX126x::reset(bool verify) {
|
|||
}
|
||||
|
||||
// set mode to standby - SX126x often refuses first few commands after reset
|
||||
uint32_t start = millis();
|
||||
uint32_t start = Module::millis();
|
||||
while(true) {
|
||||
// try to set mode to standby
|
||||
int16_t state = standby();
|
||||
|
@ -178,13 +180,13 @@ int16_t SX126x::reset(bool verify) {
|
|||
}
|
||||
|
||||
// standby command failed, check timeout and try again
|
||||
if(millis() - start >= 3000) {
|
||||
if(Module::millis() - start >= 3000) {
|
||||
// timed out, possibly incorrect wiring
|
||||
return(state);
|
||||
}
|
||||
|
||||
// wait a bit to not spam the module
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,16 +225,16 @@ int16_t SX126x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
clearIrqStatus();
|
||||
standby();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
uint32_t elapsed = micros() - start;
|
||||
uint32_t elapsed = Module::micros() - start;
|
||||
|
||||
// update data rate
|
||||
_dataRate = (len*8.0)/((float)elapsed/1000000.0);
|
||||
|
@ -283,10 +285,10 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
fixImplicitTimeout();
|
||||
clearIrqStatus();
|
||||
standby();
|
||||
|
@ -354,8 +356,8 @@ int16_t SX126x::scanChannel() {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for channel activity detected or timeout
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
}
|
||||
|
||||
// check CAD result
|
||||
|
@ -384,7 +386,7 @@ int16_t SX126x::sleep(bool retainConfig) {
|
|||
int16_t state = SPIwriteCommand(SX126X_CMD_SET_SLEEP, &sleepMode, 1, false);
|
||||
|
||||
// wait for SX126x to safely enter sleep mode
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -402,11 +404,11 @@ int16_t SX126x::standby(uint8_t mode) {
|
|||
}
|
||||
|
||||
void SX126x::setDio1Action(void (*func)(void)) {
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
}
|
||||
|
||||
void SX126x::clearDio1Action() {
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
}
|
||||
|
||||
int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -463,8 +465,8 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for BUSY to go low (= PA ramp up done)
|
||||
while(digitalRead(_mod->getGpio())) {
|
||||
yield();
|
||||
while(Module::digitalRead(_mod->getGpio())) {
|
||||
Module::yield();
|
||||
}
|
||||
|
||||
return(state);
|
||||
|
@ -730,11 +732,17 @@ int16_t SX126x::setFrequencyDeviation(float freqDev) {
|
|||
if(getPacketType() != SX126X_PACKET_TYPE_GFSK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
if(freqDev < 0.0) {
|
||||
newFreqDev = 0.6;
|
||||
}
|
||||
|
||||
RADIOLIB_CHECK_RANGE(freqDev, 0.0, 200.0, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
RADIOLIB_CHECK_RANGE(newFreqDev, 0.6, 200.0, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
|
||||
// calculate raw frequency deviation value
|
||||
uint32_t freqDevRaw = (uint32_t)(((freqDev * 1000.0) * (float)((uint32_t)(1) << 25)) / (SX126X_CRYSTAL_FREQ * 1000000.0));
|
||||
uint32_t freqDevRaw = (uint32_t)(((newFreqDev * 1000.0) * (float)((uint32_t)(1) << 25)) / (SX126X_CRYSTAL_FREQ * 1000000.0));
|
||||
|
||||
// check modulation parameters
|
||||
/*if(2 * freqDevRaw + _br > _rxBwKhz * 1000.0) {
|
||||
|
@ -1128,6 +1136,13 @@ uint32_t SX126x::getTimeOnAir(size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
float SX126x::getRSSIInst() {
|
||||
uint8_t data[3] = {0, 0, 0}; // RssiInst, Status, RFU
|
||||
SPIreadCommand(SX126X_CMD_GET_RSSI_INST, data, 3);
|
||||
|
||||
return (float)data[0] / (-2.0);
|
||||
}
|
||||
|
||||
int16_t SX126x::implicitHeader(size_t len) {
|
||||
return(setHeaderType(SX126X_LORA_HEADER_IMPLICIT, len));
|
||||
}
|
||||
|
@ -1173,6 +1188,27 @@ int16_t SX126x::autoLDRO() {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
uint8_t SX126x::random() {
|
||||
// set mode to Rx
|
||||
setRx(SX126X_RX_TIMEOUT_INF);
|
||||
|
||||
// wait a bit for the RSSI reading to stabilise
|
||||
Module::delay(10);
|
||||
|
||||
// read RSSI value 8 times, always keep just the least significant bit
|
||||
uint8_t randByte = 0x00;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
uint8_t val = 0x00;
|
||||
readRegister(SX126X_REG_RANDOM_NUMBER_0, &val, sizeof(uint8_t));
|
||||
randByte |= ((val & 0x01) << i);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
||||
return(randByte);
|
||||
}
|
||||
|
||||
int16_t SX126x::setTCXO(float voltage, uint32_t delay) {
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
@ -1182,6 +1218,11 @@ int16_t SX126x::setTCXO(float voltage, uint32_t delay) {
|
|||
clearDeviceErrors();
|
||||
}
|
||||
|
||||
// check 0 V disable
|
||||
if(abs(voltage - 0.0) <= 0.001) {
|
||||
return(reset(true));
|
||||
}
|
||||
|
||||
// check alowed voltage values
|
||||
uint8_t data[4];
|
||||
if(abs(voltage - 1.6) <= 0.001) {
|
||||
|
@ -1531,9 +1572,9 @@ int16_t SX126x::config(uint8_t modem) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for calibration completion
|
||||
delay(5);
|
||||
while(digitalRead(_mod->getGpio())) {
|
||||
yield();
|
||||
Module::delay(5);
|
||||
while(Module::digitalRead(_mod->getGpio())) {
|
||||
Module::yield();
|
||||
}
|
||||
|
||||
return(ERR_NONE);
|
||||
|
@ -1565,14 +1606,14 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
#endif
|
||||
|
||||
// pull NSS low
|
||||
digitalWrite(_mod->getCs(), LOW);
|
||||
Module::digitalWrite(_mod->getCs(), LOW);
|
||||
|
||||
// ensure BUSY is low (state machine ready)
|
||||
uint32_t start = millis();
|
||||
while(digitalRead(_mod->getGpio())) {
|
||||
yield();
|
||||
if(millis() - start >= timeout) {
|
||||
digitalWrite(_mod->getCs(), HIGH);
|
||||
uint32_t start = Module::millis();
|
||||
while(Module::digitalRead(_mod->getGpio())) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start >= timeout) {
|
||||
Module::digitalWrite(_mod->getCs(), HIGH);
|
||||
return(ERR_SPI_CMD_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
@ -1632,15 +1673,15 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
|
||||
// stop transfer
|
||||
spi->endTransaction();
|
||||
digitalWrite(_mod->getCs(), HIGH);
|
||||
Module::digitalWrite(_mod->getCs(), HIGH);
|
||||
|
||||
// wait for BUSY to go high and then low
|
||||
if(waitForBusy) {
|
||||
delayMicroseconds(1);
|
||||
start = millis();
|
||||
while(digitalRead(_mod->getGpio())) {
|
||||
yield();
|
||||
if(millis() - start >= timeout) {
|
||||
Module::delayMicroseconds(1);
|
||||
start = Module::millis();
|
||||
while(Module::digitalRead(_mod->getGpio())) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start >= timeout) {
|
||||
status = SX126X_STATUS_CMD_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
@ -1689,8 +1730,8 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
// some faster platforms require a short delay here
|
||||
// not sure why, but it seems that long enough SPI transaction
|
||||
// (e.g. setPacketParams for GFSK) will fail without it
|
||||
#if defined(ARDUINO_ARCH_STM32) || defined(SAMD_SERIES)
|
||||
delay(1);
|
||||
#if defined(RADIOLIB_SPI_SLOWDOWN)
|
||||
Module::delay(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -733,9 +733,12 @@ class SX126x: public PhysicalLayer {
|
|||
/*!
|
||||
\brief Sets TCXO (Temperature Compensated Crystal Oscillator) configuration.
|
||||
|
||||
\param TCXO reference voltage in volts. Allowed values are 1.6, 1.7, 1.8, 2.2. 2.4, 2.7, 3.0 and 3.3 V
|
||||
\param TCXO reference voltage in volts. Allowed values are 1.6, 1.7, 1.8, 2.2. 2.4, 2.7, 3.0 and 3.3 V. Set to 0 to disable TCXO.
|
||||
NOTE: After setting this parameter to 0, the module will be reset (since there's no other way to disable TCXO).
|
||||
|
||||
\param TCXO timeout in us. Defaults to 5000 us.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setTCXO(float voltage, uint32_t delay = 5000);
|
||||
|
||||
|
@ -803,6 +806,13 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
uint32_t getTimeOnAir(size_t len);
|
||||
|
||||
/*!
|
||||
\brief Get instantaneous RSSI value during recption of the packet. Should switch to FSK receive mode for LBT implementation.
|
||||
|
||||
\returns Instantaneous RSSI value in dBm, in steps of 0.5dBm
|
||||
*/
|
||||
float getRSSIInst();
|
||||
|
||||
/*!
|
||||
\brief Set implicit header mode for future reception/transmission.
|
||||
|
||||
|
@ -854,7 +864,7 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Forces LoRa low data rate optimization. Only available in LoRa mode. After calling this method, LDRO will always be set to
|
||||
the provided value, regardless of symbol length. To re-enable automatic LDRO configuration, call SX1278::autoLDRO()
|
||||
the provided value, regardless of symbol length. To re-enable automatic LDRO configuration, call SX126x::autoLDRO()
|
||||
|
||||
\param enable Force LDRO to be always enabled (true) or disabled (false).
|
||||
|
||||
|
@ -870,6 +880,13 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t autoLDRO();
|
||||
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t random();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
|
@ -911,11 +928,22 @@ class SX126x: public PhysicalLayer {
|
|||
int16_t fixImplicitTimeout();
|
||||
int16_t fixInvertedIQ(uint8_t iqConfig);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
// common low-level SPI interface
|
||||
int16_t SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout = 5000);
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
uint8_t _bw = 0, _sf = 0, _cr = 0, _ldro = 0, _crcType = 0, _headerType = 0;
|
||||
uint16_t _preambleLength = 0;
|
||||
float _bwKhz = 0;
|
||||
|
@ -933,13 +961,6 @@ class SX126x: public PhysicalLayer {
|
|||
size_t _implicitLen = 0;
|
||||
|
||||
int16_t config(uint8_t modem);
|
||||
|
||||
// common low-level SPI interface
|
||||
int16_t SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout = 5000);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,20 +10,16 @@ int16_t SX1272::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t state = SX127x::begin(SX1272_CHIP_VERSION, syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// mitigation of receiver spurious response
|
||||
// see SX1272/73 Errata, section 2.2 for details
|
||||
state = _mod->SPIsetRegValue(0x31, 0b10000000, 7, 7);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
@ -54,21 +50,26 @@ int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t
|
|||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
if(enableOOK) {
|
||||
state = setDataShapingOOK(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
} else {
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
void SX1272::reset() {
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delay(5);
|
||||
Module::delay(5);
|
||||
}
|
||||
|
||||
int16_t SX1272::setFrequency(float freq) {
|
||||
|
@ -242,11 +243,6 @@ int16_t SX1272::setOutputPower(int8_t power) {
|
|||
}
|
||||
|
||||
int16_t SX1272::setGain(uint8_t gain) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// check allowed range
|
||||
if(gain > 6) {
|
||||
return(ERR_INVALID_GAIN);
|
||||
|
@ -255,14 +251,30 @@ int16_t SX1272::setGain(uint8_t gain) {
|
|||
// set mode to standby
|
||||
int16_t state = SX127x::standby();
|
||||
|
||||
// set gain
|
||||
if(gain == 0) {
|
||||
// gain set to 0, enable AGC loop
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_ON, 2, 2);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_OFF, 2, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_LNA, (gain << 5) | SX127X_LNA_BOOST_ON);
|
||||
// get modem
|
||||
int16_t modem = getActiveModem();
|
||||
if(modem == SX127X_LORA){
|
||||
// set gain
|
||||
if(gain == 0) {
|
||||
// gain set to 0, enable AGC loop
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_ON, 2, 2);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_OFF, 2, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_LNA, (gain << 5) | SX127X_LNA_BOOST_ON);
|
||||
}
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// set gain
|
||||
if(gain == 0) {
|
||||
// gain set to 0, enable AGC loop
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_RX_CONFIG, SX127X_AGC_AUTO_ON, 3, 3);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_RX_CONFIG, SX127X_AGC_AUTO_ON, 3, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_LNA, (gain << 5) | SX127X_LNA_BOOST_ON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -273,7 +285,7 @@ int16_t SX1272::setDataShaping(uint8_t sh) {
|
|||
}
|
||||
|
||||
// check modulation
|
||||
if(!SX127x::_ook) {
|
||||
if(SX127x::_ook) {
|
||||
return(ERR_INVALID_MODULATION);
|
||||
}
|
||||
|
||||
|
@ -329,7 +341,7 @@ int16_t SX1272::setDataShapingOOK(uint8_t sh) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
float SX1272::getRSSI() {
|
||||
float SX1272::getRSSI(bool skipReceive) {
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// RSSI calculation uses different constant for low-frequency and high-frequency ports
|
||||
float lastPacketRSSI = -139 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
|
||||
|
@ -345,33 +357,47 @@ float SX1272::getRSSI() {
|
|||
|
||||
} else {
|
||||
// enable listen mode
|
||||
startReceive();
|
||||
if(!skipReceive) {
|
||||
startReceive();
|
||||
}
|
||||
|
||||
// read the value for FSK
|
||||
float rssi = (float)_mod->SPIgetRegValue(SX127X_REG_RSSI_VALUE_FSK) / -2.0;
|
||||
|
||||
// set mode back to standby
|
||||
standby();
|
||||
if(!skipReceive) {
|
||||
standby();
|
||||
}
|
||||
|
||||
// return the value
|
||||
return(rssi);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t SX1272::setCRC(bool enableCRC) {
|
||||
int16_t SX1272::setCRC(bool enable, bool mode) {
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// set LoRa CRC
|
||||
if(enableCRC) {
|
||||
SX127x::_crcEnabled = enable;
|
||||
if(enable) {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_RX_CRC_MODE_ON, 2, 2));
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_RX_CRC_MODE_OFF, 2, 2));
|
||||
}
|
||||
} else {
|
||||
// set FSK CRC
|
||||
if(enableCRC) {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_ON, 4, 4));
|
||||
int16_t state = ERR_NONE;
|
||||
if(enable) {
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_ON, 4, 4);
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_OFF, 4, 4));
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_OFF, 4, 4);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set FSK CRC mode
|
||||
if(mode) {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_WHITENING_TYPE_IBM, 0, 0));
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_WHITENING_TYPE_CCITT, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -398,6 +424,13 @@ int16_t SX1272::autoLDRO() {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX1272::implicitHeader(size_t len) {
|
||||
return(setHeaderType(SX1272_HEADER_IMPL_MODE, len));
|
||||
}
|
||||
|
||||
int16_t SX1272::explicitHeader() {
|
||||
return(setHeaderType(SX1272_HEADER_EXPL_MODE));
|
||||
}
|
||||
|
||||
int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) {
|
||||
// set mode to standby
|
||||
|
@ -414,12 +447,12 @@ int16_t SX1272::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
|
|||
|
||||
// write registers
|
||||
if(newSpreadingFactor == SX127X_SF_6) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_IMPL_MODE | SX1272_RX_CRC_MODE_ON, 2, 1);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_IMPL_MODE | (SX127x::_crcEnabled ? SX1272_RX_CRC_MODE_ON : SX1272_RX_CRC_MODE_OFF), 2, 1);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE, 7, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_EXPL_MODE | SX1272_RX_CRC_MODE_ON, 2, 1);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_EXPL_MODE | (SX127x::_crcEnabled ? SX1272_RX_CRC_MODE_ON : SX1272_RX_CRC_MODE_OFF), 2, 1);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | SX127X_TX_MODE_SINGLE, 7, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_7_12);
|
||||
|
@ -436,6 +469,26 @@ int16_t SX1272::setCodingRateRaw(uint8_t newCodingRate) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1272::setHeaderType(uint8_t headerType, size_t len) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set requested packet mode
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, headerType, 2, 2);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH, len);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update cached value
|
||||
_packetLength = len;
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1272::configFSK() {
|
||||
// configure common registers
|
||||
int16_t state = SX127x::configFSK();
|
||||
|
@ -443,11 +496,6 @@ int16_t SX1272::configFSK() {
|
|||
|
||||
// set fast PLL hop
|
||||
state = _mod->SPIsetRegValue(SX1272_REG_PLL_HOP, SX127X_FAST_HOP_ON, 7, 7);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set Gauss filter BT product to 0.5
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_FSK_GAUSSIAN_0_5, 4, 3);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define SX1272_FRF_MID 0xC0 // 7 0 where F(XOSC) = 32 MHz
|
||||
#define SX1272_FRF_LSB 0x00 // 7 0 FRF = 3 byte value of FRF registers
|
||||
|
||||
// SX1272_REG_MODEM_CONFIG_1
|
||||
// SX127X_REG_MODEM_CONFIG_1
|
||||
#define SX1272_BW_125_00_KHZ 0b00000000 // 7 6 bandwidth: 125 kHz
|
||||
#define SX1272_BW_250_00_KHZ 0b01000000 // 7 6 250 kHz
|
||||
#define SX1272_BW_500_00_KHZ 0b10000000 // 7 6 500 kHz
|
||||
|
@ -42,7 +42,7 @@
|
|||
#define SX1272_LOW_DATA_RATE_OPT_OFF 0b00000000 // 0 0 low data rate optimization disabled
|
||||
#define SX1272_LOW_DATA_RATE_OPT_ON 0b00000001 // 0 0 low data rate optimization enabled, mandatory for SF 11 and 12 with BW 125 kHz
|
||||
|
||||
// SX1272_REG_MODEM_CONFIG_2
|
||||
// SX127X_REG_MODEM_CONFIG_2
|
||||
#define SX1272_AGC_AUTO_OFF 0b00000000 // 2 2 LNA gain set by REG_LNA
|
||||
#define SX1272_AGC_AUTO_ON 0b00000100 // 2 2 LNA gain set by internal AGC loop
|
||||
|
||||
|
@ -240,18 +240,22 @@ class SX1272: public SX127x {
|
|||
/*!
|
||||
\brief Gets recorded signal strength indicator of the latest received packet for LoRa modem, or current RSSI level for FSK modem.
|
||||
|
||||
\param skipReceive Set to true to skip putting radio in receive mode for the RSSI measurement in FKS/OOK mode.
|
||||
|
||||
\returns Last packet RSSI for LoRa modem, or current RSSI level for FSK modem.
|
||||
*/
|
||||
float getRSSI();
|
||||
float getRSSI(bool skipReceive = false);
|
||||
|
||||
/*!
|
||||
\brief Enables/disables CRC check of received packets.
|
||||
|
||||
\param enableCRC Enable (true) or disable (false) CRC.
|
||||
\param enable Enable (true) or disable (false) CRC.
|
||||
|
||||
\param mode Set CRC mode to SX127X_CRC_WHITENING_TYPE_CCITT for CCITT, polynomial X16 + X12 + X5 + 1 (false) or SX127X_CRC_WHITENING_TYPE_IBM for IBM, polynomial X16 + X15 + X2 + 1 (true). Only valid in FSK mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCRC(bool enableCRC);
|
||||
int16_t setCRC(bool enable, bool mode = false);
|
||||
|
||||
/*!
|
||||
\brief Forces LoRa low data rate optimization. Only available in LoRa mode. After calling this method, LDRO will always be set to
|
||||
|
@ -271,16 +275,33 @@ class SX1272: public SX127x {
|
|||
*/
|
||||
int16_t autoLDRO();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
/*!
|
||||
\brief Set implicit header mode for future reception/transmission.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t implicitHeader(size_t len);
|
||||
|
||||
/*!
|
||||
\brief Set explicit header mode for future reception/transmission.
|
||||
|
||||
\param len Payload length in bytes.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t explicitHeader();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
int16_t setBandwidthRaw(uint8_t newBandwidth);
|
||||
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
|
||||
int16_t setCodingRateRaw(uint8_t newCodingRate);
|
||||
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
|
||||
|
||||
int16_t configFSK();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
bool _ldroAuto = true;
|
||||
|
|
|
@ -10,20 +10,16 @@ int16_t SX1273::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t state = SX127x::begin(SX1272_CHIP_VERSION, syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// mitigation of receiver spurious response
|
||||
// see SX1272/73 Errata, section 2.2 for details
|
||||
state = _mod->SPIsetRegValue(0x31, 0b10000000, 7, 7);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
|
|
@ -62,7 +62,7 @@ class SX1273: public SX1272 {
|
|||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,15 +10,11 @@ int16_t SX1276::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
@ -36,6 +32,24 @@ int16_t SX1276::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1276::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(SX1278_CHIP_VERSION, br, freqDev, rxBw, preambleLength, enableOOK);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1276::setFrequency(float freq) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 137.0, 1020.0, ERR_INVALID_FREQUENCY);
|
||||
|
||||
|
@ -102,8 +116,12 @@ int16_t SX1276::setFrequency(float freq) {
|
|||
}
|
||||
}
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
// set frequency and if successful, save the new setting
|
||||
int16_t state = SX127x::setFrequencyRaw(freq);
|
||||
if(state == ERR_NONE) {
|
||||
SX127x::_freq = freq;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,28 @@ class SX1276: public SX1278 {
|
|||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = 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 = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
|
@ -62,7 +84,7 @@ class SX1276: public SX1278 {
|
|||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,15 +10,11 @@ int16_t SX1277::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
@ -36,6 +32,24 @@ int16_t SX1277::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1277::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(SX1278_CHIP_VERSION, br, freqDev, rxBw, preambleLength, enableOOK);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1277::setFrequency(float freq) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 137.0, 1020.0, ERR_INVALID_FREQUENCY);
|
||||
|
||||
|
@ -103,7 +117,11 @@ int16_t SX1277::setFrequency(float freq) {
|
|||
}
|
||||
|
||||
// set frequency and if successful, save the new setting
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
int16_t state = SX127x::setFrequencyRaw(freq);
|
||||
if(state == ERR_NONE) {
|
||||
SX127x::_freq = freq;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1277::setSpreadingFactor(uint8_t sf) {
|
||||
|
|
|
@ -51,6 +51,28 @@ class SX1277: public SX1278 {
|
|||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = 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 = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
|
@ -71,7 +93,7 @@ class SX1277: public SX1278 {
|
|||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,15 +10,11 @@ int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
@ -52,8 +48,13 @@ int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
|
|||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
if(enableOOK) {
|
||||
state = setDataShapingOOK(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
} else {
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -61,9 +62,9 @@ int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
|
|||
void SX1278::reset() {
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
delay(5);
|
||||
Module::delay(5);
|
||||
}
|
||||
|
||||
int16_t SX1278::setFrequency(float freq) {
|
||||
|
@ -314,11 +315,6 @@ int16_t SX1278::setOutputPower(int8_t power) {
|
|||
}
|
||||
|
||||
int16_t SX1278::setGain(uint8_t gain) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// check allowed range
|
||||
if(gain > 6) {
|
||||
return(ERR_INVALID_GAIN);
|
||||
|
@ -327,14 +323,30 @@ int16_t SX1278::setGain(uint8_t gain) {
|
|||
// set mode to standby
|
||||
int16_t state = SX127x::standby();
|
||||
|
||||
// set gain
|
||||
if(gain == 0) {
|
||||
// gain set to 0, enable AGC loop
|
||||
state |= _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_AGC_AUTO_ON, 2, 2);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_AGC_AUTO_OFF, 2, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_LNA, (gain << 5) | SX127X_LNA_BOOST_ON);
|
||||
// get modem
|
||||
int16_t modem = getActiveModem();
|
||||
if(modem == SX127X_LORA){
|
||||
// set gain
|
||||
if(gain == 0) {
|
||||
// gain set to 0, enable AGC loop
|
||||
state |= _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_AGC_AUTO_ON, 2, 2);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_AGC_AUTO_OFF, 2, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_LNA, (gain << 5) | SX127X_LNA_BOOST_ON);
|
||||
}
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// set gain
|
||||
if(gain == 0) {
|
||||
// gain set to 0, enable AGC loop
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_RX_CONFIG, SX127X_AGC_AUTO_ON, 3, 3);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_RX_CONFIG, SX127X_AGC_AUTO_ON, 3, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_LNA, (gain << 5) | SX127X_LNA_BOOST_ON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -356,13 +368,13 @@ int16_t SX1278::setDataShaping(uint8_t sh) {
|
|||
// set data shaping
|
||||
switch(sh) {
|
||||
case RADIOLIB_SHAPING_NONE:
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1278_NO_SHAPING, 6, 5));
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_NO_SHAPING, 6, 5));
|
||||
case RADIOLIB_SHAPING_0_3:
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1278_FSK_GAUSSIAN_0_3, 6, 5));
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_FSK_GAUSSIAN_0_3, 6, 5));
|
||||
case RADIOLIB_SHAPING_0_5:
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1278_FSK_GAUSSIAN_0_5, 6, 5));
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_FSK_GAUSSIAN_0_5, 6, 5));
|
||||
case RADIOLIB_SHAPING_1_0:
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1278_FSK_GAUSSIAN_1_0, 6, 5));
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_FSK_GAUSSIAN_1_0, 6, 5));
|
||||
default:
|
||||
return(ERR_INVALID_DATA_SHAPING);
|
||||
}
|
||||
|
@ -400,7 +412,7 @@ int16_t SX1278::setDataShapingOOK(uint8_t sh) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
float SX1278::getRSSI() {
|
||||
float SX1278::getRSSI(bool skipReceive) {
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// for LoRa, get RSSI of the last packet
|
||||
float lastPacketRSSI;
|
||||
|
@ -423,33 +435,47 @@ float SX1278::getRSSI() {
|
|||
|
||||
} else {
|
||||
// enable listen mode
|
||||
startReceive();
|
||||
if(!skipReceive) {
|
||||
startReceive();
|
||||
}
|
||||
|
||||
// read the value for FSK
|
||||
float rssi = (float)_mod->SPIgetRegValue(SX127X_REG_RSSI_VALUE_FSK) / -2.0;
|
||||
|
||||
// set mode back to standby
|
||||
standby();
|
||||
if(!skipReceive) {
|
||||
standby();
|
||||
}
|
||||
|
||||
// return the value
|
||||
return(rssi);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t SX1278::setCRC(bool enableCRC) {
|
||||
int16_t SX1278::setCRC(bool enable, bool mode) {
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// set LoRa CRC
|
||||
if(enableCRC) {
|
||||
SX127x::_crcEnabled = enable;
|
||||
if(enable) {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_ON, 2, 2));
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_OFF, 2, 2));
|
||||
}
|
||||
} else {
|
||||
// set FSK CRC
|
||||
if(enableCRC) {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_ON, 4, 4));
|
||||
int16_t state = ERR_NONE;
|
||||
if(enable) {
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_ON, 4, 4);
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_OFF, 4, 4));
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_OFF, 4, 4);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set FSK CRC mode
|
||||
if(mode) {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_WHITENING_TYPE_IBM, 0, 0));
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_WHITENING_TYPE_CCITT, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -476,6 +502,14 @@ int16_t SX1278::autoLDRO() {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX1278::implicitHeader(size_t len) {
|
||||
return(setHeaderType(SX1278_HEADER_IMPL_MODE, len));
|
||||
}
|
||||
|
||||
int16_t SX1278::explicitHeader() {
|
||||
return(setHeaderType(SX1278_HEADER_EXPL_MODE));
|
||||
}
|
||||
|
||||
int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) {
|
||||
// set mode to standby
|
||||
int16_t state = SX127x::standby();
|
||||
|
@ -492,12 +526,12 @@ int16_t SX1278::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
|
|||
// write registers
|
||||
if(newSpreadingFactor == SX127X_SF_6) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1278_HEADER_IMPL_MODE, 0, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_ON, 7, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE | (SX127x::_crcEnabled ? SX1278_RX_CRC_MODE_ON : SX1278_RX_CRC_MODE_OFF), 7, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6);
|
||||
} else {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1278_HEADER_EXPL_MODE, 0, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | SX127X_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_ON, 7, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | SX127X_TX_MODE_SINGLE | (SX127x::_crcEnabled ? SX1278_RX_CRC_MODE_ON : SX1278_RX_CRC_MODE_OFF), 7, 2);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_7_12);
|
||||
}
|
||||
|
@ -513,6 +547,26 @@ int16_t SX1278::setCodingRateRaw(uint8_t newCodingRate) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1278::setHeaderType(uint8_t headerType, size_t len) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set requested packet mode
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, headerType, 0, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH, len);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update cached value
|
||||
_packetLength = len;
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1278::configFSK() {
|
||||
// configure common registers
|
||||
int16_t state = SX127x::configFSK();
|
||||
|
@ -520,11 +574,6 @@ int16_t SX1278::configFSK() {
|
|||
|
||||
// set fast PLL hop
|
||||
state = _mod->SPIsetRegValue(SX1278_REG_PLL_HOP, SX127X_FAST_HOP_ON, 7, 7);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set Gauss filter BT product to 0.5
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_FSK_GAUSSIAN_0_5, 6, 5);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
// SX1278_REG_LNA
|
||||
#define SX1278_LNA_BOOST_LF_OFF 0b00000000 // 4 3 default LNA current
|
||||
|
||||
// SX1278_REG_MODEM_CONFIG_1
|
||||
// SX127X_REG_MODEM_CONFIG_1
|
||||
#define SX1278_BW_7_80_KHZ 0b00000000 // 7 4 bandwidth: 7.80 kHz
|
||||
#define SX1278_BW_10_40_KHZ 0b00010000 // 7 4 10.40 kHz
|
||||
#define SX1278_BW_15_60_KHZ 0b00100000 // 7 4 15.60 kHz
|
||||
|
@ -56,7 +56,7 @@
|
|||
#define SX1278_HEADER_EXPL_MODE 0b00000000 // 0 0 explicit header mode
|
||||
#define SX1278_HEADER_IMPL_MODE 0b00000001 // 0 0 implicit header mode
|
||||
|
||||
// SX1278_REG_MODEM_CONFIG_2
|
||||
// SX127X_REG_MODEM_CONFIG_2
|
||||
#define SX1278_RX_CRC_MODE_OFF 0b00000000 // 2 2 CRC disabled
|
||||
#define SX1278_RX_CRC_MODE_ON 0b00000100 // 2 2 CRC enabled
|
||||
|
||||
|
@ -248,18 +248,22 @@ class SX1278: public SX127x {
|
|||
/*!
|
||||
\brief Gets recorded signal strength indicator of the latest received packet for LoRa modem, or current RSSI level for FSK modem.
|
||||
|
||||
\param skipReceive Set to true to skip putting radio in receive mode for the RSSI measurement in FKS/OOK mode.
|
||||
|
||||
\returns Last packet RSSI for LoRa modem, or current RSSI level for FSK modem.
|
||||
*/
|
||||
float getRSSI();
|
||||
float getRSSI(bool skipReceive = false);
|
||||
|
||||
/*!
|
||||
\brief Enables/disables CRC check of received packets.
|
||||
|
||||
\param enableCRC Enable (true) or disable (false) CRC.
|
||||
\param enable Enable (true) or disable (false) CRC.
|
||||
|
||||
\param mode Set CRC mode to SX127X_CRC_WHITENING_TYPE_CCITT for CCITT, polynomial X16 + X12 + X5 + 1 (false) or SX127X_CRC_WHITENING_TYPE_IBM for IBM, polynomial X16 + X15 + X2 + 1 (true). Only valid in FSK mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCRC(bool enableCRC);
|
||||
int16_t setCRC(bool enable, bool mode = false);
|
||||
|
||||
/*!
|
||||
\brief Forces LoRa low data rate optimization. Only available in LoRa mode. After calling this method, LDRO will always be set to
|
||||
|
@ -279,16 +283,33 @@ class SX1278: public SX127x {
|
|||
*/
|
||||
int16_t autoLDRO();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
/*!
|
||||
\brief Set implicit header mode for future reception/transmission.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t implicitHeader(size_t len);
|
||||
|
||||
/*!
|
||||
\brief Set explicit header mode for future reception/transmission.
|
||||
|
||||
\param len Payload length in bytes.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t explicitHeader();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
int16_t setBandwidthRaw(uint8_t newBandwidth);
|
||||
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
|
||||
int16_t setCodingRateRaw(uint8_t newCodingRate);
|
||||
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
|
||||
|
||||
int16_t configFSK();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
bool _ldroAuto = true;
|
||||
|
|
|
@ -10,15 +10,11 @@ int16_t SX1279::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
state = setBandwidth(bw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
|
@ -36,11 +32,33 @@ int16_t SX1279::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1279::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(SX1278_CHIP_VERSION, br, freqDev, rxBw, preambleLength, enableOOK);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1279::setFrequency(float freq) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 137.0, 960.0, ERR_INVALID_FREQUENCY);
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
// set frequency and if successful, save the new setting
|
||||
int16_t state = SX127x::setFrequencyRaw(freq);
|
||||
if(state == ERR_NONE) {
|
||||
SX127x::_freq = freq;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,28 @@ class SX1279: public SX1278 {
|
|||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = 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 = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
|
@ -62,7 +84,7 @@ class SX1279: public SX1278 {
|
|||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,14 +16,17 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint16_t preambleLe
|
|||
RADIOLIB_DEBUG_PRINTLN(F("No SX127x found!"));
|
||||
_mod->term(RADIOLIB_USE_SPI);
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found SX127x!"));
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX127x"));
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
// set LoRa mode
|
||||
|
@ -59,12 +62,14 @@ int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxB
|
|||
RADIOLIB_DEBUG_PRINTLN(F("No SX127x found!"));
|
||||
_mod->term(RADIOLIB_USE_SPI);
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found SX127x!"));
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX127x"));
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check currently active modem
|
||||
int16_t state;
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
// set FSK mode
|
||||
state = setActiveModem(SX127X_FSK_OOK);
|
||||
|
@ -143,10 +148,10 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
|
@ -161,10 +166,10 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission end or timeout
|
||||
start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
standby();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
|
@ -175,7 +180,7 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
// update data rate
|
||||
uint32_t elapsed = micros() - start;
|
||||
uint32_t elapsed = Module::micros() - start;
|
||||
_dataRate = (len*8.0)/((float)elapsed/1000000.0);
|
||||
|
||||
// clear interrupt flags
|
||||
|
@ -197,9 +202,9 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout (100 LoRa symbols)
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(digitalRead(_mod->getGpio())) {
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::digitalRead(_mod->getGpio())) {
|
||||
clearIRQFlags();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
|
@ -214,10 +219,10 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
|
@ -255,9 +260,9 @@ int16_t SX127x::scanChannel() {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for channel activity detected or timeout
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(digitalRead(_mod->getGpio())) {
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::digitalRead(_mod->getGpio())) {
|
||||
clearIRQFlags();
|
||||
return(PREAMBLE_DETECTED);
|
||||
}
|
||||
|
@ -395,25 +400,25 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
|||
}
|
||||
|
||||
void SX127x::setDio0Action(void (*func)(void)) {
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
}
|
||||
|
||||
void SX127x::clearDio0Action() {
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
}
|
||||
|
||||
void SX127x::setDio1Action(void (*func)(void)) {
|
||||
if(_mod->getGpio() != RADIOLIB_NC) {
|
||||
if(_mod->getGpio() == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), func, RISING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), func, RISING);
|
||||
}
|
||||
|
||||
void SX127x::clearDio1Action() {
|
||||
if(_mod->getGpio() != RADIOLIB_NC) {
|
||||
if(_mod->getGpio() == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()));
|
||||
}
|
||||
|
||||
int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -453,7 +458,9 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
clearIRQFlags();
|
||||
|
||||
// set packet length
|
||||
_mod->SPIwriteRegister(SX127X_REG_FIFO, len);
|
||||
if (_packetLengthConfig == SX127X_PACKET_VARIABLE) {
|
||||
_mod->SPIwriteRegister(SX127X_REG_FIFO, len);
|
||||
}
|
||||
|
||||
// check address filtering
|
||||
uint8_t filter = _mod->SPIgetRegValue(SX127X_REG_PACKET_CONFIG_1, 2, 1);
|
||||
|
@ -488,11 +495,18 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
|
|||
length = getPacketLength();
|
||||
}
|
||||
|
||||
// check integrity CRC
|
||||
// check packet header integrity
|
||||
if(_crcEnabled && (_mod->SPIgetRegValue(SX127X_REG_HOP_CHANNEL, 6, 6)) == 0) {
|
||||
// CRC is disabled according to packet header and enabled according to user
|
||||
// most likely damaged packet header
|
||||
clearIRQFlags();
|
||||
return(ERR_LORA_HEADER_DAMAGED);
|
||||
}
|
||||
|
||||
// check payload CRC
|
||||
if(_mod->SPIgetRegValue(SX127X_REG_IRQ_FLAGS, 5, 5) == SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
||||
return(ERR_CRC_MISMATCH);
|
||||
}
|
||||
|
||||
|
@ -581,9 +595,10 @@ int16_t SX127x::setPreambleLength(uint16_t preambleLength) {
|
|||
return(state);
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// set preamble length
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB_FSK, (uint8_t)((preambleLength >> 8) & 0xFF));
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB_FSK, (uint8_t)(preambleLength & 0xFF));
|
||||
// set preamble length (in bytes)
|
||||
uint16_t numBytes = preambleLength / 8;
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB_FSK, (uint8_t)((numBytes >> 8) & 0xFF));
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB_FSK, (uint8_t)(numBytes & 0xFF));
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -693,8 +708,14 @@ int16_t SX127x::setFrequencyDeviation(float freqDev) {
|
|||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
if(freqDev < 0.0) {
|
||||
newFreqDev = 0.6;
|
||||
}
|
||||
|
||||
// check frequency deviation range
|
||||
if(!((freqDev + _br/2.0 <= 250.0) && (freqDev <= 200.0))) {
|
||||
if(!((newFreqDev + _br/2.0 <= 250.0) && (freqDev <= 200.0))) {
|
||||
return(ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
}
|
||||
|
||||
|
@ -704,7 +725,7 @@ int16_t SX127x::setFrequencyDeviation(float freqDev) {
|
|||
|
||||
// set allowed frequency deviation
|
||||
uint32_t base = 1;
|
||||
uint32_t FDEV = (freqDev * (base << 19)) / 32000;
|
||||
uint32_t FDEV = (newFreqDev * (base << 19)) / 32000;
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_FDEV_MSB, (FDEV & 0xFF00) >> 8, 5, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_FDEV_LSB, FDEV & 0x00FF, 7, 0);
|
||||
return(state);
|
||||
|
@ -753,7 +774,7 @@ int16_t SX127x::setSyncWord(uint8_t* syncWord, size_t len) {
|
|||
RADIOLIB_CHECK_RANGE(len, 1, 8, ERR_INVALID_SYNC_WORD);
|
||||
|
||||
// sync word must not contain value 0x00
|
||||
for(uint8_t i = 0; i < len; i++) {
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
if(syncWord[i] == 0x00) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
@ -815,6 +836,30 @@ int16_t SX127x::disableAddressFiltering() {
|
|||
return(_mod->SPIsetRegValue(SX127X_REG_BROADCAST_ADRS, 0x00));
|
||||
}
|
||||
|
||||
int16_t SX127x::setOokThresholdType(uint8_t type) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_OOK_PEAK, type, 4, 3, 5));
|
||||
}
|
||||
|
||||
int16_t SX127x::setOokFixedOrFloorThreshold(uint8_t value) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_OOK_FIX, value, 7, 0, 5));
|
||||
}
|
||||
|
||||
int16_t SX127x::setOokPeakThresholdDecrement(uint8_t value) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_OOK_AVG, value, 7, 5, 5));
|
||||
}
|
||||
|
||||
int16_t SX127x::setOOK(bool enableOOK) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
|
@ -858,14 +903,18 @@ size_t SX127x::getPacketLength(bool update) {
|
|||
return(_mod->SPIreadRegister(SX127X_REG_RX_NB_BYTES));
|
||||
|
||||
} else {
|
||||
// return the maximum value for SF6
|
||||
return(SX127X_MAX_PACKET_LENGTH);
|
||||
// return the cached value for SF6
|
||||
return(_packetLength);
|
||||
}
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// get packet length
|
||||
if(!_packetLengthQueried && update) {
|
||||
_packetLength = _mod->SPIreadRegister(SX127X_REG_FIFO);
|
||||
if (_packetLengthConfig == SX127X_PACKET_VARIABLE) {
|
||||
_packetLength = _mod->SPIreadRegister(SX127X_REG_FIFO);
|
||||
} else {
|
||||
_packetLength = _mod->SPIreadRegister(SX127X_REG_PAYLOAD_LENGTH_FSK);
|
||||
}
|
||||
_packetLengthQueried = true;
|
||||
}
|
||||
}
|
||||
|
@ -952,6 +1001,35 @@ void SX127x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
|||
_mod->setRfSwitchPins(rxEn, txEn);
|
||||
}
|
||||
|
||||
uint8_t SX127x::random() {
|
||||
// check active modem
|
||||
uint8_t rssiValueReg = SX127X_REG_RSSI_WIDEBAND;
|
||||
if(getActiveModem() == SX127X_FSK_OOK) {
|
||||
rssiValueReg = SX127X_REG_RSSI_VALUE_FSK;
|
||||
}
|
||||
|
||||
// set mode to Rx
|
||||
setMode(SX127X_RX);
|
||||
|
||||
// wait a bit for the RSSI reading to stabilise
|
||||
Module::delay(10);
|
||||
|
||||
// read RSSI value 8 times, always keep just the least significant bit
|
||||
uint8_t randByte = 0x00;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
randByte |= ((_mod->SPIreadRegister(rssiValueReg) & 0x01) << i);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
setMode(SX127X_STANDBY);
|
||||
|
||||
return(randByte);
|
||||
}
|
||||
|
||||
int16_t SX127x::getChipVersion() {
|
||||
return(_mod->SPIgetRegValue(SX127X_REG_VERSION));
|
||||
}
|
||||
|
||||
int8_t SX127x::getTempRaw() {
|
||||
int8_t temp = 0;
|
||||
uint8_t previousOpMode;
|
||||
|
@ -975,7 +1053,7 @@ int8_t SX127x::getTempRaw() {
|
|||
_mod->SPIsetRegValue(SX127X_REG_IMAGE_CAL, SX127X_TEMP_MONITOR_ON, 0, 0);
|
||||
|
||||
// wait
|
||||
delayMicroseconds(200);
|
||||
Module::delayMicroseconds(200);
|
||||
|
||||
// disable temperature reading
|
||||
_mod->SPIsetRegValue(SX127X_REG_IMAGE_CAL, SX127X_TEMP_MONITOR_OFF, 0, 0);
|
||||
|
@ -1019,7 +1097,7 @@ int16_t SX127x::configFSK() {
|
|||
_mod->SPIwriteRegister(SX127X_REG_IRQ_FLAGS_2, SX127X_FLAG_FIFO_OVERRUN);
|
||||
|
||||
// set packet configuration
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_PACKET_VARIABLE | SX127X_DC_FREE_WHITENING | SX127X_CRC_ON | SX127X_CRC_AUTOCLEAR_ON | SX127X_ADDRESS_FILTERING_OFF | SX127X_CRC_WHITENING_TYPE_CCITT, 7, 0);
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_PACKET_VARIABLE | SX127X_DC_FREE_NONE | SX127X_CRC_ON | SX127X_CRC_AUTOCLEAR_ON | SX127X_ADDRESS_FILTERING_OFF | SX127X_CRC_WHITENING_TYPE_CCITT, 7, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_2, SX127X_DATA_MODE_PACKET | SX127X_IO_HOME_OFF, 6, 5);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
|
@ -1038,10 +1116,8 @@ int16_t SX127x::configFSK() {
|
|||
state |= _mod->SPIsetRegValue(SX127X_REG_RX_TIMEOUT_3, SX127X_TIMEOUT_SIGNAL_SYNC_OFF);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable preamble detector and set preamble length
|
||||
// enable preamble detector
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_DETECT, SX127X_PREAMBLE_DETECTOR_ON | SX127X_PREAMBLE_DETECTOR_2_BYTE | SX127X_PREAMBLE_DETECTOR_TOL);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB_FSK, SX127X_PREAMBLE_SIZE_MSB);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB_FSK, SX127X_PREAMBLE_SIZE_LSB);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -1078,7 +1154,7 @@ bool SX127x::findChip(uint8_t ver) {
|
|||
reset();
|
||||
|
||||
// check version register
|
||||
uint8_t version = _mod->SPIreadRegister(SX127X_REG_VERSION);
|
||||
int16_t version = getChipVersion();
|
||||
if(version == ver) {
|
||||
flagFound = true;
|
||||
} else {
|
||||
|
@ -1088,12 +1164,12 @@ bool SX127x::findChip(uint8_t ver) {
|
|||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) SX127X_REG_VERSION == "));
|
||||
|
||||
char buffHex[12];
|
||||
sprintf(buffHex, "0x%02X", version);
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x00"));
|
||||
RADIOLIB_DEBUG_PRINTLN(ver, HEX);
|
||||
#endif
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -1138,4 +1214,24 @@ void SX127x::clearFIFO(size_t count) {
|
|||
}
|
||||
}
|
||||
|
||||
int16_t SX127x::invertIQ(bool invertIQ) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
int16_t state;
|
||||
if(invertIQ) {
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_INVERT_IQ, SX127X_INVERT_IQ_RXPATH_ON, 6, 6);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_INVERT_IQ, SX127X_INVERT_IQ_TXPATH_ON, 0, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_INVERT_IQ2, SX127X_IQ2_ENABLE);
|
||||
} else {
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_INVERT_IQ, SX127X_INVERT_IQ_RXPATH_OFF, 6, 6);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_INVERT_IQ, SX127X_INVERT_IQ_TXPATH_OFF, 0, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_INVERT_IQ2, SX127X_IQ2_DISABLE);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#define SX127X_REG_INVERT_IQ 0x33
|
||||
#define SX127X_REG_DETECTION_THRESHOLD 0x37
|
||||
#define SX127X_REG_SYNC_WORD 0x39
|
||||
#define SX127X_REG_INVERT_IQ2 0x3B
|
||||
#define SX127X_REG_DIO_MAPPING_1 0x40
|
||||
#define SX127X_REG_DIO_MAPPING_2 0x41
|
||||
#define SX127X_REG_VERSION 0x42
|
||||
|
@ -122,6 +123,12 @@
|
|||
#define SX127X_DETECT_OPTIMIZE_SF_6 0b00000101 // 2 0 SF6 detection optimization
|
||||
#define SX127X_DETECT_OPTIMIZE_SF_7_12 0b00000011 // 2 0 SF7 to SF12 detection optimization
|
||||
|
||||
// SX127X_REG_INVERT_IQ
|
||||
#define SX127X_INVERT_IQ_RXPATH_ON 0b01000000 // 6 6 I and Q signals are inverted
|
||||
#define SX127X_INVERT_IQ_RXPATH_OFF 0b00000000 // 6 6 normal mode
|
||||
#define SX127X_INVERT_IQ_TXPATH_ON 0b00000001 // 0 0 I and Q signals are inverted
|
||||
#define SX127X_INVERT_IQ_TXPATH_OFF 0b00000000 // 0 0 normal mode
|
||||
|
||||
// SX127X_REG_DETECTION_THRESHOLD
|
||||
#define SX127X_DETECTION_THRESHOLD_SF_6 0b00001100 // 7 0 SF6 detection threshold
|
||||
#define SX127X_DETECTION_THRESHOLD_SF_7_12 0b00001010 // 7 0 SF7 to SF12 detection threshold
|
||||
|
@ -172,6 +179,10 @@
|
|||
#define SX127X_SYNC_WORD 0x12 // 7 0 default LoRa sync word
|
||||
#define SX127X_SYNC_WORD_LORAWAN 0x34 // 7 0 sync word reserved for LoRaWAN networks
|
||||
|
||||
// SX127X_REG_INVERT_IQ2
|
||||
#define SX127X_IQ2_ENABLE 0x19 // 7 0 enable optimize for inverted IQ
|
||||
#define SX127X_IQ2_DISABLE 0x1D // 7 0 reset optimize for inverted IQ
|
||||
|
||||
// SX127x series common FSK registers
|
||||
// NOTE: FSK register names that are conflicting with LoRa registers are marked with "_FSK" suffix
|
||||
#define SX127X_REG_BITRATE_MSB 0x02
|
||||
|
@ -745,9 +756,9 @@ class SX127x: public PhysicalLayer {
|
|||
int16_t setCurrentLimit(uint8_t currentLimit);
|
||||
|
||||
/*!
|
||||
\brief Sets %LoRa preamble length. Allowed values range from 6 to 65535. Only available in %LoRa mode.
|
||||
\brief Sets %LoRa or FSK preamble length. Allowed values range from 6 to 65535 in %LoRa mode or 0 to 65535 in FSK mode.
|
||||
|
||||
\param preambleLength Preamble length to be set (in symbols).
|
||||
\param preambleLength Preamble length to be set (in symbols when in LoRa mode or bits in FSK mode).
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
|
@ -848,6 +859,33 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setOOK(bool enableOOK);
|
||||
|
||||
/*!
|
||||
\brief Selects the type of threshold in the OOK data slicer.
|
||||
|
||||
\param type Threshold type: SX127X_OOK_THRESH_PEAK(default), SX127X_OOK_THRESH_FIXED, SX127X_OOK_THRESH_AVERAGE
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOokThresholdType(uint8_t type);
|
||||
|
||||
/*!
|
||||
\brief Period of decrement of the RSSI threshold in the OOK demodulator.
|
||||
|
||||
\param value Use defines SX127X_OOK_PEAK_THRESH_DEC_X_X_CHIP
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOokPeakThresholdDecrement(uint8_t value);
|
||||
|
||||
/*!
|
||||
\brief Fixed threshold for the Data Slicer in OOK mode or floor threshold for the Data Slicer in OOK when Peak mode is used.
|
||||
|
||||
\param value The actual value used by teh data slicer is (128 - value/2).
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOokFixedOrFloorThreshold(uint8_t value);
|
||||
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
|
||||
|
@ -931,11 +969,38 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t random();
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return SX1278_CHIP_VERSION (0x12) or SX1272_CHIP_VERSION (0x22) if SX127x is connected and working.
|
||||
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
int16_t getChipVersion();
|
||||
|
||||
/*!
|
||||
\brief Enables/disables Invert the LoRa I and Q signals.
|
||||
|
||||
\param invertIQ Enable (true) or disable (false) LoRa I and Q signals.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t invertIQ(bool invertIQ);
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
float _freq = 0;
|
||||
float _bw = 0;
|
||||
uint8_t _sf = 0;
|
||||
|
@ -943,6 +1008,8 @@ class SX127x: public PhysicalLayer {
|
|||
float _br = 0;
|
||||
float _rxBw = 0;
|
||||
bool _ook = false;
|
||||
bool _crcEnabled = false;
|
||||
size_t _packetLength = 0;
|
||||
|
||||
int16_t setFrequencyRaw(float newFreq);
|
||||
int16_t config();
|
||||
|
@ -951,11 +1018,10 @@ class SX127x: public PhysicalLayer {
|
|||
int16_t directMode();
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
float _dataRate = 0;
|
||||
size_t _packetLength = 0;
|
||||
bool _packetLengthQueried = false; // FSK packet length is the first byte in FIFO, length can only be queried once
|
||||
uint8_t _packetLengthConfig = SX127X_PACKET_VARIABLE;
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ int16_t SX1280::range(bool master, uint32_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait until ranging is finished
|
||||
uint32_t start = millis();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(millis() - start > 10000) {
|
||||
uint32_t start = Module::millis();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start > 10000) {
|
||||
clearIrqStatus();
|
||||
standby();
|
||||
return(ERR_RANGING_TIMEOUT);
|
||||
|
|
|
@ -52,7 +52,7 @@ class SX1280: public SX1281 {
|
|||
*/
|
||||
float getRangingResult();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class SX1281: public SX128x {
|
|||
*/
|
||||
SX1281(Module* mod);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class SX1282: public SX1280 {
|
|||
*/
|
||||
SX1282(Module* mod);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ int16_t SX128x::begin(float freq, float bw, uint8_t sf, uint8_t cr, int8_t power
|
|||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX128x"));
|
||||
|
||||
// initialize LoRa modulation variables
|
||||
_bwKhz = bw;
|
||||
|
@ -61,6 +62,7 @@ int16_t SX128x::beginGFSK(float freq, uint16_t br, float freqDev, int8_t power,
|
|||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX128x"));
|
||||
|
||||
// initialize GFSK modulation variables
|
||||
_brKbps = br;
|
||||
|
@ -123,6 +125,7 @@ int16_t SX128x::beginBLE(float freq, uint16_t br, float freqDev, int8_t power, u
|
|||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX128x"));
|
||||
|
||||
// initialize BLE modulation variables
|
||||
_brKbps = br;
|
||||
|
@ -171,6 +174,7 @@ int16_t SX128x::beginFLRC(float freq, uint16_t br, uint8_t cr, int8_t power, uin
|
|||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSX128x"));
|
||||
|
||||
// initialize FLRC modulation variables
|
||||
_brKbps = br;
|
||||
|
@ -228,7 +232,7 @@ int16_t SX128x::reset(bool verify) {
|
|||
// run the reset sequence - same as SX126x, as SX128x docs don't seem to mention this
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
|
||||
// return immediately when verification is disabled
|
||||
|
@ -237,7 +241,7 @@ int16_t SX128x::reset(bool verify) {
|
|||
}
|
||||
|
||||
// set mode to standby
|
||||
uint32_t start = millis();
|
||||
uint32_t start = Module::millis();
|
||||
while(true) {
|
||||
// try to set mode to standby
|
||||
int16_t state = standby();
|
||||
|
@ -247,13 +251,13 @@ int16_t SX128x::reset(bool verify) {
|
|||
}
|
||||
|
||||
// standby command failed, check timeout and try again
|
||||
if(millis() - start >= 3000) {
|
||||
if(Module::millis() - start >= 3000) {
|
||||
// timed out, possibly incorrect wiring
|
||||
return(state);
|
||||
}
|
||||
|
||||
// wait a bit to not spam the module
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,10 +289,10 @@ int16_t SX128x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
clearIrqStatus();
|
||||
standby();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
|
@ -329,10 +333,10 @@ int16_t SX128x::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
uint32_t start = Module::micros();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
clearIrqStatus();
|
||||
standby();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
|
@ -392,8 +396,8 @@ int16_t SX128x::scanChannel() {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for channel activity detected or timeout
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
while(!Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
}
|
||||
|
||||
// check CAD result
|
||||
|
@ -422,7 +426,7 @@ int16_t SX128x::sleep(bool retainConfig) {
|
|||
int16_t state = SPIwriteCommand(SX128X_CMD_SET_SLEEP, &sleepConfig, 1, false);
|
||||
|
||||
// wait for SX128x to safely enter sleep mode
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -440,11 +444,11 @@ int16_t SX128x::standby(uint8_t mode) {
|
|||
}
|
||||
|
||||
void SX128x::setDio1Action(void (*func)(void)) {
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING);
|
||||
}
|
||||
|
||||
void SX128x::clearDio1Action() {
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
}
|
||||
|
||||
int16_t SX128x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -504,8 +508,8 @@ int16_t SX128x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for BUSY to go low (= PA ramp up done)
|
||||
while(digitalRead(_mod->getGpio())) {
|
||||
yield();
|
||||
while(Module::digitalRead(_mod->getGpio())) {
|
||||
Module::yield();
|
||||
}
|
||||
|
||||
return(state);
|
||||
|
@ -798,17 +802,23 @@ int16_t SX128x::setFrequencyDeviation(float freqDev) {
|
|||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
RADIOLIB_CHECK_RANGE(freqDev, 0.0, 3200.0, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
if(freqDev < 0.0) {
|
||||
newFreqDev = 62.5;
|
||||
}
|
||||
|
||||
RADIOLIB_CHECK_RANGE(newFreqDev, 62.5, 1000.0, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
|
||||
// override for the lowest possible frequency deviation - required for some PhysicalLayer protocols
|
||||
if(freqDev == 0.0) {
|
||||
if(newFreqDev == 0.0) {
|
||||
_modIndex = SX128X_BLE_GFSK_MOD_IND_0_35;
|
||||
_br = SX128X_BLE_GFSK_BR_0_125_BW_0_3;
|
||||
return(setModulationParams(_br, _modIndex, _shaping));
|
||||
}
|
||||
|
||||
// update modulation parameters
|
||||
uint8_t modIndex = (uint8_t)((8.0 * (freqDev / (float)_brKbps)) - 1.0);
|
||||
uint8_t modIndex = (uint8_t)((8.0 * (newFreqDev / (float)_brKbps)) - 1.0);
|
||||
if(modIndex > SX128X_BLE_GFSK_MOD_IND_4_00) {
|
||||
return(ERR_INVALID_MODULATION_PARAMETERS);
|
||||
}
|
||||
|
@ -1122,6 +1132,12 @@ void SX128x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
|||
_mod->setRfSwitchPins(rxEn, txEn);
|
||||
}
|
||||
|
||||
uint8_t SX128x::random() {
|
||||
// it's unclear whether SX128x can measure RSSI while not receiving a packet
|
||||
// this method is implemented only for PhysicalLayer compatibility
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint8_t SX128x::getStatus() {
|
||||
uint8_t data = 0;
|
||||
SPIreadCommand(SX128X_CMD_GET_STATUS, &data, 1);
|
||||
|
@ -1295,17 +1311,17 @@ int16_t SX128x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
#endif
|
||||
|
||||
// ensure BUSY is low (state machine ready)
|
||||
uint32_t start = millis();
|
||||
while(digitalRead(_mod->getGpio())) {
|
||||
yield();
|
||||
if(millis() - start >= timeout) {
|
||||
digitalWrite(_mod->getCs(), HIGH);
|
||||
uint32_t start = Module::millis();
|
||||
while(Module::digitalRead(_mod->getGpio())) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start >= timeout) {
|
||||
Module::digitalWrite(_mod->getCs(), HIGH);
|
||||
return(ERR_SPI_CMD_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// pull NSS low
|
||||
digitalWrite(_mod->getCs(), LOW);
|
||||
Module::digitalWrite(_mod->getCs(), LOW);
|
||||
|
||||
// start transfer
|
||||
spi->beginTransaction(spiSettings);
|
||||
|
@ -1362,15 +1378,15 @@ int16_t SX128x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
|
||||
// stop transfer
|
||||
spi->endTransaction();
|
||||
digitalWrite(_mod->getCs(), HIGH);
|
||||
Module::digitalWrite(_mod->getCs(), HIGH);
|
||||
|
||||
// wait for BUSY to go high and then low
|
||||
if(waitForBusy) {
|
||||
delayMicroseconds(1);
|
||||
start = millis();
|
||||
while(digitalRead(_mod->getGpio())) {
|
||||
yield();
|
||||
if(millis() - start >= timeout) {
|
||||
Module::delayMicroseconds(1);
|
||||
start = Module::millis();
|
||||
while(Module::digitalRead(_mod->getGpio())) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start >= timeout) {
|
||||
status = SX128X_STATUS_CMD_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
@ -1419,8 +1435,8 @@ int16_t SX128x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
// some faster platforms require a short delay here
|
||||
// not sure why, but it seems that long enough SPI transaction
|
||||
// (e.g. setPacketParams for GFSK) will fail without it
|
||||
#if defined(ARDUINO_ARCH_STM32) || defined(SAMD_SERIES)
|
||||
delay(1);
|
||||
#if defined(RADIOLIB_SPI_SLOWDOWN)
|
||||
Module::delay(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -753,11 +753,22 @@ class SX128x: public PhysicalLayer {
|
|||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
/*!
|
||||
\brief Dummy random method, to ensure PhysicalLayer compatibility.
|
||||
|
||||
\returns Always returns 0.
|
||||
*/
|
||||
uint8_t random();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
// cached LoRa parameters
|
||||
float _bwKhz = 0;
|
||||
uint8_t _bw = 0, _sf = 0, _cr = 0;
|
||||
|
@ -788,7 +799,18 @@ class SX128x: public PhysicalLayer {
|
|||
|
||||
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
private:
|
||||
#endif
|
||||
|
||||
// common low-level SPI interface
|
||||
int16_t SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout = 5000);
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
// common parameters
|
||||
|
@ -807,13 +829,6 @@ class SX128x: public PhysicalLayer {
|
|||
uint8_t _connectionState = 0, _crcBLE = 0, _bleTestPayload = 0;
|
||||
|
||||
int16_t config(uint8_t modem);
|
||||
|
||||
// common low-level SPI interface
|
||||
int16_t SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout = 5000);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,7 @@ int16_t Si4430::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
// execute common part
|
||||
int16_t state = Si443x::begin(br, freqDev, rxBw, preambleLen);
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSi4430"));
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
|
|
|
@ -67,11 +67,11 @@ class Si4430: public Si4432 {
|
|||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ int16_t Si4431::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
// execute common part
|
||||
int16_t state = Si443x::begin(br, freqDev, rxBw, preambleLen);
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSi4431"));
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
|
|
|
@ -58,11 +58,11 @@ class Si4431: public Si4432 {
|
|||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ int16_t Si4432::begin(float freq, float br, float freqDev, float rxBw, int8_t po
|
|||
// execute common part
|
||||
int16_t state = Si443x::begin(br, freqDev, rxBw, preambleLen);
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSi4432"));
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
|
|
|
@ -67,11 +67,11 @@ class Si4432: public Si443x {
|
|||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ int16_t Si443x::begin(float br, float freqDev, float rxBw, uint8_t preambleLen)
|
|||
_mod->term(RADIOLIB_USE_SPI);
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found Si443x!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tSi443x"));
|
||||
}
|
||||
|
||||
// clear POR interrupt
|
||||
|
@ -60,9 +60,9 @@ int16_t Si443x::begin(float br, float freqDev, float rxBw, uint8_t preambleLen)
|
|||
void Si443x::reset() {
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delay(100);
|
||||
Module::delay(100);
|
||||
}
|
||||
|
||||
int16_t Si443x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -74,22 +74,27 @@ int16_t Si443x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission end or timeout
|
||||
uint32_t start = micros();
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
if(micros() - start > timeout) {
|
||||
uint32_t start = Module::micros();
|
||||
while(Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
clearIRQFlags();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
state = standby();
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
||||
// the next transmission will timeout without the following
|
||||
_mod->SPIwriteRegister(SI443X_REG_INTERRUPT_ENABLE_2, 0x00);
|
||||
_mod->SPIsetRegValue(SI443X_REG_MODULATION_MODE_CONTROL_2, SI443X_TX_DATA_SOURCE_FIFO, 5, 4);
|
||||
state = setFrequencyRaw(_freq);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -102,9 +107,9 @@ int16_t Si443x::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = micros();
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
if(micros() - start > timeout) {
|
||||
uint32_t start = Module::micros();
|
||||
while(Module::digitalRead(_mod->getIrq())) {
|
||||
if(Module::micros() - start > timeout) {
|
||||
standby();
|
||||
clearIRQFlags();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
|
@ -135,7 +140,8 @@ int16_t Si443x::standby() {
|
|||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(LOW, LOW);
|
||||
|
||||
return(_mod->SPIsetRegValue(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_XTAL_ON, 7, 0, 10));
|
||||
//return(_mod->SPIsetRegValue(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_XTAL_ON, 7, 0, 10));
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t Si443x::transmitDirect(uint32_t frf) {
|
||||
|
@ -166,7 +172,7 @@ int16_t Si443x::transmitDirect(uint32_t frf) {
|
|||
|
||||
// start direct transmission
|
||||
directMode();
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_TX_ON);
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_TX_ON | SI443X_XTAL_ON);
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
@ -176,7 +182,7 @@ int16_t Si443x::transmitDirect(uint32_t frf) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start transmitting
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_TX_ON);
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_TX_ON | SI443X_XTAL_ON);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -189,7 +195,7 @@ int16_t Si443x::receiveDirect() {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start receiving
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_RX_ON);
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_RX_ON | SI443X_XTAL_ON);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -198,11 +204,11 @@ int16_t Si443x::packetMode() {
|
|||
}
|
||||
|
||||
void Si443x::setIrqAction(void (*func)(void)) {
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, FALLING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, FALLING);
|
||||
}
|
||||
|
||||
void Si443x::clearIrqAction() {
|
||||
detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()));
|
||||
}
|
||||
|
||||
int16_t Si443x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -219,10 +225,6 @@ int16_t Si443x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
_mod->SPIsetRegValue(SI443X_REG_OP_FUNC_CONTROL_2, SI443X_TX_FIFO_RESET, 0, 0);
|
||||
_mod->SPIsetRegValue(SI443X_REG_OP_FUNC_CONTROL_2, SI443X_TX_FIFO_CLEAR, 0, 0);
|
||||
|
||||
// set interrupt mapping
|
||||
state = _mod->SPIsetRegValue(SI443X_REG_INTERRUPT_ENABLE_1, SI443X_PACKET_SENT_ENABLED);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
||||
|
@ -239,8 +241,12 @@ int16_t Si443x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(LOW, HIGH);
|
||||
|
||||
// set interrupt mapping
|
||||
_mod->SPIwriteRegister(SI443X_REG_INTERRUPT_ENABLE_1, SI443X_PACKET_SENT_ENABLED);
|
||||
_mod->SPIwriteRegister(SI443X_REG_INTERRUPT_ENABLE_2, 0x00);
|
||||
|
||||
// set mode to transmit
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_TX_ON);
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_TX_ON | SI443X_XTAL_ON);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -254,20 +260,18 @@ int16_t Si443x::startReceive() {
|
|||
_mod->SPIsetRegValue(SI443X_REG_OP_FUNC_CONTROL_2, SI443X_RX_FIFO_RESET, 1, 1);
|
||||
_mod->SPIsetRegValue(SI443X_REG_OP_FUNC_CONTROL_2, SI443X_RX_FIFO_CLEAR, 1, 1);
|
||||
|
||||
// set interrupt mapping
|
||||
state = _mod->SPIsetRegValue(SI443X_REG_INTERRUPT_ENABLE_1, SI443X_VALID_PACKET_RECEIVED_ENABLED, SI443X_CRC_ERROR_ENABLED);
|
||||
RADIOLIB_ASSERT(state);
|
||||
state = _mod->SPIsetRegValue(SI443X_REG_INTERRUPT_ENABLE_2, 0x00);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
||||
// set RF switch (if present)
|
||||
_mod->setRfSwitchState(HIGH, LOW);
|
||||
|
||||
// set interrupt mapping
|
||||
_mod->SPIwriteRegister(SI443X_REG_INTERRUPT_ENABLE_1, SI443X_PACKET_SENT_ENABLED);
|
||||
_mod->SPIwriteRegister(SI443X_REG_INTERRUPT_ENABLE_2, 0x00);
|
||||
|
||||
// set mode to receive
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_RX_ON);
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_RX_ON | SI443X_XTAL_ON);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -330,28 +334,23 @@ int16_t Si443x::setBitRate(float br) {
|
|||
}
|
||||
|
||||
int16_t Si443x::setFrequencyDeviation(float freqDev) {
|
||||
// set frequency deviation to lowest available setting (required for RTTY)
|
||||
if(freqDev == 0.0) {
|
||||
int16_t state = _mod->SPIsetRegValue(SI443X_REG_MODULATION_MODE_CONTROL_2, 0x00, 2, 2);
|
||||
_mod->SPIwriteRegister(SI443X_REG_FREQUENCY_DEVIATION, 0x00);
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
_freqDev = freqDev;
|
||||
}
|
||||
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
if(freqDev < 0.0) {
|
||||
newFreqDev = 0.625;
|
||||
}
|
||||
|
||||
RADIOLIB_CHECK_RANGE(freqDev, 0.625, 320.0, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
RADIOLIB_CHECK_RANGE(newFreqDev, 0.625, 320.0, ERR_INVALID_FREQUENCY_DEVIATION);
|
||||
|
||||
// calculate raw frequency deviation value
|
||||
uint16_t fdev = (uint16_t)(freqDev / 0.625);
|
||||
uint16_t fdev = (uint16_t)(newFreqDev / 0.625);
|
||||
|
||||
// update registers
|
||||
int16_t state = _mod->SPIsetRegValue(SI443X_REG_MODULATION_MODE_CONTROL_2, (uint8_t)((fdev & 0x0100) >> 6), 2, 2);
|
||||
_mod->SPIwriteRegister(SI443X_REG_FREQUENCY_DEVIATION, (uint8_t)(fdev & 0xFF));
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
_freqDev = freqDev;
|
||||
_freqDev = newFreqDev;
|
||||
}
|
||||
|
||||
return(state);
|
||||
|
@ -386,63 +385,64 @@ int16_t Si443x::setRxBandwidth(float rxBw) {
|
|||
filterSet = ((rxBw - 60.286)/10.7000 + 0.5);
|
||||
|
||||
// this is the "Lord help thee who tread 'ere" section - no way to approximate this mess
|
||||
} else if(rxBw == 142.8) {
|
||||
/// \todo float tolerance equality as macro?
|
||||
} else if(abs(rxBw - 142.8) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 1;
|
||||
filterSet = 4;
|
||||
} else if(rxBw == 167.8) {
|
||||
} else if(abs(rxBw - 167.8) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 1;
|
||||
filterSet = 5;
|
||||
} else if(rxBw == 181.1) {
|
||||
} else if(abs(rxBw - 181.1) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 1;
|
||||
filterSet = 6;
|
||||
} else if(rxBw == 191.5) {
|
||||
} else if(abs(rxBw - 191.5) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 15;
|
||||
} else if(rxBw == 225.1) {
|
||||
} else if(abs(rxBw - 225.1) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 1;
|
||||
} else if(rxBw == 248.8) {
|
||||
} else if(abs(rxBw - 248.8) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 2;
|
||||
} else if(rxBw == 269.3) {
|
||||
} else if(abs(rxBw - 269.3) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 3;
|
||||
} else if(rxBw == 284.8) {
|
||||
} else if(abs(rxBw - 284.8) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 4;
|
||||
} else if(rxBw == 335.5) {
|
||||
} else if(abs(rxBw -335.5) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 8;
|
||||
} else if(rxBw == 391.8) {
|
||||
} else if(abs(rxBw - 391.8) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 9;
|
||||
} else if(rxBw == 420.2) {
|
||||
} else if(abs(rxBw - 420.2) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 10;
|
||||
} else if(rxBw == 468.4) {
|
||||
} else if(abs(rxBw - 468.4) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 11;
|
||||
} else if(rxBw == 518.8) {
|
||||
} else if(abs(rxBw - 518.8) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 12;
|
||||
} else if(rxBw == 577.0) {
|
||||
} else if(abs(rxBw - 577.0) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 13;
|
||||
} else if(rxBw == 620.7) {
|
||||
} else if(abs(rxBw - 620.7) <= 0.001) {
|
||||
bypass = SI443X_BYPASS_DEC_BY_3_ON;
|
||||
decRate = 0;
|
||||
filterSet = 14;
|
||||
|
@ -493,7 +493,7 @@ int16_t Si443x::setPreambleLength(uint8_t preambleLen) {
|
|||
|
||||
// set default preamble detection threshold to 50% of preamble length (in units of 4 bits)
|
||||
uint8_t preThreshold = preambleLen / 4;
|
||||
return(_mod->SPIsetRegValue(SI443X_REG_PREAMBLE_DET_CONTROL, preThreshold << 4, 3, 7));
|
||||
return(_mod->SPIsetRegValue(SI443X_REG_PREAMBLE_DET_CONTROL, preThreshold << 4, 7, 3));
|
||||
}
|
||||
|
||||
size_t Si443x::getPacketLength(bool update) {
|
||||
|
@ -548,6 +548,29 @@ void Si443x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
|||
_mod->setRfSwitchPins(rxEn, txEn);
|
||||
}
|
||||
|
||||
uint8_t Si443x::random() {
|
||||
// set mode to Rx
|
||||
_mod->SPIwriteRegister(SI443X_REG_OP_FUNC_CONTROL_1, SI443X_RX_ON | SI443X_XTAL_ON);
|
||||
|
||||
// wait a bit for the RSSI reading to stabilise
|
||||
Module::delay(10);
|
||||
|
||||
// read RSSI value 8 times, always keep just the least significant bit
|
||||
uint8_t randByte = 0x00;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
randByte |= ((_mod->SPIreadRegister(SI443X_REG_RSSI) & 0x01) << i);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
||||
return(randByte);
|
||||
}
|
||||
|
||||
int16_t Si443x::getChipVersion() {
|
||||
return(_mod->SPIgetRegValue(SI443X_REG_DEVICE_VERSION));
|
||||
}
|
||||
|
||||
int16_t Si443x::setFrequencyRaw(float newFreq) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
|
@ -556,6 +579,7 @@ int16_t Si443x::setFrequencyRaw(float newFreq) {
|
|||
// check high/low band
|
||||
uint8_t bandSelect = SI443X_BAND_SELECT_LOW;
|
||||
uint8_t freqBand = (newFreq / 10) - 24;
|
||||
_freq = newFreq;
|
||||
if(newFreq >= 480.0) {
|
||||
bandSelect = SI443X_BAND_SELECT_HIGH;
|
||||
freqBand = (newFreq / 20) - 24;
|
||||
|
@ -595,7 +619,7 @@ bool Si443x::findChip() {
|
|||
RADIOLIB_DEBUG_PRINT(F(", expected 0x00"));
|
||||
RADIOLIB_DEBUG_PRINTLN(SI443X_DEVICE_VERSION, HEX);
|
||||
#endif
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -604,8 +628,8 @@ bool Si443x::findChip() {
|
|||
}
|
||||
|
||||
void Si443x::clearIRQFlags() {
|
||||
_mod->SPIreadRegister(SI443X_REG_INTERRUPT_STATUS_1);
|
||||
_mod->SPIreadRegister(SI443X_REG_INTERRUPT_STATUS_2);
|
||||
uint8_t buff[2];
|
||||
_mod->SPIreadRegisterBurst(SI443X_REG_INTERRUPT_STATUS_1, 2, buff);
|
||||
}
|
||||
|
||||
int16_t Si443x::config() {
|
||||
|
@ -614,8 +638,7 @@ int16_t Si443x::config() {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable POR and chip ready interrupts
|
||||
state = _mod->SPIsetRegValue(SI443X_REG_INTERRUPT_ENABLE_2, 0x00);
|
||||
RADIOLIB_ASSERT(state);
|
||||
_mod->SPIwriteRegister(SI443X_REG_INTERRUPT_ENABLE_2, 0x00);
|
||||
|
||||
// disable packet header
|
||||
state = _mod->SPIsetRegValue(SI443X_REG_HEADER_CONTROL_2, SI443X_SYNC_WORD_TIMEOUT_ON | SI443X_HEADER_LENGTH_HEADER_NONE, 7, 4);
|
||||
|
|
|
@ -785,20 +785,39 @@ class Si443x: public PhysicalLayer {
|
|||
*/
|
||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t random();
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return SI443X_DEVICE_VERSION (0x06) if Si443x is connected and working.
|
||||
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
int16_t getChipVersion();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
float _br = 0;
|
||||
float _freqDev = 0;
|
||||
float _freq = 0;
|
||||
|
||||
size_t _packetLength = 0;
|
||||
bool _packetLengthQueried = false;
|
||||
|
||||
int16_t setFrequencyRaw(float newFreq);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
bool findChip();
|
||||
|
|
|
@ -34,7 +34,7 @@ int16_t XBee::begin(long speed) {
|
|||
RADIOLIB_DEBUG_PRINTLN(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Resetting ..."));
|
||||
reset();
|
||||
delay(10);
|
||||
Module::delay(10);
|
||||
_mod->ATemptyBuffer();
|
||||
i++;
|
||||
}
|
||||
|
@ -51,10 +51,10 @@ int16_t XBee::begin(long speed) {
|
|||
}
|
||||
|
||||
void XBee::reset() {
|
||||
pinMode(_mod->getRst(), OUTPUT);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
delay(1);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
}
|
||||
|
||||
int16_t XBee::transmit(uint8_t* dest, const char* payload, uint8_t radius) {
|
||||
|
@ -216,11 +216,11 @@ int16_t XBeeSerial::begin(long speed) {
|
|||
}
|
||||
|
||||
void XBeeSerial::reset() {
|
||||
pinMode(_mod->getRst(), OUTPUT);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
delay(1);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
pinMode(_mod->getRst(), INPUT);
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
Module::pinMode(_mod->getRst(), INPUT);
|
||||
}
|
||||
|
||||
int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) {
|
||||
|
@ -308,13 +308,13 @@ int16_t XBeeSerial::setPanId(const char* panId) {
|
|||
|
||||
bool XBeeSerial::enterCmdMode() {
|
||||
for(uint8_t i = 0; i < 10; i++) {
|
||||
delay(1000);
|
||||
Module::delay(1000);
|
||||
|
||||
_mod->ModuleSerial->write('+');
|
||||
_mod->ModuleSerial->write('+');
|
||||
_mod->ModuleSerial->write('+');
|
||||
|
||||
delay(1000);
|
||||
Module::delay(1000);
|
||||
|
||||
if(_mod->ATgetResponse()) {
|
||||
return(true);
|
||||
|
@ -374,13 +374,13 @@ void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length
|
|||
|
||||
// calculate the checksum
|
||||
uint8_t checksum = 0;
|
||||
for(uint16_t i = 3; i < frameLength - 1; i++) {
|
||||
for(size_t i = 3; i < frameLength - 1; i++) {
|
||||
checksum += frame[i];
|
||||
}
|
||||
frame[5 + length] = 0xFF - checksum;
|
||||
|
||||
// send the frame
|
||||
for(uint16_t i = 0; i < frameLength; i++) {
|
||||
for(size_t i = 0; i < frameLength; i++) {
|
||||
_mod->ModuleSerial->write(frame[i]);
|
||||
}
|
||||
|
||||
|
@ -403,10 +403,10 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) {
|
|||
numBytes++;
|
||||
|
||||
// wait until all response bytes are available (5s timeout)
|
||||
uint32_t start = millis();
|
||||
uint32_t start = Module::millis();
|
||||
while(_mod->ModuleSerial->available() < (int16_t)numBytes) {
|
||||
yield();
|
||||
if(millis() - start >= timeout/2) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start >= timeout/2) {
|
||||
return(ERR_FRAME_MALFORMED);
|
||||
}
|
||||
}
|
||||
|
@ -455,10 +455,10 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) {
|
|||
|
||||
uint16_t XBee::getNumBytes(uint32_t timeout, size_t minBytes) {
|
||||
// wait for available data
|
||||
uint32_t start = millis();
|
||||
uint32_t start = Module::millis();
|
||||
while((size_t)_mod->ModuleSerial->available() < minBytes) {
|
||||
yield();
|
||||
if(millis() - start >= timeout) {
|
||||
Module::yield();
|
||||
if(Module::millis() - start >= timeout) {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ uint16_t XBee::getNumBytes(uint32_t timeout, size_t minBytes) {
|
|||
uint8_t i = 0;
|
||||
RADIOLIB_DEBUG_PRINT(F("reading frame length: "));
|
||||
while(_mod->ModuleSerial->available() > 0) {
|
||||
yield();
|
||||
Module::yield();
|
||||
uint8_t b = _mod->ModuleSerial->read();
|
||||
RADIOLIB_DEBUG_PRINT(b, HEX);
|
||||
RADIOLIB_DEBUG_PRINT('\t');
|
||||
|
|
|
@ -81,7 +81,7 @@ class XBeeSerial: public ISerial {
|
|||
*/
|
||||
int16_t setPanId(const char* panId);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
bool enterCmdMode();
|
||||
|
@ -172,10 +172,15 @@ class XBee {
|
|||
*/
|
||||
int16_t setPanId(uint8_t* panId);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
uint8_t _frameID = 0x01;
|
||||
size_t _frameLength = 0;
|
||||
bool _frameHeaderProcessed = false;
|
||||
|
|
|
@ -10,13 +10,14 @@ int16_t nRF24::begin(int16_t freq, int16_t dataRate, int8_t power, uint8_t addrW
|
|||
_mod->SPIreadCommand = NRF24_CMD_READ;
|
||||
_mod->SPIwriteCommand = NRF24_CMD_WRITE;
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
|
||||
// set pin mode on RST (connected to nRF24 CE pin)
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
|
||||
// wait for minimum power-on reset duration
|
||||
delay(100);
|
||||
Module::delay(100);
|
||||
|
||||
// check SPI connection
|
||||
int16_t val = _mod->SPIgetRegValue(NRF24_REG_SETUP_AW);
|
||||
|
@ -25,6 +26,7 @@ int16_t nRF24::begin(int16_t freq, int16_t dataRate, int8_t power, uint8_t addrW
|
|||
_mod->term(RADIOLIB_USE_SPI);
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN(F("M\tnRF24"));
|
||||
|
||||
// configure settings inaccessible by public API
|
||||
int16_t state = config();
|
||||
|
@ -69,7 +71,7 @@ int16_t nRF24::standby() {
|
|||
// make sure carrier output is disabled
|
||||
_mod->SPIsetRegValue(NRF24_REG_RF_SETUP, NRF24_CONT_WAVE_OFF, 7, 7);
|
||||
_mod->SPIsetRegValue(NRF24_REG_RF_SETUP, NRF24_PLL_LOCK_OFF, 4, 4);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
|
||||
// use standby-1 mode
|
||||
return(_mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_POWER_UP, 1, 1));
|
||||
|
@ -81,9 +83,9 @@ int16_t nRF24::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait until transmission is finished
|
||||
uint32_t start = micros();
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
uint32_t start = Module::micros();
|
||||
while(Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
// check maximum number of retransmits
|
||||
if(getStatus(NRF24_MAX_RT)) {
|
||||
|
@ -93,7 +95,7 @@ int16_t nRF24::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
// check timeout: 15 retries * 4ms (max Tx time as per datasheet)
|
||||
if(micros() - start >= 60000) {
|
||||
if(Module::micros() - start >= 60000) {
|
||||
standby();
|
||||
clearIRQ();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
|
@ -112,12 +114,12 @@ int16_t nRF24::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for Rx_DataReady or timeout
|
||||
uint32_t start = micros();
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
uint32_t start = Module::micros();
|
||||
while(Module::digitalRead(_mod->getIrq())) {
|
||||
Module::yield();
|
||||
|
||||
// check timeout: 15 retries * 4ms (max Tx time as per datasheet)
|
||||
if(micros() - start >= 60000) {
|
||||
if(Module::micros() - start >= 60000) {
|
||||
standby();
|
||||
clearIRQ();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
|
@ -139,7 +141,7 @@ int16_t nRF24::transmitDirect(uint32_t frf) {
|
|||
int16_t state = _mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_PTX, 0, 0);
|
||||
state |= _mod->SPIsetRegValue(NRF24_REG_RF_SETUP, NRF24_CONT_WAVE_ON, 7, 7);
|
||||
state |= _mod->SPIsetRegValue(NRF24_REG_RF_SETUP, NRF24_PLL_LOCK_ON, 4, 4);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -150,7 +152,7 @@ int16_t nRF24::receiveDirect() {
|
|||
}
|
||||
|
||||
void nRF24::setIrqAction(void (*func)(void)) {
|
||||
attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, FALLING);
|
||||
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, FALLING);
|
||||
}
|
||||
|
||||
int16_t nRF24::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -186,9 +188,9 @@ int16_t nRF24::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
SPIwriteTxPayload(data, len);
|
||||
|
||||
// CE high to start transmitting
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
delay(1);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
Module::delay(1);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -211,10 +213,10 @@ int16_t nRF24::startReceive() {
|
|||
SPItransfer(NRF24_CMD_FLUSH_RX);
|
||||
|
||||
// CE high to start receiving
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
|
||||
// wait to enter Rx state
|
||||
delay(1);
|
||||
Module::delay(1);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -457,32 +459,32 @@ int16_t nRF24::setCrcFiltering(bool crcOn) {
|
|||
}
|
||||
|
||||
// Disable CRC
|
||||
return _mod->SPIsetRegValue(NRF24_REG_CONFIG, crcOn ? NRF24_CRC_ON : NRF24_CRC_OFF, 3, 3);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_CONFIG, (crcOn ? NRF24_CRC_ON : NRF24_CRC_OFF), 3, 3);
|
||||
}
|
||||
|
||||
int16_t nRF24::setAutoAck(bool autoAckOn){
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, autoAckOn ? NRF24_AA_ALL_ON : NRF24_AA_ALL_OFF, 5, 0);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, (autoAckOn ? NRF24_AA_ALL_ON : NRF24_AA_ALL_OFF), 5, 0);
|
||||
}
|
||||
|
||||
int16_t nRF24::setAutoAck(uint8_t pipeNum, bool autoAckOn){
|
||||
switch(pipeNum) {
|
||||
case 0:
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, autoAckOn ? NRF24_AA_P0_ON : NRF24_AA_P0_OFF, 0, 0);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, (autoAckOn ? NRF24_AA_P0_ON : NRF24_AA_P0_OFF), 0, 0);
|
||||
break;
|
||||
case 1:
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, autoAckOn ? NRF24_AA_P1_ON : NRF24_AA_P1_OFF, 1, 1);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, (autoAckOn ? NRF24_AA_P1_ON : NRF24_AA_P1_OFF), 1, 1);
|
||||
break;
|
||||
case 2:
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, autoAckOn ? NRF24_AA_P2_ON : NRF24_AA_P2_OFF, 2, 2);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, (autoAckOn ? NRF24_AA_P2_ON : NRF24_AA_P2_OFF), 2, 2);
|
||||
break;
|
||||
case 3:
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, autoAckOn ? NRF24_AA_P3_ON : NRF24_AA_P3_OFF, 3, 3);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, (autoAckOn ? NRF24_AA_P3_ON : NRF24_AA_P3_OFF), 3, 3);
|
||||
break;
|
||||
case 4:
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, autoAckOn ? NRF24_AA_P4_ON : NRF24_AA_P4_OFF, 4, 4);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, (autoAckOn ? NRF24_AA_P4_ON : NRF24_AA_P4_OFF), 4, 4);
|
||||
break;
|
||||
case 5:
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, autoAckOn ? NRF24_AA_P5_ON : NRF24_AA_P5_OFF, 5, 5);
|
||||
return _mod->SPIsetRegValue(NRF24_REG_EN_AA, (autoAckOn ? NRF24_AA_P5_ON : NRF24_AA_P5_OFF), 5, 5);
|
||||
break;
|
||||
default:
|
||||
return (ERR_INVALID_PIPE_NUMBER);
|
||||
|
@ -503,6 +505,12 @@ int16_t nRF24::setEncoding(uint8_t encoding) {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
uint8_t nRF24::random() {
|
||||
// nRF24 is unable to measure RSSI, hence no TRNG
|
||||
// this method is implemented only for PhysicalLayer compatibility
|
||||
return(0);
|
||||
}
|
||||
|
||||
void nRF24::clearIRQ() {
|
||||
// clear status bits
|
||||
_mod->SPIsetRegValue(NRF24_REG_STATUS, NRF24_RX_DR | NRF24_TX_DS | NRF24_MAX_RT, 6, 4);
|
||||
|
@ -539,7 +547,7 @@ int16_t nRF24::config() {
|
|||
|
||||
// power up
|
||||
_mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_POWER_UP, 1, 1);
|
||||
delay(5);
|
||||
Module::delay(5);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -558,7 +566,7 @@ void nRF24::SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* data
|
|||
SPISettings spiSettings = _mod->getSpiSettings();
|
||||
|
||||
// start transfer
|
||||
digitalWrite(_mod->getCs(), LOW);
|
||||
Module::digitalWrite(_mod->getCs(), LOW);
|
||||
spi->beginTransaction(spiSettings);
|
||||
|
||||
// send command
|
||||
|
@ -577,7 +585,7 @@ void nRF24::SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* data
|
|||
|
||||
// stop transfer
|
||||
spi->endTransaction();
|
||||
digitalWrite(_mod->getCs(), HIGH);
|
||||
Module::digitalWrite(_mod->getCs(), HIGH);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -464,19 +464,30 @@ class nRF24: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setEncoding(uint8_t encoding) override;
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
/*!
|
||||
\brief Dummy random method, to ensure PhysicalLayer compatibility.
|
||||
|
||||
\returns Always returns 0.
|
||||
*/
|
||||
uint8_t random();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL)
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
void SPIreadRxPayload(uint8_t* data, uint8_t numBytes);
|
||||
void SPIwriteTxPayload(uint8_t* data, uint8_t numBytes);
|
||||
void SPItransfer(uint8_t cmd, bool write = false, uint8_t* dataOut = NULL, uint8_t* dataIn = NULL, uint8_t numBytes = 0);
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
|
||||
uint8_t _addrWidth = 0;
|
||||
|
||||
int16_t config();
|
||||
void clearIRQ();
|
||||
|
||||
void SPIreadRxPayload(uint8_t* data, uint8_t numBytes);
|
||||
void SPIwriteTxPayload(uint8_t* data, uint8_t numBytes);
|
||||
void SPItransfer(uint8_t cmd, bool write = false, uint8_t* dataOut = NULL, uint8_t* dataIn = NULL, uint8_t numBytes = 0);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,10 @@ AFSKClient::AFSKClient(PhysicalLayer* phy, RADIOLIB_PIN_TYPE pin): _pin(pin) {
|
|||
_phy = phy;
|
||||
}
|
||||
|
||||
int16_t AFSKClient::begin() {
|
||||
return(_phy->startDirect());
|
||||
}
|
||||
|
||||
int16_t AFSKClient::tone(uint16_t freq, bool autoStart) {
|
||||
if(freq == 0) {
|
||||
return(ERR_INVALID_FREQUENCY);
|
||||
|
|
|
@ -25,6 +25,13 @@ class AFSKClient {
|
|||
*/
|
||||
AFSKClient(PhysicalLayer* phy, RADIOLIB_PIN_TYPE pin);
|
||||
|
||||
/*!
|
||||
\brief Initialization method.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin();
|
||||
|
||||
/*!
|
||||
\brief Start transmitting audio tone.
|
||||
|
||||
|
|
|
@ -179,17 +179,8 @@ int16_t AX25Client::begin(const char* srcCallsign, uint8_t srcSSID, uint8_t prea
|
|||
// save preamble length
|
||||
_preambleLen = preambleLen;
|
||||
|
||||
// set module frequency deviation to 0 if using FSK
|
||||
int16_t state = ERR_NONE;
|
||||
#if !defined(RADIOLIB_EXCLUDE_AFSK)
|
||||
if(_audio == nullptr) {
|
||||
state = _phy->setFrequencyDeviation(0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = _phy->setEncoding(0);
|
||||
}
|
||||
#endif
|
||||
return(state);
|
||||
// configure for direct mode
|
||||
return(_phy->startDirect());
|
||||
}
|
||||
|
||||
int16_t AX25Client::transmit(const char* str, const char* destCallsign, uint8_t destSSID) {
|
||||
|
@ -234,7 +225,7 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) {
|
|||
|
||||
// set destination callsign - all address field bytes are shifted by one bit to make room for HDLC address extension bit
|
||||
memset(frameBuffPtr, ' ' << 1, AX25_MAX_CALLSIGN_LEN);
|
||||
for(uint8_t i = 0; i < strlen(frame->destCallsign); i++) {
|
||||
for(size_t i = 0; i < strlen(frame->destCallsign); i++) {
|
||||
*(frameBuffPtr + i) = frame->destCallsign[i] << 1;
|
||||
}
|
||||
frameBuffPtr += AX25_MAX_CALLSIGN_LEN;
|
||||
|
@ -244,7 +235,7 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) {
|
|||
|
||||
// set source callsign - all address field bytes are shifted by one bit to make room for HDLC address extension bit
|
||||
memset(frameBuffPtr, ' ' << 1, AX25_MAX_CALLSIGN_LEN);
|
||||
for(uint8_t i = 0; i < strlen(frame->srcCallsign); i++) {
|
||||
for(size_t i = 0; i < strlen(frame->srcCallsign); i++) {
|
||||
*(frameBuffPtr + i) = frame->srcCallsign[i] << 1;
|
||||
}
|
||||
frameBuffPtr += AX25_MAX_CALLSIGN_LEN;
|
||||
|
@ -255,7 +246,7 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) {
|
|||
// set repeater callsigns
|
||||
for(uint16_t i = 0; i < frame->numRepeaters; i++) {
|
||||
memset(frameBuffPtr, ' ' << 1, AX25_MAX_CALLSIGN_LEN);
|
||||
for(uint8_t j = 0; j < strlen(frame->repeaterCallsigns[i]); j++) {
|
||||
for(size_t j = 0; j < strlen(frame->repeaterCallsigns[i]); j++) {
|
||||
*(frameBuffPtr + j) = frame->repeaterCallsigns[i][j] << 1;
|
||||
}
|
||||
frameBuffPtr += AX25_MAX_CALLSIGN_LEN;
|
||||
|
@ -314,7 +305,7 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) {
|
|||
// stuff bits (skip preamble and both flags)
|
||||
uint16_t stuffedFrameBuffLenBits = 8*(_preambleLen + 1);
|
||||
uint8_t count = 0;
|
||||
for(uint16_t i = 0; i < frameBuffLen + 2; i++) {
|
||||
for(size_t i = 0; i < frameBuffLen + 2; i++) {
|
||||
for(int8_t shift = 7; shift >= 0; shift--) {
|
||||
uint16_t stuffedFrameBuffPos = stuffedFrameBuffLenBits + 7 - 2*(stuffedFrameBuffLenBits%8);
|
||||
if((frameBuff[i] >> shift) & 0x01) {
|
||||
|
@ -400,14 +391,14 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) {
|
|||
|
||||
// check each bit
|
||||
for(uint16_t mask = 0x80; mask >= 0x01; mask >>= 1) {
|
||||
uint32_t start = micros();
|
||||
uint32_t start = Module::micros();
|
||||
if(stuffedFrameBuff[i] & mask) {
|
||||
_audio->tone(AX25_AFSK_MARK, false);
|
||||
} else {
|
||||
_audio->tone(AX25_AFSK_SPACE, false);
|
||||
}
|
||||
while(micros() - start < 833) {
|
||||
yield();
|
||||
while(Module::micros() - start < AX25_AFSK_TONE_DURATION) {
|
||||
Module::yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,8 +64,6 @@ int16_t HTTPClient::get(const char* url, String& response) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
//delay(1000);
|
||||
|
||||
// get the response length
|
||||
size_t numBytes = _tl->getNumBytes();
|
||||
if(numBytes == 0) {
|
||||
|
|
|
@ -24,28 +24,21 @@ int16_t HellClient::begin(float base, float rate) {
|
|||
// calculate "pixel" duration
|
||||
_pixelDuration = 1000000.0/rate;
|
||||
|
||||
// set module frequency deviation to 0 if using FSK
|
||||
int16_t state = ERR_NONE;
|
||||
#if !defined(RADIOLIB_EXCLUDE_AFSK)
|
||||
if(_audio == nullptr) {
|
||||
state = _phy->setFrequencyDeviation(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
// configure for direct mode
|
||||
return(_phy->startDirect());
|
||||
}
|
||||
|
||||
size_t HellClient::printGlyph(uint8_t* buff) {
|
||||
// print the character
|
||||
for(uint8_t mask = 0x40; mask >= 0x01; mask >>= 1) {
|
||||
for(int8_t i = HELL_FONT_HEIGHT - 1; i >= 0; i--) {
|
||||
uint32_t start = micros();
|
||||
uint32_t start = Module::micros();
|
||||
if(buff[i] & mask) {
|
||||
transmitDirect(_base, _baseHz);
|
||||
} else {
|
||||
standby();
|
||||
}
|
||||
while(micros() - start < _pixelDuration);
|
||||
while(Module::micros() - start < _pixelDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +78,7 @@ size_t HellClient::write(uint8_t b) {
|
|||
uint8_t buff[HELL_FONT_WIDTH];
|
||||
buff[0] = 0x00;
|
||||
for(uint8_t i = 0; i < HELL_FONT_WIDTH - 2; i++) {
|
||||
buff[i + 1] = pgm_read_byte(&HellFont[pos][i]);
|
||||
buff[i + 1] = RADIOLIB_PROGMEM_READ_BYTE(&HellFont[pos][i]);
|
||||
}
|
||||
buff[HELL_FONT_WIDTH - 1] = 0x00;
|
||||
|
||||
|
@ -97,7 +90,7 @@ size_t HellClient::print(__FlashStringHelper* fstr) {
|
|||
PGM_P p = reinterpret_cast<PGM_P>(fstr);
|
||||
size_t n = 0;
|
||||
while(true) {
|
||||
char c = pgm_read_byte(p++);
|
||||
char c = RADIOLIB_PROGMEM_READ_BYTE(p++);
|
||||
if(c == '\0') {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// font definition: characters are stored in rows,
|
||||
// least significant byte of each character is the first row
|
||||
// Hellschreiber use 7x7 characters, but this simplified font uses only 5x5 - the extra bytes aren't stored
|
||||
static const uint8_t HellFont[64][HELL_FONT_WIDTH - 2] PROGMEM = {
|
||||
static const uint8_t HellFont[64][HELL_FONT_WIDTH - 2] RADIOLIB_PROGMEM = {
|
||||
{ 0b0000000, 0b0000000, 0b0000000, 0b0000000, 0b0000000 }, // space
|
||||
{ 0b0001000, 0b0001000, 0b0001000, 0b0000000, 0b0001000 }, // !
|
||||
{ 0b0010100, 0b0010100, 0b0000000, 0b0000000, 0b0000000 }, // "
|
||||
|
|
|
@ -23,15 +23,8 @@ int16_t MorseClient::begin(float base, uint8_t speed) {
|
|||
// calculate dot length (assumes PARIS as typical word)
|
||||
_dotLength = 1200 / speed;
|
||||
|
||||
// set module frequency deviation to 0 if using FSK
|
||||
int16_t state = ERR_NONE;
|
||||
#if !defined(RADIOLIB_EXCLUDE_AFSK)
|
||||
if(_audio == nullptr) {
|
||||
state = _phy->setFrequencyDeviation(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
// configure for direct mode
|
||||
return(_phy->startDirect());
|
||||
}
|
||||
|
||||
size_t MorseClient::startSignal() {
|
||||
|
@ -64,12 +57,12 @@ size_t MorseClient::write(uint8_t b) {
|
|||
if(b == ' ') {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("space"));
|
||||
standby();
|
||||
delay(4 * _dotLength);
|
||||
Module::delay(4 * _dotLength);
|
||||
return(1);
|
||||
}
|
||||
|
||||
// get morse code from lookup table
|
||||
uint8_t code = pgm_read_byte(&MorseTable[(uint8_t)(toupper(b) - 32)]);
|
||||
uint8_t code = RADIOLIB_PROGMEM_READ_BYTE(&MorseTable[(uint8_t)(toupper(b) - 32)]);
|
||||
|
||||
// check unsupported characters
|
||||
if(code == MORSE_UNSUPORTED) {
|
||||
|
@ -83,16 +76,16 @@ size_t MorseClient::write(uint8_t b) {
|
|||
if (code & MORSE_DASH) {
|
||||
RADIOLIB_DEBUG_PRINT('-');
|
||||
transmitDirect(_base, _baseHz);
|
||||
delay(3 * _dotLength);
|
||||
Module::delay(3 * _dotLength);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINT('.');
|
||||
transmitDirect(_base, _baseHz);
|
||||
delay(_dotLength);
|
||||
Module::delay(_dotLength);
|
||||
}
|
||||
|
||||
// symbol space
|
||||
standby();
|
||||
delay(_dotLength);
|
||||
Module::delay(_dotLength);
|
||||
|
||||
// move onto the next bit
|
||||
code >>= 1;
|
||||
|
@ -100,7 +93,7 @@ size_t MorseClient::write(uint8_t b) {
|
|||
|
||||
// letter space
|
||||
standby();
|
||||
delay(2 * _dotLength);
|
||||
Module::delay(2 * _dotLength);
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
|
||||
return(1);
|
||||
|
@ -110,7 +103,7 @@ size_t MorseClient::print(__FlashStringHelper* fstr) {
|
|||
PGM_P p = reinterpret_cast<PGM_P>(fstr);
|
||||
size_t n = 0;
|
||||
while(true) {
|
||||
char c = pgm_read_byte(p++);
|
||||
char c = RADIOLIB_PROGMEM_READ_BYTE(p++);
|
||||
if(c == '\0') {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// - Morse code representation is saved LSb first, using additional bit as guard
|
||||
// - position in array corresponds ASCII code minus MORSE_ASCII_OFFSET
|
||||
// - ASCII characters marked MORSE_UNSUPORTED do not have ITU-R M.1677-1 equivalent
|
||||
static const uint8_t MorseTable[] PROGMEM = {
|
||||
static const uint8_t MorseTable[] RADIOLIB_PROGMEM = {
|
||||
0b00, // space
|
||||
0b110101, // ! (unsupported)
|
||||
0b1010010, // "
|
||||
|
|
|
@ -10,7 +10,7 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
|
|||
size_t len = 0;
|
||||
PGM_P p = reinterpret_cast<PGM_P>(fstr);
|
||||
while(true) {
|
||||
char c = pgm_read_byte(p++);
|
||||
char c = RADIOLIB_PROGMEM_READ_BYTE(p++);
|
||||
len++;
|
||||
if(c == '\0') {
|
||||
break;
|
||||
|
@ -27,7 +27,7 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
|
|||
// copy string from flash
|
||||
p = reinterpret_cast<PGM_P>(fstr);
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
str[i] = pgm_read_byte(p + i);
|
||||
str[i] = RADIOLIB_PROGMEM_READ_BYTE(p + i);
|
||||
}
|
||||
|
||||
// transmit string
|
||||
|
@ -143,3 +143,41 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
|
|||
float PhysicalLayer::getFreqStep() const {
|
||||
return(_freqStep);
|
||||
}
|
||||
|
||||
int32_t PhysicalLayer::random(int32_t max) {
|
||||
if(max == 0) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
// get random bytes from the radio
|
||||
uint8_t randBuff[4];
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
randBuff[i] = random();
|
||||
}
|
||||
|
||||
// create 32-bit TRNG number
|
||||
int32_t randNum = ((int32_t)randBuff[0] << 24) | ((int32_t)randBuff[1] << 16) | ((int32_t)randBuff[2] << 8) | ((int32_t)randBuff[3]);
|
||||
return(randNum % max);
|
||||
}
|
||||
|
||||
int32_t PhysicalLayer::random(int32_t min, int32_t max) {
|
||||
if(min >= max) {
|
||||
return(min);
|
||||
}
|
||||
|
||||
return(PhysicalLayer::random(max - min) + min);
|
||||
}
|
||||
|
||||
int16_t PhysicalLayer::startDirect() {
|
||||
// disable encodings
|
||||
int16_t state = setEncoding(RADIOLIB_ENCODING_NRZ);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable shaping
|
||||
state = setDataShaping(RADIOLIB_SHAPING_NONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set frequency deviation to the lowest possible value
|
||||
state = setFrequencyDeviation(-1);
|
||||
return(state);
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ class PhysicalLayer {
|
|||
float getFreqStep() const;
|
||||
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
\brief Query modem for the packet length of received payload. Must be implemented in module class.
|
||||
|
||||
\param update Update received packet length. Will return cached value when set to false.
|
||||
|
||||
|
@ -224,6 +224,40 @@ class PhysicalLayer {
|
|||
*/
|
||||
virtual size_t getPacketLength(bool update = true) = 0;
|
||||
|
||||
/*!
|
||||
\brief Get truly random number in range 0 - max.
|
||||
|
||||
\param max The maximum value of the random number (non-inclusive).
|
||||
|
||||
\returns Random number.
|
||||
*/
|
||||
int32_t random(int32_t max);
|
||||
|
||||
/*!
|
||||
\brief Get truly random number in range min - max.
|
||||
|
||||
\param min The minimum value of the random number (inclusive).
|
||||
|
||||
\param max The maximum value of the random number (non-inclusive).
|
||||
|
||||
\returns Random number.
|
||||
*/
|
||||
int32_t random(int32_t min, int32_t max);
|
||||
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise. Must be implemented in module class.
|
||||
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
virtual uint8_t random() = 0;
|
||||
|
||||
/*!
|
||||
\brief Configure module parameters for direct modes. Must be called prior to "ham" modes like RTTY or AX.25. Only available in FSK mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startDirect();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
|
|
@ -91,11 +91,11 @@ uint16_t ITA2String::getBits(char c) {
|
|||
// search ITA2 table
|
||||
uint16_t code = 0x0000;
|
||||
for(uint8_t i = 0; i < ITA2_LENGTH; i++) {
|
||||
if(pgm_read_byte(&ITA2Table[i][0]) == c) {
|
||||
if(RADIOLIB_PROGMEM_READ_BYTE(&ITA2Table[i][0]) == c) {
|
||||
// character is in letter shift
|
||||
code = (ITA2_LTRS << 5) | i;
|
||||
break;
|
||||
} else if(pgm_read_byte(&ITA2Table[i][1]) == c) {
|
||||
} else if(RADIOLIB_PROGMEM_READ_BYTE(&ITA2Table[i][1]) == c) {
|
||||
// character is in figures shift
|
||||
code = (ITA2_FIGS << 5) | i;
|
||||
break;
|
||||
|
@ -161,19 +161,11 @@ int16_t RTTYClient::begin(float base, uint32_t shift, uint16_t rate, uint8_t enc
|
|||
// calculate 24-bit frequency
|
||||
_base = (base * 1000000.0) / _phy->getFreqStep();
|
||||
|
||||
// set module frequency deviation to 0 if using FSK
|
||||
int16_t state = ERR_NONE;
|
||||
#if !defined(RADIOLIB_EXCLUDE_AFSK)
|
||||
if(_audio == nullptr) {
|
||||
state = _phy->setFrequencyDeviation(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
// configure for direct mode
|
||||
return(_phy->startDirect());
|
||||
}
|
||||
|
||||
void RTTYClient::idle() {
|
||||
transmitDirect();
|
||||
mark();
|
||||
}
|
||||
|
||||
|
@ -195,7 +187,8 @@ size_t RTTYClient::write(uint8_t* buff, size_t len) {
|
|||
size_t RTTYClient::write(uint8_t b) {
|
||||
space();
|
||||
|
||||
for(uint16_t mask = 0x01; mask <= (uint16_t)(0x01 << (_dataBits - 1)); mask <<= 1) {
|
||||
uint16_t maxDataMask = 0x01 << (_dataBits - 1);
|
||||
for(uint16_t mask = 0x01; mask <= maxDataMask; mask <<= 1) {
|
||||
if(b & mask) {
|
||||
mark();
|
||||
} else {
|
||||
|
@ -217,7 +210,7 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) {
|
|||
size_t len = 0;
|
||||
PGM_P p = reinterpret_cast<PGM_P>(fstr);
|
||||
while(true) {
|
||||
char c = pgm_read_byte(p++);
|
||||
char c = RADIOLIB_PROGMEM_READ_BYTE(p++);
|
||||
len++;
|
||||
if(c == '\0') {
|
||||
break;
|
||||
|
@ -234,7 +227,7 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) {
|
|||
// copy string from flash
|
||||
p = reinterpret_cast<PGM_P>(fstr);
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
str[i] = pgm_read_byte(p + i);
|
||||
str[i] = RADIOLIB_PROGMEM_READ_BYTE(p + i);
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
|
@ -407,18 +400,18 @@ size_t RTTYClient::println(double d, int digits) {
|
|||
}
|
||||
|
||||
void RTTYClient::mark() {
|
||||
uint32_t start = micros();
|
||||
uint32_t start = Module::micros();
|
||||
transmitDirect(_base + _shift, _baseHz + _shiftHz);
|
||||
while(micros() - start < _bitDuration) {
|
||||
yield();
|
||||
while(Module::micros() - start < _bitDuration) {
|
||||
Module::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void RTTYClient::space() {
|
||||
uint32_t start = micros();
|
||||
uint32_t start = Module::micros();
|
||||
transmitDirect(_base, _baseHz);
|
||||
while(micros() - start < _bitDuration) {
|
||||
yield();
|
||||
while(Module::micros() - start < _bitDuration) {
|
||||
Module::yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
// ITA2 character table: - position in array corresponds to 5-bit ITA2 code
|
||||
// - characters to the left are in letters shift, characters to the right in figures shift
|
||||
// - characters marked 0x7F do not have ASCII equivalent
|
||||
static const char ITA2Table[ITA2_LENGTH][2] PROGMEM = {{'\0', '\0'}, {'E', '3'}, {'\n', '\n'}, {'A', '-'}, {' ', ' '}, {'S', '\''}, {'I', '8'}, {'U', '7'},
|
||||
{'\r', '\r'}, {'D', 0x05}, {'R', '4'}, {'J', '\a'}, {'N', ','}, {'F', '!'}, {'C', ':'}, {'K', '('},
|
||||
{'T', '5'}, {'Z', '+'}, {'L', ')'}, {'W', '2'}, {'H', 0x7F}, {'Y', '6'}, {'P', '0'}, {'Q', '1'},
|
||||
{'O', '9'}, {'B', '?'}, {'G', '&'}, {0x7F, 0x7F}, {'M', '.'}, {'X', '/'}, {'V', ';'}, {0x7F, 0x7F}};
|
||||
static const char ITA2Table[ITA2_LENGTH][2] RADIOLIB_PROGMEM = {{'\0', '\0'}, {'E', '3'}, {'\n', '\n'}, {'A', '-'}, {' ', ' '}, {'S', '\''}, {'I', '8'}, {'U', '7'},
|
||||
{'\r', '\r'}, {'D', 0x05}, {'R', '4'}, {'J', '\a'}, {'N', ','}, {'F', '!'}, {'C', ':'}, {'K', '('},
|
||||
{'T', '5'}, {'Z', '+'}, {'L', ')'}, {'W', '2'}, {'H', 0x7F}, {'Y', '6'}, {'P', '0'}, {'Q', '1'},
|
||||
{'O', '9'}, {'B', '?'}, {'G', '&'}, {0x7F, 0x7F}, {'M', '.'}, {'X', '/'}, {'V', ';'}, {0x7F, 0x7F}};
|
||||
|
||||
/*!
|
||||
\class ITA2String
|
||||
|
|
|
@ -192,20 +192,13 @@ int16_t SSTVClient::begin(float base, const SSTVMode_t& mode, float correction)
|
|||
// calculate 24-bit frequency
|
||||
_base = (base * 1000000.0) / _phy->getFreqStep();
|
||||
|
||||
// set module frequency deviation to 0 if using FSK
|
||||
int16_t state = ERR_NONE;
|
||||
#if !defined(RADIOLIB_EXCLUDE_AFSK)
|
||||
if(_audio == nullptr) {
|
||||
state = _phy->setFrequencyDeviation(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
// configure for direct mode
|
||||
return(_phy->startDirect());
|
||||
}
|
||||
|
||||
void SSTVClient::idle() {
|
||||
_phy->transmitDirect();
|
||||
tone(SSTV_TONE_LEADER);
|
||||
this->tone(SSTV_TONE_LEADER);
|
||||
}
|
||||
|
||||
void SSTVClient::sendHeader() {
|
||||
|
@ -214,35 +207,35 @@ void SSTVClient::sendHeader() {
|
|||
_phy->transmitDirect();
|
||||
|
||||
// send the first part of header (leader-break-leader)
|
||||
tone(SSTV_TONE_LEADER, SSTV_HEADER_LEADER_LENGTH);
|
||||
tone(SSTV_TONE_BREAK, SSTV_HEADER_BREAK_LENGTH);
|
||||
tone(SSTV_TONE_LEADER, SSTV_HEADER_LEADER_LENGTH);
|
||||
this->tone(SSTV_TONE_LEADER, SSTV_HEADER_LEADER_LENGTH);
|
||||
this->tone(SSTV_TONE_BREAK, SSTV_HEADER_BREAK_LENGTH);
|
||||
this->tone(SSTV_TONE_LEADER, SSTV_HEADER_LEADER_LENGTH);
|
||||
|
||||
// VIS start bit
|
||||
tone(SSTV_TONE_BREAK, SSTV_HEADER_BIT_LENGTH);
|
||||
this->tone(SSTV_TONE_BREAK, SSTV_HEADER_BIT_LENGTH);
|
||||
|
||||
// VIS code
|
||||
uint8_t parityCount = 0;
|
||||
for(uint8_t mask = 0x01; mask < 0x80; mask <<= 1) {
|
||||
if(_mode.visCode & mask) {
|
||||
tone(SSTV_TONE_VIS_1, SSTV_HEADER_BIT_LENGTH);
|
||||
this->tone(SSTV_TONE_VIS_1, SSTV_HEADER_BIT_LENGTH);
|
||||
parityCount++;
|
||||
} else {
|
||||
tone(SSTV_TONE_VIS_0, SSTV_HEADER_BIT_LENGTH);
|
||||
this->tone(SSTV_TONE_VIS_0, SSTV_HEADER_BIT_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
// VIS parity
|
||||
if(parityCount % 2 == 0) {
|
||||
// even parity
|
||||
tone(SSTV_TONE_VIS_0, SSTV_HEADER_BIT_LENGTH);
|
||||
this->tone(SSTV_TONE_VIS_0, SSTV_HEADER_BIT_LENGTH);
|
||||
} else {
|
||||
// odd parity
|
||||
tone(SSTV_TONE_VIS_1, SSTV_HEADER_BIT_LENGTH);
|
||||
this->tone(SSTV_TONE_VIS_1, SSTV_HEADER_BIT_LENGTH);
|
||||
}
|
||||
|
||||
// VIS stop bit
|
||||
tone(SSTV_TONE_BREAK, SSTV_HEADER_BIT_LENGTH);
|
||||
this->tone(SSTV_TONE_BREAK, SSTV_HEADER_BIT_LENGTH);
|
||||
}
|
||||
|
||||
void SSTVClient::sendLine(uint32_t* imgLine) {
|
||||
|
@ -251,14 +244,14 @@ void SSTVClient::sendLine(uint32_t* imgLine) {
|
|||
_firstLine = false;
|
||||
|
||||
// send start sync tone
|
||||
tone(SSTV_TONE_BREAK, 9000);
|
||||
this->tone(SSTV_TONE_BREAK, 9000);
|
||||
}
|
||||
|
||||
// send all tones in sequence
|
||||
for(uint8_t i = 0; i < _mode.numTones; i++) {
|
||||
if((_mode.tones[i].type == tone_t::GENERIC) && (_mode.tones[i].len > 0)) {
|
||||
// sync/porch tones
|
||||
tone(_mode.tones[i].freq, _mode.tones[i].len);
|
||||
this->tone(_mode.tones[i].freq, _mode.tones[i].len);
|
||||
} else {
|
||||
// scan lines
|
||||
for(uint16_t j = 0; j < _mode.width; j++) {
|
||||
|
@ -278,7 +271,7 @@ void SSTVClient::sendLine(uint32_t* imgLine) {
|
|||
case(tone_t::GENERIC):
|
||||
break;
|
||||
}
|
||||
tone(SSTV_TONE_BRIGHTNESS_MIN + ((float)color * 3.1372549), _mode.scanPixelLen);
|
||||
this->tone(SSTV_TONE_BRIGHTNESS_MIN + ((float)color * 3.1372549), _mode.scanPixelLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +282,7 @@ uint16_t SSTVClient::getPictureHeight() const {
|
|||
}
|
||||
|
||||
void SSTVClient::tone(float freq, uint32_t len) {
|
||||
uint32_t start = micros();
|
||||
uint32_t start = Module::micros();
|
||||
#if !defined(RADIOLIB_EXCLUDE_AFSK)
|
||||
if(_audio != nullptr) {
|
||||
_audio->tone(freq, false);
|
||||
|
@ -299,8 +292,8 @@ void SSTVClient::tone(float freq, uint32_t len) {
|
|||
#else
|
||||
_phy->transmitDirect(_base + (freq / _phy->getFreqStep()));
|
||||
#endif
|
||||
while(micros() - start < len) {
|
||||
yield();
|
||||
while(Module::micros() - start < len) {
|
||||
Module::yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue