mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-10-31 15:07:12 -04:00
M17 mod: implement BERT
This commit is contained in:
parent
71c486310a
commit
242a5843d8
@ -98,7 +98,7 @@ void M17Demodulator::dcd_off()
|
|||||||
if (diagnostic_callback)
|
if (diagnostic_callback)
|
||||||
{
|
{
|
||||||
diagnostic_callback(
|
diagnostic_callback(
|
||||||
int(dcd_),
|
dcd_,
|
||||||
dev.error(),
|
dev.error(),
|
||||||
dev.deviation(),
|
dev.deviation(),
|
||||||
dev.offset(),
|
dev.offset(),
|
||||||
@ -482,7 +482,7 @@ void M17Demodulator::operator()(const float input)
|
|||||||
if (diagnostic_callback)
|
if (diagnostic_callback)
|
||||||
{
|
{
|
||||||
diagnostic_callback(
|
diagnostic_callback(
|
||||||
int(dcd_),
|
dcd_,
|
||||||
dev.error(),
|
dev.error(),
|
||||||
dev.deviation(),
|
dev.deviation(),
|
||||||
dev.offset(),
|
dev.offset(),
|
||||||
@ -570,7 +570,7 @@ void M17Demodulator::operator()(const float input)
|
|||||||
if (diagnostic_callback)
|
if (diagnostic_callback)
|
||||||
{
|
{
|
||||||
diagnostic_callback(
|
diagnostic_callback(
|
||||||
int(dcd_),
|
dcd_,
|
||||||
dev.error(),
|
dev.error(),
|
||||||
dev.deviation(),
|
dev.deviation(),
|
||||||
dev.offset(),
|
dev.offset(),
|
||||||
|
@ -368,6 +368,82 @@ public:
|
|||||||
return punctured;
|
return punctured;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::array<int8_t, 368> make_bert_frame(PRBS9& prbs)
|
||||||
|
{
|
||||||
|
std::array<uint8_t, 25> data; // 24.6125 bytes, 197 bits
|
||||||
|
|
||||||
|
// Generate the data.
|
||||||
|
for (size_t i = 0; i != data.size() - 1; ++i)
|
||||||
|
{
|
||||||
|
uint8_t byte = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i != 8; ++i)
|
||||||
|
{
|
||||||
|
byte <<= 1;
|
||||||
|
byte |= prbs.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
data[i] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t byte = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i != 5; ++i)
|
||||||
|
{
|
||||||
|
byte <<= 1;
|
||||||
|
byte |= prbs.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte <<= 3;
|
||||||
|
data[24] = byte;
|
||||||
|
|
||||||
|
std::array<uint8_t, 402> encoded;
|
||||||
|
size_t index = 0;
|
||||||
|
uint32_t memory = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i != data.size() - 1; ++i)
|
||||||
|
{
|
||||||
|
auto b = data[i];
|
||||||
|
|
||||||
|
for (size_t j = 0; j != 8; ++j)
|
||||||
|
{
|
||||||
|
uint32_t x = (b & 0x80) >> 7;
|
||||||
|
b <<= 1;
|
||||||
|
memory = update_memory<4>(memory, x);
|
||||||
|
encoded[index++] = convolve_bit(031, memory);
|
||||||
|
encoded[index++] = convolve_bit(027, memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto b = data[24];
|
||||||
|
|
||||||
|
for (size_t j = 0; j != 5; ++j)
|
||||||
|
{
|
||||||
|
uint32_t x = (b & 0x80) >> 7;
|
||||||
|
b <<= 1;
|
||||||
|
memory = update_memory<4>(memory, x);
|
||||||
|
encoded[index++] = convolve_bit(031, memory);
|
||||||
|
encoded[index++] = convolve_bit(027, memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the encoder.
|
||||||
|
for (size_t i = 0; i != 4; ++i)
|
||||||
|
{
|
||||||
|
memory = update_memory<4>(memory, 0);
|
||||||
|
encoded[index++] = convolve_bit(031, memory);
|
||||||
|
encoded[index++] = convolve_bit(027, memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<int8_t, 368> punctured;
|
||||||
|
auto size = puncture(encoded, punctured, P2);
|
||||||
|
|
||||||
|
if (size != 368) {
|
||||||
|
std::cerr << "mobilinkd::M17Modulator::make_bert_frame: incorrect size (not 368)" << size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return punctured;
|
||||||
|
}
|
||||||
|
|
||||||
static void interleave_and_randomize(std::array<int8_t, 368>& punctured)
|
static void interleave_and_randomize(std::array<int8_t, 368>& punctured)
|
||||||
{
|
{
|
||||||
M17Randomizer<368> randomizer;
|
M17Randomizer<368> randomizer;
|
||||||
|
@ -292,6 +292,13 @@ void M17ModGUI::on_packetMode_toggled(bool checked)
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M17ModGUI::on_bertMode_toggled(bool checked)
|
||||||
|
{
|
||||||
|
m_settings.m_m17Mode = checked ? M17ModSettings::M17ModeM17BERT : M17ModSettings::M17ModeNone;
|
||||||
|
displayModes();
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
void M17ModGUI::on_sendPacket_clicked(bool)
|
void M17ModGUI::on_sendPacket_clicked(bool)
|
||||||
{
|
{
|
||||||
m_m17Mod->sendPacket();
|
m_m17Mod->sendPacket();
|
||||||
@ -602,6 +609,19 @@ void M17ModGUI::displayModes()
|
|||||||
{
|
{
|
||||||
ui->packetMode->setChecked(true);
|
ui->packetMode->setChecked(true);
|
||||||
ui->packetMode->setEnabled(true);
|
ui->packetMode->setEnabled(true);
|
||||||
|
ui->bertMode->setChecked(false);
|
||||||
|
ui->tone->setChecked(false);
|
||||||
|
ui->mic->setChecked(false);
|
||||||
|
ui->play->setChecked(false);
|
||||||
|
ui->bertMode->setEnabled(false);
|
||||||
|
ui->tone->setEnabled(false);
|
||||||
|
ui->mic->setEnabled(false);
|
||||||
|
ui->play->setEnabled(false);
|
||||||
|
}
|
||||||
|
if (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeM17BERT)
|
||||||
|
{
|
||||||
|
ui->bertMode->setChecked(true);
|
||||||
|
ui->bertMode->setEnabled(true);
|
||||||
ui->tone->setChecked(false);
|
ui->tone->setChecked(false);
|
||||||
ui->mic->setChecked(false);
|
ui->mic->setChecked(false);
|
||||||
ui->play->setChecked(false);
|
ui->play->setChecked(false);
|
||||||
@ -614,9 +634,11 @@ void M17ModGUI::displayModes()
|
|||||||
ui->tone->setChecked(true);
|
ui->tone->setChecked(true);
|
||||||
ui->tone->setEnabled(true);
|
ui->tone->setEnabled(true);
|
||||||
ui->packetMode->setChecked(false);
|
ui->packetMode->setChecked(false);
|
||||||
|
ui->bertMode->setChecked(false);
|
||||||
ui->mic->setChecked(false);
|
ui->mic->setChecked(false);
|
||||||
ui->play->setChecked(false);
|
ui->play->setChecked(false);
|
||||||
ui->packetMode->setEnabled(false);
|
ui->packetMode->setEnabled(false);
|
||||||
|
ui->bertMode->setEnabled(true);
|
||||||
ui->mic->setEnabled(false);
|
ui->mic->setEnabled(false);
|
||||||
ui->play->setEnabled(false);
|
ui->play->setEnabled(false);
|
||||||
}
|
}
|
||||||
@ -625,8 +647,10 @@ void M17ModGUI::displayModes()
|
|||||||
{
|
{
|
||||||
ui->tone->setChecked(false);
|
ui->tone->setChecked(false);
|
||||||
ui->packetMode->setChecked(false);
|
ui->packetMode->setChecked(false);
|
||||||
|
ui->bertMode->setChecked(false);
|
||||||
ui->tone->setEnabled(false);
|
ui->tone->setEnabled(false);
|
||||||
ui->packetMode->setEnabled(false);
|
ui->packetMode->setEnabled(false);
|
||||||
|
ui->bertMode->setEnabled(true);
|
||||||
|
|
||||||
if (m_settings.m_audioType == M17ModSettings::AudioType::AudioInput)
|
if (m_settings.m_audioType == M17ModSettings::AudioType::AudioInput)
|
||||||
{
|
{
|
||||||
@ -653,10 +677,12 @@ void M17ModGUI::displayModes()
|
|||||||
else if (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeNone)
|
else if (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeNone)
|
||||||
{
|
{
|
||||||
ui->packetMode->setChecked(false);
|
ui->packetMode->setChecked(false);
|
||||||
|
ui->bertMode->setChecked(false);
|
||||||
ui->tone->setChecked(false);
|
ui->tone->setChecked(false);
|
||||||
ui->mic->setChecked(false);
|
ui->mic->setChecked(false);
|
||||||
ui->play->setChecked(false);
|
ui->play->setChecked(false);
|
||||||
ui->packetMode->setEnabled(true);
|
ui->packetMode->setEnabled(true);
|
||||||
|
ui->bertMode->setEnabled(true);
|
||||||
ui->tone->setEnabled(true);
|
ui->tone->setEnabled(true);
|
||||||
ui->mic->setEnabled(true);
|
ui->mic->setEnabled(true);
|
||||||
ui->play->setEnabled(true);
|
ui->play->setEnabled(true);
|
||||||
@ -792,6 +818,7 @@ void M17ModGUI::makeUIConnections()
|
|||||||
QObject::connect(ui->feedbackVolume, &QDial::valueChanged, this, &M17ModGUI::on_feedbackVolume_valueChanged);
|
QObject::connect(ui->feedbackVolume, &QDial::valueChanged, this, &M17ModGUI::on_feedbackVolume_valueChanged);
|
||||||
QObject::connect(ui->fmAudio, &ButtonSwitch::toggled, this, &M17ModGUI::on_fmAudio_toggled);
|
QObject::connect(ui->fmAudio, &ButtonSwitch::toggled, this, &M17ModGUI::on_fmAudio_toggled);
|
||||||
QObject::connect(ui->packetMode, &ButtonSwitch::toggled, this, &M17ModGUI::on_packetMode_toggled);
|
QObject::connect(ui->packetMode, &ButtonSwitch::toggled, this, &M17ModGUI::on_packetMode_toggled);
|
||||||
|
QObject::connect(ui->bertMode, &ButtonSwitch::toggled, this, &M17ModGUI::on_bertMode_toggled);
|
||||||
QObject::connect(ui->sendPacket, &QPushButton::clicked, this, &M17ModGUI::on_sendPacket_clicked);
|
QObject::connect(ui->sendPacket, &QPushButton::clicked, this, &M17ModGUI::on_sendPacket_clicked);
|
||||||
QObject::connect(ui->loopPacket, &ButtonSwitch::toggled, this, &M17ModGUI::on_loopPacket_toggled);
|
QObject::connect(ui->loopPacket, &ButtonSwitch::toggled, this, &M17ModGUI::on_loopPacket_toggled);
|
||||||
QObject::connect(ui->loopPacketInterval, &QDial::valueChanged, this, &M17ModGUI::on_loopPacketInterval_valueChanged);
|
QObject::connect(ui->loopPacketInterval, &QDial::valueChanged, this, &M17ModGUI::on_loopPacketInterval_valueChanged);
|
||||||
|
@ -134,6 +134,7 @@ private slots:
|
|||||||
void on_feedbackVolume_valueChanged(int value);
|
void on_feedbackVolume_valueChanged(int value);
|
||||||
|
|
||||||
void on_packetMode_toggled(bool checked);
|
void on_packetMode_toggled(bool checked);
|
||||||
|
void on_bertMode_toggled(bool checked);
|
||||||
void on_sendPacket_clicked(bool checked);
|
void on_sendPacket_clicked(bool checked);
|
||||||
void on_loopPacket_toggled(bool checked);
|
void on_loopPacket_toggled(bool checked);
|
||||||
void on_loopPacketInterval_valueChanged(int value);
|
void on_loopPacketInterval_valueChanged(int value);
|
||||||
|
@ -858,6 +858,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="ButtonSwitch" name="bertMode">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>BERT mode</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>BERT</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -28,6 +28,9 @@ MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAPRS, Message)
|
|||||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAudioFrame, Message)
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAudioFrame, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStartAudio, Message)
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStartAudio, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStopAudio, Message)
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStopAudio, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStartBERT, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendBERTFrame, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStopBERT, Message)
|
||||||
|
|
||||||
M17ModProcessor::M17ModProcessor() :
|
M17ModProcessor::M17ModProcessor() :
|
||||||
m_m17Modulator("MYCALL", ""),
|
m_m17Modulator("MYCALL", ""),
|
||||||
@ -108,6 +111,24 @@ bool M17ModProcessor::handleMessage(const Message& cmd)
|
|||||||
audioStop();
|
audioStop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (MsgStartBERT::match(cmd))
|
||||||
|
{
|
||||||
|
qDebug("M17ModProcessor::handleMessage: MsgStartBERT");
|
||||||
|
m_prbs.reset();
|
||||||
|
send_preamble(); // preamble
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (MsgSendBERTFrame::match(cmd))
|
||||||
|
{
|
||||||
|
processBERTFrame();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (MsgStopBERT::match(cmd))
|
||||||
|
{
|
||||||
|
qDebug("M17ModProcessor::handleMessage: MsgStopBERT");
|
||||||
|
send_eot(); // EOT
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -243,6 +264,13 @@ void M17ModProcessor::processAudioFrame()
|
|||||||
output_baseband(mobilinkd::M17Modulator::STREAM_SYNC_WORD, temp);
|
output_baseband(mobilinkd::M17Modulator::STREAM_SYNC_WORD, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M17ModProcessor::processBERTFrame()
|
||||||
|
{
|
||||||
|
std::array<int8_t, 368> temp = mobilinkd::M17Modulator::make_bert_frame(m_prbs);
|
||||||
|
mobilinkd::M17Modulator::interleave_and_randomize(temp);
|
||||||
|
output_baseband(mobilinkd::M17Modulator::BERT_SYNC_WORD, temp);
|
||||||
|
}
|
||||||
|
|
||||||
std::array<uint8_t, 16> M17ModProcessor::encodeAudio(std::array<int16_t, 320*6>& audioFrame)
|
std::array<uint8_t, 16> M17ModProcessor::encodeAudio(std::array<int16_t, 320*6>& audioFrame)
|
||||||
{
|
{
|
||||||
std::array<int16_t, 320> audioFrame8k;
|
std::array<int16_t, 320> audioFrame8k;
|
||||||
|
@ -183,6 +183,51 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MsgStartBERT : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
static MsgStartBERT* create() {
|
||||||
|
return new MsgStartBERT();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MsgStartBERT() :
|
||||||
|
Message()
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
class MsgSendBERTFrame : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
static MsgSendBERTFrame* create() {
|
||||||
|
return new MsgSendBERTFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MsgSendBERTFrame() :
|
||||||
|
Message()
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
class MsgStopBERT : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
static MsgStopBERT* create() {
|
||||||
|
return new MsgStopBERT();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MsgStopBERT() :
|
||||||
|
Message()
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
M17ModProcessor();
|
M17ModProcessor();
|
||||||
~M17ModProcessor();
|
~M17ModProcessor();
|
||||||
|
|
||||||
@ -203,6 +248,7 @@ private:
|
|||||||
int m_audioFrameIndex;
|
int m_audioFrameIndex;
|
||||||
uint16_t m_audioFrameNumber;
|
uint16_t m_audioFrameNumber;
|
||||||
struct CODEC2 *m_codec2;
|
struct CODEC2 *m_codec2;
|
||||||
|
mobilinkd::PRBS9 m_prbs;
|
||||||
bool m_insertPositionToggle;
|
bool m_insertPositionToggle;
|
||||||
|
|
||||||
bool handleMessage(const Message& cmd);
|
bool handleMessage(const Message& cmd);
|
||||||
@ -211,6 +257,7 @@ private:
|
|||||||
void audioStop();
|
void audioStop();
|
||||||
void processAudioFrame();
|
void processAudioFrame();
|
||||||
std::array<uint8_t, 16> encodeAudio(std::array<int16_t, 320*6>& audioFrame);
|
std::array<uint8_t, 16> encodeAudio(std::array<int16_t, 320*6>& audioFrame);
|
||||||
|
void processBERTFrame();
|
||||||
void test(const QString& sourceCall, const QString& destCall);
|
void test(const QString& sourceCall, const QString& destCall);
|
||||||
void send_preamble();
|
void send_preamble();
|
||||||
void send_eot();
|
void send_eot();
|
||||||
|
@ -51,6 +51,7 @@ M17ModSource::M17ModSource() :
|
|||||||
m_audioReadBufferIndex = 0;
|
m_audioReadBufferIndex = 0;
|
||||||
m_m17PullAudio = false;
|
m_m17PullAudio = false;
|
||||||
m_m17PullCount = 0;
|
m_m17PullCount = 0;
|
||||||
|
m_m17PullBERT = false;
|
||||||
|
|
||||||
m_feedbackAudioBuffer.resize(1<<14);
|
m_feedbackAudioBuffer.resize(1<<14);
|
||||||
m_feedbackAudioBufferFill = 0;
|
m_feedbackAudioBufferFill = 0;
|
||||||
@ -358,6 +359,22 @@ void M17ModSource::pullM17(Real& sample, bool& carrier)
|
|||||||
m_m17PullCount = 0;
|
m_m17PullCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (m_settings.m_m17Mode == M17ModSettings::M17ModeM17BERT)
|
||||||
|
{
|
||||||
|
if (!m_m17PullBERT)
|
||||||
|
{
|
||||||
|
M17ModProcessor::MsgStartBERT *msg = M17ModProcessor::MsgStartBERT::create();
|
||||||
|
m_processor->getInputMessageQueue()->push(msg);
|
||||||
|
m_m17PullBERT = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_processor->getBasebandFifo()->getFill() < 1920) && (m_m17PullCount > 192))
|
||||||
|
{
|
||||||
|
M17ModProcessor::MsgSendBERTFrame *msg = M17ModProcessor::MsgSendBERTFrame::create();
|
||||||
|
m_processor->getInputMessageQueue()->push(msg);
|
||||||
|
m_m17PullCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_m17PullAudio)
|
if (m_m17PullAudio)
|
||||||
@ -366,6 +383,12 @@ void M17ModSource::pullM17(Real& sample, bool& carrier)
|
|||||||
m_processor->getInputMessageQueue()->push(msg);
|
m_processor->getInputMessageQueue()->push(msg);
|
||||||
m_m17PullAudio = false;
|
m_m17PullAudio = false;
|
||||||
}
|
}
|
||||||
|
else if (m_m17PullBERT)
|
||||||
|
{
|
||||||
|
M17ModProcessor::MsgStopBERT *msg = M17ModProcessor::MsgStopBERT::create();
|
||||||
|
m_processor->getInputMessageQueue()->push(msg);
|
||||||
|
m_m17PullBERT = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get sample from processor FIFO
|
// get sample from processor FIFO
|
||||||
|
@ -110,6 +110,7 @@ private:
|
|||||||
AudioFifo m_audioFifo;
|
AudioFifo m_audioFifo;
|
||||||
bool m_m17PullAudio;
|
bool m_m17PullAudio;
|
||||||
int m_m17PullCount;
|
int m_m17PullCount;
|
||||||
|
bool m_m17PullBERT;
|
||||||
|
|
||||||
int m_feedbackAudioSampleRate;
|
int m_feedbackAudioSampleRate;
|
||||||
AudioVector m_feedbackAudioBuffer;
|
AudioVector m_feedbackAudioBuffer;
|
||||||
|
Loading…
Reference in New Issue
Block a user