[Hell] Added AFSK support

This commit is contained in:
jgromes 2020-04-30 17:10:37 +02:00
parent ed69931041
commit 21c0703383
4 changed files with 171 additions and 8 deletions

View file

@ -13,6 +13,9 @@
- nRF24
- Si443x/RFM2x
- SX128x
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library

View file

@ -0,0 +1,122 @@
/*
RadioLib Hellschreiber Transmit AFSK Example
This example sends Hellschreiber message using
SX1278's FSK modem. The data is modulated
as AFSK.
Other modules that can be used for Hellschreiber
with AFSK modulation:
- SX127x/RFM9x
- RF69
- SX1231
- CC1101
- Si443x/RFM2x
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 fsk = new Module(10, 2, 9, 3);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1278 fsk = RadioShield.ModuleA;
// create AFSK client instance using the FSK module
// pin 5 is connected to SX1278 DIO2
AFSKClient audio(&fsk, 5);
// create Hellschreiber client instance using the AFSK instance
HellClient hell(&audio);
void setup() {
Serial.begin(9600);
// initialize SX1278
Serial.print(F("[SX1278] Initializing ... "));
// carrier frequency: 434.0 MHz
// bit rate: 48.0 kbps
// frequency deviation: 50.0 kHz
// Rx bandwidth: 125.0 kHz
// output power: 13 dBm
// current limit: 100 mA
int state = fsk.beginFSK();
// when using one of the non-LoRa modules for Morse code
// (RF69, CC1101, Si4432 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 Hellschreiber client
Serial.print(F("[Hell] Initializing ... "));
// AFSK tone frequency: 400 Hz
// speed: 122.5 Baud ("Feld Hell")
state = hell.begin(400);
if(state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while(true);
}
}
void loop() {
Serial.print(F("[Hell] Sending Hellschreiber data ... "));
// HellClient supports all methods of the Serial class
// NOTE: Lower case letter will be capitalized.
// Arduino String class
String aStr = "Arduino String";
hell.print(aStr);
// character array (C-String)
hell.print("C-String");
// string saved in flash
hell.print(F("Flash String"));
// character
hell.print('c');
// byte
// formatting DEC/HEX/OCT/BIN is supported for
// any integer type (byte/int/long)
hell.print(255, HEX);
// integer number
int i = 1000;
hell.print(i);
// floating point number
// NOTE: println() has no effect on the transmission,
// and is only kept for compatibility reasons.
float f = -3.1415;
hell.println(f, 3);
// custom glyph - must be a 7 byte array of rows 7 pixels long
uint8_t customGlyph[] = { 0b0000000, 0b0010100, 0b0010100, 0b0000000, 0b0100010, 0b0011100, 0b0000000 };
hell.printGlyph(customGlyph);
Serial.println(F("done!"));
// wait for a second before transmitting again
delay(1000);
}

View file

@ -2,17 +2,27 @@
HellClient::HellClient(PhysicalLayer* phy) {
_phy = phy;
_audio = nullptr;
}
HellClient::HellClient(AFSKClient* audio) {
_phy = audio->_phy;
_audio = audio;
}
int16_t HellClient::begin(float base, float rate) {
// calculate 24-bit frequency
_baseHz = base;
_base = (base * 1000000.0) / _phy->getFreqStep();
// calculate "pixel" duration
_pixelDuration = 1000000.0/rate;
// set module frequency deviation to 0
int16_t state = _phy->setFrequencyDeviation(0);
// set module frequency deviation to 0 if using FSK
int16_t state = ERR_NONE;
if(_audio == nullptr) {
state = _phy->setFrequencyDeviation(0);
}
return(state);
}
@ -23,16 +33,16 @@ size_t HellClient::printGlyph(uint8_t* buff) {
for(int8_t i = HELL_FONT_HEIGHT - 1; i >= 0; i--) {
uint32_t start = micros();
if(buff[i] & mask) {
_phy->transmitDirect(_base);
transmitDirect(_base, _baseHz);
} else {
_phy->standby();
standby();
}
while(micros() - start < _pixelDuration);
}
}
// make sure transmitter is off
_phy->standby();
standby();
return(1);
}
@ -269,3 +279,19 @@ size_t HellClient::printFloat(double number, uint8_t digits) {
return n;
}
int16_t HellClient::transmitDirect(uint32_t freq, uint32_t freqHz) {
if(_audio != nullptr) {
return(_audio->tone(freqHz));
} else {
return(_phy->transmitDirect(freq));
}
}
int16_t HellClient::standby() {
if(_audio != nullptr) {
return(_audio->noTone());
} else {
return(_phy->standby());
}
}

View file

@ -3,6 +3,7 @@
#include "../../TypeDef.h"
#include "../PhysicalLayer/PhysicalLayer.h"
#include "../AFSK/AFSK.h"
#define HELL_FONT_WIDTH 7
#define HELL_FONT_HEIGHT 7
@ -85,18 +86,25 @@ static const uint8_t HellFont[64][HELL_FONT_WIDTH - 2] PROGMEM = {
class HellClient {
public:
/*!
\brief Default constructor.
\brief Constructor for 2-FSK mode.
\param phy Pointer to the wireless module providing PhysicalLayer communication.
*/
HellClient(PhysicalLayer* phy);
/*!
\brief Constructor for AFSK mode.
\param audio Pointer to the AFSK instance providing audio.
*/
HellClient(AFSKClient* audio);
// basic methods
/*!
\brief Initialization method.
\param base Base RF frequency to be used in MHz.
\param base Base RF frequency to be used in MHz (in 2-FSK mode), or the tone frequency in Hz (in AFSK mode).
\param rate Baud rate to be used during transmission. Defaults to 122.5 ("Feld Hell")
*/
@ -140,12 +148,16 @@ class HellClient {
private:
#endif
PhysicalLayer* _phy;
AFSKClient* _audio;
uint32_t _base;
uint32_t _base, _baseHz;
uint32_t _pixelDuration;
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
int16_t transmitDirect(uint32_t freq = 0, uint32_t freqHz = 0);
int16_t standby();
};
#endif