mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05:00 
			
		
		
		
	
		
			
	
	
		
			235 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			235 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								///////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								// Copyright (C) 2023 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_UTIL_DSC_H
							 | 
						||
| 
								 | 
							
								#define INCLUDE_UTIL_DSC_H
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "export.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <QByteArray>
							 | 
						||
| 
								 | 
							
								#include <QString>
							 | 
						||
| 
								 | 
							
								#include <QDateTime>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Digital Select Calling
							 | 
						||
| 
								 | 
							
								// https://www.itu.int/dms_pubrec/itu-r/rec/m/R-REC-M.493-15-201901-I!!PDF-E.pdf
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class SDRBASE_API DSCDecoder {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void init(int offset);
							 | 
						||
| 
								 | 
							
								    bool decodeBits(int bits);
							 | 
						||
| 
								 | 
							
								    QByteArray getMessage() const { return m_bytes; }
							 | 
						||
| 
								 | 
							
								    int getErrors() const { return m_errors; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static int m_maxBytes;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static const int BUFFER_SIZE = 3;
							 | 
						||
| 
								 | 
							
								    signed char m_buf[3];
							 | 
						||
| 
								 | 
							
								    enum State {
							 | 
						||
| 
								 | 
							
								        PHASING,
							 | 
						||
| 
								 | 
							
								        FILL_DX,
							 | 
						||
| 
								 | 
							
								        FILL_RX,
							 | 
						||
| 
								 | 
							
								        DX,
							 | 
						||
| 
								 | 
							
								        RX,
							 | 
						||
| 
								 | 
							
								        DX_EOS,
							 | 
						||
| 
								 | 
							
								        RX_EOS,
							 | 
						||
| 
								 | 
							
								        DONE,
							 | 
						||
| 
								 | 
							
								        NO_EOS
							 | 
						||
| 
								 | 
							
								    } m_state;
							 | 
						||
| 
								 | 
							
								    int m_idx;
							 | 
						||
| 
								 | 
							
								    int m_errors;
							 | 
						||
| 
								 | 
							
								    int m_phaseIdx;
							 | 
						||
| 
								 | 
							
								    bool m_eos;
							 | 
						||
| 
								 | 
							
								    static const signed char m_expectedSymbols[];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QByteArray m_bytes;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    bool decodeSymbol(signed char symbol);
							 | 
						||
| 
								 | 
							
								    static signed char bitsToSymbol(unsigned int bits);
							 | 
						||
| 
								 | 
							
								    static unsigned char reverse(unsigned char b);
							 | 
						||
| 
								 | 
							
								    signed char selectSymbol(signed char dx, signed char rx);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class SDRBASE_API DSCMessage {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    enum FormatSpecifier {
							 | 
						||
| 
								 | 
							
								        GEOGRAPHIC_CALL = 102,
							 | 
						||
| 
								 | 
							
								        DISTRESS_ALERT = 112,
							 | 
						||
| 
								 | 
							
								        GROUP_CALL = 114,
							 | 
						||
| 
								 | 
							
								        ALL_SHIPS = 116,
							 | 
						||
| 
								 | 
							
								        SELECTIVE_CALL = 120,
							 | 
						||
| 
								 | 
							
								        AUTOMATIC_CALL = 123
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    enum Category {
							 | 
						||
| 
								 | 
							
								        ROUTINE = 100,
							 | 
						||
| 
								 | 
							
								        SAFETY = 108,
							 | 
						||
| 
								 | 
							
								        URGENCY = 110,
							 | 
						||
| 
								 | 
							
								        DISTRESS = 112
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    enum FirstTelecommand {
							 | 
						||
| 
								 | 
							
								        F3E_G3E_ALL_MODES_TP = 100,
							 | 
						||
| 
								 | 
							
								        F3E_G3E_DUPLEX_TP = 101,
							 | 
						||
| 
								 | 
							
								        POLLING = 103,
							 | 
						||
| 
								 | 
							
								        UNABLE_TO_COMPLY = 104,
							 | 
						||
| 
								 | 
							
								        END_OF_CALL = 105,
							 | 
						||
| 
								 | 
							
								        DATA = 106,
							 | 
						||
| 
								 | 
							
								        J3E_TP = 109,
							 | 
						||
| 
								 | 
							
								        DISTRESS_ACKNOWLEDGEMENT = 110,
							 | 
						||
| 
								 | 
							
								        DISTRESS_ALERT_RELAY = 112,
							 | 
						||
| 
								 | 
							
								        F1B_J2B_TTY_FEC = 113,
							 | 
						||
| 
								 | 
							
								        F1B_J2B_TTY_AQR = 115,
							 | 
						||
| 
								 | 
							
								        TEST = 118,
							 | 
						||
| 
								 | 
							
								        POSITION_UPDATE = 121,
							 | 
						||
| 
								 | 
							
								        NO_INFORMATION = 126
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    enum SecondTelecommand {
							 | 
						||
| 
								 | 
							
								        NO_REASON = 100,
							 | 
						||
| 
								 | 
							
								        CONGESTION = 101,
							 | 
						||
| 
								 | 
							
								        BUSY = 102,
							 | 
						||
| 
								 | 
							
								        QUEUE = 103,
							 | 
						||
| 
								 | 
							
								        BARRED = 104,
							 | 
						||
| 
								 | 
							
								        NO_OPERATOR = 105,
							 | 
						||
| 
								 | 
							
								        OPERATOR_UNAVAILABLE = 106,
							 | 
						||
| 
								 | 
							
								        EQUIPMENT_DISABLED = 107,
							 | 
						||
| 
								 | 
							
								        UNABLE_TO_USE_CHANNEL = 108,
							 | 
						||
| 
								 | 
							
								        UNABLE_TO_USE_MODE = 109,
							 | 
						||
| 
								 | 
							
								        NOT_PARTIES_TO_CONFLICT = 110,
							 | 
						||
| 
								 | 
							
								        MEDICAL_TRANSPORTS = 111,
							 | 
						||
| 
								 | 
							
								        PAY_PHONE = 112,
							 | 
						||
| 
								 | 
							
								        FAX = 113,
							 | 
						||
| 
								 | 
							
								        NO_INFORMATION_2 = 126
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    enum DistressNature {
							 | 
						||
| 
								 | 
							
								        FIRE = 100,
							 | 
						||
| 
								 | 
							
								        FLOODING = 101,
							 | 
						||
| 
								 | 
							
								        COLLISION = 102,
							 | 
						||
| 
								 | 
							
								        GROUNDING = 103,
							 | 
						||
| 
								 | 
							
								        LISTING = 104,
							 | 
						||
| 
								 | 
							
								        SINKING = 105,
							 | 
						||
| 
								 | 
							
								        ADRIFT = 106,
							 | 
						||
| 
								 | 
							
								        UNDESIGNATED = 107,
							 | 
						||
| 
								 | 
							
								        ABANDONING_SHIP = 108,
							 | 
						||
| 
								 | 
							
								        PIRACY = 109,
							 | 
						||
| 
								 | 
							
								        MAN_OVERBOARD = 110,
							 | 
						||
| 
								 | 
							
								        EPIRB = 112
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    enum EndOfSignal {
							 | 
						||
| 
								 | 
							
								        REQ = 117,
							 | 
						||
| 
								 | 
							
								        ACK = 122,
							 | 
						||
| 
								 | 
							
								        EOS = 127
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static QMap<FormatSpecifier, QString> m_formatSpecifierStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<FormatSpecifier, QString> m_formatSpecifierShortStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<Category, QString> m_categoryStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<Category, QString> m_categoryShortStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<FirstTelecommand, QString> m_telecommand1Strings;
							 | 
						||
| 
								 | 
							
								    static QMap<FirstTelecommand, QString> m_telecommand1ShortStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<SecondTelecommand, QString> m_telecommand2Strings;
							 | 
						||
| 
								 | 
							
								    static QMap<SecondTelecommand, QString> m_telecommand2ShortStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<DistressNature, QString> m_distressNatureStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<EndOfSignal, QString> m_endOfSignalStrings;
							 | 
						||
| 
								 | 
							
								    static QMap<EndOfSignal, QString> m_endOfSignalShortStrings;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    FormatSpecifier m_formatSpecifier;
							 | 
						||
| 
								 | 
							
								    bool m_formatSpecifierMatch;
							 | 
						||
| 
								 | 
							
								    QString m_address;
							 | 
						||
| 
								 | 
							
								    bool m_hasAddress;
							 | 
						||
| 
								 | 
							
								    int m_addressLatitude;      // For GEOGRAPHIC_CALL
							 | 
						||
| 
								 | 
							
								    int m_addressLongitude;
							 | 
						||
| 
								 | 
							
								    int m_addressLatAngle;
							 | 
						||
| 
								 | 
							
								    int m_addressLonAngle;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Category m_category;
							 | 
						||
| 
								 | 
							
								    bool m_hasCategory;
							 | 
						||
| 
								 | 
							
								    QString m_selfId;
							 | 
						||
| 
								 | 
							
								    FirstTelecommand m_telecommand1;
							 | 
						||
| 
								 | 
							
								    bool m_hasTelecommand1;
							 | 
						||
| 
								 | 
							
								    SecondTelecommand m_telecommand2;
							 | 
						||
| 
								 | 
							
								    bool m_hasTelecommand2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QString m_distressId;
							 | 
						||
| 
								 | 
							
								    bool m_hasDistressId;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DistressNature m_distressNature;
							 | 
						||
| 
								 | 
							
								    bool m_hasDistressNature;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QString m_position;
							 | 
						||
| 
								 | 
							
								    bool m_hasPosition;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    int m_frequency1;  // Rx
							 | 
						||
| 
								 | 
							
								    bool m_hasFrequency1;
							 | 
						||
| 
								 | 
							
								    QString m_channel1;
							 | 
						||
| 
								 | 
							
								    bool m_hasChannel1;
							 | 
						||
| 
								 | 
							
								    int m_frequency2;   // Tx
							 | 
						||
| 
								 | 
							
								    bool m_hasFrequency2;
							 | 
						||
| 
								 | 
							
								    QString m_channel2;
							 | 
						||
| 
								 | 
							
								    bool m_hasChannel2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QString m_number; // Phone number
							 | 
						||
| 
								 | 
							
								    bool m_hasNumber;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QTime m_time;
							 | 
						||
| 
								 | 
							
								    bool m_hasTime;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    FirstTelecommand m_subsequenceComms;
							 | 
						||
| 
								 | 
							
								    bool m_hasSubsequenceComms;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    EndOfSignal m_eos;
							 | 
						||
| 
								 | 
							
								    signed char m_ecc; // Error checking code (parity)
							 | 
						||
| 
								 | 
							
								    signed char m_calculatedECC;
							 | 
						||
| 
								 | 
							
								    bool m_eccOk;
							 | 
						||
| 
								 | 
							
								    bool m_valid; // Data is within defined values
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QDateTime m_dateTime; // Date/time when received
							 | 
						||
| 
								 | 
							
								    QByteArray m_data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DSCMessage(const QByteArray& data, QDateTime dateTime);
							 | 
						||
| 
								 | 
							
								    QString toString(const QString separator = " ") const;
							 | 
						||
| 
								 | 
							
								    QString toYaddNetFormat(const QString& id, qint64 frequency) const;
							 | 
						||
| 
								 | 
							
								    QString formatSpecifier(bool shortString=false) const;
							 | 
						||
| 
								 | 
							
								    QString category(bool shortString=false) const;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static QString telecommand1(FirstTelecommand telecommand, bool shortString=false);
							 | 
						||
| 
								 | 
							
								    static QString telecommand2(SecondTelecommand telecommand, bool shortString=false);
							 | 
						||
| 
								 | 
							
								    static QString distressNature(DistressNature nature);
							 | 
						||
| 
								 | 
							
								    static QString endOfSignal(EndOfSignal eos, bool shortString=false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QString symbolsToDigits(const QByteArray data, int startIdx, int length);
							 | 
						||
| 
								 | 
							
								    QString formatCoordinates(int latitude, int longitude);
							 | 
						||
| 
								 | 
							
								    void decode(const QByteArray& data);
							 | 
						||
| 
								 | 
							
								    void checkECC(const QByteArray& data);
							 | 
						||
| 
								 | 
							
								    void decodeFrequency(const QByteArray& data, int& idx, int& frequency, QString& channel);
							 | 
						||
| 
								 | 
							
								    QString formatAddress(const QString &address) const;
							 | 
						||
| 
								 | 
							
								    QString formatCoordinates(const QString& coords);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* INCLUDE_UTIL_DSC_H */
							 |