From 8612f124f07312d5560c02fc0a74c18a7456a3a3 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 11 May 2021 10:04:58 +0100 Subject: [PATCH 1/4] Hopefully fix decoding of Class B messages. Add ship type. --- sdrbase/util/ais.cpp | 21 ++++++++++++--------- sdrbase/util/ais.h | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/sdrbase/util/ais.cpp b/sdrbase/util/ais.cpp index 12920509a..69b6bed43 100644 --- a/sdrbase/util/ais.cpp +++ b/sdrbase/util/ais.cpp @@ -531,7 +531,7 @@ AISStandardClassBPositionReport::AISStandardClassBPositionReport(QByteArray ba) m_longitudeAvailable = longitude != 0x6791ac0; m_longitude = longitude / 60.0f / 10000.0f; - int32_t latitude = ((ba[10] & 0x3) << 24) | ((ba[11] & 0xff) << 16) | ((ba[12] & 0xff) << 8) | (ba[13] & 0xff); + int32_t latitude = ((ba[10] & 0x7) << 24) | ((ba[11] & 0xff) << 16) | ((ba[12] & 0xff) << 8) | (ba[13] & 0xff); latitude = (latitude << 5) >> 5; m_latitudeAvailable = latitude != 0x3412140; m_latitude = latitude / 60.0f / 10000.0f; @@ -540,10 +540,10 @@ AISStandardClassBPositionReport::AISStandardClassBPositionReport(QByteArray ba) m_courseAvailable = cog != 3600; m_course = cog * 0.1f; - m_heading = ((ba[15] & 0xf) << 5) | ((ba[17] >> 3) & 0x1f); + m_heading = ((ba[15] & 0xf) << 5) | ((ba[16] >> 3) & 0x1f); m_headingAvailable = m_heading != 511; - m_timeStamp = ((ba[17] & 0x7) << 3) | ((ba[18] >> 5) & 0x7); + m_timeStamp = ((ba[16] & 0x7) << 3) | ((ba[17] >> 5) & 0x7); } QString AISStandardClassBPositionReport::toString() @@ -571,7 +571,7 @@ AISExtendedClassBPositionReport::AISExtendedClassBPositionReport(QByteArray ba) m_longitudeAvailable = longitude != 0x6791ac0; m_longitude = longitude / 60.0f / 10000.0f; - int32_t latitude = ((ba[10] & 0x3) << 24) | ((ba[11] & 0xff) << 16) | ((ba[12] & 0xff) << 8) | (ba[13] & 0xff); + int32_t latitude = ((ba[10] & 0x7) << 24) | ((ba[11] & 0xff) << 16) | ((ba[12] & 0xff) << 8) | (ba[13] & 0xff); latitude = (latitude << 5) >> 5; m_latitudeAvailable = latitude != 0x3412140; m_latitude = latitude / 60.0f / 10000.0f; @@ -580,23 +580,26 @@ AISExtendedClassBPositionReport::AISExtendedClassBPositionReport(QByteArray ba) m_courseAvailable = cog != 3600; m_course = cog * 0.1f; - m_heading = ((ba[15] & 0xf) << 5) | ((ba[17] >> 3) & 0x1f); + m_heading = ((ba[15] & 0xf) << 5) | ((ba[16] >> 3) & 0x1f); m_headingAvailable = m_heading != 511; - m_timeStamp = ((ba[17] & 0x7) << 3) | ((ba[18] >> 5) & 0x7); + m_timeStamp = ((ba[16] & 0x7) << 3) | ((ba[17] >> 5) & 0x7); - m_name = AISMessage::getString(ba, 18, 1, 20); + m_name = AISMessage::getString(ba, 17, 1, 20); + + m_type = ((ba[32] & 1) << 7) | ((ba[33] >> 1) & 0x3f); } QString AISExtendedClassBPositionReport::toString() { - return QString("Lat: %1%5 Lon: %2%5 Speed: %3 knts Course: %4%5 Name: %6") + return QString("Lat: %1%5 Lon: %2%5 Speed: %3 knts Course: %4%5 Name: %6 Type: %7") .arg(m_latitude) .arg(m_longitude) .arg(m_speedOverGround) .arg(m_course) .arg(QChar(0xb0)) - .arg(m_name); + .arg(m_name) + .arg(typeToString(m_type)); } AISDatalinkManagement::AISDatalinkManagement(QByteArray ba) : diff --git a/sdrbase/util/ais.h b/sdrbase/util/ais.h index 81f66e0bb..ec94f5d95 100644 --- a/sdrbase/util/ais.h +++ b/sdrbase/util/ais.h @@ -276,6 +276,7 @@ public: int m_heading; // Degrees int m_timeStamp; QString m_name; + quint8 m_type; AISExtendedClassBPositionReport(const QByteArray ba); virtual QString getType() override { return "Extended Class B equipment position report"; } From da107c925801be4572f8a1dad723a4d9e6d048c4 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 11 May 2021 10:05:25 +0100 Subject: [PATCH 2/4] Add display of ship type from class B messages --- plugins/feature/ais/aisgui.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/feature/ais/aisgui.cpp b/plugins/feature/ais/aisgui.cpp index adf368e76..33498620f 100644 --- a/plugins/feature/ais/aisgui.cpp +++ b/plugins/feature/ais/aisgui.cpp @@ -450,6 +450,13 @@ void AISGUI::updateVessels(AISMessage *ais) statusItem->setText(AISPositionReport::getStatusString(lrpr->m_status)); } } + if (ais->m_id == 19) + { + AISExtendedClassBPositionReport *ext = dynamic_cast(ais); + if (ext) { + shipTypeItem->setText(AISMessage::typeToString(ext->m_type)); + } + } if (ais->m_id == 24) { AISStaticDataReport *dr = dynamic_cast(ais); From b0ba1c33a96796cc50cce9afc96b235e4780d8eb Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 11 May 2021 10:06:03 +0100 Subject: [PATCH 3/4] Rename sample to symbol --- plugins/channelrx/demodais/aisdemodsink.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/channelrx/demodais/aisdemodsink.cpp b/plugins/channelrx/demodais/aisdemodsink.cpp index bf6f75ee3..007501d4a 100644 --- a/plugins/channelrx/demodais/aisdemodsink.cpp +++ b/plugins/channelrx/demodais/aisdemodsink.cpp @@ -186,21 +186,21 @@ void AISDemodSink::processOneSample(Complex &ci) for (int i = 0; i < sampleCnt; i++) { sampleSum += m_rxBuf[(x + sampleOffset + i) % m_rxBufLength] - dcOffset; } - int sample = sampleSum >= 0.0f ? 1 : 0; + int symbol = sampleSum >= 0.0f ? 1 : 0; - // Move to next sample + // Move to next symbol x = (x + m_samplesPerSymbol) % m_rxBufLength; // HDLC deframing // NRZI decoding int bit; - if (sample != symbolPrev) { + if (symbol != symbolPrev) { bit = 0; } else { bit = 1; } - symbolPrev = sample; + symbolPrev = symbol; // Store in shift reg bits |= bit << bitCount; From 6f291ac399e53c4a1119f265310f369c547987a5 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 11 May 2021 10:07:31 +0100 Subject: [PATCH 4/4] Save/restore scope settings --- plugins/channelrx/demodais/aisdemodgui.cpp | 1 + plugins/channelrx/demodais/aisdemodsettings.cpp | 10 +++++++++- plugins/channelrx/demodais/aisdemodsettings.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/channelrx/demodais/aisdemodgui.cpp b/plugins/channelrx/demodais/aisdemodgui.cpp index 992da993a..c9fb22ead 100644 --- a/plugins/channelrx/demodais/aisdemodgui.cpp +++ b/plugins/channelrx/demodais/aisdemodgui.cpp @@ -462,6 +462,7 @@ AISDemodGUI::AISDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban setTitleColor(m_channelMarker.getColor()); m_settings.setChannelMarker(&m_channelMarker); + m_settings.setScopeGUI(ui->scopeGUI); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodais/aisdemodsettings.cpp b/plugins/channelrx/demodais/aisdemodsettings.cpp index d2c4a1a75..18b517e62 100644 --- a/plugins/channelrx/demodais/aisdemodsettings.cpp +++ b/plugins/channelrx/demodais/aisdemodsettings.cpp @@ -24,7 +24,8 @@ #include "aisdemodsettings.h" AISDemodSettings::AISDemodSettings() : - m_channelMarker(0) + m_channelMarker(0), + m_scopeGUI(0) { resetToDefaults(); } @@ -85,6 +86,7 @@ QByteArray AISDemodSettings::serialize() const s.writeU32(18, m_reverseAPIPort); s.writeU32(19, m_reverseAPIDeviceIndex); s.writeU32(20, m_reverseAPIChannelIndex); + s.writeBlob(21, m_scopeGUI->serialize()); for (int i = 0; i < AISDEMOD_MESSAGE_COLUMNS; i++) s.writeS32(100 + i, m_messageColumnIndexes[i]); @@ -146,6 +148,12 @@ bool AISDemodSettings::deserialize(const QByteArray& data) d.readU32(20, &utmp, 0); m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; + if (m_scopeGUI) + { + d.readBlob(21, &bytetmp); + m_scopeGUI->deserialize(bytetmp); + } + for (int i = 0; i < AISDEMOD_MESSAGE_COLUMNS; i++) d.readS32(100 + i, &m_messageColumnIndexes[i], i); for (int i = 0; i < AISDEMOD_MESSAGE_COLUMNS; i++) diff --git a/plugins/channelrx/demodais/aisdemodsettings.h b/plugins/channelrx/demodais/aisdemodsettings.h index 6e889566a..609b85d11 100644 --- a/plugins/channelrx/demodais/aisdemodsettings.h +++ b/plugins/channelrx/demodais/aisdemodsettings.h @@ -56,6 +56,7 @@ struct AISDemodSettings uint16_t m_reverseAPIPort; uint16_t m_reverseAPIDeviceIndex; uint16_t m_reverseAPIChannelIndex; + Serializable *m_scopeGUI; int m_messageColumnIndexes[AISDEMOD_MESSAGE_COLUMNS];//!< How the columns are ordered in the table int m_messageColumnSizes[AISDEMOD_MESSAGE_COLUMNS]; //!< Size of the columns in the table @@ -63,6 +64,7 @@ struct AISDemodSettings AISDemodSettings(); void resetToDefaults(); void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + void setScopeGUI(Serializable *scopeGUI) { m_scopeGUI = scopeGUI; } QByteArray serialize() const; bool deserialize(const QByteArray& data); };