Merge branch 'master' into development
This commit is contained in:
commit
8a791d269e
88 changed files with 3064 additions and 1847 deletions
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -11,7 +11,7 @@ assignees: ''
|
|||
Before submitting new issue, please check the [Wiki](https://github.com/jgromes/RadioLib/wiki) and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
A clear and concise description of what the bug is. When applicable, please include debug mode output: uncomment [debug macro definitions in TypeDef.h](https://github.com/jgromes/RadioLib/blob/master/src/TypeDef.h#L36) and post the output.
|
||||
|
||||
**To Reproduce**
|
||||
Minimal Arduino sketch to reproduce the behavior. Please user Markdown to style the code to make it readable (see [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)).
|
||||
|
|
|
@ -7,6 +7,7 @@ env:
|
|||
- BOARD="esp32:esp32:esp32"
|
||||
- BOARD="STM32:stm32:GenF3:pnum=BLACKPILL_F303CC"
|
||||
- BOARD="esp8266:esp8266:generic:xtal=80,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=512K"
|
||||
# - BOARD="SparkFun:apollo3:amap3redboard"
|
||||
- BOARD="arduino:samd:arduino_zero_native"
|
||||
- BOARD="arduino:sam:arduino_due_x"
|
||||
- BOARD="arduino:avr:uno"
|
||||
|
@ -29,7 +30,7 @@ before_install:
|
|||
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# install 3rd party boards
|
||||
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json" --save-prefs 2>&1
|
||||
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json,https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json" --save-prefs 2>&1
|
||||
- if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then
|
||||
arduino --install-boards esp8266:esp8266;
|
||||
export SKIP_PAT='(HTTP|MQTT).*ino';
|
||||
|
@ -41,6 +42,8 @@ before_install:
|
|||
arduino --install-boards arduino:samd;
|
||||
elif [[ "$BOARD" =~ "arduino:sam:" ]]; then
|
||||
arduino --install-boards arduino:sam;
|
||||
elif [[ "$BOARD" =~ "SparkFun:apollo3:" ]]; then
|
||||
arduino --install-boards SparkFun:apollo3;
|
||||
fi
|
||||
|
||||
# create directory to save the library and create symbolic link
|
||||
|
|
|
@ -15,8 +15,6 @@ To report bugs or suggest new features, use the provided issue templates. Use th
|
|||
Issues with generic titles (e.g. "not working", "lora", etc.) will be **CLOSED** until the title is fixed, since the title is supposed to categorize the issue. The same applies for issues with very little information and extensive grammatical or formatting errors that make it difficult to find out what is the actual issue.
|
||||
4. **Issues deserve some attention too.**
|
||||
Issues that are left for 2 weeks without response by the original author when asked for further information will be closed due to inactivity. This is to keep track of important issues, the author is encouraged to reopen the issue at a later date.
|
||||
5. **LoRaLib is a separate project.**
|
||||
RadioLib was created as an extension of LoRaLib for radios other than SX127x. However, LoRaLib project is still active and RadioLib is reusing its code. **Because of that, please open issues/PRs related to SX127x in [LoRaLib](https://github.com/jgromes/LoRaLib)**.
|
||||
|
||||
## Code style guidelines
|
||||
|
||||
|
|
22
README.md
22
README.md
|
@ -27,14 +27,21 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
* __HTTP__ for modules: ESP8266
|
||||
* __RTTY__ for modules: SX127x, RFM9x, SX126x, RF69, SX1231, CC1101 and nRF24L01
|
||||
* __Morse Code__ for modules: SX127x, RFM9x, SX126x, RF69, SX1231, CC1101 and nRF24L01
|
||||
* __AX.25__ for modules: SX127x, RFM9x, SX126x, RF69, SX1231 and CC1101
|
||||
|
||||
### Supported platforms:
|
||||
* __Arduino AVR boards__ - tested on Uno, Mega and Leonardo
|
||||
* __ESP8266 boards__ - NodeMCU, Wemos D1, etc.
|
||||
* __ESP32 boards__ - tested on ESP-WROOM-32
|
||||
* __STM32 boards__ - tested on Nucleo L452RE-P
|
||||
* __SAMD boards__ - Arduino Zero
|
||||
* __SAM boards__ - Arduino Due
|
||||
* __AVR__ - tested with hardware on Uno, Mega and Leonardo
|
||||
* __ESP8266__ - tested with hardware on NodeMCU and Wemos D1
|
||||
* __ESP32__ - tested with hardware on ESP-WROOM-32
|
||||
* __STM32__ - tested with hardware on Nucleo L452RE-P
|
||||
* __SAMD__ - Arduino Zero, Arduino MKR boards, M0 Pro etc.
|
||||
* __SAM__ - Arduino Due
|
||||
* __nRF52__ - Adafruit Bluefruit Feather etc.
|
||||
* _Intel Curie_ - Arduino 101
|
||||
* _megaAVR_ - Arduino Uno WiFi Rev.2 etc.
|
||||
* _Apollo3_ - SparkFun Artemis Redboard 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 platoforms in __bold__ on each git push. Platforms in _italic_ are not tested on each push, but do compile and should be working.
|
||||
|
||||
### In development:
|
||||
* __SIM800C__ GSM module
|
||||
|
@ -46,5 +53,8 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
### Where should I start?
|
||||
First of all, take a look at the [examples](https://github.com/jgromes/RadioLib/tree/master/examples) and the [Wiki](https://github.com/jgromes/RadioLib/wiki) - especially the [Basics](https://github.com/jgromes/RadioLib/wiki/Basics) page. There's a lot of useful information over there. Also, you should check out [RadioShield](https://github.com/jgromes/RadioShield) - open source Arduino shield that will allow you to easily connect any two wireless modules supported by RadioLib!
|
||||
|
||||
### 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.
|
||||
|
||||
### 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.
|
||||
|
|
167
examples/AX25/AX25_Frames/AX25_Frames.ino
Normal file
167
examples/AX25/AX25_Frames/AX25_Frames.ino
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
RadioLib AX.25 Frame Example
|
||||
|
||||
This example shows how to send various
|
||||
AX.25 frames using SX1278's FSK modem.
|
||||
|
||||
Other modules that can be used for AX.25:
|
||||
- SX127x/RFM9x
|
||||
- RF69
|
||||
- SX1231
|
||||
- CC1101
|
||||
- SX126x
|
||||
- nRF24
|
||||
|
||||
Using raw AX.25 frames requires some
|
||||
knowledge of the protocol, refer to
|
||||
AX25_Transmit for basic operation.
|
||||
Frames shown in this example are not
|
||||
exhaustive; all possible AX.25 frames
|
||||
should be supported.
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 fsk = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//SX1278 fsk = RadioShield.ModuleA;
|
||||
|
||||
// create AX.25 client instance using the FSK module
|
||||
AX25Client ax25(&fsk);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1278
|
||||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 1.2 kbps (1200 baud AFSK AX.25)
|
||||
// frequency deviation: 0.5 kHz (1200 baud AFSK AX.25)
|
||||
int state = fsk.beginFSK(434.0, 1.2, 0.5);
|
||||
|
||||
// when using one of the non-LoRa modules for AX.25
|
||||
// (RF69, CC1101, etc.), use the basic begin() method
|
||||
// int state = fsk.begin();
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// initialize AX.25 client
|
||||
Serial.print(F("[AX.25] Initializing ... "));
|
||||
// source station callsign: "N7LEM"
|
||||
// source station SSID: 0
|
||||
// preamble length: 8 bytes
|
||||
state = ax25.begin("N7LEM");
|
||||
if(state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// create AX.25 Unnumbered Information frame
|
||||
// destination station callsign: "NJ7P"
|
||||
// destination station SSID: 0
|
||||
// source station callsign: "N7LEM"
|
||||
// source station SSID: 0
|
||||
// control field: UI, P/F not used, unnumbered frame
|
||||
// protocol identifier: no layer 3 protocol implemented
|
||||
// information field: "Hello World!"
|
||||
AX25Frame frameUI("NJ7P", 0, "N7LEM", 0, AX25_CONTROL_U_UNNUMBERED_INFORMATION |
|
||||
AX25_CONTROL_POLL_FINAL_DISABLED | AX25_CONTROL_UNNUMBERED_FRAME,
|
||||
AX25_PID_NO_LAYER_3, "Hello World (unnumbered)!");
|
||||
|
||||
// send the frame
|
||||
Serial.print(F("[AX.25] Sending UI frame ... "));
|
||||
int state = ax25.sendFrame(&frameUI);
|
||||
if (state == ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
} else {
|
||||
// some error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
|
||||
// create AX.25 Receive Ready frame
|
||||
// destination station callsign: "NJ7P"
|
||||
// destination station SSID: 0
|
||||
// source station callsign: "N7LEM"
|
||||
// source station SSID: 0
|
||||
// control field: RR, P/F not used, supervisory frame
|
||||
AX25Frame frameRR("NJ7P", 0, "N7LEM", 0, AX25_CONTROL_S_RECEIVE_READY |
|
||||
AX25_CONTROL_POLL_FINAL_DISABLED | AX25_CONTROL_SUPERVISORY_FRAME);
|
||||
|
||||
// set receive sequence number (0 - 7)
|
||||
frameRR.setRecvSequence(0);
|
||||
|
||||
// send the frame
|
||||
Serial.print(F("[AX.25] Sending RR frame ... "));
|
||||
state = ax25.sendFrame(&frameRR);
|
||||
if (state == ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
} else {
|
||||
// some error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
|
||||
// create AX.25 Information frame
|
||||
// destination station callsign: "NJ7P"
|
||||
// destination station SSID: 0
|
||||
// source station callsign: "N7LEM"
|
||||
// source station SSID: 0
|
||||
// control field: P/F not used, information frame
|
||||
// protocol identifier: no layer 3 protocol implemented
|
||||
// information field: "Hello World (numbered)!"
|
||||
AX25Frame frameI("NJ7P", 0, "N7LEM", 0, AX25_CONTROL_POLL_FINAL_DISABLED |
|
||||
AX25_CONTROL_INFORMATION_FRAME, AX25_PID_NO_LAYER_3,
|
||||
"Hello World (numbered)!");
|
||||
|
||||
// set receive sequence number (0 - 7)
|
||||
frameI.setRecvSequence(0);
|
||||
|
||||
// set send sequence number (0 - 7)
|
||||
frameI.setSendSequence(0);
|
||||
|
||||
// send the frame
|
||||
Serial.print(F("[AX.25] Sending I frame ... "));
|
||||
state = ax25.sendFrame(&frameI);
|
||||
if (state == ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
} else {
|
||||
// some error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
88
examples/AX25/AX25_Transmit/AX25_Transmit.ino
Normal file
88
examples/AX25/AX25_Transmit/AX25_Transmit.ino
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
RadioLib AX.25 Transmit Example
|
||||
|
||||
This example sends AX.25 messages using
|
||||
SX1278's FSK modem.
|
||||
|
||||
Other modules that can be used for AX.25:
|
||||
- SX127x/RFM9x
|
||||
- RF69
|
||||
- SX1231
|
||||
- CC1101
|
||||
- SX126x
|
||||
- nRF24
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 fsk = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//SX1278 fsk = RadioShield.ModuleA;
|
||||
|
||||
// create AX.25 client instance using the FSK module
|
||||
AX25Client ax25(&fsk);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1278
|
||||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 1.2 kbps (1200 baud AFSK AX.25)
|
||||
// frequency deviation: 0.5 kHz (1200 baud AFSK AX.25)
|
||||
int state = fsk.beginFSK(434.0, 1.2, 0.5);
|
||||
|
||||
// when using one of the non-LoRa modules for AX.25
|
||||
// (RF69, CC1101, etc.), use the basic begin() method
|
||||
// int state = fsk.begin();
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// initialize AX.25 client
|
||||
Serial.print(F("[AX.25] Initializing ... "));
|
||||
// source station callsign: "N7LEM"
|
||||
// source station SSID: 0
|
||||
// preamble length: 8 bytes
|
||||
state = ax25.begin("N7LEM");
|
||||
if(state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// send AX.25 unnumbered infomration frame
|
||||
Serial.print(F("[AX.25] Sending UI frame ... "));
|
||||
// destination station callsign: "NJ7P"
|
||||
// destination station SSID: 0
|
||||
int state = ax25.transmit("Hello World!", "NJ7P");
|
||||
if (state == ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
} else {
|
||||
// some error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
|
@ -17,10 +17,11 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// CC1101 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// GDO0 pin: 2
|
||||
// GDO2 pin: 3
|
||||
CC1101 cc = new Module(10, 2, 3);
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 3 (optional)
|
||||
CC1101 cc = new Module(10, 2, NC, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
@ -33,8 +34,8 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 4.8 kbps
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// frequency deviation: 48.0 kHz
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// sync word: 0xD391
|
||||
int state = cc.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// CC1101 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// GDO0 pin: 2
|
||||
// GDO2 pin: 3
|
||||
CC1101 cc = new Module(10, 2, 3);
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 3 (optional)
|
||||
CC1101 cc = new Module(10, 2, NC, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
@ -31,8 +32,8 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 4.8 kbps
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// frequency deviation: 48.0 kHz
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// sync word: 0xD391
|
||||
int state = cc.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// CC1101 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// GDO0 pin: 2
|
||||
// GDO2 pin: 3
|
||||
CC1101 cc = new Module(10, 2, 3);
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 3 (optional)
|
||||
CC1101 cc = new Module(10, 2, NC, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
@ -36,8 +37,8 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 4.8 kbps
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// frequency deviation: 48.0 kHz
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// sync word: 0xD391
|
||||
int state = cc.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
@ -110,7 +111,7 @@ void loop() {
|
|||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = cc.receive(byteArr, 8);
|
||||
int state = cc.readData(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -19,14 +19,22 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// CC1101 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// GDO0 pin: 2
|
||||
// GDO2 pin: 3
|
||||
CC1101 cc1 = new Module(10, 2, 3);
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 3 (optional)
|
||||
CC1101 cc1 = new Module(10, 2, NC, 3);
|
||||
|
||||
// second CC1101 has different connections:
|
||||
// CS pin: 9
|
||||
// GDO0 pin: 4
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 5 (optional)
|
||||
CC1101 cc2 = new Module(9, 4, NC, 53);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
CC1101 cc2 = RadioShield.ModuleB;
|
||||
//CC1101 cc3 = RadioShield.ModuleB;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
@ -35,8 +43,8 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 4.8 kbps
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// frequency deviation: 48.0 kHz
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// sync word: 0xD391
|
||||
int state = cc1.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
@ -51,10 +59,10 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 32.0 kbps
|
||||
// Rx bandwidth: 250.0 kHz
|
||||
// frequency deviation: 60.0 kHz
|
||||
// Rx bandwidth: 250.0 kHz
|
||||
// sync word: 0xD391
|
||||
state = cc2.begin(434.0, 32.0, 250.0, 60.0);
|
||||
state = cc2.begin(434.0, 32.0, 60.0, 250.0);
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// CC1101 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// GDO0 pin: 2
|
||||
// GDO2 pin: 3
|
||||
CC1101 cc = new Module(10, 2, 3);
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 3 (optional)
|
||||
CC1101 cc = new Module(10, 2, NC, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
@ -31,8 +32,8 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 4.8 kbps
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// frequency deviation: 48.0 kHz
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// sync word: 0xD391
|
||||
int state = cc.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// CC1101 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// GDO0 pin: 2
|
||||
// GDO2 pin: 3
|
||||
CC1101 cc = new Module(10, 2, 3);
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 3 (optional)
|
||||
CC1101 cc = new Module(10, 2, NC, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
@ -31,8 +32,8 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 4.8 kbps
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// frequency deviation: 48.0 kHz
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// sync word: 0xD391
|
||||
int state = cc.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// CC1101 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// GDO0 pin: 2
|
||||
// GDO2 pin: 3
|
||||
CC1101 cc = new Module(10, 2, 3);
|
||||
// RST pin: unused
|
||||
// GDO2 pin: 3 (optional)
|
||||
CC1101 cc = new Module(10, 2, NC, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
@ -35,8 +36,8 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 4.8 kbps
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// frequency deviation: 48.0 kHz
|
||||
// Rx bandwidth: 325.0 kHz
|
||||
// sync word: 0xD391
|
||||
int state = cc.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
@ -62,7 +63,7 @@ void setup() {
|
|||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56,
|
||||
0x78, 0xAB, 0xCD, 0xEF};
|
||||
state = cc.transmit(byteArr, 8);
|
||||
state = cc.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -124,7 +125,7 @@ void loop() {
|
|||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56,
|
||||
0x78, 0xAB, 0xCD, 0xEF};
|
||||
int state = cc.transmit(byteArr, 8);
|
||||
int state = cc.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 fsk = new Module(10, 2, 3);
|
||||
SX1278 fsk = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
@ -104,7 +105,7 @@ void loop() {
|
|||
|
||||
// floating point number
|
||||
// NOTE: When using println(), the transmission will be
|
||||
// terminated with cross signal (.-.-.).
|
||||
// terminated with end-of-work signal (...-.-).
|
||||
float f = -3.1415;
|
||||
morse.println(f, 3);
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -33,8 +33,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -29,8 +29,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -31,8 +31,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -29,8 +29,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
@ -104,7 +104,7 @@ void loop() {
|
|||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = lora.receive(byteArr, 8);
|
||||
int state = lora.readData(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -19,14 +19,20 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf1 = new Module(10, 2, 3);
|
||||
|
||||
// second CC1101 has different connections:
|
||||
// CS pin: 9
|
||||
// DIO0 pin: 4
|
||||
// RESET pin: 5
|
||||
RF69 rf2 = new Module(9, 4, 5);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
RF69 rf2 = RadioShield.ModuleB;
|
||||
//RF69 rf3 = RadioShield.ModuleB;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
@ -35,8 +41,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf1.begin();
|
||||
|
@ -52,11 +58,11 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 868.0 MHz
|
||||
// bit rate: 300.0 kbps
|
||||
// Rx bandwidth: 250.0 kHz
|
||||
// frequency deviation: 60.0 kHz
|
||||
// Rx bandwidth: 250.0 kHz
|
||||
// output power: 17 dBm
|
||||
// sync word: 0x2D01
|
||||
state = rf2.begin(868.0, 300.0, 250.0, 60.0, 17);
|
||||
state = rf2.begin(868.0, 300.0, 60.0, 250.0, 17);
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -31,8 +31,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -29,8 +29,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -31,8 +31,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// RF69 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
RF69 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -35,8 +35,8 @@ void setup() {
|
|||
Serial.print(F("[RF69] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bit rate: 48.0 kbps
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// frequency deviation: 50.0 kHz
|
||||
// Rx bandwidth: 125.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
int state = rf.begin();
|
||||
|
@ -63,7 +63,7 @@ void setup() {
|
|||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56,
|
||||
0x78, 0xAB, 0xCD, 0xEF};
|
||||
state = rf.transmit(byteArr, 8);
|
||||
state = rf.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -121,11 +121,11 @@ void loop() {
|
|||
// 256 characters long
|
||||
transmissionState = rf.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
// you can also transmit byte array up to 64 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56,
|
||||
0x78, 0xAB, 0xCD, 0xEF};
|
||||
int state = rf.transmit(byteArr, 8);
|
||||
int state = rf.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
// we're ready to send more packets,
|
||||
|
|
|
@ -22,8 +22,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 fsk = new Module(10, 2, 3);
|
||||
SX1278 fsk = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// SX1231 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
SX1231 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
@ -35,7 +35,7 @@ void setup() {
|
|||
// frequency deviation: 50.0 kHz
|
||||
// output power: 13 dBm
|
||||
// sync word: 0x2D01
|
||||
byte state = rf.begin();
|
||||
int state = rf.begin();
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// SX1231 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// DIO1 pin: 3
|
||||
// RESET pin: 3
|
||||
SX1231 rf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
RadioLib SX126x Channel Activity Detection Example
|
||||
|
||||
This example uses SX1262 to scan the current LoRa
|
||||
This example uses SX1262 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, SX126x can detect any part
|
||||
Unlike SX127x CAD, SX126x can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
Other modules from SX126x family can also be used.
|
||||
|
@ -18,7 +18,7 @@
|
|||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 lora = new Module(10, 2, 3, 9);
|
||||
|
||||
|
@ -35,10 +35,12 @@ void setup() {
|
|||
// bandwidth: 125.0 kHz
|
||||
// spreading factor: 9
|
||||
// coding rate: 7
|
||||
// sync word: 0x1424 (private network)
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 14 dBm
|
||||
// current limit: 60 mA
|
||||
// preamble length: 8 symbols
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// CRC: enabled
|
||||
int state = lora.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 fsk = new Module(10, 2, 3, 9);
|
||||
|
||||
|
@ -40,6 +40,8 @@ void setup() {
|
|||
// current limit: 60.0 mA
|
||||
// preamble length: 16 bits
|
||||
// data shaping: Gaussian, BT = 0.5
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// sync word: 0x2D 0x01
|
||||
// CRC: enabled, CRC16 (CCIT)
|
||||
int state = fsk.beginFSK();
|
||||
|
@ -73,7 +75,7 @@ void setup() {
|
|||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
|
||||
// FSK modem on SX126x can handle the sync word setting in bits, not just
|
||||
// whole bytes. The value used is left-justified.
|
||||
// This makes same result as fsk.setSyncWord(syncWord, 8):
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 lora = new Module(10, 2, 3, 9);
|
||||
|
||||
|
@ -40,10 +40,12 @@ void setup() {
|
|||
// bandwidth: 125.0 kHz
|
||||
// spreading factor: 9
|
||||
// coding rate: 7
|
||||
// sync word: 0x1424 (private network)
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 14 dBm
|
||||
// current limit: 60 mA
|
||||
// preamble length: 8 symbols
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// CRC: enabled
|
||||
int state = lora.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
@ -53,28 +55,6 @@ void setup() {
|
|||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// NOTE: Some SX126x modules use TCXO
|
||||
// (Temprature-Compensated Crystal Oscillator).
|
||||
// To be able to use these modules, TCXO
|
||||
// control must be enabled by calling
|
||||
// setTCXO() and specifying the reference
|
||||
// voltage.
|
||||
|
||||
/*
|
||||
Serial.print(F("[SX1262] Setting TCXO reference ... "));
|
||||
// enable TCXO
|
||||
// reference voltage: 1.6 V
|
||||
// timeout: 5000 us
|
||||
state = lora.setTCXO(1.6);
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 lora = new Module(10, 2, 3, 9);
|
||||
|
||||
|
@ -41,10 +41,12 @@ void setup() {
|
|||
// bandwidth: 125.0 kHz
|
||||
// spreading factor: 9
|
||||
// coding rate: 7
|
||||
// sync word: 0x1424 (private network)
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 14 dBm
|
||||
// current limit: 60 mA
|
||||
// preamble length: 8 symbols
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// CRC: enabled
|
||||
int state = lora.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
@ -118,7 +120,7 @@ void loop() {
|
|||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = lora.receive(byteArr, 8);
|
||||
int state = lora.readData(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -27,13 +27,20 @@
|
|||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 loraSX1262 = new Module(10, 2, 3, 9);
|
||||
|
||||
// SX12628 has different connections:
|
||||
// NSS pin: 8
|
||||
// DIO1 pin: 4
|
||||
// NRST pin: 5
|
||||
// BUSY pin: 6
|
||||
SX1268 loraSX1268 = new Module(8, 4, 5, 6);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
SX1268 loraSX1268 = RadioShield.ModuleB;
|
||||
//SX1261 loraSX1261 = RadioShield.ModuleB;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
@ -44,10 +51,12 @@ void setup() {
|
|||
// bandwidth: 125.0 kHz
|
||||
// spreading factor: 9
|
||||
// coding rate: 7
|
||||
// sync word: 0x1424 (private network)
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 14 dBm
|
||||
// current limit: 60 mA
|
||||
// preamble length: 8 symbols
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// CRC: enabled
|
||||
int state = loraSX1262.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
@ -67,7 +76,7 @@ void setup() {
|
|||
// bandwidth: 500.0 kHz
|
||||
// spreading factor: 6
|
||||
// coding rate: 5
|
||||
// sync word: 0x3444 (public network)
|
||||
// sync word: 0x34 (public network)
|
||||
// output power: 2 dBm
|
||||
// current limit: 50 mA
|
||||
// preamble length: 20 symbols
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 lora = new Module(10, 2, 3, 9);
|
||||
|
||||
|
@ -36,10 +36,12 @@ void setup() {
|
|||
// bandwidth: 125.0 kHz
|
||||
// spreading factor: 9
|
||||
// coding rate: 7
|
||||
// sync word: 0x1424 (private network)
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 14 dBm
|
||||
// current limit: 60 mA
|
||||
// preamble length: 8 symbols
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// CRC: enabled
|
||||
int state = lora.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
@ -49,29 +51,6 @@ void setup() {
|
|||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// NOTE: Some SX126x modules use TCXO
|
||||
// (Temprature-Compensated Crystal Oscillator).
|
||||
// To be able to use these modules, TCXO
|
||||
// control must be enabled by calling
|
||||
// setTCXO() and specifying the reference
|
||||
// voltage.
|
||||
|
||||
/*
|
||||
Serial.print(F("[SX1262] Setting TCXO reference ... "));
|
||||
// enable TCXO
|
||||
// reference voltage: 1.6 V
|
||||
// timeout: 5000 us
|
||||
state = lora.setTCXO(1.6);
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 lora = new Module(10, 2, 3, 9);
|
||||
|
||||
|
@ -36,10 +36,12 @@ void setup() {
|
|||
// bandwidth: 125.0 kHz
|
||||
// spreading factor: 9
|
||||
// coding rate: 7
|
||||
// sync word: 0x1424 (private network)
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 14 dBm
|
||||
// current limit: 60 mA
|
||||
// preamble length: 8 symbols
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// CRC: enabled
|
||||
int state = lora.begin();
|
||||
if (state == ERR_NONE) {
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 lora = new Module(10, 2, 3);
|
||||
SX1278 lora = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 fsk = new Module(10, 2, 3);
|
||||
SX1278 fsk = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -23,8 +23,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 lora = new Module(10, 2, 3);
|
||||
SX1278 lora = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -24,8 +24,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 lora = new Module(10, 2, 3);
|
||||
SX1278 lora = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -22,14 +22,21 @@
|
|||
|
||||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// DIO2 pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1278 loraSX1278 = new Module(10, 2, 3, 9);
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 loraSX1278 = new Module(10, 2, 9, 3);
|
||||
|
||||
// SX1272 has different connections:
|
||||
// NSS pin: 9
|
||||
// DIO0 pin: 4
|
||||
// RESET pin: 5
|
||||
// DIO1 pin: 6
|
||||
SX1272 loraSX1272 = new Module(9, 4, 5, 6);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
SX1272 loraSX1272 = RadioShield.ModuleB;
|
||||
//SX1276 loraSX1276 = RadioShield.ModuleB;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 lora = new Module(10, 2, 3);
|
||||
SX1278 lora = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -20,8 +20,9 @@
|
|||
// SX1278 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO0 pin: 2
|
||||
// RESET pin: 9
|
||||
// DIO1 pin: 3
|
||||
SX1278 lora = new Module(10, 2, 3);
|
||||
SX1278 lora = new Module(10, 2, 9, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// TX pin: 9
|
||||
// RX pin: 8
|
||||
// RESET pin: 3
|
||||
XBee bee = new Module(9, 8);
|
||||
XBee bee = new Module(9, 8, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// TX pin: 9
|
||||
// RX pin: 8
|
||||
// RESET pin: 3
|
||||
XBee bee = new Module(9, 8);
|
||||
XBee bee = new Module(9, 8, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
// TX pin: 9
|
||||
// RX pin: 8
|
||||
// RESET pin: 3
|
||||
XBeeSerial bee = new Module(9, 8);
|
||||
XBeeSerial bee = new Module(9, 8, 3);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// nRF24 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CE pin: 2
|
||||
// IRQ pin: 3
|
||||
// CS pin: 10
|
||||
// IRQ pin: 2
|
||||
// CE pin: 3
|
||||
nRF24 nrf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// nRF24 has the following connections:
|
||||
// NSS pin: 10
|
||||
// CE pin: 2
|
||||
// IRQ pin: 3
|
||||
// CS pin: 10
|
||||
// IRQ pin: 2
|
||||
// CE pin: 3
|
||||
nRF24 nrf = new Module(10, 2, 3);
|
||||
|
||||
// or using RadioShield
|
||||
|
|
32
keywords.txt
32
keywords.txt
|
@ -39,6 +39,8 @@ HTTPClient KEYWORD1
|
|||
RTTYClient KEYWORD1
|
||||
MorseClient KEYWORD1
|
||||
PagerClient KEYWORD1
|
||||
AX25Client KEYWORD1
|
||||
AX25Frame KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
|
@ -62,6 +64,8 @@ receiveDirect KEYWORD2
|
|||
packetMode KEYWORD2
|
||||
setDio0Action KEYWORD2
|
||||
setDio1Action KEYWORD2
|
||||
clearDio0Action KEYWORD2
|
||||
clearDio1Action KEYWORD2
|
||||
startTransmit KEYWORD2
|
||||
startReceive KEYWORD2
|
||||
readData KEYWORD2
|
||||
|
@ -107,15 +111,23 @@ setAmbientTemperature KEYWORD2
|
|||
# CC1101-specific
|
||||
getLQI KEYWORD2
|
||||
setGdo0Action KEYWORD2
|
||||
setGdo1Action KEYWORD2
|
||||
setGdo2Action KEYWORD2
|
||||
clearGdo0Action KEYWORD2
|
||||
clearGdo2Action KEYWORD2
|
||||
|
||||
# SX126x-specific
|
||||
setDio2Action KEYWORD2
|
||||
setTCXO KEYWORD2
|
||||
setDio2AsRfSwitch KEYWORD2
|
||||
getTimeOnAir KEYWORD2
|
||||
implicitHeader KEYWORD2
|
||||
explicitHeader KEYWORD2
|
||||
setSyncBits KEYWORD2
|
||||
setWhitening KEYWORD2
|
||||
startReceiveDutyCycle KEYWORD2
|
||||
startReceiveDutyCycleAuto KEYWORD2
|
||||
setRegulatorLDO KEYWORD2
|
||||
setRegulatorDCDC KEYWORD2
|
||||
getCurrentLimit KEYWORD2
|
||||
|
||||
# ESP8266
|
||||
join KEYWORD2
|
||||
|
@ -133,6 +145,7 @@ setTransmitPipe KEYWORD2
|
|||
setReceivePipe KEYWORD2
|
||||
disablePipe KEYWORD2
|
||||
getStatus KEYWORD2
|
||||
setAutoAck KEYWORD2
|
||||
|
||||
# HTTP
|
||||
get KEYWORD2
|
||||
|
@ -165,10 +178,19 @@ getNumBytes KEYWORD2
|
|||
sendSMS KEYWORD2
|
||||
shutdown KEYWORD2
|
||||
|
||||
# AX.25
|
||||
setRepeaters KEYWORD2
|
||||
setRecvSequence KEYWORD2
|
||||
setSendSequence KEYWORD2
|
||||
sendFrame KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
NC LITERAL1
|
||||
RADIOLIB_VERSION LITERAL1
|
||||
|
||||
ERR_NONE LITERAL1
|
||||
ERR_UNKNOWN LITERAL1
|
||||
|
||||
|
@ -246,3 +268,9 @@ ERR_INVALID_MODULATION_PARAMETERS LITERAL1
|
|||
ERR_SPI_CMD_TIMEOUT LITERAL1
|
||||
ERR_SPI_CMD_INVALID LITERAL1
|
||||
ERR_SPI_CMD_FAILED LITERAL1
|
||||
ERR_INVALID_SLEEP_PERIOD LITERAL1
|
||||
ERR_INVALID_RX_PERIOD LITERAL1
|
||||
|
||||
ERR_INVALID_CALLSIGN LITERAL1
|
||||
ERR_INVALID_NUM_REPEATERS LITERAL1
|
||||
ERR_INVALID_REPEATER_CALLSIGN LITERAL1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=RadioLib
|
||||
version=1.8.0
|
||||
version=3.3.0
|
||||
author=Jan Gromes <gromes.jan@gmail.com>
|
||||
maintainer=Jan Gromes <gromes.jan@gmail.com>
|
||||
sentence=Universal wireless communication library for Arduino
|
||||
|
|
112
src/Module.cpp
112
src/Module.cpp
|
@ -1,11 +1,11 @@
|
|||
#include "Module.h"
|
||||
|
||||
Module::Module(int rx, int tx, HardwareSerial* useSer) {
|
||||
_cs = -1;
|
||||
Module::Module(int16_t rx, int16_t tx, HardwareSerial* useSer, int16_t rst) {
|
||||
_cs = NC;
|
||||
_rx = rx;
|
||||
_tx = tx;
|
||||
_int0 = -1;
|
||||
_int1 = -1;
|
||||
_irq = NC;
|
||||
_rst = rst;
|
||||
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
ModuleSerial = useSer;
|
||||
|
@ -15,22 +15,32 @@ Module::Module(int rx, int tx, HardwareSerial* useSer) {
|
|||
#endif
|
||||
}
|
||||
|
||||
Module::Module(int cs, int int0, int int1, SPIClass& spi, SPISettings spiSettings) {
|
||||
Module::Module(int16_t cs, int16_t irq, int16_t rst, SPIClass& spi, SPISettings spiSettings) {
|
||||
_cs = cs;
|
||||
_rx = -1;
|
||||
_tx = -1;
|
||||
_int0 = int0;
|
||||
_int1 = int1;
|
||||
_rx = NC;
|
||||
_tx = NC;
|
||||
_irq = irq;
|
||||
_rst = rst;
|
||||
_spi = &spi;
|
||||
_spiSettings = spiSettings;
|
||||
}
|
||||
|
||||
Module::Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi, SPISettings spiSettings, HardwareSerial* useSer) {
|
||||
Module::Module(int16_t cs, int16_t irq, int16_t rst, int16_t gpio, SPIClass& spi, SPISettings spiSettings) {
|
||||
_cs = cs;
|
||||
_rx = gpio;
|
||||
_tx = NC;
|
||||
_irq = irq;
|
||||
_rst = rst;
|
||||
_spi = &spi;
|
||||
_spiSettings = spiSettings;
|
||||
}
|
||||
|
||||
Module::Module(int16_t cs, int16_t irq, int16_t rst, int16_t rx, int16_t tx, SPIClass& spi, SPISettings spiSettings, HardwareSerial* useSer) {
|
||||
_cs = cs;
|
||||
_rx = rx;
|
||||
_tx = tx;
|
||||
_int0 = int0;
|
||||
_int1 = int1;
|
||||
_irq = irq;
|
||||
_rst = rst;
|
||||
_spi = &spi;
|
||||
_spiSettings = spiSettings;
|
||||
|
||||
|
@ -42,22 +52,12 @@ Module::Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi, SPISet
|
|||
#endif
|
||||
}
|
||||
|
||||
Module::Module(int cs, int int0, int int1, int int2, SPIClass& spi, SPISettings spiSettings) {
|
||||
_cs = cs;
|
||||
_rx = int2;
|
||||
_tx = -1;
|
||||
_int0 = int0;
|
||||
_int1 = int1;
|
||||
_spi = &spi;
|
||||
_spiSettings = spiSettings;
|
||||
}
|
||||
|
||||
void Module::init(uint8_t interface, uint8_t gpio) {
|
||||
void Module::init(uint8_t interface) {
|
||||
// select interface
|
||||
switch(interface) {
|
||||
case RADIOLIB_USE_SPI:
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH);
|
||||
Module::pinMode(_cs, OUTPUT);
|
||||
Module::digitalWrite(_cs, HIGH);
|
||||
_spi->begin();
|
||||
break;
|
||||
case RADIOLIB_USE_UART:
|
||||
|
@ -70,27 +70,17 @@ void Module::init(uint8_t interface, uint8_t gpio) {
|
|||
case RADIOLIB_USE_I2C:
|
||||
break;
|
||||
}
|
||||
|
||||
// select GPIO
|
||||
switch(gpio) {
|
||||
case RADIOLIB_INT_NONE:
|
||||
break;
|
||||
case RADIOLIB_INT_0:
|
||||
pinMode(_int0, INPUT);
|
||||
break;
|
||||
case RADIOLIB_INT_1:
|
||||
pinMode(_int1, INPUT);
|
||||
break;
|
||||
case RADIOLIB_INT_BOTH:
|
||||
pinMode(_int0, INPUT);
|
||||
pinMode(_int1, INPUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Module::term() {
|
||||
// stop SPI
|
||||
_spi->end();
|
||||
// stop hardware interfaces
|
||||
if(_spi != nullptr) {
|
||||
_spi->end();
|
||||
}
|
||||
|
||||
if(ModuleSerial != nullptr) {
|
||||
ModuleSerial->end();
|
||||
}
|
||||
}
|
||||
|
||||
void Module::ATemptyBuffer() {
|
||||
|
@ -199,7 +189,7 @@ void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inByte
|
|||
}
|
||||
|
||||
uint8_t Module::SPIreadRegister(uint8_t reg) {
|
||||
uint8_t resp;
|
||||
uint8_t resp = 0;
|
||||
SPItransfer(SPIreadCommand, reg, NULL, &resp, 1);
|
||||
return(resp);
|
||||
}
|
||||
|
@ -217,14 +207,20 @@ void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* da
|
|||
_spi->beginTransaction(_spiSettings);
|
||||
|
||||
// pull CS low
|
||||
digitalWrite(_cs, LOW);
|
||||
Module::digitalWrite(_cs, LOW);
|
||||
|
||||
// send SPI register address with access command
|
||||
_spi->transfer(reg | cmd);
|
||||
RADIOLIB_VERBOSE_PRINT(reg | cmd, HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(reg | cmd, BIN);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
#ifdef RADIOLIB_VERBOSE
|
||||
if(cmd == SPIwriteCommand) {
|
||||
RADIOLIB_VERBOSE_PRINT('W');
|
||||
} else if(cmd == SPIreadCommand) {
|
||||
RADIOLIB_VERBOSE_PRINT('R');
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINT('\t')
|
||||
RADIOLIB_VERBOSE_PRINT(reg, HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
#endif
|
||||
|
||||
// send data or get response
|
||||
if(cmd == SPIwriteCommand) {
|
||||
|
@ -232,23 +228,31 @@ void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* da
|
|||
_spi->transfer(dataOut[n]);
|
||||
RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(dataOut[n], BIN);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
}
|
||||
} else if (cmd == SPIreadCommand) {
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
dataIn[n] = _spi->transfer(0x00);
|
||||
RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(dataIn[n], BIN);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
}
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
|
||||
// release CS
|
||||
digitalWrite(_cs, HIGH);
|
||||
Module::digitalWrite(_cs, HIGH);
|
||||
|
||||
// end SPI transaction
|
||||
_spi->endTransaction();
|
||||
}
|
||||
|
||||
void Module::pinMode(int16_t pin, uint8_t mode) {
|
||||
if(pin != NC) {
|
||||
::pinMode(pin, mode);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::digitalWrite(int16_t pin, uint8_t value) {
|
||||
if(pin != NC) {
|
||||
::digitalWrite(pin, value);
|
||||
}
|
||||
}
|
||||
|
|
87
src/Module.h
87
src/Module.h
|
@ -25,12 +25,14 @@ class Module {
|
|||
|
||||
\param rx Arduino pin to be used as Rx pin for SoftwareSerial communication.
|
||||
|
||||
\param serial HardwareSerial to be used on ESP32 and SAMD. Defaults to 1
|
||||
\param serial HardwareSerial to be used on platforms that do not support SoftwareSerial. Defaults to Serial1.
|
||||
|
||||
\param rst Arduino pin to be used as hardware reset for the module. Defaults to -1 (unused).
|
||||
*/
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
Module(int tx, int rx, HardwareSerial* useSer = &Serial1);
|
||||
Module(int16_t tx, int16_t rx, HardwareSerial* serial = &Serial1, int16_t rst = -1);
|
||||
#else
|
||||
Module(int tx, int rx, HardwareSerial* useSer = nullptr);
|
||||
Module(int16_t tx, int16_t rx, HardwareSerial* serial = nullptr, int16_t rst = -1);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
@ -38,41 +40,41 @@ class Module {
|
|||
|
||||
\param cs Arduino pin to be used as chip select.
|
||||
|
||||
\param int0 Arduino pin to be used as interrupt/GPIO 0.
|
||||
\param irq Arduino pin to be used as interrupt/GPIO.
|
||||
|
||||
\param int1 Arduino pin to be used as interrupt/GPIO 1.
|
||||
\param rst Arduino pin to be used as hardware reset for the module.
|
||||
|
||||
\param spi SPI interface to be used. Defaults to Arduino hardware SPI interface, can also use software SPI implementations.
|
||||
|
||||
\param spiSettings SPI interface settings. Defaults to 2 MHz clock, MSB first, mode 0.
|
||||
*/
|
||||
Module(int cs, int int0, int int1, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
Module(int16_t cs, int16_t irq, int16_t rst, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
/*!
|
||||
\brief Extended SPI-based module constructor.
|
||||
|
||||
\param cs Arduino pin to be used as chip select.
|
||||
|
||||
\param int0 Arduino pin to be used as interrupt/GPIO 0.
|
||||
\param irq Arduino pin to be used as interrupt/GPIO.
|
||||
|
||||
\param int1 Arduino pin to be used as interrupt/GPIO 1.
|
||||
\param rst Arduino pin to be used as hardware reset for the module.
|
||||
|
||||
\param int2 Arduino pin to be used as interrupt/GPIO 2.
|
||||
\param gpio Arduino pin to be used as additional interrupt/GPIO.
|
||||
|
||||
\param spi SPI interface to be used. Defaults to Arduino hardware SPI interface, can also use software SPI implementations.
|
||||
|
||||
\param spiSettings SPI interface settings. Defaults to 2 MHz clock, MSB first, mode 0.
|
||||
*/
|
||||
Module(int cs, int int0, int int1, int int2, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
Module(int16_t cs, int16_t irq, int16_t rst, int16_t gpio, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
/*!
|
||||
\brief Generic module constructor.
|
||||
|
||||
\param cs Arduino pin to be used as chip select.
|
||||
|
||||
\param int0 Arduino pin to be used as interrupt/GPIO 0.
|
||||
\param irq Arduino pin to be used as interrupt/GPIO.
|
||||
|
||||
\param int1 Arduino pin to be used as interrupt/GPIO 1.
|
||||
\param rst Arduino pin to be used as hardware reset for the module.
|
||||
|
||||
\param tx Arduino pin to be used as Tx pin for SoftwareSerial communication.
|
||||
|
||||
|
@ -85,9 +87,9 @@ class Module {
|
|||
\param serial HardwareSerial to be used on ESP32 and SAMD. Defaults to 1
|
||||
*/
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0), HardwareSerial* useSer = &Serial1);
|
||||
Module(int16_t cs, int16_t irq, int16_t rst, int16_t rx, int16_t tx, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0), HardwareSerial* serial = &Serial1);
|
||||
#else
|
||||
Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0), HardwareSerial* useSer = nullptr);
|
||||
Module(int16_t cs, int16_t irq, int16_t rst, int16_t rx, int16_t tx, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0), HardwareSerial* serial = nullptr);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -128,10 +130,8 @@ class Module {
|
|||
\brief Initialize low-level module control.
|
||||
|
||||
\param interface Interface to be used on the module. See \ref shield_config for details.
|
||||
|
||||
\param gpio GPIO/interrupt pins to be used on the module. See \ref uart_config for details.
|
||||
*/
|
||||
void init(uint8_t interface, uint8_t gpio);
|
||||
void init(uint8_t interface);
|
||||
|
||||
/*!
|
||||
\brief Terminate low-level module control.
|
||||
|
@ -266,35 +266,42 @@ class Module {
|
|||
|
||||
\returns Pin number of SPI chip select configured in the constructor.
|
||||
*/
|
||||
int getCs() const { return(_cs); }
|
||||
int16_t getCs() const { return(_cs); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of interrupt/GPIO 0.
|
||||
\brief Access method to get the pin number of interrupt/GPIO.
|
||||
|
||||
\returns Pin number of interrupt/GPIO 0 configured in the constructor.
|
||||
\returns Pin number of interrupt/GPIO configured in the constructor.
|
||||
*/
|
||||
int getInt0() const { return(_int0); }
|
||||
int16_t getIrq() const { return(_irq); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of interrupt/GPIO 1.
|
||||
\brief Access method to get the pin number of hardware reset pin.
|
||||
|
||||
\returns Pin number of interrupt/GPIO 1 configured in the constructor.
|
||||
\returns Pin number of hardware reset pin configured in the constructor.
|
||||
*/
|
||||
int getInt1() const { return(_int1); }
|
||||
int16_t getRst() const { return(_rst); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of second interrupt/GPIO.
|
||||
|
||||
\returns Pin number of second interrupt/GPIO configured in the constructor.
|
||||
*/
|
||||
int16_t getGpio() const { return(_rx); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of UART Rx.
|
||||
|
||||
\returns Pin number of UART Rx configured in the constructor.
|
||||
*/
|
||||
int getRx() const { return(_rx); }
|
||||
int16_t getRx() const { return(_rx); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the pin number of UART Rx.
|
||||
|
||||
\returns Pin number of UART Rx configured in the constructor.
|
||||
*/
|
||||
int getTx() const { return(_tx); }
|
||||
int16_t getTx() const { return(_tx); }
|
||||
|
||||
/*!
|
||||
\brief Access method to get the SPI interface.
|
||||
|
@ -310,14 +317,32 @@ class Module {
|
|||
*/
|
||||
SPISettings getSpiSettings() const { return(_spiSettings); }
|
||||
|
||||
/*!
|
||||
\brief Arduino core pinMode override that checks -1 as alias for unused pin.
|
||||
|
||||
\param pin Pin to change the mode of.
|
||||
|
||||
\param mode Which mode to set.
|
||||
*/
|
||||
static void pinMode(int16_t pin, uint8_t mode);
|
||||
|
||||
/*!
|
||||
\brief Arduino core digitalWrite override that checks -1 as alias for unused pin.
|
||||
|
||||
\param pin Pin to write to.
|
||||
|
||||
\param value Whether to set the pin high or low.
|
||||
*/
|
||||
static void digitalWrite(int16_t pin, uint8_t value);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
int _cs;
|
||||
int _tx;
|
||||
int _rx;
|
||||
int _int0;
|
||||
int _int1;
|
||||
int16_t _cs;
|
||||
int16_t _tx;
|
||||
int16_t _rx;
|
||||
int16_t _irq;
|
||||
int16_t _rst;
|
||||
|
||||
SPIClass* _spi;
|
||||
SPISettings _spiSettings;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
- PhysicalLayer protocols
|
||||
- RTTY (RTTYClient)
|
||||
- Morse Code (MorseClient)
|
||||
- AX.25 (AX25Client)
|
||||
- TransportLayer protocols
|
||||
- HTTP (HTTPClient)
|
||||
- MQTT (MQTTClient)
|
||||
|
@ -67,6 +68,7 @@
|
|||
|
||||
// physical layer protocols
|
||||
#include "protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
#include "protocols/AX25/AX25.h"
|
||||
#include "protocols/Morse/Morse.h"
|
||||
#include "protocols/RTTY/RTTY.h"
|
||||
|
||||
|
@ -77,6 +79,9 @@
|
|||
#include "protocols/MQTT/MQTT.h"
|
||||
#endif
|
||||
|
||||
// only create Radio class when using RadioShield
|
||||
#ifdef RADIOLIB_RADIOSHIELD
|
||||
|
||||
// RadioShield pin definitions
|
||||
#define RADIOSHIELD_CS_A 10
|
||||
#define RADIOSHIELD_RX_A 9
|
||||
|
@ -115,5 +120,6 @@ class Radio {
|
|||
};
|
||||
|
||||
Radio RadioShield;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
242
src/TypeDef.h
242
src/TypeDef.h
|
@ -1,11 +1,20 @@
|
|||
#ifndef _RADIOLIB_TYPES_H
|
||||
#define _RADIOLIB_TYPES_H
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#error "Unsupported Arduino version (< 1.0.0)"
|
||||
#endif
|
||||
|
||||
// version definitions
|
||||
#define RADIOLIB_VERSION_MAJOR (0x03)
|
||||
#define RADIOLIB_VERSION_MINOR (0x03)
|
||||
#define RADIOLIB_VERSION_PATCH (0x00)
|
||||
#define RADIOLIB_VERSION_EXTRA (0x00)
|
||||
|
||||
#define RADIOLIB_VERSION ((RADIOLIB_VERSION_MAJOR << 24) | (RADIOLIB_VERSION_MAJOR << 16) | (RADIOLIB_VERSION_MAJOR << 8) | (RADIOLIB_VERSION_EXTRA))
|
||||
|
||||
/*
|
||||
* 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.
|
||||
|
@ -53,13 +62,30 @@
|
|||
*/
|
||||
//#define RADIOLIB_GODMODE
|
||||
|
||||
/*
|
||||
* Uncomment to enable pre-defined modules when using RadioShield.
|
||||
*/
|
||||
//#define RADIOLIB_RADIOSHIELD
|
||||
|
||||
/*
|
||||
* The following platforms do not support SoftwareSerial library.
|
||||
*/
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined(ARDUINO_ARCH_STM32) || defined(__SAM3X8E__)
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined(ARDUINO_ARCH_STM32) || defined(__SAM3X8E__) || defined(AM_PART_APOLLO3)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Alias for unused pin, if not supplied by the Arduino core.
|
||||
*/
|
||||
#if !(defined(NC) || defined(ARDUINO_ARCH_STM32))
|
||||
#define NC (-1)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief A simple assert macro, will return on error.
|
||||
*/
|
||||
#define RADIOLIB_ASSERT(STATEVAR) { if(STATEVAR != ERR_NONE) { return(STATEVAR); } }
|
||||
|
||||
/*!
|
||||
\defgroup shield_config Shield Configuration
|
||||
|
||||
|
@ -69,37 +95,17 @@
|
|||
/*!
|
||||
\brief Use SPI interface.
|
||||
*/
|
||||
#define RADIOLIB_USE_SPI 0x00
|
||||
#define RADIOLIB_USE_SPI 0x00
|
||||
|
||||
/*!
|
||||
\brief Use UART interface.
|
||||
*/
|
||||
#define RADIOLIB_USE_UART 0x01
|
||||
#define RADIOLIB_USE_UART 0x01
|
||||
|
||||
/*!
|
||||
\brief Use I2C interface.
|
||||
*/
|
||||
#define RADIOLIB_USE_I2C 0x02
|
||||
|
||||
/*!
|
||||
\brief Do not use any interrupts/GPIOs.
|
||||
*/
|
||||
#define RADIOLIB_INT_NONE 0x00
|
||||
|
||||
/*!
|
||||
\brief Use interrupt/GPIO 0.
|
||||
*/
|
||||
#define RADIOLIB_INT_0 0x01
|
||||
|
||||
/*!
|
||||
\brief Use interrupt/GPIO 1.
|
||||
*/
|
||||
#define RADIOLIB_INT_1 0x02
|
||||
|
||||
/*!
|
||||
\brief Use both interrupts/GPIOs.
|
||||
*/
|
||||
#define RADIOLIB_INT_BOTH 0x03
|
||||
#define RADIOLIB_USE_I2C 0x02
|
||||
|
||||
/*!
|
||||
\}
|
||||
|
@ -114,52 +120,52 @@
|
|||
/*!
|
||||
\brief Use 1 bit stop.
|
||||
*/
|
||||
#define RADIOLIB_UART_STOPBIT_1 0x01
|
||||
#define RADIOLIB_UART_STOPBIT_1 0x01
|
||||
|
||||
/*!
|
||||
\brief Use 1.5 bit stop.
|
||||
*/
|
||||
#define RADIOLIB_UART_STOPBIT_1_5 0x02
|
||||
#define RADIOLIB_UART_STOPBIT_1_5 0x02
|
||||
|
||||
/*!
|
||||
\brief Use 2 bit stop.
|
||||
*/
|
||||
#define RADIOLIB_UART_STOPBIT_2 0x03
|
||||
#define RADIOLIB_UART_STOPBIT_2 0x03
|
||||
|
||||
/*!
|
||||
\brief No parity.
|
||||
*/
|
||||
#define RADIOLIB_UART_PARITY_NONE 0x00
|
||||
#define RADIOLIB_UART_PARITY_NONE 0x00
|
||||
|
||||
/*!
|
||||
\brief Odd parity.
|
||||
*/
|
||||
#define RADIOLIB_UART_PARITY_ODD 0x01
|
||||
#define RADIOLIB_UART_PARITY_ODD 0x01
|
||||
|
||||
/*!
|
||||
\brief Even parity.
|
||||
*/
|
||||
#define RADIOLIB_UART_PARITY_EVEN 0x02
|
||||
#define RADIOLIB_UART_PARITY_EVEN 0x02
|
||||
|
||||
/*!
|
||||
\brief No flow control.
|
||||
*/
|
||||
#define RADIOLIB_UART_FLOW_NONE 0x00
|
||||
#define RADIOLIB_UART_FLOW_NONE 0x00
|
||||
|
||||
/*!
|
||||
\brief RTS only.
|
||||
*/
|
||||
#define RADIOLIB_UART_FLOW_RTS 0x01
|
||||
#define RADIOLIB_UART_FLOW_RTS 0x01
|
||||
|
||||
/*!
|
||||
\brief CTS only.
|
||||
*/
|
||||
#define RADIOLIB_UART_FLOW_CTS 0x02
|
||||
#define RADIOLIB_UART_FLOW_CTS 0x02
|
||||
|
||||
/*!
|
||||
\brief Both RTS and CTS.
|
||||
*/
|
||||
#define RADIOLIB_UART_FLOW_BOTH 0x03
|
||||
#define RADIOLIB_UART_FLOW_BOTH 0x03
|
||||
|
||||
/*!
|
||||
\}
|
||||
|
@ -176,13 +182,13 @@
|
|||
/*!
|
||||
\brief No error, method executed successfully.
|
||||
*/
|
||||
#define ERR_NONE 0
|
||||
#define ERR_NONE 0
|
||||
|
||||
/*!
|
||||
\brief There was an unexpected, unknown error. If you see this, something went incredibly wrong.
|
||||
Your Arduino may be possessed, contact your local exorcist to resolve this error.
|
||||
*/
|
||||
#define ERR_UNKNOWN -1
|
||||
#define ERR_UNKNOWN -1
|
||||
|
||||
// SX127x/RFM9x status codes
|
||||
|
||||
|
@ -190,334 +196,372 @@
|
|||
\brief Radio chip was not found during initialization. This can be caused by specifying wrong chip type in the constructor
|
||||
(i.e. calling SX1272 constructor for SX1278 chip) or by a fault in your wiring (incorrect slave select pin).
|
||||
*/
|
||||
#define ERR_CHIP_NOT_FOUND -2
|
||||
#define ERR_CHIP_NOT_FOUND -2
|
||||
|
||||
/*!
|
||||
\brief Failed to allocate memory for temporary buffer. This can be cause by not enough RAM or by passing invalid pointer.
|
||||
*/
|
||||
#define ERR_MEMORY_ALLOCATION_FAILED -3
|
||||
#define ERR_MEMORY_ALLOCATION_FAILED -3
|
||||
|
||||
/*!
|
||||
\brief Packet supplied to transmission method was longer than limit.
|
||||
*/
|
||||
#define ERR_PACKET_TOO_LONG -4
|
||||
#define ERR_PACKET_TOO_LONG -4
|
||||
|
||||
/*!
|
||||
\brief Timed out waiting for transmission finish.
|
||||
*/
|
||||
#define ERR_TX_TIMEOUT -5
|
||||
#define ERR_TX_TIMEOUT -5
|
||||
|
||||
/*!
|
||||
\brief Timed out waiting for incoming transmission.
|
||||
*/
|
||||
#define ERR_RX_TIMEOUT -6
|
||||
#define ERR_RX_TIMEOUT -6
|
||||
|
||||
/*!
|
||||
\brief The calculated and expected CRCs of received packet do not match.
|
||||
This means that the packet was damaged during transmission and should be sent again.
|
||||
*/
|
||||
#define ERR_CRC_MISMATCH -7
|
||||
#define ERR_CRC_MISMATCH -7
|
||||
|
||||
/*!
|
||||
\brief The supplied bandwidth value is invalid for this module.
|
||||
*/
|
||||
#define ERR_INVALID_BANDWIDTH -8
|
||||
#define ERR_INVALID_BANDWIDTH -8
|
||||
|
||||
/*!
|
||||
\brief The supplied spreading factor value is invalid for this module.
|
||||
*/
|
||||
#define ERR_INVALID_SPREADING_FACTOR -9
|
||||
#define ERR_INVALID_SPREADING_FACTOR -9
|
||||
|
||||
/*!
|
||||
\brief The supplied coding rate value is invalid for this module.
|
||||
*/
|
||||
#define ERR_INVALID_CODING_RATE -10
|
||||
#define ERR_INVALID_CODING_RATE -10
|
||||
|
||||
/*!
|
||||
\brief Internal only.
|
||||
*/
|
||||
#define ERR_INVALID_BIT_RANGE -11
|
||||
#define ERR_INVALID_BIT_RANGE -11
|
||||
|
||||
/*!
|
||||
\brief The supplied frequency value is invalid for this module.
|
||||
*/
|
||||
#define ERR_INVALID_FREQUENCY -12
|
||||
#define ERR_INVALID_FREQUENCY -12
|
||||
|
||||
/*!
|
||||
\brief The supplied output power value is invalid for this module.
|
||||
*/
|
||||
#define ERR_INVALID_OUTPUT_POWER -13
|
||||
#define ERR_INVALID_OUTPUT_POWER -13
|
||||
|
||||
/*!
|
||||
\brief LoRa preamble was detected during channel activity detection.
|
||||
This means that there is some LoRa device currently transmitting in your channel.
|
||||
*/
|
||||
#define PREAMBLE_DETECTED -14
|
||||
#define PREAMBLE_DETECTED -14
|
||||
|
||||
/*!
|
||||
\brief No LoRa preambles were detected during channel activity detection. Your channel is free.
|
||||
*/
|
||||
#define CHANNEL_FREE -15
|
||||
#define CHANNEL_FREE -15
|
||||
|
||||
/*!
|
||||
\brief Real value in SPI register does not match the expected one. This can be caused by faulty SPI wiring.
|
||||
*/
|
||||
#define ERR_SPI_WRITE_FAILED -16
|
||||
#define ERR_SPI_WRITE_FAILED -16
|
||||
|
||||
/*!
|
||||
\brief The supplied current limit value is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_CURRENT_LIMIT -17
|
||||
#define ERR_INVALID_CURRENT_LIMIT -17
|
||||
|
||||
/*!
|
||||
\brief The supplied preamble length is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_PREAMBLE_LENGTH -18
|
||||
#define ERR_INVALID_PREAMBLE_LENGTH -18
|
||||
|
||||
/*!
|
||||
\brief The supplied gain value is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_GAIN -19
|
||||
#define ERR_INVALID_GAIN -19
|
||||
|
||||
/*!
|
||||
\brief User tried to execute modem-exclusive method on a wrong modem.
|
||||
For example, this can happen when you try to change LoRa configuration when FSK modem is active.
|
||||
*/
|
||||
#define ERR_WRONG_MODEM -20
|
||||
#define ERR_WRONG_MODEM -20
|
||||
|
||||
/*!
|
||||
\brief The supplied number of RSSI samples is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_NUM_SAMPLES -21
|
||||
#define ERR_INVALID_NUM_SAMPLES -21
|
||||
|
||||
/*!
|
||||
\brief The supplied RSSI offset is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_RSSI_OFFSET -22
|
||||
#define ERR_INVALID_RSSI_OFFSET -22
|
||||
|
||||
/*!
|
||||
\brief The supplied encoding is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_ENCODING -23
|
||||
#define ERR_INVALID_ENCODING -23
|
||||
|
||||
// RF69-specific status codes
|
||||
|
||||
/*!
|
||||
\brief The supplied bit rate value is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_BIT_RATE -101
|
||||
#define ERR_INVALID_BIT_RATE -101
|
||||
|
||||
/*!
|
||||
\brief The supplied frequency deviation value is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_FREQUENCY_DEVIATION -102
|
||||
#define ERR_INVALID_FREQUENCY_DEVIATION -102
|
||||
|
||||
/*!
|
||||
\brief The supplied bit rate to bandwidth ratio is invalid. See the module datasheet for more information.
|
||||
*/
|
||||
#define ERR_INVALID_BIT_RATE_BW_RATIO -103
|
||||
#define ERR_INVALID_BIT_RATE_BW_RATIO -103
|
||||
|
||||
/*!
|
||||
\brief The supplied receiver bandwidth value is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_RX_BANDWIDTH -104
|
||||
#define ERR_INVALID_RX_BANDWIDTH -104
|
||||
|
||||
/*!
|
||||
\brief The supplied FSK sync word is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_SYNC_WORD -105
|
||||
#define ERR_INVALID_SYNC_WORD -105
|
||||
|
||||
/*!
|
||||
\brief The supplied FSK data shaping option is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_DATA_SHAPING -106
|
||||
#define ERR_INVALID_DATA_SHAPING -106
|
||||
|
||||
/*!
|
||||
\brief The current modulation is invalid for the requested operation.
|
||||
*/
|
||||
#define ERR_INVALID_MODULATION -107
|
||||
#define ERR_INVALID_MODULATION -107
|
||||
|
||||
// ESP8266 status codes
|
||||
|
||||
/*!
|
||||
\brief AT command failed to execute, or timed out.
|
||||
*/
|
||||
#define ERR_AT_FAILED -201
|
||||
#define ERR_AT_FAILED -201
|
||||
|
||||
/*!
|
||||
\brief Supplied URL is malformed or invalid.
|
||||
*/
|
||||
#define ERR_URL_MALFORMED -202
|
||||
#define ERR_URL_MALFORMED -202
|
||||
|
||||
/*!
|
||||
\brief AT command response was malformed.
|
||||
*/
|
||||
#define ERR_RESPONSE_MALFORMED_AT -203
|
||||
#define ERR_RESPONSE_MALFORMED_AT -203
|
||||
|
||||
/*!
|
||||
\brief Data response was malformed.
|
||||
*/
|
||||
#define ERR_RESPONSE_MALFORMED -204
|
||||
#define ERR_RESPONSE_MALFORMED -204
|
||||
|
||||
/*!
|
||||
\brief MQTT broker rejected connection due to version mismatch.
|
||||
*/
|
||||
#define ERR_MQTT_CONN_VERSION_REJECTED -205
|
||||
#define ERR_MQTT_CONN_VERSION_REJECTED -205
|
||||
|
||||
/*!
|
||||
\brief MQTT broker rejected connection due to unknown ID.
|
||||
*/
|
||||
#define ERR_MQTT_CONN_ID_REJECTED -206
|
||||
#define ERR_MQTT_CONN_ID_REJECTED -206
|
||||
|
||||
/*!
|
||||
\brief Failed to establish connection with MQTT broker.
|
||||
*/
|
||||
#define ERR_MQTT_CONN_SERVER_UNAVAILABLE -207
|
||||
#define ERR_MQTT_CONN_SERVER_UNAVAILABLE -207
|
||||
|
||||
/*!
|
||||
\brief Supplied username/password combination is incorrect.
|
||||
*/
|
||||
#define ERR_MQTT_CONN_BAD_USERNAME_PASSWORD -208
|
||||
#define ERR_MQTT_CONN_BAD_USERNAME_PASSWORD -208
|
||||
|
||||
/*!
|
||||
\brief Unauthorized connection to MQTT broker.
|
||||
*/
|
||||
#define ERR_MQTT_CONN_NOT_AUTHORIZED -208
|
||||
#define ERR_MQTT_CONN_NOT_AUTHORIZED -208
|
||||
|
||||
/*!
|
||||
\brief Received packet ID does not match the expected ID.
|
||||
*/
|
||||
#define ERR_MQTT_UNEXPECTED_PACKET_ID -209
|
||||
#define ERR_MQTT_UNEXPECTED_PACKET_ID -209
|
||||
|
||||
/*!
|
||||
\brief No new packet was received since the last check.
|
||||
*/
|
||||
#define ERR_MQTT_NO_NEW_PACKET_AVAILABLE -210
|
||||
#define ERR_MQTT_NO_NEW_PACKET_AVAILABLE -210
|
||||
|
||||
/*!
|
||||
\brief Successfully subscribed to MQTT topic with QoS 0.
|
||||
*/
|
||||
#define MQTT_SUBS_SUCCESS_QOS_0 0x00
|
||||
#define MQTT_SUBS_SUCCESS_QOS_0 0x00
|
||||
|
||||
/*!
|
||||
\brief Successfully subscribed to MQTT topic with QoS 1.
|
||||
*/
|
||||
#define MQTT_SUBS_SUCCESS_QOS_1 0x01
|
||||
#define MQTT_SUBS_SUCCESS_QOS_1 0x01
|
||||
|
||||
/*!
|
||||
\brief Successfully subscribed to MQTT topic with QoS 2.
|
||||
*/
|
||||
#define MQTT_SUBS_SUCCESS_QOS_2 0x02
|
||||
#define MQTT_SUBS_SUCCESS_QOS_2 0x02
|
||||
|
||||
/*!
|
||||
\brief Failed to subscribe to MQTT topic.
|
||||
*/
|
||||
#define ERR_MQTT_SUBS_FAILED 0x80
|
||||
#define ERR_MQTT_SUBS_FAILED 0x80
|
||||
|
||||
// XBee status codes
|
||||
|
||||
/*!
|
||||
\brief Failed to enter command mode.
|
||||
*/
|
||||
#define ERR_CMD_MODE_FAILED -301
|
||||
#define ERR_CMD_MODE_FAILED -301
|
||||
|
||||
/*!
|
||||
\brief Received ZigBee frame is malformed.
|
||||
*/
|
||||
#define ERR_FRAME_MALFORMED -302
|
||||
#define ERR_FRAME_MALFORMED -302
|
||||
|
||||
/*!
|
||||
\brief Received ZigBee frame checksum does not match the calculated.
|
||||
*/
|
||||
#define ERR_FRAME_INCORRECT_CHECKSUM -303
|
||||
#define ERR_FRAME_INCORRECT_CHECKSUM -303
|
||||
|
||||
/*!
|
||||
\brief Received ZigBee frame with unexpected ID.
|
||||
*/
|
||||
#define ERR_FRAME_UNEXPECTED_ID -304
|
||||
#define ERR_FRAME_UNEXPECTED_ID -304
|
||||
|
||||
/*!
|
||||
\brief Timed out waiting for response to ZigBee frame.
|
||||
*/
|
||||
#define ERR_FRAME_NO_RESPONSE -305
|
||||
#define ERR_FRAME_NO_RESPONSE -305
|
||||
|
||||
// RTTY status codes
|
||||
|
||||
/*!
|
||||
\brief Supplied RTTY frequency shift is invalid for this module.
|
||||
*/
|
||||
#define ERR_INVALID_RTTY_SHIFT -401
|
||||
#define ERR_INVALID_RTTY_SHIFT -401
|
||||
|
||||
/*!
|
||||
\brief Supplied RTTY encoding is invalid.
|
||||
*/
|
||||
#define ERR_UNSUPPORTED_ENCODING -402
|
||||
#define ERR_UNSUPPORTED_ENCODING -402
|
||||
|
||||
// nRF24-specific status codes
|
||||
|
||||
/*!
|
||||
\brief Supplied data rate is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_DATA_RATE -501
|
||||
#define ERR_INVALID_DATA_RATE -501
|
||||
|
||||
/*!
|
||||
\brief Supplied address width is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_ADDRESS_WIDTH -502
|
||||
#define ERR_INVALID_ADDRESS_WIDTH -502
|
||||
|
||||
/*!
|
||||
\brief Supplied data pipe number is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_PIPE_NUMBER -503
|
||||
#define ERR_INVALID_PIPE_NUMBER -503
|
||||
|
||||
/*!
|
||||
\brief ACK packet from destination module was not received within 15 retries.
|
||||
*/
|
||||
#define ERR_ACK_NOT_RECEIVED -504
|
||||
#define ERR_ACK_NOT_RECEIVED -504
|
||||
|
||||
// CC1101-specific status codes
|
||||
|
||||
/*!
|
||||
\brief Supplied number of broadcast addresses is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_NUM_BROAD_ADDRS -601
|
||||
#define ERR_INVALID_NUM_BROAD_ADDRS -601
|
||||
|
||||
// SX126x-specific status codes
|
||||
|
||||
/*!
|
||||
\brief Supplied CRC configuration is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_CRC_CONFIGURATION -701
|
||||
#define ERR_INVALID_CRC_CONFIGURATION -701
|
||||
|
||||
/*!
|
||||
\brief Detected LoRa transmission while scanning channel.
|
||||
*/
|
||||
#define LORA_DETECTED -702
|
||||
#define LORA_DETECTED -702
|
||||
|
||||
/*!
|
||||
\brief Supplied TCXO reference voltage is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_TCXO_VOLTAGE -703
|
||||
#define ERR_INVALID_TCXO_VOLTAGE -703
|
||||
|
||||
/*!
|
||||
\brief Bit rate / bandwidth / frequency deviation ratio is invalid. See SX126x datasheet for details.
|
||||
*/
|
||||
#define ERR_INVALID_MODULATION_PARAMETERS -704
|
||||
#define ERR_INVALID_MODULATION_PARAMETERS -704
|
||||
|
||||
/*!
|
||||
\brief SX126x timed out while waiting for complete SPI command.
|
||||
*/
|
||||
#define ERR_SPI_CMD_TIMEOUT -705
|
||||
#define ERR_SPI_CMD_TIMEOUT -705
|
||||
|
||||
/*!
|
||||
\brief SX126x received invalid SPI command.
|
||||
*/
|
||||
#define ERR_SPI_CMD_INVALID -706
|
||||
#define ERR_SPI_CMD_INVALID -706
|
||||
|
||||
/*!
|
||||
\brief SX126x failed to execute SPI command.
|
||||
*/
|
||||
#define ERR_SPI_CMD_FAILED -707
|
||||
#define ERR_SPI_CMD_FAILED -707
|
||||
|
||||
/*!
|
||||
\brief The supplied sleep period is invalid.
|
||||
|
||||
The specified sleep period is shorter than the time necessary to sleep and wake the hardware
|
||||
including TCXO delay, or longer than the maximum possible
|
||||
*/
|
||||
#define ERR_INVALID_SLEEP_PERIOD -708
|
||||
|
||||
/*!
|
||||
\brief The supplied Rx period is invalid.
|
||||
|
||||
The specified Rx period is shorter or longer than the hardware can handle.
|
||||
*/
|
||||
#define ERR_INVALID_RX_PERIOD -709
|
||||
|
||||
// AX.25-specific status codes
|
||||
|
||||
/*!
|
||||
\brief The provided callsign is invalid.
|
||||
|
||||
The specified callsign is longer than 6 ASCII characters.
|
||||
*/
|
||||
#define ERR_INVALID_CALLSIGN -801
|
||||
|
||||
/*!
|
||||
\brief The provided repeater configuration is invalid.
|
||||
|
||||
The specified number of repeaters does not match number of repeater IDs or their callsigns.
|
||||
*/
|
||||
#define ERR_INVALID_NUM_REPEATERS -802
|
||||
|
||||
/*!
|
||||
\brief One of the provided repeater callsigns is invalid.
|
||||
|
||||
The specified callsign is longer than 6 ASCII characters.
|
||||
*/
|
||||
#define ERR_INVALID_REPEATER_CALLSIGN -803
|
||||
|
||||
/*!
|
||||
\}
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
#include "CC1101.h"
|
||||
|
||||
CC1101::CC1101(Module* module) : PhysicalLayer(CC1101_CRYSTAL_FREQ, CC1101_DIV_EXPONENT, CC1101_MAX_PACKET_LENGTH) {
|
||||
CC1101::CC1101(Module* module) : PhysicalLayer(CC1101_FREQUENCY_STEP_SIZE, CC1101_MAX_PACKET_LENGTH) {
|
||||
_mod = module;
|
||||
_packetLengthQueried = false;
|
||||
_packetLengthConfig = CC1101_LENGTH_CONFIG_VARIABLE;
|
||||
_modulation = CC1101_MOD_FORMAT_2_FSK;
|
||||
|
||||
_syncWordLength = 2;
|
||||
}
|
||||
|
||||
int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t power, uint8_t preambleLength) {
|
||||
int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t preambleLength) {
|
||||
// set module properties
|
||||
_mod->SPIreadCommand = CC1101_CMD_READ;
|
||||
_mod->SPIwriteCommand = CC1101_CMD_WRITE;
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_0);
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
|
||||
// try to find the CC1101 chip
|
||||
uint8_t i = 0;
|
||||
|
@ -40,7 +42,7 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
|
||||
if(!flagFound) {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No CC1101 found!"));
|
||||
SPI.end();
|
||||
_mod->term();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found CC1101! (match by CC1101_REG_VERSION == 0x14)"));
|
||||
|
@ -48,51 +50,43 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
|
||||
// configure settings not accessible by API
|
||||
int16_t state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure bitrate
|
||||
state = setBitRate(br);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default RX bandwidth
|
||||
state = setRxBandwidth(rxBw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default frequency deviation
|
||||
state = setFrequencyDeviation(freqDev);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default TX output power
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default preamble lenght
|
||||
state = setPreambleLength(preambleLength);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default data shaping
|
||||
state = setDataShaping(0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default encoding
|
||||
state = setEncoding(2);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// flush FIFOs
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_RX);
|
||||
|
@ -104,15 +98,17 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// start transmission
|
||||
int16_t state = startTransmit(data, len, addr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission start
|
||||
while(!digitalRead(_mod->getInt0()));
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
}
|
||||
|
||||
// wait for transmission end
|
||||
while(digitalRead(_mod->getInt0()));
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
@ -126,15 +122,17 @@ int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t CC1101::receive(uint8_t* data, size_t len) {
|
||||
// start reception
|
||||
int16_t state = startReceive();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for sync word
|
||||
while(!digitalRead(_mod->getInt0()));
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
}
|
||||
|
||||
// wait for packet end
|
||||
while(digitalRead(_mod->getInt0()));
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
yield();
|
||||
}
|
||||
|
||||
// read packet data
|
||||
return(readData(data, len));
|
||||
|
@ -157,9 +155,7 @@ int16_t CC1101::transmitDirect(uint32_t frf) {
|
|||
|
||||
// activate direct mode
|
||||
int16_t state = directMode();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start transmitting
|
||||
SPIsendCommand(CC1101_CMD_TX);
|
||||
|
@ -169,9 +165,7 @@ int16_t CC1101::transmitDirect(uint32_t frf) {
|
|||
int16_t CC1101::receiveDirect() {
|
||||
// activate direct mode
|
||||
int16_t state = directMode();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start receiving
|
||||
SPIsendCommand(CC1101_CMD_RX);
|
||||
|
@ -186,11 +180,26 @@ int16_t CC1101::packetMode() {
|
|||
}
|
||||
|
||||
void CC1101::setGdo0Action(void (*func)(void), uint8_t dir) {
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getInt0()), func, dir);
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getIrq()), func, dir);
|
||||
}
|
||||
|
||||
void CC1101::clearGdo0Action() {
|
||||
detachInterrupt(digitalPinToInterrupt(_mod->getIrq()));
|
||||
}
|
||||
|
||||
void CC1101::setGdo2Action(void (*func)(void), uint8_t dir) {
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getInt1()), func, dir);
|
||||
if(_mod->getGpio() != NC) {
|
||||
return;
|
||||
}
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getGpio()), func, dir);
|
||||
}
|
||||
|
||||
void CC1101::clearGdo2Action() {
|
||||
if(_mod->getGpio() != NC) {
|
||||
return;
|
||||
}
|
||||
detachInterrupt(digitalPinToInterrupt(_mod->getGpio()));
|
||||
}
|
||||
|
||||
int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -206,10 +215,8 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
SPIsendCommand(CC1101_CMD_FLUSH_TX);
|
||||
|
||||
// set GDO0 mapping
|
||||
int state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// optionally write packet length
|
||||
if (_packetLengthConfig == CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
|
@ -240,9 +247,7 @@ int16_t CC1101::startReceive() {
|
|||
|
||||
// set GDO0 mapping
|
||||
int state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set mode to receive
|
||||
SPIsendCommand(CC1101_CMD_RX);
|
||||
|
@ -273,9 +278,6 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
|
|||
uint8_t val = SPIgetRegValue(CC1101_REG_FIFO);
|
||||
_rawLQI = val & 0x7F;
|
||||
|
||||
// add terminating null
|
||||
data[length] = 0;
|
||||
|
||||
// flush Rx FIFO
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_RX);
|
||||
|
||||
|
@ -286,8 +288,8 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
|
|||
standby();
|
||||
|
||||
// check CRC
|
||||
if((val & 0b10000000) == 0b00000000) {
|
||||
return(ERR_CRC_MISMATCH);
|
||||
if (_crcOn && (val & 0b10000000) == 0b00000000) {
|
||||
return (ERR_CRC_MISMATCH);
|
||||
}
|
||||
|
||||
return(ERR_NONE);
|
||||
|
@ -315,7 +317,8 @@ int16_t CC1101::setFrequency(float freq) {
|
|||
_freq = freq;
|
||||
}
|
||||
|
||||
return(state);
|
||||
// Update the TX power accordingly to new freq. (PA values depend on chosen freq)
|
||||
return(setOutputPower(_power));
|
||||
}
|
||||
|
||||
int16_t CC1101::setBitRate(float br) {
|
||||
|
@ -351,14 +354,14 @@ int16_t CC1101::setRxBandwidth(float rxBw) {
|
|||
for(int8_t e = 3; e >= 0; e--) {
|
||||
for(int8_t m = 3; m >= 0; m --) {
|
||||
float point = (CC1101_CRYSTAL_FREQ * 1000000.0)/(8 * (m + 4) * ((uint32_t)1 << e));
|
||||
if(abs((rxBw * 1000.0) - point) <= 0.001) {
|
||||
if(abs((rxBw * 1000.0) - point) <= 1000) {
|
||||
// set Rx channel filter bandwidth
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG4, (e << 6) | (m << 4), 7, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(ERR_UNKNOWN);
|
||||
return(ERR_INVALID_RX_BANDWIDTH);
|
||||
}
|
||||
|
||||
int16_t CC1101::setFrequencyDeviation(float freqDev) {
|
||||
|
@ -445,12 +448,27 @@ int16_t CC1101::setOutputPower(int8_t power) {
|
|||
return(ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
// write raw power setting
|
||||
return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw));
|
||||
// store the value
|
||||
_power = power;
|
||||
|
||||
if(_modulation == CC1101_MOD_FORMAT_ASK_OOK){
|
||||
// Amplitude modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting a 0 (no power)
|
||||
// PA_TABLE[1] is the power to be used when transmitting a 1 (full power)
|
||||
|
||||
uint8_t paValues[2] = {0x00, powerRaw};
|
||||
SPIwriteRegisterBurst(CC1101_REG_PATABLE, paValues, 2);
|
||||
return(ERR_NONE);
|
||||
|
||||
} else {
|
||||
// Freq modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting.
|
||||
return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits) {
|
||||
if((maxErrBits > 1) || (len > 2)) {
|
||||
int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits, bool requireCarrierSense) {
|
||||
if((maxErrBits > 1) || (len != 2)) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
||||
|
@ -464,20 +482,19 @@ int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits)
|
|||
_syncWordLength = len;
|
||||
|
||||
// enable sync word filtering
|
||||
int16_t state = enableSyncWordFiltering(maxErrBits);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
int16_t state = enableSyncWordFiltering(maxErrBits, requireCarrierSense);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set sync word register
|
||||
_mod->SPIwriteRegisterBurst(CC1101_REG_SYNC1, syncWord, len);
|
||||
state = SPIsetRegValue(CC1101_REG_SYNC1, syncWord[0]);
|
||||
state |= SPIsetRegValue(CC1101_REG_SYNC0, syncWord[1]);
|
||||
|
||||
return(ERR_NONE);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits) {
|
||||
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits, bool requireCarrierSense) {
|
||||
uint8_t syncWord[] = { syncH, syncL };
|
||||
return(setSyncWord(syncWord, sizeof(syncWord), maxErrBits));
|
||||
return(setSyncWord(syncWord, sizeof(syncWord), maxErrBits, requireCarrierSense));
|
||||
}
|
||||
|
||||
int16_t CC1101::setPreambleLength(uint8_t preambleLength) {
|
||||
|
@ -524,9 +541,7 @@ int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) {
|
|||
|
||||
// enable address filtering
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_PKTCTRL1, numBroadcastAddrs + 0x01, 1, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set node address
|
||||
return(SPIsetRegValue(CC1101_REG_ADDR, nodeAddr));
|
||||
|
@ -535,14 +550,44 @@ 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);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set node address to default (0x00)
|
||||
return(SPIsetRegValue(CC1101_REG_ADDR, 0x00));
|
||||
}
|
||||
|
||||
|
||||
int16_t CC1101::setOOK(bool enableOOK) {
|
||||
// Change modulation
|
||||
if(enableOOK) {
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_ASK_OOK, 6, 4);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// PA_TABLE[0] is (by default) the power value used when transmitting a "0L".
|
||||
// Set PA_TABLE[1] to be used when transmitting a "1L".
|
||||
state = SPIsetRegValue(CC1101_REG_FREND0, 1, 2, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
|
||||
// update current modulation
|
||||
_modulation = CC1101_MOD_FORMAT_ASK_OOK;
|
||||
} else {
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_2_FSK, 6, 4);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// Reset FREND0 to default value.
|
||||
state = SPIsetRegValue(CC1101_REG_FREND0, 0, 2, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update current modulation
|
||||
_modulation = CC1101_MOD_FORMAT_2_FSK;
|
||||
}
|
||||
|
||||
// Update PA_TABLE values according to the new _modulation.
|
||||
return(setOutputPower(_power));
|
||||
}
|
||||
|
||||
|
||||
float CC1101::getRSSI() {
|
||||
float rssi;
|
||||
if(_rawRSSI >= 128) {
|
||||
|
@ -579,39 +624,29 @@ int16_t CC1101::variablePacketLengthMode(uint8_t maxLen) {
|
|||
return(setPacketMode(CC1101_LENGTH_CONFIG_VARIABLE, maxLen));
|
||||
}
|
||||
|
||||
int16_t CC1101::enableSyncWordFiltering(uint8_t maxErrBits) {
|
||||
if (maxErrBits > 1) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
int16_t CC1101::enableSyncWordFiltering(uint8_t maxErrBits, bool requireCarrierSense) {
|
||||
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));
|
||||
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));
|
||||
default:
|
||||
return (ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
||||
if (maxErrBits == 0) {
|
||||
if (_syncWordLength == 1) {
|
||||
// in 16 bit sync word, expect all 16 bits
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_16_16, 2, 0));
|
||||
} else {
|
||||
// there's no 32 of 32 case, so we resort to 30 of 32 bits required
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_30_32, 2, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (maxErrBits == 1) {
|
||||
if (_syncWordLength == 1) {
|
||||
// in 16 bit sync word, expect at least 15 bits
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_15_16, 2, 0));
|
||||
} else {
|
||||
// in 32 bits sync word (16 + 16), expect 30 of 32 to match
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_30_32, 2, 0));
|
||||
}
|
||||
}
|
||||
|
||||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t CC1101::disableSyncWordFiltering() {
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_NONE, 2, 0));
|
||||
int16_t CC1101::disableSyncWordFiltering(bool requireCarrierSense) {
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2,
|
||||
requireCarrierSense ? CC1101_SYNC_MODE_NONE_THR : CC1101_SYNC_MODE_NONE, 2, 0));
|
||||
}
|
||||
|
||||
int16_t CC1101::setCrcFiltering(bool crcOn) {
|
||||
_crcOn = crcOn;
|
||||
|
||||
if (crcOn == true) {
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_ON, 2, 2));
|
||||
} else {
|
||||
|
@ -629,18 +664,14 @@ int16_t CC1101::setPromiscuousMode(bool promiscuous) {
|
|||
if (promiscuous == true) {
|
||||
// disable preamble and sync word filtering and insertion
|
||||
state = disableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable CRC filtering
|
||||
state = setCrcFiltering(false);
|
||||
} else {
|
||||
// enable preamble and sync word filtering and insertion
|
||||
state = enableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable CRC filtering
|
||||
state = setCrcFiltering(true);
|
||||
|
@ -649,12 +680,57 @@ int16_t CC1101::setPromiscuousMode(bool promiscuous) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::setDataShaping(float sh) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set data shaping
|
||||
sh *= 10.0;
|
||||
if(abs(sh - 0.0) <= 0.001) {
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_2_FSK, 6, 4);
|
||||
} else if(abs(sh - 5.0) <= 0.001) {
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_MOD_FORMAT_GFSK, 6, 4);
|
||||
} else {
|
||||
return(ERR_INVALID_DATA_SHAPING);
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::setEncoding(uint8_t encoding) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set encoding
|
||||
switch(encoding) {
|
||||
case 0:
|
||||
state = _mod->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));
|
||||
case 1:
|
||||
state = _mod->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));
|
||||
case 2:
|
||||
state = _mod->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));
|
||||
default:
|
||||
return(ERR_INVALID_ENCODING);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// enable automatic frequency synthesizer calibration
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set packet mode
|
||||
state = packetMode();
|
||||
|
@ -707,19 +783,16 @@ int16_t CC1101::setPacketMode(uint8_t mode, uint8_t len) {
|
|||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
// set to fixed packet length
|
||||
int16_t state = _mod->SPIsetRegValue(CC1101_REG_PKTCTRL0, mode, 7, 7);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
// set PKTCTRL0.LENGTH_CONFIG
|
||||
int16_t state = _mod->SPIsetRegValue(CC1101_REG_PKTCTRL0, mode, 1, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_PKTLEN, len);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update the cached value
|
||||
_packetLength = len;
|
||||
_packetLengthConfig = mode;
|
||||
return(state);
|
||||
}
|
||||
|
@ -769,9 +842,9 @@ void CC1101::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len) {
|
|||
}
|
||||
|
||||
void CC1101::SPIsendCommand(uint8_t cmd) {
|
||||
digitalWrite(_mod->getCs(), LOW);
|
||||
Module::digitalWrite(_mod->getCs(), LOW);
|
||||
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
SPI.transfer(cmd);
|
||||
SPI.endTransaction();
|
||||
digitalWrite(_mod->getCs(), HIGH);
|
||||
Module::digitalWrite(_mod->getCs(), HIGH);
|
||||
}
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// CC1101 physical layer properties
|
||||
#define CC1101_FREQUENCY_STEP_SIZE 396.7285156
|
||||
#define CC1101_MAX_PACKET_LENGTH 63
|
||||
#define CC1101_CRYSTAL_FREQ 26.0
|
||||
#define CC1101_DIV_EXPONENT 16
|
||||
#define CC1101_MAX_PACKET_LENGTH 63
|
||||
|
||||
// CC1101 SPI commands
|
||||
#define CC1101_CMD_READ 0b10000000
|
||||
|
@ -524,17 +525,17 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\param br Bit rate to be used in kbps. Defaults to 4.8 kbps.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 325.0 kHz.
|
||||
|
||||
\param freqDev Frequency deviation from carrier frequency in kHz Defaults to 48.0 kHz.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 325.0 kHz.
|
||||
|
||||
\param power Output power in dBm. Defaults to 0 dBm.
|
||||
|
||||
\param preambleLength Preamble Length in bytes. Defaults to 4 bytes.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 868.0, float br = 4.8, float rxBw = 325.0, float freqDev = 48.0, int8_t power = 0, uint8_t preambleLength = 4);
|
||||
int16_t begin(float freq = 868.0, float br = 4.8, float freqDev = 48.0, float rxBw = 325.0, int8_t power = 0, uint8_t preambleLength = 4);
|
||||
|
||||
/*!
|
||||
\brief Blocking binary transmit method.
|
||||
|
@ -601,6 +602,11 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
void setGdo0Action(void (*func)(void), uint8_t dir = FALLING);
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when GDO0 activates.
|
||||
*/
|
||||
void clearGdo0Action();
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when GDO2 activates.
|
||||
|
||||
|
@ -610,6 +616,11 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
void setGdo2Action(void (*func)(void), uint8_t dir = FALLING);
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when GDO0 activates.
|
||||
*/
|
||||
void clearGdo2Action();
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method.
|
||||
Overloads for string-based transmissions are implemented in PhysicalLayer.
|
||||
|
@ -698,9 +709,11 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\param maxErrBits Maximum allowed number of bit errors in received sync word. Defaults to 0.
|
||||
|
||||
\param requireCarrierSense Require carrier sense above threshold in addition to sync word.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits = 0);
|
||||
int16_t setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits = 0, bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
\brief Sets 1 or 2 bytes of sync word.
|
||||
|
@ -711,9 +724,11 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\param maxErrBits Maximum allowed number of bit errors in received sync word. Defaults to 0.
|
||||
|
||||
\param requireCarrierSense Require carrier sense above threshold in addition to sync word.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits = 0);
|
||||
int16_t setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits = 0, bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
\brief Sets preamble length.
|
||||
|
@ -742,6 +757,15 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
int16_t disableAddressFiltering();
|
||||
|
||||
/*!
|
||||
\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 Gets RSSI (Recorded Signal Strength Indicator) of the last received packet.
|
||||
|
||||
|
@ -788,16 +812,20 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\param numBits Sync word length in bits.
|
||||
|
||||
\param requireCarrierSense Require carrier sense above threshold in addition to sync word.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t enableSyncWordFiltering(uint8_t maxErrBits = 0);
|
||||
int16_t enableSyncWordFiltering(uint8_t maxErrBits = 0, bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
\brief Disable preamble and sync word filtering and generation.
|
||||
|
||||
\param requireCarrierSense Require carrier sense above threshold.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t disableSyncWordFiltering();
|
||||
int16_t disableSyncWordFiltering(bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
@ -817,6 +845,25 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setPromiscuousMode(bool promiscuous = true);
|
||||
|
||||
/*!
|
||||
\brief Sets Gaussian filter bandwidth-time product that will be used for data shaping.
|
||||
Allowed value is 0.5. Set to 0 to disable data shaping.
|
||||
|
||||
\param sh Gaussian shaping bandwidth-time product that will be used for data shaping
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setDataShaping(float sh);
|
||||
|
||||
/*!
|
||||
\brief Sets transmission encoding.
|
||||
|
||||
\param encoding Encoding to be used. Set to 0 for NRZ, 1 for Manchester and 2 for whitening.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setEncoding(uint8_t encoding);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
@ -825,14 +872,17 @@ class CC1101: public PhysicalLayer {
|
|||
float _freq;
|
||||
uint8_t _rawRSSI;
|
||||
uint8_t _rawLQI;
|
||||
uint8_t _modulation;
|
||||
|
||||
size_t _packetLength;
|
||||
bool _packetLengthQueried;
|
||||
uint8_t _packetLengthConfig;
|
||||
|
||||
bool _promiscuous;
|
||||
bool _crcOn = true;
|
||||
|
||||
uint8_t _syncWordLength;
|
||||
int8_t _power;
|
||||
|
||||
int16_t config();
|
||||
int16_t directMode();
|
||||
|
|
|
@ -9,7 +9,7 @@ int16_t ESP8266::begin(long speed) {
|
|||
// set module properties
|
||||
_mod->AtLineFeed = "\r\n";
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
_mod->init(RADIOLIB_USE_UART);
|
||||
|
||||
// empty UART buffer (garbage data)
|
||||
_mod->ATemptyBuffer();
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "HC05.h"
|
||||
|
||||
HC05::HC05(Module* mod) : ISerial(mod) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void HC05::begin(long speed) {
|
||||
// set module properties
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
_mod->init(RADIOLIB_USE_UART);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#include "JDY08.h"
|
||||
|
||||
JDY08::JDY08(Module* mod) : ISerial(mod) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void JDY08::begin(long speed) {
|
||||
// set module properties
|
||||
_mod->AtLineFeed = "";
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
_mod->init(RADIOLIB_USE_UART);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "RF69.h"
|
||||
|
||||
RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT, RF69_MAX_PACKET_LENGTH) {
|
||||
RF69::RF69(Module* module) : PhysicalLayer(RF69_FREQUENCY_STEP_SIZE, RF69_MAX_PACKET_LENGTH) {
|
||||
_mod = module;
|
||||
_tempOffset = 0;
|
||||
|
||||
|
@ -12,14 +12,19 @@ RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT,
|
|||
_syncWordLength = 2;
|
||||
}
|
||||
|
||||
int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
|
||||
int16_t RF69::begin(float freq, float br, float freqDev, float rxBw, int8_t power) {
|
||||
// set module properties
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_0);
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
|
||||
// try to find the RF69 chip
|
||||
uint8_t i = 0;
|
||||
bool flagFound = false;
|
||||
while((i < 10) && !flagFound) {
|
||||
// reset the module
|
||||
reset();
|
||||
|
||||
// check version register
|
||||
uint8_t version = _mod->SPIreadRegister(RF69_REG_VERSION);
|
||||
if(version == 0x24) {
|
||||
flagFound = true;
|
||||
|
@ -42,7 +47,7 @@ int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t powe
|
|||
|
||||
if(!flagFound) {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No RF69 found!"));
|
||||
SPI.end();
|
||||
_mod->term();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found RF69! (match by RF69_REG_VERSION == 0x24)"));
|
||||
|
@ -50,66 +55,77 @@ int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t powe
|
|||
|
||||
// configure settings not accessible by API
|
||||
int16_t state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure bitrate
|
||||
_rxBw = 125.0;
|
||||
state = setBitRate(br);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default RX bandwidth
|
||||
state = setRxBandwidth(rxBw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default frequency deviation
|
||||
state = setFrequencyDeviation(freqDev);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default TX output power
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// default sync word values 0x2D01 is the same as the default in LowPowerLab RFM69 library
|
||||
uint8_t syncWord[] = {0x2D, 0x01};
|
||||
state = setSyncWord(syncWord, sizeof(syncWord));
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default data shaping
|
||||
state = setDataShaping(0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default encoding
|
||||
state = setEncoding(0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
void RF69::reset() {
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
delayMicroseconds(100);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
int16_t RF69::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);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission end or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
if(micros() - start > timeout) {
|
||||
standby();
|
||||
clearIRQFlags();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// wait for transmission end
|
||||
while(!digitalRead(_mod->getInt0()));
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
@ -118,15 +134,18 @@ int16_t RF69::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
int16_t RF69::receive(uint8_t* data, size_t len) {
|
||||
// calculate timeout (500 ms + 400 full 64-byte packets at current bit rate)
|
||||
uint32_t timeout = 500000 + (1.0/(_br*1000.0))*(RF69_MAX_PACKET_LENGTH*400.0);
|
||||
|
||||
// start reception
|
||||
int16_t state = startReceive(true);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
int16_t state = startReceive();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
if(digitalRead(_mod->getInt1())) {
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
if(micros() - start > timeout) {
|
||||
standby();
|
||||
clearIRQFlags();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
|
@ -158,9 +177,7 @@ int16_t RF69::transmitDirect(uint32_t frf) {
|
|||
|
||||
// activate direct mode
|
||||
int16_t state = directMode();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start transmitting
|
||||
return(setMode(RF69_TX));
|
||||
|
@ -169,9 +186,7 @@ int16_t RF69::transmitDirect(uint32_t frf) {
|
|||
int16_t RF69::receiveDirect() {
|
||||
// activate direct mode
|
||||
int16_t state = directMode();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start receiving
|
||||
return(setMode(RF69_RX));
|
||||
|
@ -180,16 +195,14 @@ int16_t RF69::receiveDirect() {
|
|||
int16_t RF69::directMode() {
|
||||
// set mode to standby
|
||||
int16_t state = setMode(RF69_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set DIO mapping
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO1_CONT_DCLK | RF69_DIO2_CONT_DATA, 5, 2);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set continuous mode
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_CONTINUOUS_MODE_WITH_SYNC, 6, 5);
|
||||
return(state);
|
||||
return(_mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_CONTINUOUS_MODE_WITH_SYNC, 6, 5));
|
||||
}
|
||||
|
||||
int16_t RF69::packetMode() {
|
||||
|
@ -208,23 +221,15 @@ int16_t RF69::disableAES() {
|
|||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_2, RF69_AES_OFF, 0, 0));
|
||||
}
|
||||
|
||||
int16_t RF69::startReceive(bool timeout) {
|
||||
int16_t RF69::startReceive() {
|
||||
// set mode to standby
|
||||
int16_t state = setMode(RF69_STANDBY);
|
||||
|
||||
// set RX timeouts and DIO pin mapping
|
||||
if(timeout) {
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PAYLOAD_READY | RF69_DIO1_PACK_TIMEOUT, 7, 4);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_1, RF69_TIMEOUT_RX_START);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_2, RF69_TIMEOUT_RSSI_THRESH);
|
||||
} else {
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PAYLOAD_READY, 7, 6);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_1, RF69_TIMEOUT_RX_START_OFF);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_2, RF69_TIMEOUT_RSSI_THRESH_OFF);
|
||||
}
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PAYLOAD_READY, 7, 4);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_1, RF69_TIMEOUT_RX_START);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_2, RF69_TIMEOUT_RSSI_THRESH);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
@ -238,11 +243,26 @@ int16_t RF69::startReceive(bool timeout) {
|
|||
}
|
||||
|
||||
void RF69::setDio0Action(void (*func)(void)) {
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getInt0()), func, RISING);
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getIrq()), func, RISING);
|
||||
}
|
||||
|
||||
void RF69::clearDio0Action() {
|
||||
detachInterrupt(digitalPinToInterrupt(_mod->getIrq()));
|
||||
}
|
||||
|
||||
void RF69::setDio1Action(void (*func)(void)) {
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getInt1()), func, RISING);
|
||||
if(_mod->getGpio() != NC) {
|
||||
return;
|
||||
}
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getGpio()), func, RISING);
|
||||
}
|
||||
|
||||
void RF69::clearDio1Action() {
|
||||
if(_mod->getGpio() != NC) {
|
||||
return;
|
||||
}
|
||||
detachInterrupt(digitalPinToInterrupt(_mod->getGpio()));
|
||||
}
|
||||
|
||||
int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -253,12 +273,11 @@ int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
// set mode to standby
|
||||
int16_t state = setMode(RF69_STANDBY);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set DIO pin mapping
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PACKET_SENT, 7, 6);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PACKET_SENT, 7, 6);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
@ -291,10 +310,7 @@ int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t RF69::readData(uint8_t* data, size_t len) {
|
||||
// set mdoe to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
// get packet length
|
||||
size_t length = len;
|
||||
if(len == RF69_MAX_PACKET_LENGTH) {
|
||||
|
@ -310,9 +326,6 @@ int16_t RF69::readData(uint8_t* data, size_t len) {
|
|||
// read packet data
|
||||
_mod->SPIreadRegisterBurst(RF69_REG_FIFO, length, data);
|
||||
|
||||
// add terminating null
|
||||
data[length] = 0;
|
||||
|
||||
// update RSSI
|
||||
lastPacketRSSI = -1.0 * (_mod->SPIgetRegValue(RF69_REG_RSSI_VALUE)/2.0);
|
||||
|
||||
|
@ -520,9 +533,7 @@ int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
|
|||
_syncWordLength = len;
|
||||
|
||||
int16_t state = enableSyncWordFiltering(maxErrBits);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set sync word register
|
||||
_mod->SPIwriteRegisterBurst(RF69_REG_SYNC_VALUE_1, syncWord, len);
|
||||
|
@ -532,9 +543,7 @@ int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
|
|||
int16_t RF69::setNodeAddress(uint8_t nodeAddr) {
|
||||
// enable address filtering (node only)
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_ADDRESS_FILTERING_NODE, 2, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set node address
|
||||
return(_mod->SPIsetRegValue(RF69_REG_NODE_ADRS, nodeAddr));
|
||||
|
@ -543,9 +552,7 @@ int16_t RF69::setNodeAddress(uint8_t nodeAddr) {
|
|||
int16_t RF69::setBroadcastAddress(uint8_t broadAddr) {
|
||||
// enable address filtering (node + broadcast)
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_ADDRESS_FILTERING_NODE_BROADCAST, 2, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set broadcast address
|
||||
return(_mod->SPIsetRegValue(RF69_REG_BROADCAST_ADRS, broadAddr));
|
||||
|
@ -554,15 +561,11 @@ int16_t RF69::setBroadcastAddress(uint8_t broadAddr) {
|
|||
int16_t RF69::disableAddressFiltering() {
|
||||
// disable address filtering
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_ADDRESS_FILTERING_OFF, 2, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set node address to default (0x00)
|
||||
state = _mod->SPIsetRegValue(RF69_REG_NODE_ADRS, 0x00);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set broadcast address to default (0x00)
|
||||
return(_mod->SPIsetRegValue(RF69_REG_BROADCAST_ADRS, 0x00));
|
||||
|
@ -612,27 +615,17 @@ int16_t RF69::variablePacketLengthMode(uint8_t maxLen) {
|
|||
|
||||
int16_t RF69::enableSyncWordFiltering(uint8_t maxErrBits) {
|
||||
// enable sync word recognition
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | (_syncWordLength - 1) << 3 | maxErrBits, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
return(_mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | (_syncWordLength - 1) << 3 | maxErrBits, 7, 0));
|
||||
}
|
||||
|
||||
int16_t RF69::disableSyncWordFiltering() {
|
||||
// disable preamble detection and generation
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_PREAMBLE_LSB, 0, 7, 0);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_PREAMBLE_MSB, 0, 7, 0);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable sync word detection and generation
|
||||
state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_OFF | RF69_FIFO_FILL_CONDITION, 7, 6);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -655,18 +648,14 @@ int16_t RF69::setPromiscuousMode(bool promiscuous) {
|
|||
if (promiscuous == true) {
|
||||
// disable preamble and sync word filtering and insertion
|
||||
state = disableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable CRC filtering
|
||||
state = setCrcFiltering(false);
|
||||
} else {
|
||||
// enable preamble and sync word filtering and insertion
|
||||
state = enableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable CRC filtering
|
||||
state = setCrcFiltering(true);
|
||||
|
@ -675,81 +664,97 @@ int16_t RF69::setPromiscuousMode(bool promiscuous) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::setDataShaping(float sh) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set data shaping
|
||||
sh *= 10.0;
|
||||
if(abs(sh - 0.0) <= 0.001) {
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_NO_SHAPING, 1, 0);
|
||||
} else if(abs(sh - 3.0) <= 0.001) {
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_FSK_GAUSSIAN_0_3, 1, 0);
|
||||
} else if(abs(sh - 5.0) <= 0.001) {
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_FSK_GAUSSIAN_0_5, 1, 0);
|
||||
} else if(abs(sh - 10.0) <= 0.001) {
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_FSK_GAUSSIAN_1_0, 1, 0);
|
||||
} else {
|
||||
return(ERR_INVALID_DATA_SHAPING);
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::setEncoding(uint8_t encoding) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set encoding
|
||||
switch(encoding) {
|
||||
case 0:
|
||||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_DC_FREE_NONE, 6, 5));
|
||||
case 1:
|
||||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_DC_FREE_MANCHESTER, 6, 5));
|
||||
case 2:
|
||||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_DC_FREE_WHITENING, 6, 5));
|
||||
default:
|
||||
return(ERR_INVALID_ENCODING);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t RF69::config() {
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
// set mode to STANDBY
|
||||
state = setMode(RF69_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set operation modes
|
||||
state = _mod->SPIsetRegValue(RF69_REG_OP_MODE, RF69_SEQUENCER_ON | RF69_LISTEN_OFF, 7, 6);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable over-current protection
|
||||
state = _mod->SPIsetRegValue(RF69_REG_OCP, RF69_OCP_ON, 4, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set data mode, modulation type and shaping
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_PACKET_MODE | RF69_FSK, 6, 3);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_FSK_GAUSSIAN_0_3, 1, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set RSSI threshold
|
||||
state = _mod->SPIsetRegValue(RF69_REG_RSSI_THRESH, RF69_RSSI_THRESHOLD, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// reset FIFO flag
|
||||
_mod->SPIwriteRegister(RF69_REG_IRQ_FLAGS_2, RF69_IRQ_FIFO_OVERRUN);
|
||||
|
||||
// disable ClkOut on DIO5
|
||||
state = _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_2, RF69_CLK_OUT_OFF, 2, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set packet configuration and disable encryption
|
||||
state = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_PACKET_FORMAT_VARIABLE | RF69_DC_FREE_NONE | RF69_CRC_ON | RF69_CRC_AUTOCLEAR_ON | RF69_ADDRESS_FILTERING_OFF, 7, 1);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_2, RF69_INTER_PACKET_RX_DELAY, 7, 4);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_2, RF69_AUTO_RX_RESTART_ON | RF69_AES_OFF, 1, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set payload length
|
||||
state = _mod->SPIsetRegValue(RF69_REG_PAYLOAD_LENGTH, RF69_PAYLOAD_LENGTH, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set FIFO threshold
|
||||
state = _mod->SPIsetRegValue(RF69_REG_FIFO_THRESH, RF69_TX_START_CONDITION_FIFO_NOT_EMPTY | RF69_FIFO_THRESHOLD, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set Rx timeouts
|
||||
state = _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_1, RF69_TIMEOUT_RX_START, 7, 0);
|
||||
state = _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_2, RF69_TIMEOUT_RSSI_THRESH, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable improved fading margin
|
||||
state = _mod->SPIsetRegValue(RF69_REG_TEST_DAGC, RF69_CONTINUOUS_DAGC_LOW_BETA_OFF, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
@ -762,15 +767,11 @@ int16_t RF69::setPacketMode(uint8_t mode, uint8_t len) {
|
|||
|
||||
// set to fixed packet length
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, mode, 7, 7);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(RF69_REG_PAYLOAD_LENGTH, len);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update the cached value
|
||||
_packetLengthConfig = mode;
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// RF69 physical layer properties
|
||||
#define RF69_FREQUENCY_STEP_SIZE 61.03515625
|
||||
#define RF69_MAX_PACKET_LENGTH 64
|
||||
#define RF69_CRYSTAL_FREQ 32.0
|
||||
#define RF69_DIV_EXPONENT 19
|
||||
#define RF69_MAX_PACKET_LENGTH 64
|
||||
|
||||
// RF69 register map
|
||||
#define RF69_REG_FIFO 0x00
|
||||
|
@ -454,15 +455,20 @@ class RF69: public PhysicalLayer {
|
|||
|
||||
\param br Bit rate to be used in kbps. Defaults to 48.0 kbps.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
|
||||
\param freqDev Frequency deviation from carrier frequency in kHz Defaults to 50.0 kHz.
|
||||
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
|
||||
\param power Output power in dBm. Defaults to 13 dBm.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float br = 48.0, float rxBw = 125.0, float freqDev = 50.0, int8_t power = 13);
|
||||
int16_t begin(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 13);
|
||||
|
||||
/*!
|
||||
\brief Reset method. Will reset the chip to the default state using RST pin.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/*!
|
||||
\brief Blocking binary transmit method.
|
||||
|
@ -557,6 +563,11 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
void setDio0Action(void (*func)(void));
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when DIO0 activates.
|
||||
*/
|
||||
void clearDio0Action();
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when DIO1 activates.
|
||||
|
||||
|
@ -564,6 +575,11 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
void setDio1Action(void (*func)(void));
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when DIO1 activates.
|
||||
*/
|
||||
void clearDio1Action();
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method.
|
||||
Overloads for string-based transmissions are implemented in PhysicalLayer.
|
||||
|
@ -581,11 +597,9 @@ class RF69: public PhysicalLayer {
|
|||
/*!
|
||||
\brief Interrupt-driven receive method. GDO0 will be activated when full packet is received.
|
||||
|
||||
\param timeout Enable module-driven timeout. Set to false for listen mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(bool timeout = false);
|
||||
int16_t startReceive();
|
||||
|
||||
/*!
|
||||
\brief Reads data received after calling startReceive method.
|
||||
|
@ -758,6 +772,25 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setPromiscuousMode(bool promiscuous = true);
|
||||
|
||||
/*!
|
||||
\brief Sets Gaussian filter bandwidth-time product that will be used for data shaping.
|
||||
Allowed values are 0.3, 0.5 or 1.0. Set to 0 to disable data shaping.
|
||||
|
||||
\param sh Gaussian shaping bandwidth-time product that will be used for data shaping
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setDataShaping(float sh);
|
||||
|
||||
/*!
|
||||
\brief Sets transmission encoding.
|
||||
|
||||
\param encoding Encoding to be used. Set to 0 for NRZ, 1 for Manchester and 2 for whitening.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setEncoding(uint8_t encoding);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
|
|
|
@ -7,47 +7,30 @@ RFM95::RFM95(Module* mod) : SX1278(mod) {
|
|||
int16_t RFM95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(RFM95_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -56,7 +39,7 @@ int16_t RFM95::setFrequency(float freq) {
|
|||
if((freq < 868.0) || (freq > 915.0)) {
|
||||
return(ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
}
|
||||
|
|
|
@ -7,47 +7,30 @@ RFM96::RFM96(Module* mod) : SX1278(mod) {
|
|||
int16_t RFM96::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(RFM9X_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -56,7 +39,7 @@ int16_t RFM96::setFrequency(float freq) {
|
|||
if((freq < 433.0) || (freq > 470.0)) {
|
||||
return(ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ int16_t RFM97::setSpreadingFactor(uint8_t sf) {
|
|||
}
|
||||
|
||||
uint8_t newSpreadingFactor;
|
||||
|
||||
|
||||
// check allowed spreading factor values
|
||||
switch(sf) {
|
||||
case 6:
|
||||
|
@ -29,7 +29,7 @@ int16_t RFM97::setSpreadingFactor(uint8_t sf) {
|
|||
default:
|
||||
return(ERR_INVALID_SPREADING_FACTOR);
|
||||
}
|
||||
|
||||
|
||||
// set spreading factor and if successful, save the new setting
|
||||
int16_t state = SX1278::setSpreadingFactorRaw(newSpreadingFactor);
|
||||
if(state == ERR_NONE) {
|
||||
|
|
|
@ -6,7 +6,9 @@ SX1231::SX1231(Module* mod) : RF69(mod) {
|
|||
|
||||
int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
|
||||
// set module properties
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
|
||||
// try to find the SX1231 chip
|
||||
uint8_t i = 0;
|
||||
|
@ -35,7 +37,7 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
|
||||
if(!flagFound) {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No SX1231 found!"));
|
||||
SPI.end();
|
||||
_mod->term();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found SX1231!"));
|
||||
|
@ -43,47 +45,33 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
|
||||
// configure settings not accessible by API
|
||||
int16_t state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure bitrate
|
||||
_rxBw = 125.0;
|
||||
state = setBitRate(br);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default RX bandwidth
|
||||
state = setRxBandwidth(rxBw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default frequency deviation
|
||||
state = setFrequencyDeviation(freqDev);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure default TX output power
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// default sync word values 0x2D01 is the same as the default in LowPowerLab RFM69 library
|
||||
uint8_t syncWord[] = {0x2D, 0x01};
|
||||
state = setSyncWord(syncWord, 2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
|
@ -95,15 +83,11 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
if(_chipRevision == SX1231_CHIP_REVISION_2_A) {
|
||||
// modify default OOK threshold value
|
||||
state = _mod->SPIsetRegValue(SX1231_REG_TEST_OOK, SX1231_OOK_DELTA_THRESHOLD);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable OCP with 95 mA limit
|
||||
state = _mod->SPIsetRegValue(RF69_REG_OCP, RF69_OCP_ON | RF69_OCP_TRIM, 4, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
return(ERR_NONE);
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#include "SX1261.h"
|
||||
|
||||
SX1261::SX1261(Module* mod)
|
||||
: SX1262(mod) {
|
||||
SX1261::SX1261(Module* mod): SX1262(mod) {
|
||||
|
||||
}
|
||||
|
||||
int16_t SX1261::setOutputPower(int8_t power) {
|
||||
int16_t SX1261::setOutputPower(int8_t power) {
|
||||
// check allowed power range
|
||||
if (!((power >= -17) && (power <= 14))) {
|
||||
return(ERR_INVALID_OUTPUT_POWER);
|
||||
|
@ -14,37 +13,17 @@ int16_t SX1261::setOutputPower(int8_t power) {
|
|||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOptimalLowPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
// set PA config
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// restore OCP configuration
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
}
|
||||
|
||||
int16_t SX1261::setOptimalLowPowerPaConfig(int8_t* inOutPower)
|
||||
{
|
||||
int16_t state;
|
||||
if (*inOutPower > 10) {
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
}
|
||||
else {
|
||||
state = SX126x::setPaConfig(0x01, SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
// changing the PaConfig means output power is now scaled so we get 3 dB less than requested.
|
||||
// see datasheet table 13-21 and comments in setOptimalHiPowerPaConfig.
|
||||
*inOutPower -= 3;
|
||||
}
|
||||
return state;
|
||||
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class SX1261 : public SX1262 {
|
|||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
int16_t setOptimalLowPowerPaConfig(int8_t* inOutPower);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -4,54 +4,36 @@ SX1262::SX1262(Module* mod) : SX126x(mod) {
|
|||
|
||||
}
|
||||
|
||||
int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, int8_t power, float currentLimit, uint16_t preambleLength) {
|
||||
int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, float currentLimit, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
// execute common part
|
||||
int16_t state = SX126x::begin(bw, sf, cr, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
int16_t state = SX126x::begin(bw, sf, cr, syncWord, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, float currentLimit, uint16_t preambleLength, float dataShaping) {
|
||||
int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, float currentLimit, uint16_t preambleLength, float dataShaping, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
// execute common part
|
||||
int16_t state = SX126x::beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
int16_t state = SX126x::beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping, tcxoVoltage, useRegulatorLDO);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -84,9 +66,7 @@ int16_t SX1262::setFrequency(float freq, bool calibrate) {
|
|||
data[1] = SX126X_CAL_IMG_430_MHZ_2;
|
||||
}
|
||||
state = SX126x::calibrateImage(data);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set frequency
|
||||
|
@ -102,25 +82,17 @@ int16_t SX1262::setOutputPower(int8_t power) {
|
|||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// this function sets the optimal PA settings
|
||||
// and adjusts power based on the PA settings chosen
|
||||
// so that output power matches requested power.
|
||||
state = SX126x::setOptimalHiPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
// set PA config
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// restore OCP configuration
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#include "../../Module.h"
|
||||
#include "SX126x.h"
|
||||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_SX1262 0x00
|
||||
|
||||
/*!
|
||||
\class SX1262
|
||||
|
||||
|
@ -32,7 +35,7 @@ class SX1262: public SX126x {
|
|||
|
||||
\param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
|
||||
|
||||
\param syncWord 2-byte LoRa sync word. Defaults to SX126X_SYNC_WORD_PRIVATE (0x1424).
|
||||
\param syncWord 2-byte LoRa sync word. Defaults to SX126X_SYNC_WORD_PRIVATE (0x12).
|
||||
|
||||
\param power Output power in dBm. Defaults to 14 dBm.
|
||||
|
||||
|
@ -40,9 +43,11 @@ class SX1262: public SX126x {
|
|||
|
||||
\param preambleLength LoRa preamble length in symbols.Defaults to 8 symbols.
|
||||
|
||||
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint16_t syncWord = SX126X_SYNC_WORD_PRIVATE, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 8);
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX126X_SYNC_WORD_PRIVATE, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem.
|
||||
|
@ -63,9 +68,11 @@ class SX1262: public SX126x {
|
|||
|
||||
\param dataShaping Time-bandwidth product of the Gaussian filter to be used for shaping. Defaults to 0.5.
|
||||
|
||||
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 156.2, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 16, float dataShaping = 0.5);
|
||||
int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 156.2, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 16, float dataShaping = 0.5, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
|
|
@ -4,53 +4,35 @@ SX1268::SX1268(Module* mod) : SX126x(mod) {
|
|||
|
||||
}
|
||||
|
||||
int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, int8_t power, float currentLimit, uint16_t preambleLength) {
|
||||
int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, float currentLimit, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
// execute common part
|
||||
int16_t state = SX126x::begin(bw, sf, cr, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
int16_t state = SX126x::begin(bw, sf, cr, syncWord, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, float currentLimit, uint16_t preambleLength, float dataShaping) {
|
||||
int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, float currentLimit, uint16_t preambleLength, float dataShaping, float tcxoVoltage, bool useRegulatorLDO) {
|
||||
// execute common part
|
||||
int16_t state = SX126x::beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
int16_t state = SX126x::beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping, tcxoVoltage, useRegulatorLDO);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -77,9 +59,7 @@ int16_t SX1268::setFrequency(float freq, bool calibrate) {
|
|||
data[1] = SX126X_CAL_IMG_430_MHZ_2;
|
||||
}
|
||||
state = SX126x::calibrateImage(data);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set frequency
|
||||
|
@ -95,23 +75,17 @@ int16_t SX1268::setOutputPower(int8_t power) {
|
|||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable optimal PA - this changes the value of power.
|
||||
state = SX126x::setOptimalHiPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
// set PA config
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1268);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// restore OCP configuration
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
|
|
@ -35,17 +35,19 @@ class SX1268: public SX126x {
|
|||
|
||||
\param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
|
||||
|
||||
\param syncWord 2-byte LoRa sync word. Defaults to SX126X_SYNC_WORD_PRIVATE (0x1424).
|
||||
\param syncWord 2-byte LoRa sync word. Defaults to SX126X_SYNC_WORD_PRIVATE (0x12).
|
||||
|
||||
\param power Output power in dBm. Defaults to 14 dBm.
|
||||
|
||||
\param currentLimit Current protection limit in mA. Defaults to 60.0 mA.
|
||||
|
||||
\param preambleLength LoRa preamble length in symbols.Defaults to 8 symbols.
|
||||
\param preambleLength LoRa preamble length in symbols. Defaults to 8 symbols.
|
||||
|
||||
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint16_t syncWord = SX126X_SYNC_WORD_PRIVATE, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 8);
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX126X_SYNC_WORD_PRIVATE, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem.
|
||||
|
@ -66,14 +68,16 @@ class SX1268: public SX126x {
|
|||
|
||||
\param dataShaping Time-bandwidth product of the Gaussian filter to be used for shaping. Defaults to 0.5.
|
||||
|
||||
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 156.2, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 16, float dataShaping = 0.5);
|
||||
int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 156.2, int8_t power = 14, float currentLimit = 60.0, uint16_t preambleLength = 16, float dataShaping = 0.5, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz.
|
||||
\brief Sets carrier frequency. Allowed values are in range from 410.0 to 810.0 MHz.
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
|
@ -84,7 +88,7 @@ class SX1268: public SX126x {
|
|||
int16_t setFrequency(float freq, bool calibrate = true);
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -17 to 22 dBm.
|
||||
\brief Sets output power. Allowed values are in range from -9 to 22 dBm.
|
||||
|
||||
\param power Output power to be set in dBm.
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,9 +7,10 @@
|
|||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// SX126X physical layer properties
|
||||
#define SX126X_FREQUENCY_STEP_SIZE 0.9536743164
|
||||
#define SX126X_MAX_PACKET_LENGTH 255
|
||||
#define SX126X_CRYSTAL_FREQ 32.0
|
||||
#define SX126X_DIV_EXPONENT 25
|
||||
#define SX126X_MAX_PACKET_LENGTH 255
|
||||
|
||||
// SX126X SPI commands
|
||||
// operational modes commands
|
||||
|
@ -325,8 +326,8 @@
|
|||
|
||||
// SX126X SPI register variables
|
||||
//SX126X_REG_LORA_SYNC_WORD_MSB + LSB
|
||||
#define SX126X_SYNC_WORD_PUBLIC 0x3444
|
||||
#define SX126X_SYNC_WORD_PRIVATE 0x1424
|
||||
#define SX126X_SYNC_WORD_PUBLIC 0x34 // actually 0x3444 NOTE: The low nibbles in each byte (0x_4_4) are masked out since apparently, they're reserved.
|
||||
#define SX126X_SYNC_WORD_PRIVATE 0x12 // actually 0x1424 You couldn't make this up if you tried.
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -361,15 +362,19 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
\param cr LoRa coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
\param syncWord 2-byte LoRa sync word.
|
||||
\param syncWord 1-byte LoRa sync word.
|
||||
|
||||
\param currentLimit Current protection limit in mA.
|
||||
|
||||
\param preambleLength LoRa preamble length in symbols. Allowed values range from 1 to 65535.
|
||||
|
||||
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
|
||||
|
||||
\param useRegulatorLDO use the LDO instead of DC-DC converter (default false). This is necessary for some modules such as the LAMBDA from RF solutions.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, float currentLimit, uint16_t preambleLength);
|
||||
int16_t begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, float currentLimit, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO = false);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem.
|
||||
|
@ -386,9 +391,23 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
\param dataShaping Time-bandwidth product of the Gaussian filter to be used for shaping. Allowed values are 0.3, 0.5, 0.7 and 1.0. Set to 0 to disable shaping.
|
||||
|
||||
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip.
|
||||
|
||||
\param useRegulatorLDO use the LDO instead of DC-DC converter (default false). This is necessary for some modules such as the LAMBDA from RF solutions.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(float br, float freqDev, float rxBw, float currentLimit, uint16_t preambleLength, float dataShaping);
|
||||
int16_t beginFSK(float br, float freqDev, float rxBw, float currentLimit, uint16_t preambleLength, float dataShaping, float tcxoVoltage, bool useRegulatorLDO = false);
|
||||
|
||||
/*!
|
||||
\brief Reset method. Will reset the chip to the default state using RST pin.
|
||||
|
||||
\param verify Whether correct module startup should be verified. When set to true, RadioLib will attempt to verify the module has started correctly
|
||||
by repeatedly issuing setStandby command. Enabled by default.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t reset(bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Blocking binary transmit method.
|
||||
|
@ -443,9 +462,11 @@ class SX126x: public PhysicalLayer {
|
|||
/*!
|
||||
\brief Sets the module to sleep mode.
|
||||
|
||||
\param retainConfig Set to true to retain configuration of the currently active modem ("warm start") or to false to discard current configuration ("cold start"). Defaults to true.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t sleep();
|
||||
int16_t sleep(bool retainConfig = true);
|
||||
|
||||
/*!
|
||||
\brief Sets the module to standby mode (overload for PhysicalLayer compatibility, uses 13 MHz RC oscillator).
|
||||
|
@ -473,11 +494,9 @@ class SX126x: public PhysicalLayer {
|
|||
void setDio1Action(void (*func)(void));
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when DIO2 activates.
|
||||
|
||||
\param func ISR to call.
|
||||
\brief Clears interrupt service routine to call when DIO1 activates.
|
||||
*/
|
||||
void setDio2Action(void (*func)(void));
|
||||
void clearDio1Action();
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method.
|
||||
|
@ -502,6 +521,31 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t startReceive(uint32_t timeout = SX126X_RX_TIMEOUT_INF);
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method where the device mostly sleeps and periodically wakes to listen.
|
||||
Note that this function assumes the unit will take 500us + TCXO_delay to change state. See datasheet section 13.1.7, version 1.2.
|
||||
|
||||
\param rxPeriod The duration the receiver will be in Rx mode, in microseconds.
|
||||
|
||||
\param sleepPeriod The duration the receiver will not be in Rx mode, in microseconds.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod);
|
||||
|
||||
/*!
|
||||
\brief Calls \ref startReceiveDutyCycle with rxPeriod and sleepPeriod set so the unit shouldn't miss any messages.
|
||||
|
||||
\param senderPreambleLength Expected preamble length of the messages to receive.
|
||||
If set to zero, the currently configured preamble length will be used. Defaults to zero.
|
||||
|
||||
\param minSymbols Parameters will be chosen to ensure that the unit will catch at least this many symbols of any preamble of the specified length. Defaults to 8.
|
||||
According to Semtech, receiver requires 8 symbols to reliably latch a preamble. This makes this method redundant when transmitter preamble length is less than 17 (2*minSymbols + 1).
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceiveDutyCycleAuto(uint16_t senderPreambleLength = 0, uint16_t minSymbols = 8);
|
||||
|
||||
/*!
|
||||
\brief Reads data received after calling startReceive method.
|
||||
|
||||
|
@ -547,9 +591,11 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
\param syncWord LoRa sync word to be set.
|
||||
|
||||
\param controlBits Undocumented control bits, required for compatibility purposes.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSyncWord(uint16_t syncWord);
|
||||
int16_t setSyncWord(uint8_t syncWord, uint8_t controlBits = 0x44);
|
||||
|
||||
/*!
|
||||
\brief Sets current protection limit. Can be set in 0.25 mA steps.
|
||||
|
@ -560,6 +606,13 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setCurrentLimit(float currentLimit);
|
||||
|
||||
/*!
|
||||
\brief Reads current protection limit.
|
||||
|
||||
\returns Currently configured overcurrent protection limit in mA.
|
||||
*/
|
||||
float getCurrentLimit();
|
||||
|
||||
/*!
|
||||
\brief Sets preamble length for LoRa or FSK modem. Allowed values range from 1 to 65535.
|
||||
|
||||
|
@ -751,6 +804,45 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
uint32_t getTimeOnAir(size_t len);
|
||||
|
||||
/*!
|
||||
\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();
|
||||
|
||||
/*!
|
||||
\brief Set regulator mode to LDO.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setRegulatorLDO();
|
||||
|
||||
/*!
|
||||
\brief Set regulator mode to DC-DC.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setRegulatorDCDC();
|
||||
|
||||
/*!
|
||||
\brief Sets transmission encoding. Available in FSK mode only. Serves only as alias for PhysicalLayer compatibility.
|
||||
|
||||
\param encoding Encoding to be used. Set to 0 for NRZ, and 2 for whitening.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setEncoding(uint8_t encoding);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
|
@ -772,17 +864,19 @@ class SX126x: public PhysicalLayer {
|
|||
int16_t setTxParams(uint8_t power, uint8_t rampTime = SX126X_PA_RAMP_200U);
|
||||
int16_t setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro = 0xFF);
|
||||
int16_t setModulationParamsFSK(uint32_t br, uint8_t pulseShape, uint8_t rxBw, uint32_t freqDev);
|
||||
int16_t setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_t payloadLength = 0xFF, uint8_t headerType = SX126X_LORA_HEADER_EXPLICIT, uint8_t invertIQ = SX126X_LORA_IQ_STANDARD);
|
||||
int16_t setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_t payloadLength, uint8_t headerType, uint8_t invertIQ = SX126X_LORA_IQ_STANDARD);
|
||||
int16_t setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t whitening, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t payloadLength = 0xFF, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16);
|
||||
int16_t setBufferBaseAddress(uint8_t txBaseAddress = 0x00, uint8_t rxBaseAddress = 0x00);
|
||||
int16_t setRegulatorMode(uint8_t mode);
|
||||
uint8_t getStatus();
|
||||
uint32_t getPacketStatus();
|
||||
uint16_t getDeviceErrors();
|
||||
int16_t clearDeviceErrors();
|
||||
|
||||
int16_t startReceiveCommon();
|
||||
int16_t setFrequencyRaw(float freq);
|
||||
int16_t setOptimalHiPowerPaConfig(int8_t* inOutPower);
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
|
||||
|
||||
// fixes to errata
|
||||
int16_t fixSensitivity();
|
||||
|
@ -795,7 +889,7 @@ class SX126x: public PhysicalLayer {
|
|||
#endif
|
||||
Module* _mod;
|
||||
|
||||
uint8_t _bw, _sf, _cr, _ldro, _crcType;
|
||||
uint8_t _bw, _sf, _cr, _ldro, _crcType, _headerType;
|
||||
uint16_t _preambleLength;
|
||||
float _bwKhz;
|
||||
|
||||
|
@ -806,6 +900,10 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
float _dataRate;
|
||||
|
||||
uint32_t _tcxoDelay;
|
||||
|
||||
size_t _implicitLen;
|
||||
|
||||
int16_t config(uint8_t modem);
|
||||
|
||||
// common low-level SPI interface
|
||||
|
|
|
@ -7,53 +7,34 @@ SX1272::SX1272(Module* mod) : SX127x(mod) {
|
|||
int16_t SX1272::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(SX1272_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// mitigation of receiver spurious response
|
||||
// see SX1272/73 Errata, section 2.2 for details
|
||||
state = _mod->SPIsetRegValue(0x31, 0b10000000, 7, 7);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -61,26 +42,17 @@ int16_t SX1272::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t power, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::beginFSK(SX1272_CHIP_VERSION, br, rxBw, freqDev, currentLimit, preambleLength, enableOOK);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = configFSK();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -326,13 +298,13 @@ int16_t SX1272::setDataShapingOOK(uint8_t sh) {
|
|||
// set data shaping
|
||||
switch(sh) {
|
||||
case 0:
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1272_NO_SHAPING, 4, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_NO_SHAPING, 4, 3);
|
||||
break;
|
||||
case 1:
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1272_OOK_FILTER_BR, 4, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_OOK_FILTER_BR, 4, 3);
|
||||
break;
|
||||
case 2:
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1272_OOK_FILTER_2BR, 4, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_OOK_FILTER_2BR, 4, 3);
|
||||
break;
|
||||
default:
|
||||
state = ERR_INVALID_DATA_SHAPING;
|
||||
|
@ -429,9 +401,7 @@ int16_t SX1272::setCodingRateRaw(uint8_t newCodingRate) {
|
|||
int16_t SX1272::configFSK() {
|
||||
// configure common registers
|
||||
int16_t state = SX127x::configFSK();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set fast PLL hop
|
||||
state = _mod->SPIsetRegValue(SX1272_REG_PLL_HOP, SX127X_FAST_HOP_ON, 7, 7);
|
||||
|
|
|
@ -1,66 +1,47 @@
|
|||
#include "SX1273.h"
|
||||
|
||||
SX1273::SX1273(Module* mod) : SX1272(mod) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
int16_t SX1273::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(SX1272_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// mitigation of receiver spurious response
|
||||
// see SX1272/73 Errata, section 2.2 for details
|
||||
state = _mod->SPIsetRegValue(0x31, 0b10000000, 7, 7);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1273::setSpreadingFactor(uint8_t sf) {
|
||||
uint8_t newSpreadingFactor;
|
||||
|
||||
|
||||
// check allowed spreading factor values
|
||||
switch(sf) {
|
||||
case 6:
|
||||
|
@ -78,12 +59,12 @@ int16_t SX1273::setSpreadingFactor(uint8_t sf) {
|
|||
default:
|
||||
return(ERR_INVALID_SPREADING_FACTOR);
|
||||
}
|
||||
|
||||
|
||||
// set spreading factor and if successful, save the new setting
|
||||
int16_t state = setSpreadingFactorRaw(newSpreadingFactor);
|
||||
if(state == ERR_NONE) {
|
||||
SX127x::_sf = sf;
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
|
|
@ -1,53 +1,36 @@
|
|||
#include "SX1276.h"
|
||||
|
||||
SX1276::SX1276(Module* mod) : SX1278(mod) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
int16_t SX1276::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -56,7 +39,7 @@ int16_t SX1276::setFrequency(float freq) {
|
|||
if((freq < 137.0) || (freq > 1020.0)) {
|
||||
return(ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
|
||||
|
||||
// SX1276/77/78 Errata fixes
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// sensitivity optimization for 500kHz bandwidth
|
||||
|
@ -70,7 +53,7 @@ int16_t SX1276::setFrequency(float freq) {
|
|||
_mod->SPIwriteRegister(0x3a, 0x7F);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mitigation of receiver spurious response
|
||||
// see SX1276/77/78 Errata, section 2.3 for details
|
||||
if(abs(_bw - 7.8) <= 0.001) {
|
||||
|
@ -119,7 +102,7 @@ int16_t SX1276::setFrequency(float freq) {
|
|||
_mod->SPIsetRegValue(0x31, 0b1000000, 7, 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
}
|
||||
|
|
|
@ -1,53 +1,36 @@
|
|||
#include "SX1277.h"
|
||||
|
||||
SX1277::SX1277(Module* mod) : SX1278(mod) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
int16_t SX1277::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -56,7 +39,7 @@ int16_t SX1277::setFrequency(float freq) {
|
|||
if((freq < 137.0) || (freq > 1020.0)) {
|
||||
return(ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
|
||||
|
||||
// SX1276/77/78 Errata fixes
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// sensitivity optimization for 500kHz bandwidth
|
||||
|
@ -70,7 +53,7 @@ int16_t SX1277::setFrequency(float freq) {
|
|||
_mod->SPIwriteRegister(0x3a, 0x7F);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mitigation of receiver spurious response
|
||||
// see SX1276/77/78 Errata, section 2.3 for details
|
||||
if(abs(_bw - 7.8) <= 0.001) {
|
||||
|
@ -119,14 +102,14 @@ int16_t SX1277::setFrequency(float freq) {
|
|||
_mod->SPIsetRegValue(0x31, 0b1000000, 7, 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set frequency and if successful, save the new setting
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
}
|
||||
|
||||
int16_t SX1277::setSpreadingFactor(uint8_t sf) {
|
||||
uint8_t newSpreadingFactor;
|
||||
|
||||
|
||||
// check allowed spreading factor values
|
||||
switch(sf) {
|
||||
case 6:
|
||||
|
@ -144,12 +127,12 @@ int16_t SX1277::setSpreadingFactor(uint8_t sf) {
|
|||
default:
|
||||
return(ERR_INVALID_SPREADING_FACTOR);
|
||||
}
|
||||
|
||||
|
||||
// set spreading factor and if successful, save the new setting
|
||||
int16_t state = SX1278::setSpreadingFactorRaw(newSpreadingFactor);
|
||||
if(state == ERR_NONE) {
|
||||
SX127x::_sf = sf;
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
|
|
@ -7,46 +7,29 @@ SX1278::SX1278(Module* mod) : SX127x(mod) {
|
|||
int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -54,26 +37,17 @@ int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::beginFSK(SX1278_CHIP_VERSION, br, freqDev, rxBw, currentLimit, preambleLength, enableOOK);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = configFSK();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -505,9 +479,7 @@ int16_t SX1278::setCodingRateRaw(uint8_t newCodingRate) {
|
|||
int16_t SX1278::configFSK() {
|
||||
// configure common registers
|
||||
int16_t state = SX127x::configFSK();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set fast PLL hop
|
||||
state = _mod->SPIsetRegValue(SX1278_REG_PLL_HOP, SX127X_FAST_HOP_ON, 7, 7);
|
||||
|
|
|
@ -1,53 +1,36 @@
|
|||
#include "SX1279.h"
|
||||
|
||||
SX1279::SX1279(Module* mod) : SX1278(mod) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
int16_t SX1279::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(SX1278_CHIP_VERSION, syncWord, currentLimit, preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBandwidth(bw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSpreadingFactor(sf);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setGain(gain);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -56,7 +39,7 @@ int16_t SX1279::setFrequency(float freq) {
|
|||
if((freq < 137.0) || (freq > 960.0)) {
|
||||
return(ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
|
||||
|
||||
// set frequency
|
||||
return(SX127x::setFrequencyRaw(freq));
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
#include "SX127x.h"
|
||||
|
||||
SX127x::SX127x(Module* mod) : PhysicalLayer(SX127X_CRYSTAL_FREQ, SX127X_DIV_EXPONENT, SX127X_MAX_PACKET_LENGTH) {
|
||||
SX127x::SX127x(Module* mod) : PhysicalLayer(SX127X_FREQUENCY_STEP_SIZE, SX127X_MAX_PACKET_LENGTH) {
|
||||
_mod = mod;
|
||||
_packetLengthQueried = false;
|
||||
}
|
||||
|
||||
int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimit, uint16_t preambleLength) {
|
||||
// set module properties
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
|
||||
// try to find the SX127x chip
|
||||
if(!SX127x::findChip(chipVersion)) {
|
||||
|
@ -18,33 +20,28 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
|
|||
RADIOLIB_DEBUG_PRINTLN(F("Found SX127x!"));
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check active modem
|
||||
int16_t state;
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
// set LoRa mode
|
||||
state = setActiveModem(SX127X_LORA);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set LoRa sync word
|
||||
state = SX127x::setSyncWord(syncWord);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set over current protection
|
||||
state = SX127x::setCurrentLimit(currentLimit);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set preamble length
|
||||
state = SX127x::setPreambleLength(preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// initalize internal variables
|
||||
_dataRate = 0.0;
|
||||
|
@ -54,7 +51,11 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
|
|||
|
||||
int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
|
||||
// set module properties
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
|
||||
// reset the module
|
||||
reset();
|
||||
|
||||
// try to find the SX127x chip
|
||||
if(!SX127x::findChip(chipVersion)) {
|
||||
|
@ -70,81 +71,64 @@ int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxB
|
|||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
// set FSK mode
|
||||
state = setActiveModem(SX127X_FSK_OOK);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set bit rate
|
||||
state = SX127x::setBitRate(br);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set frequency deviation
|
||||
state = SX127x::setFrequencyDeviation(freqDev);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set receiver bandwidth
|
||||
state = SX127x::setRxBandwidth(rxBw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set over current protection
|
||||
state = SX127x::setCurrentLimit(currentLimit);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set preamble length
|
||||
state = SX127x::setPreambleLength(preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// default sync word value 0x2D01 is the same as the default in LowPowerLab RFM69 library
|
||||
uint8_t syncWord[] = {0x2D, 0x01};
|
||||
state = setSyncWord(syncWord, 2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable address filtering
|
||||
state = disableAddressFiltering();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable/disable OOK
|
||||
state = setOOK(enableOOK);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default RSSI measurement config
|
||||
state = setRSSIConfig(2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default encoding
|
||||
state = setEncoding(0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
void SX127x::reset() {
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
Module::digitalWrite(_mod->getRst(), LOW);
|
||||
delayMicroseconds(100);
|
||||
Module::digitalWrite(_mod->getRst(), HIGH);
|
||||
delay(5);
|
||||
}
|
||||
|
||||
int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// set mode to standby
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
|
@ -166,13 +150,11 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
// start transmission
|
||||
state = startTransmit(data, len, addr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
start = micros();
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
if(micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
|
@ -185,13 +167,11 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
// start transmission
|
||||
state = startTransmit(data, len, addr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission end or timeout
|
||||
start = micros();
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
if(micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
standby();
|
||||
|
@ -221,13 +201,11 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
if(modem == SX127X_LORA) {
|
||||
// set mode to receive
|
||||
state = startReceive(len, SX127X_RXSINGLE);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout (100 LoRa symbols)
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
if(digitalRead(_mod->getInt1())) {
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
if(digitalRead(_mod->getGpio())) {
|
||||
clearIRQFlags();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
|
@ -239,13 +217,11 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
|
||||
// set mode to receive
|
||||
state = startReceive(len, SX127X_RX);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
if(micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
|
@ -267,22 +243,22 @@ int16_t SX127x::scanChannel() {
|
|||
|
||||
// set mode to standby
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set DIO pin mapping
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_CAD_DONE | SX127X_DIO1_CAD_DETECTED, 7, 4);
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_CAD_DONE | SX127X_DIO1_CAD_DETECTED, 7, 4);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
||||
// set mode to CAD
|
||||
state |= setMode(SX127X_CAD);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
state = setMode(SX127X_CAD);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for channel activity detected or timeout
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
if(digitalRead(_mod->getInt1())) {
|
||||
while(!digitalRead(_mod->getIrq())) {
|
||||
if(digitalRead(_mod->getGpio())) {
|
||||
clearIRQFlags();
|
||||
return(PREAMBLE_DETECTED);
|
||||
}
|
||||
|
@ -321,9 +297,7 @@ int16_t SX127x::transmitDirect(uint32_t FRF) {
|
|||
|
||||
// activate direct mode
|
||||
int16_t state = directMode();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start transmitting
|
||||
return(setMode(SX127X_TX));
|
||||
|
@ -337,9 +311,7 @@ int16_t SX127x::receiveDirect() {
|
|||
|
||||
// activate direct mode
|
||||
int16_t state = directMode();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start receiving
|
||||
return(setMode(SX127X_RX));
|
||||
|
@ -348,16 +320,14 @@ int16_t SX127x::receiveDirect() {
|
|||
int16_t SX127x::directMode() {
|
||||
// set mode to standby
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set DIO mapping
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO1_CONT_DCLK | SX127X_DIO2_CONT_DATA, 5, 2);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set continuous mode
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_2, SX127X_DATA_MODE_CONTINUOUS, 6, 6);
|
||||
return(state);
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_2, SX127X_DATA_MODE_CONTINUOUS, 6, 6));
|
||||
}
|
||||
|
||||
int16_t SX127x::packetMode() {
|
||||
|
@ -389,9 +359,7 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
|||
// set FIFO pointers
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_RX_BASE_ADDR, SX127X_FIFO_RX_BASE_ADDR_MAX);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_RX_BASE_ADDR_MAX);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// set DIO pin mapping
|
||||
|
@ -411,11 +379,25 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
|||
}
|
||||
|
||||
void SX127x::setDio0Action(void (*func)(void)) {
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getInt0()), func, RISING);
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getIrq()), func, RISING);
|
||||
}
|
||||
|
||||
void SX127x::clearDio0Action() {
|
||||
detachInterrupt(digitalPinToInterrupt(_mod->getIrq()));
|
||||
}
|
||||
|
||||
void SX127x::setDio1Action(void (*func)(void)) {
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getInt1()), func, RISING);
|
||||
if(_mod->getGpio() != NC) {
|
||||
return;
|
||||
}
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getGpio()), func, RISING);
|
||||
}
|
||||
|
||||
void SX127x::clearDio1Action() {
|
||||
if(_mod->getGpio() != NC) {
|
||||
return;
|
||||
}
|
||||
detachInterrupt(digitalPinToInterrupt(_mod->getGpio()));
|
||||
}
|
||||
|
||||
int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -447,9 +429,7 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
// start transmission
|
||||
state |= setMode(SX127X_TX);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(ERR_NONE);
|
||||
|
||||
|
@ -479,9 +459,7 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
// start transmission
|
||||
state |= setMode(SX127X_TX);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
@ -579,9 +557,7 @@ int16_t SX127x::setCurrentLimit(uint8_t currentLimit) {
|
|||
int16_t SX127x::setPreambleLength(uint16_t preambleLength) {
|
||||
// set mode to standby
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check active modem
|
||||
uint8_t modem = getActiveModem();
|
||||
|
@ -693,9 +669,7 @@ int16_t SX127x::setBitRate(float br) {
|
|||
|
||||
// set mode to STANDBY
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set bit rate
|
||||
uint16_t bitRate = (SX127X_CRYSTAL_FREQ * 1000.0) / br;
|
||||
|
@ -722,9 +696,7 @@ int16_t SX127x::setFrequencyDeviation(float freqDev) {
|
|||
|
||||
// set mode to STANDBY
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set allowed frequency deviation
|
||||
uint32_t base = 1;
|
||||
|
@ -747,9 +719,7 @@ int16_t SX127x::setRxBandwidth(float rxBw) {
|
|||
|
||||
// set mode to STANDBY
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// calculate exponent and mantissa values
|
||||
for(uint8_t e = 7; e >= 1; e--) {
|
||||
|
@ -758,9 +728,7 @@ int16_t SX127x::setRxBandwidth(float rxBw) {
|
|||
if(abs(rxBw - ((point / 1000.0) + 0.05)) <= 0.5) {
|
||||
// set Rx bandwidth during AFC
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_AFC_BW, (m << 3) | e, 4, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set Rx bandwidth
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_RX_BW, (m << 3) | e, 4, 0);
|
||||
|
@ -796,9 +764,7 @@ int16_t SX127x::setSyncWord(uint8_t* syncWord, size_t len) {
|
|||
// enable sync word recognition
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_SYNC_CONFIG, SX127X_SYNC_ON, 4, 4);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_SYNC_CONFIG, len - 1, 2, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set sync word
|
||||
_mod->SPIwriteRegisterBurst(SX127X_REG_SYNC_VALUE_1, syncWord, len);
|
||||
|
@ -813,9 +779,7 @@ int16_t SX127x::setNodeAddress(uint8_t nodeAddr) {
|
|||
|
||||
// enable address filtering (node only)
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_ADDRESS_FILTERING_NODE, 2, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set node address
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_NODE_ADRS, nodeAddr));
|
||||
|
@ -829,9 +793,7 @@ int16_t SX127x::setBroadcastAddress(uint8_t broadAddr) {
|
|||
|
||||
// enable address filtering (node + broadcast)
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_ADDRESS_FILTERING_NODE_BROADCAST, 2, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set broadcast address
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_BROADCAST_ADRS, broadAddr));
|
||||
|
@ -845,15 +807,11 @@ int16_t SX127x::disableAddressFiltering() {
|
|||
|
||||
// disable address filtering
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_ADDRESS_FILTERING_OFF, 2, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set node address to default (0x00)
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_NODE_ADRS, 0x00);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set broadcast address to default (0x00)
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_BROADCAST_ADRS, 0x00));
|
||||
|
@ -933,9 +891,7 @@ int16_t SX127x::setRSSIConfig(uint8_t smoothingSamples, int8_t offset) {
|
|||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check provided values
|
||||
if(!(smoothingSamples <= 7)) {
|
||||
|
@ -980,9 +936,7 @@ int16_t SX127x::config() {
|
|||
int16_t SX127x::configFSK() {
|
||||
// set RSSI threshold
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_RSSI_THRESH, SX127X_RSSI_THRESHOLD);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// reset FIFO flag
|
||||
_mod->SPIwriteRegister(SX127X_REG_IRQ_FLAGS_2, SX127X_FLAG_FIFO_OVERRUN);
|
||||
|
@ -990,38 +944,27 @@ int16_t SX127x::configFSK() {
|
|||
// 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_2, SX127X_DATA_MODE_PACKET | SX127X_IO_HOME_OFF, 6, 5);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set preamble polarity
|
||||
state =_mod->SPIsetRegValue(SX127X_REG_SYNC_CONFIG, SX127X_PREAMBLE_POLARITY_55, 5, 5);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set FIFO threshold
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_FIFO_THRESH, SX127X_TX_START_FIFO_NOT_EMPTY, 7, 7);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_THRESH, SX127X_FIFO_THRESH, 5, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable Rx timeouts
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_RX_TIMEOUT_1, SX127X_TIMEOUT_RX_RSSI_OFF);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_RX_TIMEOUT_2, SX127X_TIMEOUT_RX_PREAMBLE_OFF);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_RX_TIMEOUT_3, SX127X_TIMEOUT_SIGNAL_SYNC_OFF);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable preamble detector and set preamble length
|
||||
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);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -1039,15 +982,11 @@ int16_t SX127x::setPacketMode(uint8_t mode, uint8_t len) {
|
|||
|
||||
// set to fixed packet length
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, mode, 7, 7);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH_FSK, len);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update cached value
|
||||
_packetLengthConfig = mode;
|
||||
|
@ -1058,6 +997,10 @@ bool SX127x::findChip(uint8_t ver) {
|
|||
uint8_t i = 0;
|
||||
bool flagFound = false;
|
||||
while((i < 10) && !flagFound) {
|
||||
// reset the module
|
||||
reset();
|
||||
|
||||
// check version register
|
||||
uint8_t version = _mod->SPIreadRegister(SX127X_REG_VERSION);
|
||||
if(version == ver) {
|
||||
flagFound = true;
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// SX127x physical layer properties
|
||||
#define SX127X_CRYSTAL_FREQ 32.0
|
||||
#define SX127X_DIV_EXPONENT 19
|
||||
#define SX127X_FREQUENCY_STEP_SIZE 61.03515625
|
||||
#define SX127X_MAX_PACKET_LENGTH 255
|
||||
#define SX127X_MAX_PACKET_LENGTH_FSK 64
|
||||
#define SX127X_CRYSTAL_FREQ 32.0
|
||||
#define SX127X_DIV_EXPONENT 19
|
||||
|
||||
// SX127x series common LoRa registers
|
||||
#define SX127X_REG_FIFO 0x00
|
||||
|
@ -563,6 +564,11 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimit, uint16_t preambleLength);
|
||||
|
||||
/*!
|
||||
\brief Reset method. Will reset the chip to the default state using RST pin.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem. Will be called with appropriate parameters when calling FSK initialization method from derived class.
|
||||
|
||||
|
@ -667,6 +673,11 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
void setDio0Action(void (*func)(void));
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when DIO0 activates.
|
||||
*/
|
||||
void clearDio0Action();
|
||||
|
||||
/*!
|
||||
\brief Set interrupt service routine function to call when DIO1 activates.
|
||||
|
||||
|
@ -674,6 +685,11 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
void setDio1Action(void (*func)(void));
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when DIO1 activates.
|
||||
*/
|
||||
void clearDio1Action();
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method. Will start transmitting arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem.
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ XBee::XBee(Module* mod) {
|
|||
int16_t XBee::begin(long speed) {
|
||||
// set module properties
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_1);
|
||||
_mod->init(RADIOLIB_USE_UART);
|
||||
|
||||
// reset module
|
||||
reset();
|
||||
|
@ -52,11 +52,10 @@ int16_t XBee::begin(long speed) {
|
|||
}
|
||||
|
||||
void XBee::reset() {
|
||||
pinMode(_mod->getInt1(), OUTPUT);
|
||||
digitalWrite(_mod->getInt1(), LOW);
|
||||
pinMode(_mod->getRst(), OUTPUT);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
delayMicroseconds(200);
|
||||
digitalWrite(_mod->getInt1(), HIGH);
|
||||
pinMode(_mod->getInt1(), INPUT);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
}
|
||||
|
||||
int16_t XBee::transmit(uint8_t* dest, const char* payload, uint8_t radius) {
|
||||
|
@ -173,9 +172,7 @@ int16_t XBee::setPanId(uint8_t* panId) {
|
|||
|
||||
// get response code
|
||||
int16_t state = readApiFrame(frameID, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// confirm changes
|
||||
return(confirmChanges());
|
||||
|
@ -189,7 +186,10 @@ int16_t XBeeSerial::begin(long speed) {
|
|||
// set module properties
|
||||
_mod->AtLineFeed = "\r";
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
_mod->init(RADIOLIB_USE_UART);
|
||||
|
||||
// reset module
|
||||
reset();
|
||||
|
||||
// empty UART buffer (garbage data)
|
||||
_mod->ATemptyBuffer();
|
||||
|
@ -216,11 +216,11 @@ int16_t XBeeSerial::begin(long speed) {
|
|||
}
|
||||
|
||||
void XBeeSerial::reset() {
|
||||
pinMode(_mod->getInt1(), OUTPUT);
|
||||
digitalWrite(_mod->getInt1(), LOW);
|
||||
pinMode(_mod->getRst(), OUTPUT);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
delayMicroseconds(200);
|
||||
digitalWrite(_mod->getInt1(), HIGH);
|
||||
pinMode(_mod->getInt1(), INPUT);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
pinMode(_mod->getRst(), INPUT);
|
||||
}
|
||||
|
||||
int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) {
|
||||
|
@ -340,9 +340,7 @@ int16_t XBee::confirmChanges() {
|
|||
|
||||
// get response code
|
||||
int16_t state = readApiFrame(frameID, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// apply changes
|
||||
frameID = _frameID++;
|
||||
|
@ -350,9 +348,6 @@ int16_t XBee::confirmChanges() {
|
|||
|
||||
// get response code
|
||||
state = readApiFrame(frameID, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "nRF24.h"
|
||||
|
||||
nRF24::nRF24(Module* mod) : PhysicalLayer(NRF24_CRYSTAL_FREQ, NRF24_DIV_EXPONENT, NRF24_MAX_PACKET_LENGTH) {
|
||||
nRF24::nRF24(Module* mod) : PhysicalLayer(NRF24_FREQUENCY_STEP_SIZE, NRF24_MAX_PACKET_LENGTH) {
|
||||
_mod = mod;
|
||||
}
|
||||
|
||||
|
@ -8,18 +8,18 @@ int16_t nRF24::begin(int16_t freq, int16_t dataRate, int8_t power, uint8_t addrW
|
|||
// set module properties
|
||||
_mod->SPIreadCommand = NRF24_CMD_READ;
|
||||
_mod->SPIwriteCommand = NRF24_CMD_WRITE;
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
|
||||
// override pin mode on INT0 (connected to nRF24 CE pin)
|
||||
pinMode(_mod->getInt0(), OUTPUT);
|
||||
digitalWrite(_mod->getInt0(), LOW);
|
||||
// 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);
|
||||
|
||||
// check SPI connection
|
||||
int16_t val = _mod->SPIgetRegValue(NRF24_REG_SETUP_AW);
|
||||
if(!((val >= 1) && (val <= 3))) {
|
||||
if(!((val >= 0) && (val <= 3))) {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No nRF24 found!"));
|
||||
_mod->term();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
|
@ -27,39 +27,25 @@ int16_t nRF24::begin(int16_t freq, int16_t dataRate, int8_t power, uint8_t addrW
|
|||
|
||||
// configure settings inaccessible by public API
|
||||
int16_t state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set mode to standby
|
||||
state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
// set frequency
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set data rate
|
||||
state = setDataRate(dataRate);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set address width
|
||||
state = setAddressWidth(addrWidth);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -72,7 +58,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->getInt0(), LOW);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
|
||||
// use standby-1 mode
|
||||
return(_mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_POWER_UP, 1, 1));
|
||||
|
@ -81,13 +67,11 @@ int16_t nRF24::standby() {
|
|||
int16_t nRF24::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// start transmission
|
||||
int16_t state = startTransmit(data, len, addr);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait until transmission is finished
|
||||
uint32_t start = micros();
|
||||
while(digitalRead(_mod->getInt1())) {
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
// check maximum number of retransmits
|
||||
if(getStatus(NRF24_MAX_RT)) {
|
||||
standby();
|
||||
|
@ -112,13 +96,11 @@ int16_t nRF24::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t nRF24::receive(uint8_t* data, size_t len) {
|
||||
// start reception
|
||||
int16_t state = startReceive();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for Rx_DataReady or timeout
|
||||
uint32_t start = micros();
|
||||
while(digitalRead(_mod->getInt1())) {
|
||||
while(digitalRead(_mod->getIrq())) {
|
||||
// check timeout: 15 retries * 4ms (max Tx time as per datasheet)
|
||||
if(micros() - start >= 60000) {
|
||||
standby();
|
||||
|
@ -142,7 +124,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->getInt0(), HIGH);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -153,7 +135,7 @@ int16_t nRF24::receiveDirect() {
|
|||
}
|
||||
|
||||
void nRF24::setIrqAction(void (*func)(void)) {
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getInt1()), func, FALLING);
|
||||
attachInterrupt(digitalPinToInterrupt(_mod->getIrq()), func, FALLING);
|
||||
}
|
||||
|
||||
int16_t nRF24::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
|
@ -167,9 +149,7 @@ int16_t nRF24::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable primary Tx mode
|
||||
state = _mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_PTX, 0, 0);
|
||||
|
@ -179,9 +159,7 @@ int16_t nRF24::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
// enable Tx_DataSent interrupt
|
||||
state |= _mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_MASK_TX_DS_IRQ_ON, 5, 5);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// flush Tx FIFO
|
||||
SPItransfer(NRF24_CMD_FLUSH_TX);
|
||||
|
@ -193,9 +171,9 @@ int16_t nRF24::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
SPIwriteTxPayload(data, len);
|
||||
|
||||
// CE high to start transmitting
|
||||
digitalWrite(_mod->getInt0(), HIGH);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
delayMicroseconds(10);
|
||||
digitalWrite(_mod->getInt0(), LOW);
|
||||
digitalWrite(_mod->getRst(), LOW);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -203,28 +181,22 @@ int16_t nRF24::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t nRF24::startReceive() {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable primary Rx mode
|
||||
state = _mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_PRX, 0, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable Rx_DataReady interrupt
|
||||
clearIRQ();
|
||||
state |= _mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_MASK_RX_DR_IRQ_ON, 6, 6);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
state = _mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_MASK_RX_DR_IRQ_ON, 6, 6);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// flush Rx FIFO
|
||||
SPItransfer(NRF24_CMD_FLUSH_RX);
|
||||
|
||||
// CE high to start receiving
|
||||
digitalWrite(_mod->getInt0(), HIGH);
|
||||
digitalWrite(_mod->getRst(), HIGH);
|
||||
|
||||
// wait to enter Rx state
|
||||
delayMicroseconds(130);
|
||||
|
@ -235,9 +207,7 @@ int16_t nRF24::startReceive() {
|
|||
int16_t nRF24::readData(uint8_t* data, size_t len) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// get packet length
|
||||
size_t length = len;
|
||||
|
@ -248,9 +218,6 @@ int16_t nRF24::readData(uint8_t* data, size_t len) {
|
|||
// read packet data
|
||||
SPIreadRxPayload(data, length);
|
||||
|
||||
// add terminating null
|
||||
data[length] = 0;
|
||||
|
||||
// clear interrupt
|
||||
clearIRQ();
|
||||
|
||||
|
@ -265,9 +232,7 @@ int16_t nRF24::setFrequency(int16_t freq) {
|
|||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set frequency
|
||||
uint8_t freqRaw = freq - 2400;
|
||||
|
@ -278,9 +243,7 @@ int16_t nRF24::setFrequency(int16_t freq) {
|
|||
int16_t nRF24::setDataRate(int16_t dataRate) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set data rate
|
||||
if(dataRate == 250) {
|
||||
|
@ -302,9 +265,7 @@ int16_t nRF24::setDataRate(int16_t dataRate) {
|
|||
int16_t nRF24::setOutputPower(int8_t power) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check allowed values
|
||||
uint8_t powerRaw = 0;
|
||||
|
@ -333,12 +294,15 @@ int16_t nRF24::setOutputPower(int8_t power) {
|
|||
int16_t nRF24::setAddressWidth(uint8_t addrWidth) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set address width
|
||||
switch(addrWidth) {
|
||||
case 2:
|
||||
// Even if marked as 'Illegal' on the datasheet this will work:
|
||||
// http://travisgoodspeed.blogspot.com/2011/02/promiscuity-is-nrf24l01s-duty.html
|
||||
state = _mod->SPIsetRegValue(NRF24_REG_SETUP_AW, NRF24_ADDRESS_2_BYTES, 1, 0);
|
||||
break;
|
||||
case 3:
|
||||
state = _mod->SPIsetRegValue(NRF24_REG_SETUP_AW, NRF24_ADDRESS_3_BYTES, 1, 0);
|
||||
break;
|
||||
|
@ -361,9 +325,7 @@ int16_t nRF24::setAddressWidth(uint8_t addrWidth) {
|
|||
int16_t nRF24::setTransmitPipe(uint8_t* addr) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set transmit address
|
||||
_mod->SPIwriteRegisterBurst(NRF24_REG_TX_ADDR, addr, _addrWidth);
|
||||
|
@ -377,9 +339,7 @@ int16_t nRF24::setTransmitPipe(uint8_t* addr) {
|
|||
int16_t nRF24::setReceivePipe(uint8_t pipeNum, uint8_t* addr) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// write full pipe 0 - 1 address and enable the pipe
|
||||
switch(pipeNum) {
|
||||
|
@ -401,9 +361,7 @@ int16_t nRF24::setReceivePipe(uint8_t pipeNum, uint8_t* addr) {
|
|||
int16_t nRF24::setReceivePipe(uint8_t pipeNum, uint8_t addrByte) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// write unique pipe 2 - 5 address and enable the pipe
|
||||
switch(pipeNum) {
|
||||
|
@ -433,9 +391,7 @@ int16_t nRF24::setReceivePipe(uint8_t pipeNum, uint8_t addrByte) {
|
|||
int16_t nRF24::disablePipe(uint8_t pipeNum) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
switch(pipeNum) {
|
||||
case 0:
|
||||
|
@ -481,6 +437,53 @@ size_t nRF24::getPacketLength(bool update) {
|
|||
return((size_t)length);
|
||||
}
|
||||
|
||||
int16_t nRF24::setCrcFiltering(bool crcOn) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
case 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);
|
||||
break;
|
||||
case 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);
|
||||
break;
|
||||
case 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);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t nRF24::setDataShaping(float sh) {
|
||||
// nRF24 is unable to set data shaping
|
||||
// this method is implemented only for PhysicalLayer compatibility
|
||||
(void)sh;
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t nRF24::setEncoding(uint8_t encoding) {
|
||||
// nRF24 is unable to set encoding
|
||||
// this method is implemented only for PhysicalLayer compatibility
|
||||
(void)encoding;
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
void nRF24::clearIRQ() {
|
||||
// clear status bits
|
||||
_mod->SPIsetRegValue(NRF24_REG_STATUS, NRF24_RX_DR | NRF24_TX_DS | NRF24_MAX_RT, 6, 4);
|
||||
|
@ -492,27 +495,18 @@ void nRF24::clearIRQ() {
|
|||
int16_t nRF24::config() {
|
||||
// enable 16-bit CRC
|
||||
int16_t state = _mod->SPIsetRegValue(NRF24_REG_CONFIG, NRF24_CRC_ON | NRF24_CRC_16, 3, 2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set 15 retries and delay 1500 (5*250) us
|
||||
_mod->SPIsetRegValue(NRF24_REG_SETUP_RETR, (5 << 4) | 5);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set features: dynamic payload on, payload with ACK packets off, dynamic ACK off
|
||||
state = _mod->SPIsetRegValue(NRF24_REG_FEATURE, NRF24_DPL_ON | NRF24_ACK_PAY_OFF | NRF24_DYN_ACK_OFF, 2, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// enable dynamic payloads
|
||||
state = _mod->SPIsetRegValue(NRF24_REG_DYNPD, NRF24_DPL_ALL_ON, 5, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// reset IRQ
|
||||
clearIRQ();
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
|
||||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// nRF24 physical layer properties (dummy only)
|
||||
#define NRF24_CRYSTAL_FREQ 1.0
|
||||
#define NRF24_DIV_EXPONENT 0
|
||||
// nRF24 physical layer properties
|
||||
#define NRF24_FREQUENCY_STEP_SIZE 1000000.0
|
||||
#define NRF24_MAX_PACKET_LENGTH 32
|
||||
|
||||
// nRF24 SPI commands
|
||||
|
@ -69,6 +68,8 @@
|
|||
#define NRF24_PRX 0b00000001 // 0 0 enable primary Rx
|
||||
|
||||
// NRF24_REG_EN_AA
|
||||
#define NRF24_AA_ALL_OFF 0b00000000 // 5 0 auto-ACK on all pipes: disabled
|
||||
#define NRF24_AA_ALL_ON 0b00111111 // 5 0 enabled (default)
|
||||
#define NRF24_AA_P5_OFF 0b00000000 // 5 5 auto-ACK on pipe 5: disabled
|
||||
#define NRF24_AA_P5_ON 0b00100000 // 5 5 enabled (default)
|
||||
#define NRF24_AA_P4_OFF 0b00000000 // 4 4 auto-ACK on pipe 4: disabled
|
||||
|
@ -97,7 +98,8 @@
|
|||
#define NRF24_P0_ON 0b00000001 // 0 0 enabled (default)
|
||||
|
||||
// NRF24_REG_SETUP_AW
|
||||
#define NRF24_ADDRESS_3_BYTES 0b00000001 // 1 0 address width: 3 bytes
|
||||
#define NRF24_ADDRESS_2_BYTES 0b00000000 // 1 0 address width: 2 bytes
|
||||
#define NRF24_ADDRESS_3_BYTES 0b00000001 // 1 0 3 bytes
|
||||
#define NRF24_ADDRESS_4_BYTES 0b00000010 // 1 0 4 bytes
|
||||
#define NRF24_ADDRESS_5_BYTES 0b00000011 // 1 0 5 bytes (default)
|
||||
|
||||
|
@ -408,6 +410,54 @@ class nRF24: public PhysicalLayer {
|
|||
*/
|
||||
size_t getPacketLength(bool update = true);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
||||
\param crcOn Set or unset CRC check.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCrcFiltering(bool crcOn = true);
|
||||
|
||||
/*!
|
||||
\brief Enable or disable auto-acknowlede packets on all pipes
|
||||
|
||||
\param autoAckOn Enable (true) or disable (false) auto-acks.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setAutoAck(bool autoAckOn = true);
|
||||
|
||||
/*!
|
||||
\brief Enable or disable auto-acknowlede packets on given pipe.
|
||||
|
||||
\param pipeNum Number of pipe to which enable / disable auto-acks.
|
||||
|
||||
\param autoAckOn Enable (true) or disable (false) auto-acks.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setAutoAck(uint8_t pipeNum, bool autoAckOn = true);
|
||||
|
||||
/*!
|
||||
\brief Dummy data shaping configuration method, to ensure PhysicalLayer compatibility.
|
||||
|
||||
\param sh Ignored.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setDataShaping(float sh);
|
||||
|
||||
/*!
|
||||
\brief Dummy encoding configuration method, to ensure PhysicalLayer compatibility.
|
||||
|
||||
\param sh Ignored.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setEncoding(uint8_t encoding);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
|
382
src/protocols/AX25/AX25.cpp
Normal file
382
src/protocols/AX25/AX25.cpp
Normal file
|
@ -0,0 +1,382 @@
|
|||
#include "AX25.h"
|
||||
|
||||
AX25Frame::AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control)
|
||||
: AX25Frame(destCallsign, destSSID, srcCallsign, srcSSID, control, 0, NULL, 0) {
|
||||
|
||||
}
|
||||
|
||||
AX25Frame::AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, const char* info)
|
||||
: AX25Frame(destCallsign, destSSID, srcCallsign, srcSSID, control, protocolID, (uint8_t*)info, strlen(info)) {
|
||||
|
||||
}
|
||||
|
||||
AX25Frame::AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, uint8_t* info, uint16_t infoLen) {
|
||||
// destination callsign/SSID
|
||||
memcpy(this->destCallsign, destCallsign, strlen(destCallsign));
|
||||
this->destCallsign[strlen(destCallsign)] = '\0';
|
||||
this->destSSID = destSSID;
|
||||
|
||||
// source callsign/SSID
|
||||
memcpy(this->srcCallsign, srcCallsign, strlen(srcCallsign));
|
||||
this->srcCallsign[strlen(srcCallsign)] = '\0';
|
||||
this->srcSSID = srcSSID;
|
||||
|
||||
// set repeaters
|
||||
this->numRepeaters = 0;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
this->repeaterCallsigns = NULL;
|
||||
this->repeaterSSIDs = NULL;
|
||||
#endif
|
||||
|
||||
// control field
|
||||
this->control = control;
|
||||
|
||||
// sequence numbers
|
||||
this->rcvSeqNumber = 0;
|
||||
this->sendSeqNumber = 0;
|
||||
|
||||
// PID field
|
||||
this->protocolID = protocolID;
|
||||
|
||||
// info field
|
||||
this->infoLen = infoLen;
|
||||
if(infoLen > 0) {
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
this->info = new uint8_t[infoLen];
|
||||
#endif
|
||||
memcpy(this->info, info, infoLen);
|
||||
}
|
||||
}
|
||||
|
||||
AX25Frame::~AX25Frame() {
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
// deallocate info field
|
||||
if(infoLen > 0) {
|
||||
delete[] this->info;
|
||||
}
|
||||
|
||||
// deallocate repeaters
|
||||
if(this->numRepeaters > 0) {
|
||||
for(uint8_t i = 0; i < this->numRepeaters; i++) {
|
||||
delete[] this->repeaterCallsigns[i];
|
||||
}
|
||||
delete[] this->repeaterCallsigns;
|
||||
delete[] this->repeaterSSIDs;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t AX25Frame::setRepeaters(char** repeaterCallsigns, uint8_t* repeaterSSIDs, uint8_t numRepeaters) {
|
||||
// check number of repeaters
|
||||
if((numRepeaters < 1) || (numRepeaters > 8)) {
|
||||
return(ERR_INVALID_NUM_REPEATERS);
|
||||
}
|
||||
|
||||
// check repeater configuration
|
||||
if(!(((repeaterCallsigns == NULL) && (repeaterSSIDs == NULL) && (numRepeaters == 0)) ||
|
||||
((repeaterCallsigns != NULL) && (repeaterSSIDs != NULL) && (numRepeaters != 0)))) {
|
||||
return(ERR_INVALID_NUM_REPEATERS);
|
||||
}
|
||||
for(uint16_t i = 0; i < numRepeaters; i++) {
|
||||
if(strlen(repeaterCallsigns[i]) > AX25_MAX_CALLSIGN_LEN) {
|
||||
return(ERR_INVALID_REPEATER_CALLSIGN);
|
||||
}
|
||||
}
|
||||
|
||||
// create buffers
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
this->repeaterCallsigns = new char*[numRepeaters];
|
||||
for(uint8_t i = 0; i < numRepeaters; i++) {
|
||||
this->repeaterCallsigns[i] = new char[strlen(repeaterCallsigns[i])];
|
||||
}
|
||||
this->repeaterSSIDs = new uint8_t[numRepeaters];
|
||||
#endif
|
||||
|
||||
// copy data
|
||||
this->numRepeaters = numRepeaters;
|
||||
for(uint8_t i = 0; i < numRepeaters; i++) {
|
||||
memcpy(this->repeaterCallsigns[i], repeaterCallsigns[i], strlen(repeaterCallsigns[i]));
|
||||
}
|
||||
memcpy(this->repeaterSSIDs, repeaterSSIDs, numRepeaters);
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
void AX25Frame::setRecvSequence(uint8_t seqNumber) {
|
||||
this->rcvSeqNumber = seqNumber;
|
||||
}
|
||||
|
||||
void AX25Frame::setSendSequence(uint8_t seqNumber) {
|
||||
this->sendSeqNumber = seqNumber;
|
||||
}
|
||||
|
||||
AX25Client::AX25Client(PhysicalLayer* phy) {
|
||||
_phy = phy;
|
||||
}
|
||||
|
||||
int16_t AX25Client::begin(const char* srcCallsign, uint8_t srcSSID, uint8_t preambleLen) {
|
||||
// set source SSID
|
||||
_srcSSID = srcSSID;
|
||||
|
||||
// check source callsign length (6 characters max)
|
||||
if(strlen(srcCallsign) > AX25_MAX_CALLSIGN_LEN) {
|
||||
return(ERR_INVALID_CALLSIGN);
|
||||
}
|
||||
|
||||
// copy callsign
|
||||
memcpy(_srcCallsign, srcCallsign, strlen(srcCallsign));
|
||||
_srcCallsign[strlen(srcCallsign)] = '\0';
|
||||
|
||||
// save preamble length
|
||||
_preambleLen = preambleLen;
|
||||
|
||||
// disable physical layer data shaping and set encoding to NRZ
|
||||
int16_t state = _phy->setDataShaping(0.0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = _phy->setEncoding(0);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t AX25Client::transmit(const char* str, const char* destCallsign, uint8_t destSSID) {
|
||||
// create control field
|
||||
uint8_t controlField = AX25_CONTROL_U_UNNUMBERED_INFORMATION | AX25_CONTROL_POLL_FINAL_DISABLED | AX25_CONTROL_UNNUMBERED_FRAME;
|
||||
|
||||
// build the frame
|
||||
AX25Frame frame(destCallsign, destSSID, _srcCallsign, _srcSSID, controlField, AX25_PID_NO_LAYER_3, (uint8_t*)str, strlen(str));
|
||||
|
||||
// send Unnumbered Information frame
|
||||
return(sendFrame(&frame));
|
||||
}
|
||||
|
||||
int16_t AX25Client::sendFrame(AX25Frame* frame) {
|
||||
// check destination callsign length (6 characters max)
|
||||
if(strlen(frame->destCallsign) > AX25_MAX_CALLSIGN_LEN) {
|
||||
return(ERR_INVALID_CALLSIGN);
|
||||
}
|
||||
|
||||
// check repeater configuration
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
if(!(((frame->repeaterCallsigns == NULL) && (frame->repeaterSSIDs == NULL) && (frame->numRepeaters == 0)) ||
|
||||
((frame->repeaterCallsigns != NULL) && (frame->repeaterSSIDs != NULL) && (frame->numRepeaters != 0)))) {
|
||||
return(ERR_INVALID_NUM_REPEATERS);
|
||||
}
|
||||
for(uint16_t i = 0; i < frame->numRepeaters; i++) {
|
||||
if(strlen(frame->repeaterCallsigns[i]) > AX25_MAX_CALLSIGN_LEN) {
|
||||
return(ERR_INVALID_REPEATER_CALLSIGN);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// calculate frame length without FCS (destination address, source address, repeater addresses, control, PID, info)
|
||||
size_t frameBuffLen = ((2 + frame->numRepeaters)*(AX25_MAX_CALLSIGN_LEN + 1)) + 1 + 1 + frame->infoLen;
|
||||
// create frame buffer without preamble, start or stop flags
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
uint8_t* frameBuff = new uint8_t[frameBuffLen + 2];
|
||||
#else
|
||||
uint8_t frameBuff[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#endif
|
||||
uint8_t* frameBuffPtr = frameBuff;
|
||||
|
||||
// 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++) {
|
||||
*(frameBuffPtr + i) = frame->destCallsign[i] << 1;
|
||||
}
|
||||
frameBuffPtr += AX25_MAX_CALLSIGN_LEN;
|
||||
|
||||
// set destination SSID
|
||||
*(frameBuffPtr++) = AX25_SSID_COMMAND_DEST | AX25_SSID_RESERVED_BITS | (frame->destSSID & 0x0F) << 1 | AX25_SSID_HDLC_EXTENSION_CONTINUE;
|
||||
|
||||
// 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++) {
|
||||
*(frameBuffPtr + i) = frame->srcCallsign[i] << 1;
|
||||
}
|
||||
frameBuffPtr += AX25_MAX_CALLSIGN_LEN;
|
||||
|
||||
// set source SSID
|
||||
*(frameBuffPtr++) = AX25_SSID_COMMAND_SOURCE | AX25_SSID_RESERVED_BITS | (frame->srcSSID & 0x0F) << 1 | AX25_SSID_HDLC_EXTENSION_END;
|
||||
|
||||
// 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++) {
|
||||
*(frameBuffPtr + j) = frame->repeaterCallsigns[i][j] << 1;
|
||||
}
|
||||
frameBuffPtr += AX25_MAX_CALLSIGN_LEN;
|
||||
*(frameBuffPtr++) = AX25_SSID_HAS_NOT_BEEN_REPEATED | AX25_SSID_RESERVED_BITS | (frame->repeaterSSIDs[i] & 0x0F) << 1 | AX25_SSID_HDLC_EXTENSION_CONTINUE;
|
||||
}
|
||||
|
||||
// set HDLC extension end bit
|
||||
*frameBuffPtr |= AX25_SSID_HDLC_EXTENSION_END;
|
||||
|
||||
// set sequence numbers of the frames that have it
|
||||
uint8_t controlField = frame->control;
|
||||
if((frame->control & 0x01) == 0) {
|
||||
// information frame, set both sequence numbers
|
||||
controlField |= frame->rcvSeqNumber << 5;
|
||||
controlField |= frame->sendSeqNumber << 1;
|
||||
} else if((frame->control & 0x02) == 0) {
|
||||
// supervisory frame, set only receive sequence number
|
||||
controlField |= frame->rcvSeqNumber << 5;
|
||||
}
|
||||
|
||||
// set control field
|
||||
*(frameBuffPtr++) = controlField;
|
||||
|
||||
// set PID field of the frames that have it
|
||||
if(frame->protocolID != 0x00) {
|
||||
*(frameBuffPtr++) = frame->protocolID;
|
||||
}
|
||||
|
||||
// set info field of the frames that have it
|
||||
if(frame->infoLen > 0) {
|
||||
memcpy(frameBuffPtr, frame->info, frame->infoLen);
|
||||
frameBuffPtr += frame->infoLen;
|
||||
}
|
||||
|
||||
// flip bit order
|
||||
for(size_t i = 0; i < frameBuffLen; i++) {
|
||||
frameBuff[i] = flipBits(frameBuff[i]);
|
||||
}
|
||||
|
||||
// calculate FCS
|
||||
uint16_t fcs = getFrameCheckSequence(frameBuff, frameBuffLen);
|
||||
*(frameBuffPtr++) = (uint8_t)((fcs >> 8) & 0xFF);
|
||||
*(frameBuffPtr++) = (uint8_t)(fcs & 0xFF);
|
||||
|
||||
// prepare buffer for the final frame (stuffed, with added preamble + flags and NRZI-encoded)
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
// worst-case scenario: sequence of 1s, will have 120% of the original length, stuffed frame also includes both flags
|
||||
uint8_t* stuffedFrameBuff = new uint8_t[_preambleLen + 1 + (6*frameBuffLen)/5 + 2];
|
||||
#else
|
||||
uint8_t stuffedFrameBuff[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#endif
|
||||
|
||||
// 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(int8_t shift = 7; shift >= 0; shift--) {
|
||||
uint16_t stuffedFrameBuffPos = stuffedFrameBuffLenBits + 7 - 2*(stuffedFrameBuffLenBits%8);
|
||||
if((frameBuff[i] >> shift) & 0x01) {
|
||||
// copy 1 and increment counter
|
||||
SET_BIT_IN_ARRAY(stuffedFrameBuff, stuffedFrameBuffPos);
|
||||
stuffedFrameBuffLenBits++;
|
||||
count++;
|
||||
|
||||
// check 5 consecutive 1s
|
||||
if(count == 5) {
|
||||
// get the new position in stuffed frame
|
||||
stuffedFrameBuffPos = stuffedFrameBuffLenBits + 7 - 2*(stuffedFrameBuffLenBits%8);
|
||||
|
||||
// insert 0 and reset counter
|
||||
CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, stuffedFrameBuffPos);
|
||||
stuffedFrameBuffLenBits++;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
// copy 0 and reset counter
|
||||
CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, stuffedFrameBuffPos);
|
||||
stuffedFrameBuffLenBits++;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// deallocate memory
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] frameBuff;
|
||||
#endif
|
||||
|
||||
// set preamble bytes and start flag field
|
||||
for(uint16_t i = 0; i < _preambleLen + 1; i++) {
|
||||
stuffedFrameBuff[i] = AX25_FLAG;
|
||||
}
|
||||
|
||||
// get stuffed frame length in bytes
|
||||
size_t stuffedFrameBuffLen = stuffedFrameBuffLenBits/8 + 1;
|
||||
uint8_t trailingLen = stuffedFrameBuffLenBits % 8;
|
||||
|
||||
// set end flag field (may be split into two bytes due to misalignment caused by extra stuffing bits)
|
||||
if(trailingLen != 0) {
|
||||
stuffedFrameBuffLen++;
|
||||
stuffedFrameBuff[stuffedFrameBuffLen - 2] = AX25_FLAG >> trailingLen;
|
||||
stuffedFrameBuff[stuffedFrameBuffLen - 1] = AX25_FLAG << (8 - trailingLen);
|
||||
} else {
|
||||
stuffedFrameBuff[stuffedFrameBuffLen - 1] = AX25_FLAG;
|
||||
}
|
||||
|
||||
// convert to NRZI
|
||||
for(size_t i = _preambleLen + 1; i < stuffedFrameBuffLen*8; i++) {
|
||||
size_t currBitPos = i + 7 - 2*(i%8);
|
||||
size_t prevBitPos = (i - 1) + 7 - 2*((i - 1)%8);
|
||||
if(TEST_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos)) {
|
||||
// bit is 1, no change, copy previous bit
|
||||
if(TEST_BIT_IN_ARRAY(stuffedFrameBuff, prevBitPos)) {
|
||||
SET_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos);
|
||||
} else {
|
||||
CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos);
|
||||
}
|
||||
|
||||
} else {
|
||||
// bit is 0, transition, copy inversion of the previous bit
|
||||
if(TEST_BIT_IN_ARRAY(stuffedFrameBuff, prevBitPos)) {
|
||||
CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos);
|
||||
} else {
|
||||
SET_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// transmit
|
||||
int16_t state = _phy->transmit(stuffedFrameBuff, stuffedFrameBuffLen);
|
||||
|
||||
// deallocate memory
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] stuffedFrameBuff;
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
/*
|
||||
CCITT CRC implementation based on https://github.com/kicksat/ax25
|
||||
|
||||
Licensed under Creative Commons Attribution-ShareAlike 4.0 International
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
*/
|
||||
uint16_t AX25Client::getFrameCheckSequence(uint8_t* buff, size_t len) {
|
||||
uint8_t outBit = 0;
|
||||
uint16_t mask = 0x0000;
|
||||
uint16_t shiftReg = CRC_CCITT_INIT;
|
||||
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
for(uint8_t b = 0x80; b > 0x00; b /= 2) {
|
||||
outBit = (shiftReg & 0x01) ? 0x01 : 0x00;
|
||||
shiftReg >>= 1;
|
||||
mask = XOR((buff[i] & b), outBit) ? CRC_CCITT_POLY_REVERSED : 0x0000;
|
||||
shiftReg ^= mask;
|
||||
}
|
||||
}
|
||||
|
||||
return(flipBits16(~shiftReg));
|
||||
}
|
||||
|
||||
uint8_t AX25Client::flipBits(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
uint16_t AX25Client::flipBits16(uint16_t i) {
|
||||
i = (i & 0xFF00) >> 8 | (i & 0x00FF) << 8;
|
||||
i = (i & 0xF0F0) >> 4 | (i & 0x0F0F) << 4;
|
||||
i = (i & 0xCCCC) >> 2 | (i & 0x3333) << 2;
|
||||
i = (i & 0xAAAA) >> 1 | (i & 0x5555) << 1;
|
||||
return i;
|
||||
}
|
314
src/protocols/AX25/AX25.h
Normal file
314
src/protocols/AX25/AX25.h
Normal file
|
@ -0,0 +1,314 @@
|
|||
#ifndef _RADIOLIB_AX25_H
|
||||
#define _RADIOLIB_AX25_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
#include "../PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// macros to access bits in byte array, from http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html
|
||||
#define SET_BIT_IN_ARRAY(A, k) ( A[(k/8)] |= (1 << (k%8)) )
|
||||
#define CLEAR_BIT_IN_ARRAY(A, k) ( A[(k/8)] &= ~(1 << (k%8)) )
|
||||
#define TEST_BIT_IN_ARRAY(A, k) ( A[(k/8)] & (1 << (k%8)) )
|
||||
#define GET_BIT_IN_ARRAY(A, k) ( (A[(k/8)] & (1 << (k%8))) ? 1 : 0 )
|
||||
|
||||
// CRC-CCITT calculation macros
|
||||
#define XOR(A, B) ( ((A) || (B)) && !((A) && (B)) )
|
||||
#define CRC_CCITT_POLY 0x1021 // generator polynomial
|
||||
#define CRC_CCITT_POLY_REVERSED 0x8408 // CRC_CCITT_POLY in reversed bit order
|
||||
#define CRC_CCITT_INIT 0xFFFF // initial value
|
||||
|
||||
// maximum callsign length in bytes
|
||||
#define AX25_MAX_CALLSIGN_LEN 6
|
||||
|
||||
// flag field MSB LSB DESCRIPTION
|
||||
#define AX25_FLAG 0b01111110 // 7 0 AX.25 frame start/end flag
|
||||
|
||||
// address field
|
||||
#define AX25_SSID_COMMAND_DEST 0b10000000 // 7 7 frame type: command (set in destination SSID)
|
||||
#define AX25_SSID_COMMAND_SOURCE 0b00000000 // 7 7 command (set in source SSID)
|
||||
#define AX25_SSID_RESPONSE_DEST 0b00000000 // 7 7 response (set in destination SSID)
|
||||
#define AX25_SSID_RESPONSE_SOURCE 0b10000000 // 7 7 response (set in source SSID)
|
||||
#define AX25_SSID_HAS_NOT_BEEN_REPEATED 0b00000000 // 7 7 not repeated yet (set in repeater SSID)
|
||||
#define AX25_SSID_HAS_BEEN_REPEATED 0b10000000 // 7 7 repeated (set in repeater SSID)
|
||||
#define AX25_SSID_RESERVED_BITS 0b01100000 // 6 5 reserved bits in SSID
|
||||
#define AX25_SSID_HDLC_EXTENSION_CONTINUE 0b00000000 // 0 0 HDLC extension bit: next octet contains more address information
|
||||
#define AX25_SSID_HDLC_EXTENSION_END 0b00000001 // 0 0 address field end
|
||||
|
||||
// control field
|
||||
#define AX25_CONTROL_U_SET_ASYNC_BAL_MODE 0b01101100 // 7 2 U frame type: set asynchronous balanced mode (connect request)
|
||||
#define AX25_CONTROL_U_SET_ASYNC_BAL_MODE_EXT 0b00101100 // 7 2 set asynchronous balanced mode extended (connect request with module 128)
|
||||
#define AX25_CONTROL_U_DISCONNECT 0b01000000 // 7 2 disconnect request
|
||||
#define AX25_CONTROL_U_DISCONNECT_MODE 0b00001100 // 7 2 disconnect mode (system busy or disconnected)
|
||||
#define AX25_CONTROL_U_UNNUMBERED_ACK 0b01100000 // 7 2 unnumbered acknowledge
|
||||
#define AX25_CONTROL_U_FRAME_REJECT 0b10000100 // 7 2 frame reject
|
||||
#define AX25_CONTROL_U_UNNUMBERED_INFORMATION 0b00000000 // 7 2 unnumbered information
|
||||
#define AX25_CONTROL_U_EXHANGE_IDENTIFICATION 0b10101100 // 7 2 exchange ID
|
||||
#define AX25_CONTROL_U_TEST 0b11100000 // 7 2 test
|
||||
#define AX25_CONTROL_POLL_FINAL_ENABLED 0b00010000 // 4 4 control field poll/final bit: enabled
|
||||
#define AX25_CONTROL_POLL_FINAL_DISABLED 0b00000000 // 4 4 disabled
|
||||
#define AX25_CONTROL_S_RECEIVE_READY 0b00000000 // 3 2 S frame type: receive ready (system ready to receive)
|
||||
#define AX25_CONTROL_S_RECEIVE_NOT_READY 0b00000100 // 3 2 receive not ready (TNC buffer full)
|
||||
#define AX25_CONTROL_S_REJECT 0b00001000 // 3 2 reject (out of sequence or duplicate)
|
||||
#define AX25_CONTROL_S_SELECTIVE_REJECT 0b00001100 // 3 2 selective reject (single frame repeat request)
|
||||
#define AX25_CONTROL_INFORMATION_FRAME 0b00000000 // 0 0 frame type: information (I frame)
|
||||
#define AX25_CONTROL_SUPERVISORY_FRAME 0b00000001 // 1 0 supervisory (S frame)
|
||||
#define AX25_CONTROL_UNNUMBERED_FRAME 0b00000011 // 1 0 unnumbered (U frame)
|
||||
|
||||
// protocol identifier field
|
||||
#define AX25_PID_ISO_8208 0x01
|
||||
#define AX25_PID_TCP_IP_COMPRESSED 0x06
|
||||
#define AX25_PID_TCP_IP_UNCOMPRESSED 0x07
|
||||
#define AX25_PID_SEGMENTATION_FRAGMENT 0x08
|
||||
#define AX25_PID_TEXNET_DATAGRAM_PROTOCOL 0xC3
|
||||
#define AX25_PID_LINK_QUALITY_PROTOCOL 0xC4
|
||||
#define AX25_PID_APPLETALK 0xCA
|
||||
#define AX25_PID_APPLETALK_ARP 0xCB
|
||||
#define AX25_PID_ARPA_INTERNET_PROTOCOL 0xCC
|
||||
#define AX25_PID_ARPA_ADDRESS_RESOLUTION 0xCD
|
||||
#define AX25_PID_FLEXNET 0xCE
|
||||
#define AX25_PID_NET_ROM 0xCF
|
||||
#define AX25_PID_NO_LAYER_3 0xF0
|
||||
#define AX25_PID_ESCAPE_CHARACTER 0xFF
|
||||
|
||||
/*!
|
||||
\class AX25Frame
|
||||
|
||||
\brief Abstraction of AX.25 frame format.
|
||||
*/
|
||||
class AX25Frame {
|
||||
public:
|
||||
/*!
|
||||
\brief Callsign of the destination station.
|
||||
*/
|
||||
char destCallsign[AX25_MAX_CALLSIGN_LEN + 1];
|
||||
|
||||
/*!
|
||||
\brief SSID of the destination station.
|
||||
*/
|
||||
uint8_t destSSID;
|
||||
|
||||
/*!
|
||||
\brief Callsign of the source station.
|
||||
*/
|
||||
char srcCallsign[AX25_MAX_CALLSIGN_LEN + 1];
|
||||
|
||||
/*!
|
||||
\brief SSID of the source station.
|
||||
*/
|
||||
uint8_t srcSSID;
|
||||
|
||||
/*!
|
||||
\brief Number of repeaters to be used.
|
||||
*/
|
||||
uint8_t numRepeaters;
|
||||
|
||||
/*!
|
||||
\brief The control field.
|
||||
*/
|
||||
uint8_t control;
|
||||
|
||||
/*!
|
||||
\brief The protocol identifier (PID) field.
|
||||
*/
|
||||
uint8_t protocolID;
|
||||
|
||||
/*!
|
||||
\brief Number of bytes in the information field.
|
||||
*/
|
||||
uint16_t infoLen;
|
||||
|
||||
/*!
|
||||
\brief Receive sequence number.
|
||||
*/
|
||||
uint8_t rcvSeqNumber;
|
||||
|
||||
/*!
|
||||
\brief Send sequence number.
|
||||
*/
|
||||
uint16_t sendSeqNumber;
|
||||
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
/*!
|
||||
\brief The info field.
|
||||
*/
|
||||
uint8_t* info;
|
||||
|
||||
/*!
|
||||
\brief Array of repeater callsigns.
|
||||
*/
|
||||
char** repeaterCallsigns;
|
||||
|
||||
/*!
|
||||
\brief Array of repeater SSIDs.
|
||||
*/
|
||||
uint8_t* repeaterSSIDs;
|
||||
#else
|
||||
/*!
|
||||
\brief The info field.
|
||||
*/
|
||||
uint8_t info[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
|
||||
/*!
|
||||
\brief Array of repeater callsigns.
|
||||
*/
|
||||
char repeaterCallsigns[8][AX25_MAX_CALLSIGN_LEN + 1];
|
||||
|
||||
/*!
|
||||
\brief Array of repeater SSIDs.
|
||||
*/
|
||||
uint8_t repeaterSSIDs[8];
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Overloaded constructor, for frames without info field.
|
||||
|
||||
\param destCallsign Callsign of the destination station.
|
||||
|
||||
\param destSSID SSID of the destination station.
|
||||
|
||||
\param srcCallsign Callsign of the source station.
|
||||
|
||||
\param srcSSID SSID of the source station.
|
||||
|
||||
\param control The control field.
|
||||
*/
|
||||
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control);
|
||||
|
||||
/*!
|
||||
\brief Overloaded constructor, for frames with C-string info field.
|
||||
|
||||
\param destCallsign Callsign of the destination station.
|
||||
|
||||
\param destSSID SSID of the destination station.
|
||||
|
||||
\param srcCallsign Callsign of the source station.
|
||||
|
||||
\param srcSSID SSID of the source station.
|
||||
|
||||
\param control The control field.
|
||||
|
||||
\param protocolID The protocol identifier (PID) field. Set to zero if the frame doesn't have this field.
|
||||
|
||||
\param info Information field, in the form of null-terminated C-string.
|
||||
*/
|
||||
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, const char* info);
|
||||
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param destCallsign Callsign of the destination station.
|
||||
|
||||
\param destSSID SSID of the destination station.
|
||||
|
||||
\param srcCallsign Callsign of the source station.
|
||||
|
||||
\param srcSSID SSID of the source station.
|
||||
|
||||
\param control The control field.
|
||||
|
||||
\param protocolID The protocol identifier (PID) field. Set to zero if the frame doesn't have this field.
|
||||
|
||||
\param info Information field, in the form of arbitrary binary buffer.
|
||||
|
||||
\param infoLen Number of bytes in the information field.
|
||||
*/
|
||||
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, uint8_t* info, uint16_t infoLen);
|
||||
|
||||
/*!
|
||||
\brief Default destructor.
|
||||
*/
|
||||
~AX25Frame();
|
||||
|
||||
/*!
|
||||
\brief Method to set the repeater callsigns and SSIDs.
|
||||
|
||||
\param repeaterCallsigns Array of repeater callsigns in the form of null-terminated C-strings.
|
||||
|
||||
\param repeaterSSIDs Array of repeater SSIDs.
|
||||
|
||||
\param numRepeaters Number of repeaters, maximum is 8.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setRepeaters(char** repeaterCallsigns, uint8_t* repeaterSSIDs, uint8_t numRepeaters);
|
||||
|
||||
/*!
|
||||
\brief Method to set receive sequence number.
|
||||
|
||||
\param seqNumber Sequence number to set, 0 to 7.
|
||||
*/
|
||||
void setRecvSequence(uint8_t seqNumber);
|
||||
|
||||
/*!
|
||||
\brief Method to set send sequence number.
|
||||
|
||||
\param seqNumber Sequence number to set, 0 to 7.
|
||||
*/
|
||||
void setSendSequence(uint8_t seqNumber);
|
||||
};
|
||||
|
||||
/*!
|
||||
\class AX25Client
|
||||
|
||||
\brief Client for AX25 communication.
|
||||
*/
|
||||
class AX25Client {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param phy Pointer to the wireless module providing PhysicalLayer communication.
|
||||
*/
|
||||
AX25Client(PhysicalLayer* phy);
|
||||
|
||||
// basic methods
|
||||
|
||||
/*!
|
||||
\brief Initialization method.
|
||||
|
||||
\param srcCallsign Callsign of the source station.
|
||||
|
||||
\param srcSSID 4-bit SSID of the source station (in case there are more stations with the same callsign). Defaults to 0.
|
||||
|
||||
\param preambleLen Number of "preamble" bytes (AX25_FLAG) sent ahead of the actual AX.25 frame. Does not include the first AX25_FLAG byte, which is considered part of the frame. Defaults to 8.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(const char* srcCallsign, uint8_t srcSSID = 0x00, uint8_t preambleLen = 8);
|
||||
|
||||
/*!
|
||||
\brief Transmit unnumbered information (UI) frame.
|
||||
|
||||
\param str Data to be sent.
|
||||
|
||||
\param destCallsign Callsign of the destination station.
|
||||
|
||||
\param destSSID 4-bit SSID of the destination station (in case there are more stations with the same callsign). Defaults to 0.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t transmit(const char* str, const char* destCallsign, uint8_t destSSID = 0x00);
|
||||
|
||||
/*!
|
||||
\brief Transmit arbitrary AX.25 frame.
|
||||
|
||||
\param frame Frame to be sent.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t sendFrame(AX25Frame* frame);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
PhysicalLayer* _phy;
|
||||
|
||||
char _srcCallsign[AX25_MAX_CALLSIGN_LEN + 1];
|
||||
uint8_t _srcSSID;
|
||||
uint16_t _preambleLen;
|
||||
|
||||
uint16_t getFrameCheckSequence(uint8_t* buff, size_t len);
|
||||
uint8_t flipBits(uint8_t b);
|
||||
uint16_t flipBits16(uint16_t i);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,80 +1,12 @@
|
|||
#include "Morse.h"
|
||||
|
||||
// structure to save data about character Morse code
|
||||
/*!
|
||||
\cond RADIOLIB_DOXYGEN_HIDDEN
|
||||
*/
|
||||
struct Morse_t {
|
||||
char c; // ASCII character
|
||||
char m[7]; // Morse code representation
|
||||
};
|
||||
/*!
|
||||
\endcond
|
||||
*/
|
||||
|
||||
// array of all Morse code characters
|
||||
const Morse_t MorseTable[MORSE_LENGTH] PROGMEM = {
|
||||
{'A', ".-"},
|
||||
{'B',"-..."},
|
||||
{'C', "-.-."},
|
||||
{'D',"-.."},
|
||||
{'E',"."},
|
||||
{'F',"..-."},
|
||||
{'G',"--."},
|
||||
{'H',"...."},
|
||||
{'I',".."},
|
||||
{'J',".---"},
|
||||
{'K',"-.-"},
|
||||
{'L',".-.."},
|
||||
{'M',"--"},
|
||||
{'N',"-."},
|
||||
{'O',"---"},
|
||||
{'P',".--."},
|
||||
{'Q',"--.-"},
|
||||
{'R',".-."},
|
||||
{'S',"..."},
|
||||
{'T',"-"},
|
||||
{'U',"..-"},
|
||||
{'V',"...-"},
|
||||
{'W',".--"},
|
||||
{'X',"-..-"},
|
||||
{'Y',"-.--"},
|
||||
{'Z',"--.."},
|
||||
{'1',".----"},
|
||||
{'2',"..---"},
|
||||
{'3',"...--"},
|
||||
{'4',"....-"},
|
||||
{'5',"....."},
|
||||
{'6',"-...."},
|
||||
{'7',"--..."},
|
||||
{'8',"---.."},
|
||||
{'9',"----."},
|
||||
{'0',"-----"},
|
||||
{'.',".-.-.-"},
|
||||
{',',"--..--"},
|
||||
{':',"---..."},
|
||||
{'?',"..--.."},
|
||||
{'\'',".----."},
|
||||
{'-',"-....-"},
|
||||
{'/',"-..-."},
|
||||
{'(',"-.--."},
|
||||
{')',"-.--.-"},
|
||||
{'\"',".-..-."},
|
||||
{'=',"-...-"},
|
||||
{'+',".-.-."},
|
||||
{'@',".--.-."},
|
||||
{' ',"_"}, // space is used to separate words
|
||||
{0x01,"-.-.-"}, // ASCII SOH (start of heading) is used as alias for start signal
|
||||
{0x02,".-.-."} // ASCII EOT (end of transmission) is used as alias for stop signal
|
||||
};
|
||||
|
||||
MorseClient::MorseClient(PhysicalLayer* phy) {
|
||||
_phy = phy;
|
||||
}
|
||||
|
||||
int16_t MorseClient::begin(float base, uint8_t speed) {
|
||||
// calculate 24-bit frequency
|
||||
_base = (base * (uint32_t(1) << _phy->getDivExponent())) / _phy->getCrystalFreq();
|
||||
_base = (base * 1000000.0) / _phy->getFreqStep();
|
||||
|
||||
// calculate dot length (assumes PARIS as typical word)
|
||||
_dotLength = 1200 / speed;
|
||||
|
@ -86,7 +18,7 @@ int16_t MorseClient::begin(float base, uint8_t speed) {
|
|||
}
|
||||
|
||||
size_t MorseClient::startSignal() {
|
||||
return(MorseClient::write(0x01));
|
||||
return(MorseClient::write('_'));
|
||||
}
|
||||
|
||||
size_t MorseClient::write(const char* str) {
|
||||
|
@ -106,52 +38,55 @@ size_t MorseClient::write(uint8_t* buff, size_t len) {
|
|||
}
|
||||
|
||||
size_t MorseClient::write(uint8_t b) {
|
||||
// find the correct Morse code in array
|
||||
Morse_t mc;
|
||||
bool found = false;
|
||||
for(uint8_t pos = 0; pos < MORSE_LENGTH; pos++) {
|
||||
memcpy_P(&mc, &MorseTable[pos], sizeof(Morse_t));
|
||||
if(mc.c == toupper(b)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
// check unprintable ASCII characters and boundaries
|
||||
if((b < ' ') || (b == 0x60) || (b > 'z')) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
// check if the requested code was found in the array
|
||||
if(found) {
|
||||
RADIOLIB_DEBUG_PRINT(mc.c);
|
||||
RADIOLIB_DEBUG_PRINT('\t');
|
||||
RADIOLIB_DEBUG_PRINTLN(mc.m);
|
||||
|
||||
// iterate over Morse code representation and output appropriate tones
|
||||
for(uint8_t i = 0; i < strlen(mc.m); i++) {
|
||||
switch(mc.m[i]) {
|
||||
case '.':
|
||||
_phy->transmitDirect(_base);
|
||||
delay(_dotLength);
|
||||
break;
|
||||
case '-':
|
||||
_phy->transmitDirect(_base);
|
||||
delay(_dotLength * 3);
|
||||
break;
|
||||
case '_':
|
||||
// do nothing (word space)
|
||||
break;
|
||||
}
|
||||
|
||||
// symbol space
|
||||
_phy->standby();
|
||||
delay(_dotLength);
|
||||
}
|
||||
|
||||
// letter space
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
delay(_dotLength * 3);
|
||||
|
||||
// inter-word pause (space)
|
||||
if(b == ' ') {
|
||||
RADIOLIB_DEBUG_PRINTLN(F("space"));
|
||||
_phy->standby();
|
||||
delay(4 * _dotLength);
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
// get morse code from lookup table
|
||||
uint8_t code = pgm_read_byte(&MorseTable[(uint8_t)(toupper(b) - 32)]);
|
||||
|
||||
// check unsupported characters
|
||||
if(code == MORSE_UNSUPORTED) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
// iterate through codeword until guard bit is reached
|
||||
while(code > MORSE_GUARDBIT) {
|
||||
|
||||
// send dot or dash
|
||||
if (code & MORSE_DASH) {
|
||||
RADIOLIB_DEBUG_PRINT('-');
|
||||
_phy->transmitDirect(_base);
|
||||
delay(3 * _dotLength);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINT('.');
|
||||
_phy->transmitDirect(_base);
|
||||
delay(_dotLength);
|
||||
}
|
||||
|
||||
// symbol space
|
||||
_phy->standby();
|
||||
delay(_dotLength);
|
||||
|
||||
// move onto the next bit
|
||||
code >>= 1;
|
||||
}
|
||||
|
||||
// letter space
|
||||
_phy->standby();
|
||||
delay(2 * _dotLength);
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
size_t MorseClient::print(__FlashStringHelper* fstr) {
|
||||
|
@ -219,7 +154,7 @@ size_t MorseClient::print(double n, int digits) {
|
|||
}
|
||||
|
||||
size_t MorseClient::println(void) {
|
||||
return(MorseClient::write(0x02));
|
||||
return(MorseClient::write('^'));
|
||||
}
|
||||
|
||||
size_t MorseClient::println(__FlashStringHelper* fstr) {
|
||||
|
|
|
@ -4,7 +4,81 @@
|
|||
#include "../../TypeDef.h"
|
||||
#include "../PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
#define MORSE_LENGTH 52
|
||||
#define MORSE_DOT 0b0
|
||||
#define MORSE_DASH 0b1
|
||||
#define MORSE_GUARDBIT 0b1
|
||||
#define MORSE_UNSUPORTED 0xFF
|
||||
|
||||
// Morse character table: - using codes defined in ITU-R M.1677-1
|
||||
// - 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 = {
|
||||
0b00, // space
|
||||
0b110101, // ! (unsupported)
|
||||
0b1010010, // "
|
||||
MORSE_UNSUPORTED, // # (unsupported)
|
||||
MORSE_UNSUPORTED, // $ (unsupported)
|
||||
MORSE_UNSUPORTED, // % (unsupported)
|
||||
MORSE_UNSUPORTED, // & (unsupported)
|
||||
0b1011110, // '
|
||||
0b101101, // (
|
||||
0b1101101, // )
|
||||
MORSE_UNSUPORTED, // * (unsupported)
|
||||
0b101010, // +
|
||||
0b1110011, // ,
|
||||
0b1100001, // -
|
||||
0b1101010, // .
|
||||
0b101001, // /
|
||||
0b111111, // 0
|
||||
0b111110, // 1
|
||||
0b111100, // 2
|
||||
0b111000, // 3
|
||||
0b110000, // 4
|
||||
0b100000, // 5
|
||||
0b100001, // 6
|
||||
0b100011, // 7
|
||||
0b100111, // 8
|
||||
0b101111, // 9
|
||||
0b1000111, // :
|
||||
MORSE_UNSUPORTED, // ; (unsupported)
|
||||
MORSE_UNSUPORTED, // < (unsupported)
|
||||
0b110001, // =
|
||||
MORSE_UNSUPORTED, // > (unsupported)
|
||||
0b1001100, // ?
|
||||
0b1010110, // @
|
||||
0b110, // A
|
||||
0b10001, // B
|
||||
0b10101, // C
|
||||
0b1001, // D
|
||||
0b10, // E
|
||||
0b10100, // F
|
||||
0b1011, // G
|
||||
0b10000, // H
|
||||
0b100, // I
|
||||
0b11110, // J
|
||||
0b1101, // K
|
||||
0b10010, // L
|
||||
0b111, // M
|
||||
0b101, // N
|
||||
0b1111, // O
|
||||
0b10110, // P
|
||||
0b11011, // Q
|
||||
0b1010, // R
|
||||
0b1000, // S
|
||||
0b11, // T
|
||||
0b1100, // U
|
||||
0b11000, // V
|
||||
0b1110, // W
|
||||
0b11001, // X
|
||||
0b11101, // Y
|
||||
0b10011, // Z
|
||||
MORSE_UNSUPORTED, // [ (unsupported)
|
||||
MORSE_UNSUPORTED, // \ (unsupported)
|
||||
MORSE_UNSUPORTED, // ] (unsupported)
|
||||
0b1101000, // ^ (unsupported, used as alias for end of work)
|
||||
0b110101 // _ (unsupported, used as alias for starting signal)
|
||||
};
|
||||
|
||||
/*!
|
||||
\class MorseClient
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#include "PhysicalLayer.h"
|
||||
|
||||
PhysicalLayer::PhysicalLayer(float crysFreq, uint8_t divExp, size_t maxPacketLength) {
|
||||
_crystalFreq = crysFreq;
|
||||
_divExponent = divExp;
|
||||
PhysicalLayer::PhysicalLayer(float freqStep, size_t maxPacketLength) {
|
||||
_freqStep = freqStep;
|
||||
_maxPacketLength = maxPacketLength;
|
||||
}
|
||||
|
||||
|
@ -141,10 +140,6 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
float PhysicalLayer::getCrystalFreq() {
|
||||
return(_crystalFreq);
|
||||
}
|
||||
|
||||
uint8_t PhysicalLayer::getDivExponent() {
|
||||
return(_divExponent);
|
||||
float PhysicalLayer::getFreqStep() {
|
||||
return(_freqStep);
|
||||
}
|
||||
|
|
|
@ -18,13 +18,11 @@ class PhysicalLayer {
|
|||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param crysFreq Frequency of crystal oscillator inside the module in MHz.
|
||||
|
||||
\param divExp Exponent of module frequency divider.
|
||||
\param freqStep Frequency step of the synthesizer in Hz.
|
||||
|
||||
\param maxPacketLength Maximum length of packet that can be received by the module-
|
||||
*/
|
||||
PhysicalLayer(float crysFreq, uint8_t divExp, size_t maxPacketLength);
|
||||
PhysicalLayer(float freqStep, size_t maxPacketLength);
|
||||
|
||||
// basic methods
|
||||
|
||||
|
@ -193,18 +191,29 @@ class PhysicalLayer {
|
|||
virtual int16_t setFrequencyDeviation(float freqDev) = 0;
|
||||
|
||||
/*!
|
||||
\brief Gets the module crystal oscillator frequency that was set in constructor.
|
||||
\brief Sets GFSK data shaping. Only available in FSK mode. Must be implemented in module class.
|
||||
|
||||
\returns Crystal oscillator frequency in MHz.
|
||||
\param sh Shaping to be set. Set to zero to disable data shaping.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
float getCrystalFreq();
|
||||
virtual int16_t setDataShaping(float sh) = 0;
|
||||
|
||||
/*!
|
||||
\brief Gets the module frequency divider exponent that was set in constructor.
|
||||
\brief Sets FSK data encoding. Only available in FSK mode. Must be implemented in module class.
|
||||
|
||||
\returns Frequency divider exponent.
|
||||
\param enc Encoding to be used. Set to zero to for no encoding (NRZ).
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
uint8_t getDivExponent();
|
||||
virtual int16_t setEncoding(uint8_t encoding) = 0;
|
||||
|
||||
/*!
|
||||
\brief Gets the module frequency step size that was set in constructor.
|
||||
|
||||
\returns Synthesizer frequency step size in Hz.
|
||||
*/
|
||||
float getFreqStep();
|
||||
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
|
@ -218,8 +227,7 @@ class PhysicalLayer {
|
|||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
float _crystalFreq;
|
||||
uint8_t _divExponent;
|
||||
float _freqStep;
|
||||
size_t _maxPacketLength;
|
||||
};
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ int16_t RTTYClient::begin(float base, uint32_t shift, uint16_t rate, uint8_t enc
|
|||
_bitDuration = (uint32_t)1000000/rate;
|
||||
|
||||
// calculate module carrier frequency resolution
|
||||
uint32_t step = round((_phy->getCrystalFreq() * 1000000) / (uint32_t(1) << _phy->getDivExponent()));
|
||||
uint32_t step = round(_phy->getFreqStep());
|
||||
|
||||
// check minimum shift value
|
||||
if(shift < step / 2) {
|
||||
|
@ -146,7 +146,7 @@ int16_t RTTYClient::begin(float base, uint32_t shift, uint16_t rate, uint8_t enc
|
|||
}
|
||||
|
||||
// calculate 24-bit frequency
|
||||
_base = (base * (uint32_t(1) << _phy->getDivExponent())) / _phy->getCrystalFreq();
|
||||
_base = (base * 1000000.0) / _phy->getFreqStep();
|
||||
|
||||
// set module frequency deviation to 0
|
||||
int16_t state = _phy->setFrequencyDeviation(0);
|
||||
|
|
Loading…
Add table
Reference in a new issue