mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 13:11:20 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			235 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
///////////////////////////////////////////////////////////////////////////////////
 | 
						|
// Copyright (C) 2023 Jon Beniston, M7RCE <jon@beniston.com>                     //
 | 
						|
//                                                                               //
 | 
						|
// 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 */
 |