1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-22 17:45:48 -05:00

Add support for character set mapping in Pager demod

This commit is contained in:
Jon Beniston 2021-07-19 17:57:13 +01:00
parent 1bd384fd6c
commit 480f41ab50
13 changed files with 469 additions and 6 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -27,10 +27,13 @@ if(NOT SERVER_MODE)
${demodpager_SOURCES}
pagerdemodgui.cpp
pagerdemodgui.ui
pagerdemodcharsetdialog.cpp
pagerdemodcharsetdialog.ui
)
set(demodpager_HEADERS
${demodpager_HEADERS}
pagerdemodgui.h
pagerdemodcharsetdialog.h
)
set(TARGET_NAME demodpager)

View File

@ -0,0 +1,118 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "pagerdemodcharsetdialog.h"
PagerDemodCharsetDialog::PagerDemodCharsetDialog(PagerDemodSettings *settings,
QWidget* parent) :
QDialog(parent),
m_settings(settings),
ui(new Ui::PagerDemodCharsetDialog)
{
ui->setupUi(this);
if (settings->m_sevenbit.size() > 0) {
ui->preset->setCurrentIndex(2); // User
}
ui->readingOrder->setCurrentIndex(settings->m_rightToLeft ? 1 : 0);
for (int i = 0; i < settings->m_sevenbit.size(); i++) {
addRow(settings->m_sevenbit[i], settings->m_unicode[i]);
}
connect(ui->table, &QTableWidget::cellChanged, this, &PagerDemodCharsetDialog::on_table_cellChanged);
}
PagerDemodCharsetDialog::~PagerDemodCharsetDialog()
{
delete ui;
}
void PagerDemodCharsetDialog::accept()
{
m_settings->m_sevenbit.clear();
m_settings->m_unicode.clear();
for (int i = 0; i < ui->table->rowCount(); i++)
{
int sevenbit = ui->table->item(i, SEVENBIT_COL)->data(Qt::DisplayRole).toString().toInt(nullptr, 16);
int unicode = ui->table->item(i, UNICODE_COL)->data(Qt::DisplayRole).toString().toInt(nullptr, 16);
m_settings->m_sevenbit.append(sevenbit);
m_settings->m_unicode.append(unicode);
}
m_settings->m_rightToLeft = ui->readingOrder->currentIndex() == 1;
QDialog::accept();
}
void PagerDemodCharsetDialog::on_add_clicked()
{
addRow(0, 0);
}
void PagerDemodCharsetDialog::on_remove_clicked()
{
QModelIndexList indexList = ui->table->selectionModel()->selectedRows();
if (!indexList.isEmpty())
{
int row = indexList.at(0).row();
ui->table->removeRow(row);
}
}
void PagerDemodCharsetDialog::on_preset_currentIndexChanged(int index)
{
ui->table->setRowCount(0);
ui->readingOrder->setCurrentIndex(0);
if (index == 1)
{
// Hebrew
for (int i = 0; i < 22; i++) {
addRow(96 + i, 0x05D0 + i);
}
ui->readingOrder->setCurrentIndex(1);
}
}
void PagerDemodCharsetDialog::addRow(int sevenBit, int unicode)
{
ui->table->setSortingEnabled(false);
ui->table->blockSignals(true);
int row = ui->table->rowCount();
ui->table->setRowCount(row + 1);
QTableWidgetItem *sevenbitItem = new QTableWidgetItem();
QTableWidgetItem *unicodeItem = new QTableWidgetItem();
QTableWidgetItem *glyphItem = new QTableWidgetItem();
ui->table->setItem(row, SEVENBIT_COL, sevenbitItem);
ui->table->setItem(row, UNICODE_COL, unicodeItem);
ui->table->setItem(row, GLYPH_COL, glyphItem);
sevenbitItem->setFlags(Qt::ItemIsEditable | sevenbitItem->flags());
sevenbitItem->setData(Qt::DisplayRole, QString::number(sevenBit, 16));
unicodeItem->setFlags(Qt::ItemIsEditable | unicodeItem->flags());
unicodeItem->setData(Qt::DisplayRole, QString::number(unicode, 16));
glyphItem->setFlags(glyphItem->flags() & ~Qt::ItemIsEditable);
glyphItem->setData(Qt::DisplayRole, QChar(unicode));
ui->table->blockSignals(false);
ui->table->setSortingEnabled(true);
}
void PagerDemodCharsetDialog::on_table_cellChanged(int row, int column)
{
if (column == UNICODE_COL)
{
// Update glyph to match entered unicode code point
int unicode = ui->table->item(row, UNICODE_COL)->data(Qt::DisplayRole).toString().toInt(nullptr, 16);
ui->table->item(row, GLYPH_COL)->setData(Qt::DisplayRole, QChar(unicode));
}
}

View File

@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_PAGERDEMODCHARSETDIALOG_H
#define INCLUDE_PAGERDEMODCHARSETDIALOG_H
#include <QHash>
#include <QNetworkRequest>
#include "ui_pagerdemodcharsetdialog.h"
#include "pagerdemodsettings.h"
class PagerDemodCharsetDialog : public QDialog {
Q_OBJECT
public:
explicit PagerDemodCharsetDialog(PagerDemodSettings* settings, QWidget* parent = 0);
~PagerDemodCharsetDialog();
PagerDemodSettings *m_settings;
private slots:
void accept();
void on_add_clicked();
void on_remove_clicked();
void on_preset_currentIndexChanged(int index);
void on_table_cellChanged(int row, int column);
private:
Ui::PagerDemodCharsetDialog* ui;
enum Columns {
SEVENBIT_COL,
UNICODE_COL,
GLYPH_COL
};
void addRow(int sevenBit, int unicode);
};
#endif // INCLUDE_PAGERDEMODCHARSETDIALOG_H

View File

@ -0,0 +1,208 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PagerDemodCharsetDialog</class>
<widget class="QDialog" name="PagerDemodCharsetDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<height>561</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Set chararcter encoding</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="presetLayout">
<item>
<widget class="QLabel" name="presetLabel">
<property name="text">
<string>Preset</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="preset">
<property name="toolTip">
<string>Select a pre-defined character encoding</string>
</property>
<item>
<property name="text">
<string>Latin</string>
</property>
</item>
<item>
<property name="text">
<string>Hebrew</string>
</property>
</item>
<item>
<property name="text">
<string>User</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="presetlSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="readingOrderLabel">
<property name="text">
<string>Reading Order</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="readingOrder">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Specify the order in which characters should be displayed</string>
</property>
<item>
<property name="text">
<string>Left-to-right</string>
</property>
</item>
<item>
<property name="text">
<string>Right-to-left</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="tableLayout">
<item>
<widget class="QTableWidget" name="table">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<column>
<property name="text">
<string>7-bit</string>
</property>
</column>
<column>
<property name="text">
<string>Unicode</string>
</property>
</column>
<column>
<property name="text">
<string>Glyph</string>
</property>
</column>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="buttonLayout">
<item>
<widget class="QPushButton" name="add">
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="remove">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item>
<spacer name="buttonSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PagerDemodCharsetDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PagerDemodCharsetDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -41,6 +41,7 @@
#include "maincore.h"
#include "pagerdemod.h"
#include "pagerdemodcharsetdialog.h"
void PagerDemodGUI::resizeTable()
{
@ -659,3 +660,12 @@ void PagerDemodGUI::tick()
m_tickCount++;
}
void PagerDemodGUI::on_charset_clicked()
{
PagerDemodCharsetDialog dialog(&m_settings);
if (dialog.exec() == QDialog::Accepted)
{
applySettings();
}
}

View File

@ -105,6 +105,7 @@ private slots:
void on_fmDev_valueChanged(int value);
void on_baud_currentIndexChanged(int index);
void on_decode_currentIndexChanged(int index);
void on_charset_clicked();
void on_filterAddress_editingFinished();
void on_clearTable_clicked();
void on_udpEnabled_clicked(bool checked);

View File

@ -465,6 +465,20 @@
</item>
</widget>
</item>
<item>
<widget class="QToolButton" name="charset">
<property name="toolTip">
<string>Select character encoding</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/keyboard.png</normaloff>:/keyboard.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
@ -614,7 +628,7 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="clearTable">
<widget class="QToolButton" name="clearTable">
<property name="toolTip">
<string>Clear messages from table</string>
</property>

View File

@ -17,6 +17,7 @@
///////////////////////////////////////////////////////////////////////////////////
#include <QColor>
#include <QDataStream>
#include "dsp/dspengine.h"
#include "util/simpleserializer.h"
@ -51,6 +52,7 @@ void PagerDemodSettings::resetToDefaults()
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
m_reverseAPIChannelIndex = 0;
m_rightToLeft = 0;
for (int i = 0; i < PAGERDEMOD_MESSAGE_COLUMNS; i++)
{
@ -86,6 +88,9 @@ QByteArray PagerDemodSettings::serialize() const
s.writeU32(19, m_reverseAPIDeviceIndex);
s.writeU32(20, m_reverseAPIChannelIndex);
s.writeBlob(21, m_scopeGUI->serialize());
s.writeBool(22, m_rightToLeft);
s.writeBlob(23, serializeIntList(m_sevenbit));
s.writeBlob(24, serializeIntList(m_unicode));
for (int i = 0; i < PAGERDEMOD_MESSAGE_COLUMNS; i++) {
s.writeS32(100 + i, m_messageColumnIndexes[i]);
@ -112,6 +117,7 @@ bool PagerDemodSettings::deserialize(const QByteArray& data)
QByteArray bytetmp;
uint32_t utmp;
QString strtmp;
QByteArray blob;
d.readS32(1, &m_inputFrequencyOffset, 0);
d.readFloat(2, &m_rfBandwidth, 20000.0f);
@ -154,6 +160,11 @@ bool PagerDemodSettings::deserialize(const QByteArray& data)
d.readBlob(21, &bytetmp);
m_scopeGUI->deserialize(bytetmp);
}
d.readBool(22, &m_rightToLeft, false);
d.readBlob(23, &blob);
deserializeIntList(blob, m_sevenbit);
d.readBlob(24, &blob);
deserializeIntList(blob, m_unicode);
for (int i = 0; i < PAGERDEMOD_MESSAGE_COLUMNS; i++) {
d.readS32(100 + i, &m_messageColumnIndexes[i], i);
@ -171,4 +182,18 @@ bool PagerDemodSettings::deserialize(const QByteArray& data)
}
}
QByteArray PagerDemodSettings::serializeIntList(const QList<qint32>& ints) const
{
QByteArray data;
QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly);
(*stream) << ints;
delete stream;
return data;
}
void PagerDemodSettings::deserializeIntList(const QByteArray& data, QList<qint32>& ints)
{
QDataStream *stream = new QDataStream(data);
(*stream) >> ints;
delete stream;
}

View File

@ -60,6 +60,10 @@ struct PagerDemodSettings
uint16_t m_reverseAPIChannelIndex;
Serializable *m_scopeGUI;
bool m_rightToLeft; //!< Whether characters are right to left or left to right
QList<qint32> m_sevenbit;
QList<qint32> m_unicode;
int m_messageColumnIndexes[PAGERDEMOD_MESSAGE_COLUMNS];//!< How the columns are ordered in the table
int m_messageColumnSizes[PAGERDEMOD_MESSAGE_COLUMNS]; //!< Size of the columns in the table
@ -71,6 +75,8 @@ struct PagerDemodSettings
void setScopeGUI(Serializable *scopeGUI) { m_scopeGUI = scopeGUI; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
QByteArray serializeIntList(const QList<qint32>& ints) const;
void deserializeIntList(const QByteArray& data, QList<qint32>& ints);
};
#endif /* INCLUDE_PAGERDEMODSETTINGS_H */

View File

@ -273,6 +273,21 @@ void PagerDemodSink::decodeBatch()
m_numericMessage = m_numericMessage.trimmed(); // Remove trailing spaces
if (getMessageQueueToChannel())
{
// Convert from 7-bit to UTF-8 using user specified encoding
for (int i = 0; i < m_alphaMessage; i++)
{
QChar c = m_alphaMessage[i];
int idx = m_settings.m_sevenbit.indexOf(c.toLatin1());
if (idx >= 0) {
c = m_settings.m_unicode[idx];
}
m_alphaMessage[i] = c;
}
// Reverse reading order, if required
if (m_settings.m_rightToLeft) {
std::reverse(m_alphaMessage.begin(), m_alphaMessage.end());
}
// Send to channel and GUI
PagerDemod::MsgPagerMessage *msg = PagerDemod::MsgPagerMessage::create(m_address, m_functionBits, m_alphaMessage, m_numericMessage, m_parityErrors, m_bchErrors);
getMessageQueueToChannel()->push(msg);
}

View File

@ -54,25 +54,33 @@ Specifies how messages are decoded in the Message column in the table:
The table has Numeric and Alphanumeric columns which always display the corresponding decode.
<h3>9: Find</h3>
<h3>9: Character encoding</h3>
Click to open the character encoding dialog, which allows a mapping from the received 7-bit alphanumeric characters to Unicode.
![Character encoding dialog](../../../doc/img/PagerDemod_plugin_charset.png)
Each row contains a mapping from a 7-bit value to a Unicode code point. Values should be entered in hexideicmal
<h3>10: Find</h3>
Entering a regular expression in the Find field displays only messages where the address matches the given regular expression.
<h3>10: Clear Messages from table</h3>
<h3>11: Clear Messages from table</h3>
Pressing this button clears all messages from the table.
<h3>11: UDP</h3>
<h3>12: UDP</h3>
When checked, received messages are forwarded to the specified UDP address (12) and port (13).
The messages are forwarded as null terminated ASCII strings, in the format: data time address function alpha numeric
<h3>12: UDP address</h3>
<h3>13: UDP address</h3>
IP address of the host to forward received messages to via UDP.
<h3>13: UDP port</h3>
<h3>14: UDP port</h3>
UDP port number to forward received messages to.