RadioLibSmol/src/protocols/FSK4/FSK4.cpp

119 lines
2.4 KiB
C++

#include "FSK4.h"
#if !defined(RADIOLIB_EXCLUDE_FSK4)
FSK4Client::FSK4Client(PhysicalLayer* phy) {
_phy = phy;
#if !defined(RADIOLIB_EXCLUDE_AFSK)
_audio = nullptr;
#endif
}
//#if !defined(RADIOLIB_EXCLUDE_AFSK)
// FSK4Client::FSK4Client(AFSKClient* audio) {
// _phy = audio->_phy;
// _audio = audio;
// }
//#endif
int16_t FSK4Client::begin(float base, uint32_t shift, uint16_t rate) {
// save configuration
_baseHz = base;
_shiftHz = shift;
// calculate duration of 1 bit
_bitDuration = (uint32_t)1000000/rate;
// calculate module carrier frequency resolution
uint32_t step = round(_phy->getFreqStep());
// check minimum shift value
if(shift < step / 2) {
return(ERR_INVALID_RTTY_SHIFT);
}
// round shift to multiples of frequency step size
if(shift % step < (step / 2)) {
_shift = shift / step;
} else {
_shift = (shift / step) + 1;
}
// Write resultant tones into arrays for quick lookup when modulating.
_tones[0] = 0;
_tones[1] = _shift;
_tones[2] = _shift*2;
_tones[3] = _shift*3;
_tonesHz[0] = 0;
_tonesHz[1] = _shiftHz;
_tonesHz[2] = _shiftHz*2;
_tonesHz[3] = _shiftHz*3;
// calculate 24-bit frequency
_base = (base * 1000000.0) / _phy->getFreqStep();
// configure for direct mode
return(_phy->startDirect());
}
void FSK4Client::idle() {
// Idle at Tone 0.
tone(0);
}
size_t FSK4Client::write(uint8_t* buff, size_t len) {
size_t n = 0;
for(size_t i = 0; i < len; i++) {
n += FSK4Client::write(buff[i]);
}
FSK4Client::standby();
return(n);
}
size_t FSK4Client::write(uint8_t b) {
int k;
// Send symbols MSB first.
for (k=0;k<4;k++)
{
// Extract 4FSK symbol (2 bits)
uint8_t symbol = (b & 0xC0) >> 6;
// Modulate
FSK4Client::tone(symbol);
// Shift to next symbol.
b = b << 2;
}
return(1);
}
void FSK4Client::tone(uint8_t i) {
uint32_t start = Module::micros();
transmitDirect(_base + _tones[i], _baseHz + _tonesHz[i]);
while(Module::micros() - start < _bitDuration) {
Module::yield();
}
}
int16_t FSK4Client::transmitDirect(uint32_t freq, uint32_t freqHz) {
#if !defined(RADIOLIB_EXCLUDE_AFSK)
if(_audio != nullptr) {
return(_audio->tone(freqHz));
}
#endif
return(_phy->transmitDirect(freq));
}
int16_t FSK4Client::standby() {
#if !defined(RADIOLIB_EXCLUDE_AFSK)
if(_audio != nullptr) {
return(_audio->noTone());
}
#endif
return(_phy->standby());
}
#endif