From 21c0703383706aee05f9cb5e6c13255defbdb873 Mon Sep 17 00:00:00 2001 From: jgromes Date: Thu, 30 Apr 2020 17:10:37 +0200 Subject: [PATCH] [Hell] Added AFSK support --- .../Hellschreiber_Transmit.ino | 3 + .../Hellschreiber_Transmit_AFSK.ino | 122 ++++++++++++++++++ src/protocols/Hellschreiber/Hellschreiber.cpp | 36 +++++- src/protocols/Hellschreiber/Hellschreiber.h | 18 ++- 4 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 examples/Hellschreiber/Hellschreiber_Transmit_AFSK/Hellschreiber_Transmit_AFSK.ino diff --git a/examples/Hellschreiber/Hellschreiber_Transmit/Hellschreiber_Transmit.ino b/examples/Hellschreiber/Hellschreiber_Transmit/Hellschreiber_Transmit.ino index c1d74d31..a8dda9f0 100644 --- a/examples/Hellschreiber/Hellschreiber_Transmit/Hellschreiber_Transmit.ino +++ b/examples/Hellschreiber/Hellschreiber_Transmit/Hellschreiber_Transmit.ino @@ -13,6 +13,9 @@ - nRF24 - Si443x/RFM2x - SX128x + + For full API reference, see the GitHub Pages + https://jgromes.github.io/RadioLib/ */ // include the library diff --git a/examples/Hellschreiber/Hellschreiber_Transmit_AFSK/Hellschreiber_Transmit_AFSK.ino b/examples/Hellschreiber/Hellschreiber_Transmit_AFSK/Hellschreiber_Transmit_AFSK.ino new file mode 100644 index 00000000..ec2aa4e7 --- /dev/null +++ b/examples/Hellschreiber/Hellschreiber_Transmit_AFSK/Hellschreiber_Transmit_AFSK.ino @@ -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 + +// 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); +} diff --git a/src/protocols/Hellschreiber/Hellschreiber.cpp b/src/protocols/Hellschreiber/Hellschreiber.cpp index ffc30ee3..3f769add 100644 --- a/src/protocols/Hellschreiber/Hellschreiber.cpp +++ b/src/protocols/Hellschreiber/Hellschreiber.cpp @@ -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()); + } +} diff --git a/src/protocols/Hellschreiber/Hellschreiber.h b/src/protocols/Hellschreiber/Hellschreiber.h index 9b14c27e..8756df5f 100644 --- a/src/protocols/Hellschreiber/Hellschreiber.h +++ b/src/protocols/Hellschreiber/Hellschreiber.h @@ -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