Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d62c9a6283 | ||
![]() |
b0d660cf42 |
4 changed files with 132 additions and 0 deletions
87
examples/AFSK/AFSK_No_Tone/AFSK_No_Tone.ino
Normal file
87
examples/AFSK/AFSK_No_Tone/AFSK_No_Tone.ino
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
RadioLib AFSK Example
|
||||||
|
|
||||||
|
This example shows hot to send audio FSK tones
|
||||||
|
using SX1278's FSK modem, on platforms that do
|
||||||
|
not support the tone() function.
|
||||||
|
|
||||||
|
Other modules that can be used for AFSK:
|
||||||
|
- SX127x/RFM9x
|
||||||
|
- RF69
|
||||||
|
- SX1231
|
||||||
|
- CC1101
|
||||||
|
- Si443x/RFM2x
|
||||||
|
|
||||||
|
For default module settings, see the wiki page
|
||||||
|
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||||
|
|
||||||
|
For full API reference, see the GitHub Pages
|
||||||
|
https://jgromes.github.io/RadioLib/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include the library
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
// SX1278 has the following connections:
|
||||||
|
// NSS pin: 10
|
||||||
|
// DIO0 pin: 2
|
||||||
|
// RESET pin: 9
|
||||||
|
// DIO1 pin: 3
|
||||||
|
SX1278 radio = new Module(5, 2, 9, 3);
|
||||||
|
|
||||||
|
// create AFSK client instance using the FSK module
|
||||||
|
// enable tone emulation by setting the pin to
|
||||||
|
// "not connected"
|
||||||
|
AFSKClient audio(&radio, RADIOLIB_NC);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// initialize SX1278 with default settings
|
||||||
|
Serial.print(F("[SX1278] Initializing ... "));
|
||||||
|
int state = radio.beginFSK();
|
||||||
|
|
||||||
|
// when using one of the non-LoRa modules for AFSK
|
||||||
|
// (RF69, CC1101, Si4432 etc.), use the basic begin() method
|
||||||
|
// int state = radio.begin();
|
||||||
|
|
||||||
|
if(state == RADIOLIB_ERR_NONE) {
|
||||||
|
Serial.println(F("success!"));
|
||||||
|
} else {
|
||||||
|
Serial.print(F("failed, code "));
|
||||||
|
Serial.println(state);
|
||||||
|
while(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize AFSK client
|
||||||
|
Serial.print(F("[AFSK] Initializing ... "));
|
||||||
|
state = audio.begin();
|
||||||
|
if(state == RADIOLIB_ERR_NONE) {
|
||||||
|
Serial.println(F("success!"));
|
||||||
|
} else {
|
||||||
|
Serial.print(F("failed, code "));
|
||||||
|
Serial.println(state);
|
||||||
|
while(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// AFSKClient can be used to transmit tones,
|
||||||
|
// same as Arduino tone() function
|
||||||
|
|
||||||
|
// 400 Hz tone
|
||||||
|
Serial.print(F("[AFSK] 400 Hz tone ... "));
|
||||||
|
const size_t len = 64;
|
||||||
|
uint8_t bits[len] = { 0 };
|
||||||
|
for(size_t i = 0; i < len; i++) {
|
||||||
|
bits[i] = 0xF0;
|
||||||
|
}
|
||||||
|
audio.emulateTone(400, bits, len);
|
||||||
|
Serial.println(F("done!"));
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// AFSKClient can also be used to transmit HAM-friendly
|
||||||
|
// RTTY, Morse code, Hellschreiber, SSTV and AX.25.
|
||||||
|
// Details on how to use AFSK are in the example
|
||||||
|
// folders for each of the above modes.
|
||||||
|
}
|
|
@ -6,6 +6,19 @@ AFSKClient::AFSKClient(PhysicalLayer* phy, RADIOLIB_PIN_TYPE pin): _pin(pin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t AFSKClient::begin() {
|
int16_t AFSKClient::begin() {
|
||||||
|
if(_pin == RADIOLIB_NC) {
|
||||||
|
// set encoding to NRZ
|
||||||
|
int16_t state = _phy->setEncoding(RADIOLIB_ENCODING_NRZ);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// disable preamble
|
||||||
|
state = _phy->setPreambleLength(0);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// disable CRC
|
||||||
|
state = _phy->setCrcFiltering(false);
|
||||||
|
return(state);
|
||||||
|
}
|
||||||
return(_phy->startDirect());
|
return(_phy->startDirect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,4 +47,29 @@ int16_t AFSKClient::noTone(bool keepOn) {
|
||||||
return(_phy->standby());
|
return(_phy->standby());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t AFSKClient::emulateTone(float baseFreq, uint8_t* bits, size_t len) {
|
||||||
|
// set fixed packet length mode
|
||||||
|
int16_t state = _phy->fixedPacketLengthMode(len);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
float br = baseFreq;
|
||||||
|
if((br < 1200)) {
|
||||||
|
if(br < 1200/8) {
|
||||||
|
// this is too low to achieve by a single octet
|
||||||
|
// FIXME - if tones lower than 150 Hz are needed, multiple octets must be used
|
||||||
|
return(RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||||
|
}
|
||||||
|
// this tone frequency is lower than what most modules can do
|
||||||
|
// but we can easily emulate tones in this range
|
||||||
|
br *= 8.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the base frequency
|
||||||
|
state = _phy->setBitRate(br / 1000.0);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// transmit
|
||||||
|
return(_phy->transmit(bits, len));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,6 +52,8 @@ class AFSKClient {
|
||||||
*/
|
*/
|
||||||
int16_t noTone(bool keepOn = false);
|
int16_t noTone(bool keepOn = false);
|
||||||
|
|
||||||
|
int16_t emulateTone(float baseFreq, uint8_t* bits, size_t len);
|
||||||
|
|
||||||
#if !defined(RADIOLIB_GODMODE)
|
#if !defined(RADIOLIB_GODMODE)
|
||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -302,6 +302,11 @@ class PhysicalLayer {
|
||||||
|
|
||||||
virtual Module* getMod() = 0;
|
virtual Module* getMod() = 0;
|
||||||
|
|
||||||
|
virtual int16_t setPreambleLength(uint16_t preambleLength) = 0;
|
||||||
|
virtual int16_t setCrcFiltering(bool crcOn) = 0;
|
||||||
|
virtual int16_t fixedPacketLengthMode(uint8_t preambleLength) = 0;
|
||||||
|
virtual int16_t setBitRate(float br) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateDirectBuffer(uint8_t bit);
|
void updateDirectBuffer(uint8_t bit);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue