1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-20 06:38:36 -04:00

M17: debug and SMS transmit

This commit is contained in:
f4exb
2022-06-17 02:25:34 +02:00
parent f10da64717
commit 6b863287d8
19 changed files with 659 additions and 347 deletions
+3 -3
View File
@@ -567,7 +567,7 @@
<widget class="QLabel" name="sourceText">
<property name="minimumSize">
<size>
<width>80</width>
<width>90</width>
<height>0</height>
</size>
</property>
@@ -602,7 +602,7 @@
<widget class="QLabel" name="destText">
<property name="minimumSize">
<size>
<width>80</width>
<width>90</width>
<height>0</height>
</size>
</property>
@@ -637,7 +637,7 @@
<widget class="QLabel" name="typeText">
<property name="minimumSize">
<size>
<width>110</width>
<width>120</width>
<height>0</height>
</size>
</property>
@@ -15,9 +15,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <boost/crc.hpp>
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
// #include <boost/crc.hpp>
// #include <boost/program_options.hpp>
// #include <boost/optional.hpp>
#include <codec2/codec2.h>
#include <QDebug>
@@ -278,7 +278,6 @@ void M17DemodProcessor::resetInfo()
void M17DemodProcessor::setDCDOff()
{
qDebug("M17DemodProcessor::setDCDOff");
m_demod.dcd_off();
}
@@ -301,25 +300,36 @@ void M17DemodProcessor::append_packet(std::vector<uint8_t>& result, mobilinkd::M
bool M17DemodProcessor::decode_packet(mobilinkd::M17FrameDecoder::packet_buffer_t const& packet_segment)
{
// qDebug() << tr("M17DemodProcessor::decode_packet: 0x%1").arg((int) packet_segment[25], 2, 16, QChar('0'));
if (packet_segment[25] & 0x80) // last frame of packet.
{
size_t packet_size = (packet_segment[25] & 0x7F) >> 2;
packet_size = std::min(packet_size, size_t(25)); // on last frame this is the remainder byte count
m_packetFrameCounter = 0;
for (size_t i = 0; i != packet_size; ++i) {
for (size_t i = 0; i < packet_size; ++i) {
m_currentPacket.push_back(packet_segment[i]);
}
if (m_currentPacket.size() < 3) {
if (m_currentPacket.size() < 3)
{
qDebug() << "M17DemodProcessor::decode_packet: too small:" << m_currentPacket.size();
return false;
}
else
{
qDebug() << "M17DemodProcessor::decode_packet: last chunk size:" << packet_size << " packet size:" << m_currentPacket.size();
}
boost::crc_optimal<16, 0x1021, 0xFFFF, 0xFFFF, true, true> crc;
crc.process_bytes(&m_currentPacket.front(), m_currentPacket.size());
uint16_t calcChecksum = crc.checksum();
uint16_t xmitChecksum = m_currentPacket.back() + (1<<8) * m_currentPacket.end()[-2];
mobilinkd::CRC16<0x5935, 0xFFFF> crc16;
crc16.reset();
for (std::vector<uint8_t>::const_iterator it = m_currentPacket.begin(); it != m_currentPacket.end() - 2; ++it) {
crc16(*it);
}
uint16_t calcChecksum = crc16.get_bytes()[0] + (crc16.get_bytes()[1]<<8);
uint16_t xmitChecksum = m_currentPacket.back() + (m_currentPacket.end()[-2]<<8);
if (calcChecksum == xmitChecksum) // (checksum == 0x0f47)
{
@@ -355,7 +365,9 @@ bool M17DemodProcessor::decode_packet(mobilinkd::M17FrameDecoder::packet_buffer_
return true;
}
qWarning() << "M17DemodProcessor::decode_packet: Packet checksum error: " << std::hex << calcChecksum << "vs" << xmitChecksum << std::dec;
QString ccrc = tr("0x%1").arg(calcChecksum, 4, 16, QChar('0'));
QString xcrc = tr("0x%1").arg(xmitChecksum, 4, 16, QChar('0'));
qWarning() << "M17DemodProcessor::decode_packet: Packet checksum error: " << ccrc << "vs" << xcrc;
return false;
}
@@ -368,12 +380,16 @@ bool M17DemodProcessor::decode_packet(mobilinkd::M17FrameDecoder::packet_buffer_
return false;
}
m_packetFrameCounter++;
if (m_packetFrameCounter == 0) {
m_currentPacket.clear();
}
for (size_t i = 0; i != 25; ++i) {
for (size_t i = 0; i < 25; ++i) {
m_currentPacket.push_back(packet_segment[i]);
}
m_packetFrameCounter++;
return true;
}
+4 -2
View File
@@ -759,6 +759,8 @@ void M17ModGUI::makeUIConnections()
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->smsText, &CustomTextEdit::editingFinished, this, &M17ModGUI::on_smsText_editingFinished);
QObject::connect(ui->source, &QLineEdit::editingFinished, this, &M17ModGUI::on_source_editingFinished);
QObject::connect(ui->destination, &QLineEdit::editingFinished, this, &M17ModGUI::on_destination_editingFinished);
}
void M17ModGUI::updateAbsoluteCenterFrequency()
@@ -775,7 +777,7 @@ M17ModSettings::PacketType M17ModGUI::indexToPacketType(int index)
case 1:
return M17ModSettings::PacketType::PacketAPRS;
default:
return M17ModSettings::PacketType::PacketNone;
return M17ModSettings::PacketType::PacketSMS;
}
}
@@ -788,6 +790,6 @@ int M17ModGUI::packetTypeToIndex(M17ModSettings::PacketType type)
case M17ModSettings::PacketType::PacketAPRS:
return 1;
default:
return -1;
return 0;
}
}
+71 -26
View File
@@ -19,9 +19,12 @@
#include "m17modprocessor.h"
M17ModProcessor::M17ModProcessor()
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendSMS, Message)
M17ModProcessor::M17ModProcessor() :
m_m17Modulator("MYCALL", "")
{
m_basebandFifo.setSampleSize(sizeof(int16_t), 48000);
m_basebandFifo.setSampleSize(sizeof(int16_t), 96000);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
}
@@ -37,6 +40,7 @@ bool M17ModProcessor::handleMessage(const Message& cmd)
packetBytes.prepend(0x05); // SMS standard type
packetBytes.truncate(798); // Maximum packet size is 798 payload + 2 bytes CRC = 800 bytes (32*25)
processPacket(notif.getSourceCall(), notif.getDestCall(), packetBytes);
// test(notif.getSourceCall(), notif.getDestCall());
return true;
}
@@ -56,44 +60,85 @@ void M17ModProcessor::handleInputMessages()
}
}
void M17ModProcessor::test(const QString& sourceCall, const QString& destCall)
{
m_m17Modulator.source(sourceCall.toStdString());
m_m17Modulator.dest(destCall.toStdString());
for (int i = 0; i < 25; i++) {
send_preamble();
}
}
void M17ModProcessor::processPacket(const QString& sourceCall, const QString& destCall, const QByteArray& packetBytes)
{
mobilinkd::M17Modulator modulator(sourceCall.toStdString(), destCall.toStdString());
// preamble
std::array<uint8_t, 48> preamble_bytes;
mobilinkd::M17Modulator::make_preamble(preamble_bytes);
std::array<int8_t, 48 * 4> fullframe_symbols = mobilinkd::M17Modulator::bytes_to_symbols(preamble_bytes);
std::array<int16_t, 1920> baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
m_basebandFifo.write((const quint8*) baseband.data(), 1920);
qDebug("M17ModProcessor::processPacket: %s to %s: %s", qPrintable(sourceCall), qPrintable(destCall), qPrintable(packetBytes));
m_m17Modulator.source(sourceCall.toStdString());
m_m17Modulator.dest(destCall.toStdString());
send_preamble(); // preamble
// LSF
mobilinkd::M17Modulator::lich_t lichSegments; // Not used for packet
mobilinkd::M17Modulator::frame_t frame;
modulator.make_link_setup(lichSegments, frame);
std::array<int8_t, 46 * 4> frame_symbols = mobilinkd::M17Modulator::bytes_to_symbols(frame);
std::copy(mobilinkd::M17Modulator::LSF_SYNC_WORD.begin(), mobilinkd::M17Modulator::LSF_SYNC_WORD.end(), fullframe_symbols.begin());
std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2);
baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
m_basebandFifo.write((const quint8*) baseband.data(), 1920);
std::array<uint8_t, 30> lsf;
std::array<int8_t, 368> lsf_frame = mobilinkd::M17Modulator::make_lsf(lsf, sourceCall.toStdString(), destCall.toStdString());
output_baseband(mobilinkd::M17Modulator::LSF_SYNC_WORD, lsf_frame);
// Packets
std::copy(mobilinkd::M17Modulator::DATA_SYNC_WORD.begin(), mobilinkd::M17Modulator::DATA_SYNC_WORD.end(), fullframe_symbols.begin());
mobilinkd::M17Modulator::packet_t packet;
int remainderCount = packetBytes.size();
int packetCount = 0;
std::array<int8_t, 368> packet_frame;
// std::copy(mobilinkd::M17Modulator::DATA_SYNC_WORD.begin(), mobilinkd::M17Modulator::DATA_SYNC_WORD.end(), fullframe_symbols.begin());
mobilinkd::M17Modulator::packet_t packet;
while (remainderCount > 25)
{
std::copy(packetBytes.begin() + (packetCount*25), packetBytes.begin() + ((packetCount+1)*25), packet.begin());
frame = modulator.make_packet_frame(packetCount, false, packet, 25);
std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2);
baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
m_basebandFifo.write((const quint8*) baseband.data(), 1920);
packet_frame = m_m17Modulator.make_packet_frame(packetCount, 25, false, packet);
output_baseband(mobilinkd::M17Modulator::PACKET_SYNC_WORD, packet_frame);
remainderCount -= 25;
packetCount++;
}
std::copy(packetBytes.begin() + (packetCount*25), packetBytes.begin() + (packetCount*25) + remainderCount, packet.begin());
frame = modulator.make_packet_frame(packetCount, true, packet, remainderCount);
std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2);
baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
packet_frame = m_m17Modulator.make_packet_frame(packetCount, remainderCount, true, packet);
output_baseband(mobilinkd::M17Modulator::PACKET_SYNC_WORD, packet_frame);
qDebug("M17ModProcessor::processPacket: last: packetCount: %d remainderCount: %d", packetCount, remainderCount);
send_eot(); // EOT
}
void M17ModProcessor::send_preamble()
{
// Preamble is simple... bytes -> symbols -> baseband.
std::array<uint8_t, 48> preamble_bytes;
preamble_bytes.fill(0x77);
std::array<int8_t, 192> preamble_symbols = mobilinkd::M17Modulator::bytes_to_symbols(preamble_bytes);
std::array<int16_t, 1920> preamble_baseband = m_m17Modulator.symbols_to_baseband(preamble_symbols);
m_basebandFifo.write((const quint8*) preamble_baseband.data(), 1920);
}
void M17ModProcessor::send_eot()
{
std::array<uint8_t, 2> EOT_SYNC = { 0x55, 0x5D };
std::array<uint8_t, 48> eot_bytes;
for (unsigned int i = 0; i < eot_bytes.size(); i += 2) {
std::copy(EOT_SYNC.begin(), EOT_SYNC.end(), eot_bytes.begin() + i);
}
std::array<int8_t, 192> eot_symbols = mobilinkd::M17Modulator::bytes_to_symbols(eot_bytes);
std::array<int16_t, 1920> eot_baseband = m_m17Modulator.symbols_to_baseband(eot_symbols);
m_basebandFifo.write((const quint8*) eot_baseband.data(), 1920);
}
void M17ModProcessor::output_baseband(std::array<uint8_t, 2> sync_word, const std::array<int8_t, 368>& frame)
{
std::array<int8_t, 184> symbols = mobilinkd::M17Modulator::bits_to_symbols(frame); // 368 bits -> 184 dibit symbols
std::array<int8_t, 8> sw = mobilinkd::M17Modulator::bytes_to_symbols(sync_word); // 16 bits -> 8 dibit symbols
std::array<int8_t, 192> temp; // 384 = 368 + 16 bits -> 192 dibit symbols
auto fit = std::copy(sw.begin(), sw.end(), temp.begin()); // start with sync word dibits
std::copy(symbols.begin(), symbols.end(), fit); // then the frame dibits
std::array<int16_t, 1920> baseband = m_m17Modulator.symbols_to_baseband(temp); // 1920 48 kS/s int16_t samples
m_basebandFifo.write((const quint8*) baseband.data(), 1920);
}
+7 -1
View File
@@ -21,6 +21,7 @@
#include <QObject>
#include <QByteArray>
#include "m17/M17Modulator.h"
#include "util/message.h"
#include "util/messagequeue.h"
#include "audio/audiofifo.h"
@@ -58,14 +59,19 @@ public:
~M17ModProcessor();
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
AudioFifo *getSymbolFifo() { return &m_basebandFifo; }
AudioFifo *getBasebandFifo() { return &m_basebandFifo; }
private:
MessageQueue m_inputMessageQueue;
AudioFifo m_basebandFifo; //!< Samples are 16 bit integer baseband 48 kS/s samples
mobilinkd::M17Modulator m_m17Modulator;
bool handleMessage(const Message& cmd);
void processPacket(const QString& sourceCall, const QString& destCall, const QByteArray& packetBytes);
void test(const QString& sourceCall, const QString& destCall);
void send_preamble();
void send_eot();
void output_baseband(std::array<uint8_t, 2> sync_word, const std::array<int8_t, 368>& frame);
private slots:
void handleInputMessages();
+2 -2
View File
@@ -44,7 +44,7 @@ void M17ModSettings::resetToDefaults()
m_title = "M17 Modulator";
m_m17Mode = M17Mode::M17ModeNone;
m_audioType = AudioType::AudioNone;
m_packetType = PacketType::PacketNone;
m_packetType = PacketType::PacketSMS;
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName;
m_feedbackVolumeFactor = 0.5f;
@@ -150,7 +150,7 @@ bool M17ModSettings::deserialize(const QByteArray& data)
m_m17Mode = tmp < 0 ? M17ModeNone : tmp > (int) M17ModeM17BERT ? M17ModeM17BERT : (M17Mode) tmp;
d.readS32(9, &tmp, 0);
m_audioType = tmp < 0 ? AudioNone : tmp > (int) AudioInput ? AudioInput : (AudioType) tmp;
m_packetType = tmp < 0 ? PacketNone : tmp > (int) PacketSMS ? PacketSMS : (PacketType) tmp;
m_packetType = tmp < 0 ? PacketSMS : tmp > (int) PacketAPRS ? PacketAPRS : (PacketType) tmp;
d.readBlob(11, &bytetmp);
@@ -45,7 +45,6 @@ struct M17ModSettings
enum PacketType
{
PacketNone,
PacketSMS,
PacketAPRS
};
+31 -3
View File
@@ -25,6 +25,7 @@
#include "m17modsource.h"
const int M17ModSource::m_levelNbSamples = 480; // every 10ms
const float M17ModSource::m_preemphasis = 120.0e-6; // 120us
M17ModSource::M17ModSource() :
m_channelSampleRate(48000),
@@ -37,6 +38,7 @@ M17ModSource::M17ModSource() :
m_peakLevel(0.0f),
m_levelSum(0.0f),
m_ifstream(nullptr),
m_preemphasisFilter(m_preemphasis*48000),
m_mutex(QMutex::Recursive)
{
m_audioFifo.setLabel("M17ModSource.m_audioFifo");
@@ -53,6 +55,8 @@ M17ModSource::M17ModSource() :
m_demodBufferFill = 0;
m_magsq = 0.0;
m_basebandMax = 0;
m_basebandMin = 0;
m_processor = new M17ModProcessor();
@@ -268,9 +272,30 @@ void M17ModSource::pullAF(Real& sample, bool& carrier)
void M17ModSource::pullM17(Real& sample, bool& carrier)
{
// TODO
carrier = false;
sample = 0.0f;
quint8 bbSampleBytes[2];
carrier = m_processor->getBasebandFifo()->readOne(bbSampleBytes);
int16_t basbandSample = bbSampleBytes[0] | (bbSampleBytes[1]<<8);
if (carrier)
{
if (basbandSample > m_basebandMax)
{
qDebug("M17ModSource::pullM17: max: %d", basbandSample);
m_basebandMax = basbandSample;
}
if (basbandSample < m_basebandMin)
{
qDebug("M17ModSource::pullM17: min: %d", basbandSample);
m_basebandMin = basbandSample;
}
sample = basbandSample / 32768.0f;
}
else
{
sample = 0.0f;
}
}
void M17ModSource::pushFeedback(Real sample)
@@ -351,6 +376,7 @@ void M17ModSource::applyAudioSampleRate(int sampleRate)
m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
m_lowpass.create(301, sampleRate, m_settings.m_rfBandwidth);
m_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate);
m_preemphasisFilter.configure(m_preemphasis*sampleRate);
m_audioSampleRate = sampleRate;
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
@@ -449,6 +475,8 @@ void M17ModSource::handleAudio()
void M17ModSource::sendPacket()
{
qDebug("M17ModSource::sendPacket: %d", (int) m_settings.m_packetType);
if (m_settings.m_packetType == M17ModSettings::PacketType::PacketSMS)
{
M17ModProcessor::MsgSendSMS *msg = M17ModProcessor::MsgSendSMS::create(
+3
View File
@@ -119,8 +119,11 @@ private:
std::ifstream *m_ifstream;
M17ModProcessor *m_processor;
HighPassFilterRC m_preemphasisFilter;
QMutex m_mutex;
int16_t m_basebandMin;
int16_t m_basebandMax;
static const int m_levelNbSamples;
static const float m_preemphasis;