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)
|
||||
{
|
||||
diagnostic_callback(
|
||||
int(dcd_),
|
||||
dcd_,
|
||||
dev.error(),
|
||||
dev.deviation(),
|
||||
dev.offset(),
|
||||
@ -482,7 +482,7 @@ void M17Demodulator::operator()(const float input)
|
||||
if (diagnostic_callback)
|
||||
{
|
||||
diagnostic_callback(
|
||||
int(dcd_),
|
||||
dcd_,
|
||||
dev.error(),
|
||||
dev.deviation(),
|
||||
dev.offset(),
|
||||
@ -570,7 +570,7 @@ void M17Demodulator::operator()(const float input)
|
||||
if (diagnostic_callback)
|
||||
{
|
||||
diagnostic_callback(
|
||||
int(dcd_),
|
||||
dcd_,
|
||||
dev.error(),
|
||||
dev.deviation(),
|
||||
dev.offset(),
|
||||
|
@ -368,6 +368,82 @@ public:
|
||||
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)
|
||||
{
|
||||
M17Randomizer<368> randomizer;
|
||||
|
@ -292,6 +292,13 @@ void M17ModGUI::on_packetMode_toggled(bool checked)
|
||||
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)
|
||||
{
|
||||
m_m17Mod->sendPacket();
|
||||
@ -602,6 +609,19 @@ void M17ModGUI::displayModes()
|
||||
{
|
||||
ui->packetMode->setChecked(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->mic->setChecked(false);
|
||||
ui->play->setChecked(false);
|
||||
@ -614,9 +634,11 @@ void M17ModGUI::displayModes()
|
||||
ui->tone->setChecked(true);
|
||||
ui->tone->setEnabled(true);
|
||||
ui->packetMode->setChecked(false);
|
||||
ui->bertMode->setChecked(false);
|
||||
ui->mic->setChecked(false);
|
||||
ui->play->setChecked(false);
|
||||
ui->packetMode->setEnabled(false);
|
||||
ui->bertMode->setEnabled(true);
|
||||
ui->mic->setEnabled(false);
|
||||
ui->play->setEnabled(false);
|
||||
}
|
||||
@ -625,8 +647,10 @@ void M17ModGUI::displayModes()
|
||||
{
|
||||
ui->tone->setChecked(false);
|
||||
ui->packetMode->setChecked(false);
|
||||
ui->bertMode->setChecked(false);
|
||||
ui->tone->setEnabled(false);
|
||||
ui->packetMode->setEnabled(false);
|
||||
ui->bertMode->setEnabled(true);
|
||||
|
||||
if (m_settings.m_audioType == M17ModSettings::AudioType::AudioInput)
|
||||
{
|
||||
@ -653,10 +677,12 @@ void M17ModGUI::displayModes()
|
||||
else if (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeNone)
|
||||
{
|
||||
ui->packetMode->setChecked(false);
|
||||
ui->bertMode->setChecked(false);
|
||||
ui->tone->setChecked(false);
|
||||
ui->mic->setChecked(false);
|
||||
ui->play->setChecked(false);
|
||||
ui->packetMode->setEnabled(true);
|
||||
ui->bertMode->setEnabled(true);
|
||||
ui->tone->setEnabled(true);
|
||||
ui->mic->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->fmAudio, &ButtonSwitch::toggled, this, &M17ModGUI::on_fmAudio_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->loopPacket, &ButtonSwitch::toggled, this, &M17ModGUI::on_loopPacket_toggled);
|
||||
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_packetMode_toggled(bool checked);
|
||||
void on_bertMode_toggled(bool checked);
|
||||
void on_sendPacket_clicked(bool checked);
|
||||
void on_loopPacket_toggled(bool checked);
|
||||
void on_loopPacketInterval_valueChanged(int value);
|
||||
|
@ -858,6 +858,16 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</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>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -28,6 +28,9 @@ MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAPRS, Message)
|
||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAudioFrame, Message)
|
||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStartAudio, 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() :
|
||||
m_m17Modulator("MYCALL", ""),
|
||||
@ -108,6 +111,24 @@ bool M17ModProcessor::handleMessage(const Message& cmd)
|
||||
audioStop();
|
||||
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;
|
||||
}
|
||||
@ -243,6 +264,13 @@ void M17ModProcessor::processAudioFrame()
|
||||
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<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();
|
||||
|
||||
@ -203,6 +248,7 @@ private:
|
||||
int m_audioFrameIndex;
|
||||
uint16_t m_audioFrameNumber;
|
||||
struct CODEC2 *m_codec2;
|
||||
mobilinkd::PRBS9 m_prbs;
|
||||
bool m_insertPositionToggle;
|
||||
|
||||
bool handleMessage(const Message& cmd);
|
||||
@ -211,6 +257,7 @@ private:
|
||||
void audioStop();
|
||||
void processAudioFrame();
|
||||
std::array<uint8_t, 16> encodeAudio(std::array<int16_t, 320*6>& audioFrame);
|
||||
void processBERTFrame();
|
||||
void test(const QString& sourceCall, const QString& destCall);
|
||||
void send_preamble();
|
||||
void send_eot();
|
||||
|
@ -51,6 +51,7 @@ M17ModSource::M17ModSource() :
|
||||
m_audioReadBufferIndex = 0;
|
||||
m_m17PullAudio = false;
|
||||
m_m17PullCount = 0;
|
||||
m_m17PullBERT = false;
|
||||
|
||||
m_feedbackAudioBuffer.resize(1<<14);
|
||||
m_feedbackAudioBufferFill = 0;
|
||||
@ -358,6 +359,22 @@ void M17ModSource::pullM17(Real& sample, bool& carrier)
|
||||
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
|
||||
{
|
||||
if (m_m17PullAudio)
|
||||
@ -366,6 +383,12 @@ void M17ModSource::pullM17(Real& sample, bool& carrier)
|
||||
m_processor->getInputMessageQueue()->push(msg);
|
||||
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
|
||||
|
@ -110,6 +110,7 @@ private:
|
||||
AudioFifo m_audioFifo;
|
||||
bool m_m17PullAudio;
|
||||
int m_m17PullCount;
|
||||
bool m_m17PullBERT;
|
||||
|
||||
int m_feedbackAudioSampleRate;
|
||||
AudioVector m_feedbackAudioBuffer;
|
||||
|
Loading…
Reference in New Issue
Block a user