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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user