From 6f2682d667f3eca98705b734427d81ca5be52746 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Fri, 18 Feb 2022 19:05:14 -0500 Subject: [PATCH 01/14] NCurses and NXDN Updates NCurses Terminal in pretty good shape, good enough for testing NXDN decodes RAN and RID now (from LEH) --- include/dsd.h | 187 ++++++- include/nxdn_const.h | 193 +++++++- src/dmr_data.c | 33 +- src/dsd_dibit.c | 55 +++ src/dsd_frame.c | 10 +- src/dsd_frame.c.bkp | 571 ++++++++++++++++++++++ src/dsd_frame_sync.c | 78 +-- src/dsd_main.c | 8 +- src/dsd_mbe.c | 142 +++++- src/dsd_ncurses.c | 421 +++++++++++++--- src/dsd_symbol.c | 2 +- src/nxdn_data.c | 107 +++- src/nxdn_data.c.bkp | 41 ++ src/nxdn_data.c.bkp2 | 72 +++ src/nxdn_lib.c | 1084 +++++++++++++++++++++++++++++++++++++++++ src/nxdn_voice.c | 202 ++++++-- src/nxdn_voice.c.bkp3 | 118 +++++ src/nxdnconvolution.c | 171 +++++++ 18 files changed, 3291 insertions(+), 204 deletions(-) create mode 100644 src/dsd_frame.c.bkp create mode 100644 src/nxdn_data.c.bkp create mode 100644 src/nxdn_data.c.bkp2 create mode 100644 src/nxdn_lib.c create mode 100644 src/nxdn_voice.c.bkp3 create mode 100644 src/nxdnconvolution.c diff --git a/include/dsd.h b/include/dsd.h index 7a19cc5..8d2175d 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -71,8 +71,84 @@ */ static volatile int exitflag; -//volatile int exitflag; //didn't work, couldn't build, multiple definitions of exitflag +//borrow from LEH +typedef struct +{ + uint8_t RFChannelType; + uint8_t FunctionnalChannelType; + uint8_t Option; + uint8_t Direction; + uint8_t CompleteLich; /* 7 bits of LICH without parity */ + uint8_t PreviousCompleteLich; /* 7 bits of previous LICH without parity */ +} NxdnLich_t; + + +typedef struct +{ + uint8_t StructureField; + uint8_t RAN; + uint8_t Data[18]; + uint8_t CrcIsGood; +} NxdnSacchRawPart_t; + + +typedef struct +{ + uint8_t Data[80]; + uint8_t CrcIsGood; +} NxdnFacch1RawPart_t; + + +typedef struct +{ + uint8_t Data[184]; + uint8_t CrcIsGood; +} NxdnFacch2RawPart_t; + + +typedef struct +{ + uint8_t F1; + uint8_t F2; + uint8_t MessageType; + + /****************************/ + /***** VCALL parameters *****/ + /****************************/ + uint8_t CCOption; + uint8_t CallType; + uint8_t VoiceCallOption; + uint16_t SourceUnitID; + uint16_t DestinationID; /* May be a Group ID or a Unit ID */ + uint8_t CipherType; + uint8_t KeyID; + uint8_t VCallCrcIsGood; + + /*******************************/ + /***** VCALL_IV parameters *****/ + /*******************************/ + uint8_t IV[8]; + uint8_t VCallIvCrcIsGood; + + /*****************************/ + /***** Custom parameters *****/ + /*****************************/ + + /* Specifies if the "CipherType" and the "KeyID" parameter are valid + * 1 = Valid ; 0 = CRC error */ + uint8_t CipherParameterValidity; + + /* Used on DES and AES encrypted frames */ + uint8_t PartOfCurrentEncryptedFrame; /* Could be 1 or 2 */ + uint8_t PartOfNextEncryptedFrame; /* Could be 1 or 2 */ + uint8_t CurrentIVComputed[8]; + uint8_t NextIVComputed[8]; +} NxdnElementsContent_t; + + + +//end borrow from LEH typedef struct { @@ -194,7 +270,8 @@ typedef struct int maxbuf[1024]; int minbuf[1024]; int midx; - char err_str[64]; + char err_str[64]; //actual error errorbars + char err_buf[64]; //make copy of err_str for comparison, only have string print when strcmp is different?? char fsubtype[16]; char ftype[16]; int symbolcnt; @@ -248,6 +325,35 @@ typedef struct short input_sample_buffer; //HERE HERE short pulse_raw_out_buffer; //HERE HERE //float *input_sample_buffer; //HERE HERE + short dibit_to_hex_buf; + // state->sr_0 shift registers + short hexbuf; + unsigned long long sr_0; //64-bit shift registers for pushing decoded binary or dibit data + unsigned long long sr_1; //384 + unsigned long long sr_2; // + unsigned long long sr_3; // + unsigned long long sr_4; // + unsigned long long sr_5; // + unsigned long long sr_6; // + + unsigned int dmr_color_code; + unsigned int nxdn_last_ran; + unsigned int nxdn_last_rid; + //borrow from LEH + NxdnSacchRawPart_t NxdnSacchRawPart[4]; + NxdnFacch1RawPart_t NxdnFacch1RawPart[2]; + NxdnFacch2RawPart_t NxdnFacch2RawPart; + NxdnElementsContent_t NxdnElementsContent; + NxdnLich_t NxdnLich; + + int printNXDNAmbeVoiceSampleHex; + + char ambe_ciphered[49]; + char ambe_deciphered[49]; + //end borrow + + + #ifdef TRACE_DSD char debug_prefix; @@ -277,34 +383,34 @@ typedef struct #define INV_DSTAR_HD "313131313111311331313333" #define DSTAR_SYNC "313131313133131113313111" #define INV_DSTAR_SYNC "131313131311313331131333" -// original sync numbers which is FSW plus LICH + +//bogus nxdnn data syncs to troubleshoot +/* +#define NXDN_MS_DATA_SYNC "33333313133113131111333333333111" +#define INV_NXDN_MS_DATA_SYNC "11133331313113313133331113333331" +#define INV_NXDN_BS_DATA_SYNC "33331111313113313133331313333333" +#define NXDN_BS_DATA_SYNC "11113333131331131311113133333333" +//end bogus nxdn data syncs +*/ #define NXDN_MS_DATA_SYNC "313133113131111333" #define INV_NXDN_MS_DATA_SYNC "131311331313333111" -#define NXDN_MS_VOICE_SYNC "313133113131113133" -#define INV_NXDN_MS_VOICE_SYNC "131311331313331311" #define INV_NXDN_BS_DATA_SYNC "131311331313333131" #define NXDN_BS_DATA_SYNC "313133113131111313" -#define INV_NXDN_BS_VOICE_SYNC "131311331313331331" -#define NXDN_BS_VOICE_SYNC "313133113131113113" - -//Try using only FSW and no LICH -/* -#define NXDN_MS_DATA_SYNC "3131331131" -#define INV_NXDN_MS_DATA_SYNC "1313113313" #define NXDN_MS_VOICE_SYNC "313133113131113133" #define INV_NXDN_MS_VOICE_SYNC "131311331313331311" -#define INV_NXDN_BS_DATA_SYNC "1313113313" -#define NXDN_BS_DATA_SYNC "3131331131" #define INV_NXDN_BS_VOICE_SYNC "131311331313331331" #define NXDN_BS_VOICE_SYNC "313133113131113113" -//how do two values equate to 4 symbol types? shouldn't it be -3, -1, 1, 3? -*/ #define DMR_BS_DATA_SYNC "313333111331131131331131" #define DMR_BS_VOICE_SYNC "131111333113313313113313" #define DMR_MS_DATA_SYNC "311131133313133331131113" #define DMR_MS_VOICE_SYNC "133313311131311113313331" - +//borrow extra syncs from LEH +#define DMR_DIRECT_MODE_TS1_DATA_SYNC "331333313111313133311111" +#define DMR_DIRECT_MODE_TS1_VOICE_SYNC "113111131333131311133333" +#define DMR_DIRECT_MODE_TS2_DATA_SYNC "311311111333113333133311" +#define DMR_DIRECT_MODE_TS2_VOICE_SYNC "133133333111331111311133" +//end LEH #define INV_PROVOICE_SYNC "31313111333133133311331133113311" #define PROVOICE_SYNC "13131333111311311133113311331133" #define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311" @@ -374,13 +480,60 @@ short nxdn_filter(short sample); //borrow from LEH for testing 'improved NXDN detection' int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr); +/* Global functions */ //also borrowed +uint32_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength); +uint32_t ConvertAsciiToByte(uint8_t AsciiMsbByte, uint8_t AsciiLsbByte, uint8_t * OutputByte); +void Convert49BitSampleInto7Bytes(char * InputBit, char * OutputByte); +void Convert7BytesInto49BitSample(char * InputByte, char * OutputBit); // //ifdef ncurses void ncursesOpen (); void ncursesPrinter (dsd_opts * opts, dsd_state * state); void ncursesClose (); //endif ncurses +//borrow from LEH +/* NXDN frame decoding functions */ +void ProcessNXDNFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted); +void ProcessNxdnRCCHFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted); +void ProcessNxdnRTCHFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted); +void ProcessNxdnRDCHFrame(dsd_opts * opts, dsd_state * state, uint8_t Inverted); +void ProcessNxdnRTCH_C_Frame(dsd_opts * opts, dsd_state * state, uint8_t Inverted); +void ProcessNXDNIdleData (dsd_opts * opts, dsd_state * state, uint8_t Inverted); +void ProcessNXDNFacch1Data (dsd_opts * opts, dsd_state * state, uint8_t Inverted); +void ProcessNXDNUdchData (dsd_opts * opts, dsd_state * state, uint8_t Inverted); +//end borrow +//borrow from LEH +/* NXDN functions */ +void CNXDNConvolution_start(void); +void CNXDNConvolution_decode(uint8_t s0, uint8_t s1); +void CNXDNConvolution_chainback(unsigned char* out, unsigned int nBits); +void CNXDNConvolution_encode(const unsigned char* in, unsigned char* out, unsigned int nBits); +uint8_t NXDN_decode_LICH(uint8_t InputLich[8], + uint8_t * RFChannelType, + uint8_t * FunctionnalChannelType, + uint8_t * Option, + uint8_t * Direction, + uint8_t * CompleteLichBinaryFormat, + uint8_t Inverted); +uint8_t NXDN_SACCH_raw_part_decode(uint8_t * Input, uint8_t * Output); +void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state); +uint8_t NXDN_FACCH1_decode(uint8_t * Input, uint8_t * Output); +uint8_t NXDN_UDCH_decode(uint8_t * Input, uint8_t * Output); +void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state, + uint8_t CrcCorrect, uint8_t * ElementsContent); +void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message); +void NXDN_decode_VCALL_IV(dsd_opts * opts, dsd_state * state, uint8_t * Message); +char * NXDN_Call_Type_To_Str(uint8_t CallType); +void NXDN_Voice_Call_Option_To_Str(uint8_t VoiceCallOption, uint8_t * Duplex, uint8_t * TransmissionMode); +char * NXDN_Cipher_Type_To_Str(uint8_t CipherType); +uint16_t CRC15BitNXDN(uint8_t * BufferIn, uint32_t BitLength); +uint16_t CRC12BitNXDN(uint8_t * BufferIn, uint32_t BitLength); +uint8_t CRC6BitNXDN(uint8_t * BufferIn, uint32_t BitLength); +void ScrambledNXDNVoiceBit(int * LfsrValue, char * BufferIn, char * BufferOut, int NbOfBitToScramble); +void NxdnEncryptionStreamGeneration (dsd_opts* opts, dsd_state* state, uint8_t KeyStream[1664]); +void processMbeFrameEncrypted (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24], char ambe_keystream[49], char imbe_keystream[88]); +//end borrow from LEH #ifdef __cplusplus diff --git a/include/nxdn_const.h b/include/nxdn_const.h index a447faa..9bfa907 100644 --- a/include/nxdn_const.h +++ b/include/nxdn_const.h @@ -21,13 +21,88 @@ extern const int nX[36]; extern const int nY[36]; extern const int nZ[36]; extern const char nxdnpr[145]; +extern const char nxdnpr2[145]; //why is this 145 but referenced later as 182 or 384 +//borrow from LEH +extern const unsigned char nsW[72]; +extern const int DSDNXDN_SACCH_m_Interleave[60]; +extern const int DSDNXDN_SACCH_m_PunctureList[12]; +extern const int DSDNXDN_FACCH1_m_Interleave[144]; +extern const int DSDNXDN_FACCH1_m_PunctureList[48]; +extern const int DSDNXDN_UDCH_m_Interleave[348]; +extern const int DSDNXDN_UDCH_m_PunctureList[58]; +// +//enum +//{ +#define NXDN_VCALL 0b000001 /* VCALL = VCALL_REQ = VCALL_RESP */ +#define NXDN_VCALL_IV 0b000011 +#define NXDN_DCALL_HDR 0b001001 /* Header Format - NXDN_DCALL_HDR = NXDN_DCALL_REQ = NXDN_DCALL_RESP */ +#define NXDN_DCALL_USR 0b001011 /* User Data Format */ +#define NXDN_DCALL_ACK 0b001100 +#define NXDN_REL_EX 0b000111 +#define NXDN_HEAD_DLY 0b001111 +#define NXDN_SDCALL_REQ_HDR 0b111000 /* Header Format */ +#define NXDN_SDCALL_REQ_USR 0b111001 /* User Data Format */ +#define NXDN_SDCALL_RESP 0b111011 +#define NXDN_SDCALL_IV 0b111010 +#define NXDN_STAT_INQ_REQ 0b110000 +#define NXDN_STAT_INQ_RESP 0b110001 +#define NXDN_STAT_REQ 0b110010 +#define NXDN_STAT_RESP 0b110011 +#define NXDN_REM_CON_REQ 0b110100 +#define NXDN_REM_CON_RESP 0b110101 +#define NXDN_REM_CON_E_REQ 0b110110 +#define NXDN_REM_CON_E_RESP 0b110111 +//NXDN_VCALL_REQ = 0b000001, /* VCALL = VCALL_REQ = VCALL_RESP */ +//NXDN_VCALL_RESP = 0b000001, /* VCALL = VCALL_REQ = VCALL_RESP */ +#define NXDN_VCALL_REC_REQ = 0b000010 /* NXDN_VCALL_REC_REQ = NXDN_VCALL_REC_RESP */ +//NXDN_VCALL_REC_RESP = 0b000010, +#define NXDN_VCALL_CONN_REQ = 0b000011 /* NXDN_VCALL_CONN_REQ = NXDN_VCALL_CONN_RESP */ +//NXDN_VCALL_CONN_RESP = 0b000011, /* NXDN_VCALL_CONN_REQ = NXDN_VCALL_CONN_RESP */ +#define NXDN_VCALL_ASSGN_DUP = 0b000101 +//NXDN_DCALL_REQ = 0b001001, /* NXDN_DCALL_HDR = NXDN_DCALL_REQ = NXDN_DCALL_RESP */ +//NXDN_DCALL_RESP = 0b001001, /* NXDN_DCALL_HDR = NXDN_DCALL_REQ = NXDN_DCALL_RESP */ +#define NXDN_DCALL_REC_REQ = 0b001010 /* NXDN_DCALL_REC_REQ = NXDN_DCALL_REC_RESP */ +//NXDN_DCALL_REC_RESP = 0b001010, /* NXDN_DCALL_REC_REQ = NXDN_DCALL_REC_RESP */ +#define NXDN_DCALL_ASSGN = 0b001110 +#define NXDN_DCALL_ASSGN_DUP = 0b001101 +#define NXDN_IDLE = 0b010000 +#define NXDN_DISC_REQ = 0b010001 /* NXDN_DISC_REQ = NXDN_DISC */ +#define NXDN_DISC = 0b010001 /* NXDN_DISC_REQ = NXDN_DISC */ + #else /* * pseudorandom bit sequence */ const char nxdnpr[145] = { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1 }; - +//const unsigned char nxdnpr2[384] = +const unsigned char nxdnpr2[182] = //is this a problem, should it be 384/2 for dibits? +{ + 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, + 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, + 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, + 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, + 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, + 1, 1, 0, 0, 0, 1//, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, +// 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, +// 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, +// 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, +// 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, +// 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, +// 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, +// 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, +// 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, +// 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, +// 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, +// 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, +// 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 +}; /* * NXDN AMBE interleave schedule */ @@ -63,4 +138,120 @@ const int nZ[36] = { 5, 3, 4, 2, 3, 1, 13, 2, 12, 1, 11, 0 }; +/* + * NXDN SACCH interleave + */ +const unsigned char nsW[72] = { + 0, 12, 24, 36, 48, 60, + 1, 13, 25, 37, 49, 61, + 2, 14, 26, 38, 50, 62, + 3, 15, 27, 39, 51, 63, + 4, 16, 28, 40, 52, 64, + 5, 17, 29, 41, 53, 65, + 6, 18, 30, 42, 54, 66, + 7, 19, 31, 43, 55, 67, + 8, 20, 32, 44, 56, 68, + 9, 21, 33, 45, 57, 69, + 10,22, 34, 46, 58, 70, + 11,23, 35, 47, 59, 71 +}; + +const int DSDNXDN_SACCH_m_Interleave[60] = +{ + 0, 12, 24, 36, 48, + 1, 13, 25, 37, 49, + 2, 14, 26, 38, 50, + 3, 15, 27, 39, 51, + 4, 16, 28, 40, 52, + 5, 17, 29, 41, 53, + 6, 18, 30, 42, 54, + 7, 19, 31, 43, 55, + 8, 20, 32, 44, 56, + 9, 21, 33, 45, 57, + 10, 22, 34, 46, 58, + 11, 23, 35, 47, 59, +}; + +const int DSDNXDN_SACCH_m_PunctureList[12] = { 5, 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71 }; + +const unsigned int DSDNXDN_FACCH1_m_Interleave[144] = +{ + 0, 16, 32, 48, 64, 80, 96, 112, 128, + 1, 17, 33, 49, 65, 81, 97, 113, 129, + 2, 18, 34, 50, 66, 82, 98, 114, 130, + 3, 19, 35, 51, 67, 83, 99, 115, 131, + 4, 20, 36, 52, 68, 84, 100, 116, 132, + 5, 21, 37, 53, 69, 85, 101, 117, 133, + 6, 22, 38, 54, 70, 86, 102, 118, 134, + 7, 23, 39, 55, 71, 87, 103, 119, 135, + 8, 24, 40, 56, 72, 88, 104, 120, 136, + 9, 25, 41, 57, 73, 89, 105, 121, 137, + 10, 26, 42, 58, 74, 90, 106, 122, 138, + 11, 27, 43, 59, 75, 91, 107, 123, 139, + 12, 28, 44, 60, 76, 92, 108, 124, 140, + 13, 29, 45, 61, 77, 93, 109, 125, 141, + 14, 30, 46, 62, 78, 94, 110, 126, 142, + 15, 31, 47, 63, 79, 95, 111, 127, 143, +}; + +const unsigned int DSDNXDN_FACCH1_m_PunctureList[48] = +{ + 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U, + 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U, + 81U, 85U, 89U, 93U, 97U, 101U, 105U, 109U, 113U, 117U, + 121U, 125U, 129U, 133U, 137U, 141U, 145U, 149U, 153U, 157U, + 161U, 165U, 169U, 173U, 177U, 181U, 185U, 189U +}; + +const int DSDNXDN_UDCH_m_Interleave[348] = { + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 180, 192, 204, 216, 228, 240, 252, 264, 276, 288, 300, 312, 324, 336, + 1, 13, 25, 37, 49, 61, 73, 85, 97, 109, 121, 133, 145, 157, 169, 181, 193, 205, 217, 229, 241, 253, 265, 277, 289, 301, 313, 325, 337, + 2, 14, 26, 38, 50, 62, 74, 86, 98, 110, 122, 134, 146, 158, 170, 182, 194, 206, 218, 230, 242, 254, 266, 278, 290, 302, 314, 326, 338, + 3, 15, 27, 39, 51, 63, 75, 87, 99, 111, 123, 135, 147, 159, 171, 183, 195, 207, 219, 231, 243, 255, 267, 279, 291, 303, 315, 327, 339, + 4, 16, 28, 40, 52, 64, 76, 88, 100, 112, 124, 136, 148, 160, 172, 184, 196, 208, 220, 232, 244, 256, 268, 280, 292, 304, 316, 328, 340, + 5, 17, 29, 41, 53, 65, 77, 89, 101, 113, 125, 137, 149, 161, 173, 185, 197, 209, 221, 233, 245, 257, 269, 281, 293, 305, 317, 329, 341, + 6, 18, 30, 42, 54, 66, 78, 90, 102, 114, 126, 138, 150, 162, 174, 186, 198, 210, 222, 234, 246, 258, 270, 282, 294, 306, 318, 330, 342, + 7, 19, 31, 43, 55, 67, 79, 91, 103, 115, 127, 139, 151, 163, 175, 187, 199, 211, 223, 235, 247, 259, 271, 283, 295, 307, 319, 331, 343, + 8, 20, 32, 44, 56, 68, 80, 92, 104, 116, 128, 140, 152, 164, 176, 188, 200, 212, 224, 236, 248, 260, 272, 284, 296, 308, 320, 332, 344, + 9, 21, 33, 45, 57, 69, 81, 93, 105, 117, 129, 141, 153, 165, 177, 189, 201, 213, 225, 237, 249, 261, 273, 285, 297, 309, 321, 333, 345, + 10, 22, 34, 46, 58, 70, 82, 94, 106, 118, 130, 142, 154, 166, 178, 190, 202, 214, 226, 238, 250, 262, 274, 286, 298, 310, 322, 334, 346, + 11, 23, 35, 47, 59, 71, 83, 95, 107, 119, 131, 143, 155, 167, 179, 191, 203, 215, 227, 239, 251, 263, 275, 287, 299, 311, 323, 335, 347, +}; + +const int DSDNXDN_UDCH_m_PunctureList[58] = { + 3, 11, + 17, 25, + 31, 39, + 45, 53, + 59, 67, + 73, 81, + 87, 95, + 101, 109, + 115, 123, + 129, 137, + 143, 151, + 157, 165, + 171, 179, + 185, 193, + 199, 207, + 213, 221, + 227, 235, + 241, 249, + 255, 263, + 269, 277, + 283, 291, + 297, 305, + 311, 319, + 325, 333, + 339, 347, + 353, 361, + 367, 375, + 381, 389, + 395, 403, +}; + +//#endif /* _MAIN */ + + + #endif diff --git a/src/dmr_data.c b/src/dmr_data.c index b1d870e..8d61c0f 100644 --- a/src/dmr_data.c +++ b/src/dmr_data.c @@ -28,13 +28,18 @@ processDMRdata (dsd_opts * opts, dsd_state * state) char cachdata[13]; char cc[5]; char bursttype[5]; + int dcc_buf; #ifdef DMR_DUMP int k; char syncbits[49]; char cachbits[25]; #endif - + cc[0]=0; + cc[1]=0; + cc[2]=0; + cc[3]=0; //initialize with zeroes to prevent segfault down below + state->dmr_color_code = 0; //reset cc[4] = 0; bursttype[4] = 0; @@ -95,8 +100,14 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } - cc[0] = (1 & (dibit >> 1)) + 48; // bit 1 - cc[1] = (1 & dibit) + 48; // bit 0 + //c[0] = (1 & (dibit >> 1)) + 48; // bit 1 + //cc[1] = (1 & dibit) + 48; // bit 0 + cc[0] = (1 & (dibit >> 1)); // bit 1 + cc[1] = (1 & dibit); // bit 0 + dcc_buf = 0; + //dcc_buf = (1 & (dibit >> 1)) | (1 & dibit); + dcc_buf = ((1 & (dibit >> 1)) + 48) | ((1 & dibit) + 48); + dibit = *dibit_p; dibit_p++; @@ -104,8 +115,20 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } - cc[2] = (1 & (dibit >> 1)) + 48; // bit 1 - cc[3] = (1 & dibit) + 48; // bit 0 + //cc[2] = (1 & (dibit >> 1)) + 48; // bit 1 + //cc[3] = (1 & dibit) + 48; // bit 0 + cc[2] = (1 & (dibit >> 1)); // bit 1 + cc[3] = (1 & dibit); // bit 0 + + dcc_buf = dcc_buf << 2; + //dcc_buf = (1 & (dibit >> 1)) | (1 & dibit); + dcc_buf = ((1 & (dibit >> 1)) + 48) | ((1 & dibit) + 48); + + //state->dmr_color_code = dcc_buf; + state->dmr_color_code = (unsigned int)((cc[0] << 3) + (cc[1] << 2) + (cc[2] << 1) + cc[3]); + //cc[2] = (1 & (dibit >> 1)); // bit 1 + //cc[3] = (1 & dibit); // bit 0 + dibit = *dibit_p; dibit_p++; diff --git a/src/dsd_dibit.c b/src/dsd_dibit.c index 325d443..7502861 100644 --- a/src/dsd_dibit.c +++ b/src/dsd_dibit.c @@ -358,6 +358,61 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol) } state->last_dibit = dibit; + //test loading up a shift register and printing it to stderr + //di-bit shift register for hex values + //check for which dibit is equal to which half-nibble + if (dibit == 0){state->hexbuf = 0x0;} //+1 + if (dibit == 1){state->hexbuf = 0x1;} //+3 + if (dibit == 2){state->hexbuf = 0x2;} //-1 + if (dibit == 3){state->hexbuf = 0x3;} //-3 + state->sr_0 = (state->sr_0 << 2) | (state->sr_1 >> 62); + state->sr_1 = (state->sr_1 << 2) | (state->sr_2 >> 62); + state->sr_2 = (state->sr_2 << 2) | (state->sr_3 >> 62); + state->sr_3 = (state->sr_3 << 2) | (state->sr_4 >> 62); + state->sr_4 = (state->sr_4 << 2) | (state->sr_5 >> 62); + state->sr_5 = (state->sr_5 << 2) | (state->sr_6 >> 62); + state->sr_6 = state->sr_6 << 2; + state->sr_6 |= state->hexbuf; + if (1 == 2) //disable this later on + { + fprintf (stderr, "\nsr_0 = %16llX \n", state->sr_0); + fprintf (stderr, "sr_1 = %16llX \n", state->sr_1); + fprintf (stderr, "sr_2 = %16llX \n", state->sr_2); + fprintf (stderr, "sr_3 = %16llX \n", state->sr_3); + fprintf (stderr, "sr_4 = %16llX \n", state->sr_4); + fprintf (stderr, "sr_5 = %16llX \n", state->sr_5); + fprintf (stderr, "sr_6 = %16llX \n", state->sr_6); + /* + printw ("sr_0 = %16llX \n", sr_0); + printw ("sr_1 = %16llX \n", sr_1); + printw ("sr_2 = %16llX \n", sr_2); + printw ("sr_3 = %16llX \n", sr_3); + printw ("sr_4 = %16llX \n", sr_4); + printw ("sr_5 = %16llX \n", sr_5); + printw ("sr_6 = %16llX \n", sr_6); + */ + } + + if ( state->sr_5 & 0xFFFFF == 0xDDF5D) //disable this later on + { + fprintf (stderr, "\nsr_0 = %16llX \n", state->sr_0); + fprintf (stderr, "sr_1 = %16llX \n", state->sr_1); + fprintf (stderr, "sr_2 = %16llX \n", state->sr_2); + fprintf (stderr, "sr_3 = %16llX \n", state->sr_3); + fprintf (stderr, "sr_4 = %16llX \n", state->sr_4); + fprintf (stderr, "sr_5 = %16llX \n", state->sr_5); + fprintf (stderr, "sr_6 = %16llX \n", state->sr_6); + /* + printw ("sr_0 = %16llX \n", sr_0); + printw ("sr_1 = %16llX \n", sr_1); + printw ("sr_2 = %16llX \n", sr_2); + printw ("sr_3 = %16llX \n", sr_3); + printw ("sr_4 = %16llX \n", sr_4); + printw ("sr_5 = %16llX \n", sr_5); + printw ("sr_6 = %16llX \n", sr_6); + */ + } + *state->dibit_buf_p = dibit; state->dibit_buf_p++; diff --git a/src/dsd_frame.c b/src/dsd_frame.c index 2390994..6044f5b 100644 --- a/src/dsd_frame.c +++ b/src/dsd_frame.c @@ -78,10 +78,10 @@ processFrame (dsd_opts * opts, dsd_state * state) state->minref = state->min; } - if ((state->synctype == 8) || (state->synctype == 9)) //lets make this NOT do this...maybe... + if ((state->synctype == 8) || (state->synctype == 9)) //NXDN Voice { //state->rf_mod = 2; //wrong type of modulation HERE HERE - //state->nac = 0; + state->nac = 0; state->lastsrc = 0; state->lasttg = 0; if (opts->errorbars == 1) @@ -89,7 +89,7 @@ processFrame (dsd_opts * opts, dsd_state * state) if (opts->verbose > 0) { level = (int) state->max / 164; - fprintf (stderr,"inlvl: %2i%% ", level); + fprintf (stderr, "inlvl: %2i%% ", level); } } state->nac = 0; @@ -101,10 +101,10 @@ processFrame (dsd_opts * opts, dsd_state * state) processNXDNVoice (opts, state); return; } - else if ((state->synctype == 16) || (state->synctype == 17)) + else if ((state->synctype == 16) || (state->synctype == 17)) //NXDN Data { //state->rf_mod = 2; - //state->nac = 0; + state->nac = 0; state->lastsrc = 0; state->lasttg = 0; if (opts->errorbars == 1) diff --git a/src/dsd_frame.c.bkp b/src/dsd_frame.c.bkp new file mode 100644 index 0000000..e89cfa3 --- /dev/null +++ b/src/dsd_frame.c.bkp @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2010 DSD Author + * GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0) + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "dsd.h" +#if !defined(NULL) +#define NULL 0 +#endif + +#include "p25p1_check_nid.h" + +void +printFrameInfo (dsd_opts * opts, dsd_state * state) +{ + + int level; + + level = (int) state->max / 164; + if (opts->verbose > 0) + { + fprintf (stderr,"inlvl: %2i%% ", level); + } + if (state->nac != 0) + { + fprintf (stderr,"nac: %4X ", state->nac); + } + + if (opts->verbose > 1) + { + fprintf (stderr,"src: %8i ", state->lastsrc); + } + fprintf (stderr,"tg: %5i ", state->lasttg); +} + +void +processFrame (dsd_opts * opts, dsd_state * state) +{ + + int i, j, dibit; + char duid[3]; + char nac[13]; + int level; + + char status_0; + char bch_code[63]; + int index_bch_code; + unsigned char parity; + char v; + int new_nac; + char new_duid[3]; + int check_result; + + nac[12] = 0; + duid[2] = 0; + j = 0; + + if (state->rf_mod == 1) + { + state->maxref = (int)(state->max * 0.80F); + state->minref = (int)(state->min * 0.80F); + } + else + { + state->maxref = state->max; + state->minref = state->min; + } + + if ((state->synctype == 8) || (state->synctype == 9)) //lets make this NOT do this...maybe... + { + //state->rf_mod = 2; //wrong type of modulation HERE HERE + state->nac = 0; + state->lastsrc = 0; + state->lasttg = 0; + if (opts->errorbars == 1) + { + if (opts->verbose > 0) + { + level = (int) state->max / 164; + fprintf (stderr,"inlvl: %2i%% ", level); + } + } + state->nac = 0; + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " VOICE "); + processNXDNVoice (opts, state); + return; + } + else if ((state->synctype == 16) || (state->synctype == 17)) + { + //state->rf_mod = 2; + state->nac = 0; + state->lastsrc = 0; + state->lasttg = 0; + if (opts->errorbars == 1) + { + if (opts->verbose > 0) + { + level = (int) state->max / 164; + fprintf (stderr, "inlvl: %2i%% ", level); + } + } + state->nac = 0; + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " DATA "); + processNXDNData (opts, state); + return; + } + else if ((state->synctype == 6) || (state->synctype == 7)) + { + state->nac = 0; + state->lastsrc = 0; + state->lasttg = 0; + if (opts->errorbars == 1) + { + if (opts->verbose > 0) + { + level = (int) state->max / 164; + fprintf (stderr,"inlvl: %2i%% ", level); + } + } + state->nac = 0; + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " VOICE "); + processDSTAR (opts, state); + return; + } + else if ((state->synctype == 18) || (state->synctype == 19)) + { + state->nac = 0; + state->lastsrc = 0; + state->lasttg = 0; + if (opts->errorbars == 1) + { + if (opts->verbose > 0) + { + level = (int) state->max / 164; + fprintf (stderr,"inlvl: %2i%% ", level); + } + } + state->nac = 0; + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " DATA "); + processDSTAR_HD (opts, state); + return; + } + + else if ((state->synctype >= 10) && (state->synctype <= 13)) + { + state->nac = 0; + state->lastsrc = 0; + state->lasttg = 0; + if (opts->errorbars == 1) + { + if (opts->verbose > 0) + { + level = (int) state->max / 164; + fprintf (stderr,"inlvl: %2i%% ", level); + } + } + if ((state->synctype == 11) || (state->synctype == 12)) + { + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " VOICE "); + processDMRvoice (opts, state); + } + else + { + closeMbeOutFile (opts, state); + state->err_str[0] = 0; + processDMRdata (opts, state); + } + return; + } + else if ((state->synctype >= 2) && (state->synctype <= 5)) + { + state->nac = 0; + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + } + if ((state->synctype == 3) || (state->synctype == 4)) + { + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " VOICE "); + processX2TDMAvoice (opts, state); + } + else + { + closeMbeOutFile (opts, state); + state->err_str[0] = 0; + processX2TDMAdata (opts, state); + } + return; + } + else if ((state->synctype == 14) || (state->synctype == 15)) + { + state->nac = 0; + state->lastsrc = 0; + state->lasttg = 0; + if (opts->errorbars == 1) + { + if (opts->verbose > 0) + { + level = (int) state->max / 164; + fprintf (stderr,"inlvl: %2i%% ", level); + } + } + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + openMbeOutFile (opts, state); + } + sprintf (state->fsubtype, " VOICE "); + processProVoice (opts, state); + return; + } + else + { + // Read the NAC, 12 bits + j = 0; + index_bch_code = 0; + for (i = 0; i < 6; i++) + { + dibit = getDibit (opts, state); + + v = 1 & (dibit >> 1); // bit 1 + nac[j] = v + '0'; + j++; + bch_code[index_bch_code] = v; + index_bch_code++; + + v = 1 & dibit; // bit 0 + nac[j] = v + '0'; + j++; + bch_code[index_bch_code] = v; + index_bch_code++; + } + state->nac = strtol (nac, NULL, 2); + + // Read the DUID, 4 bits + for (i = 0; i < 2; i++) + { + dibit = getDibit (opts, state); + duid[i] = dibit + '0'; + + bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 + index_bch_code++; + bch_code[index_bch_code] = 1 & dibit; // bit 0 + index_bch_code++; + } + + // Read the BCH data for error correction of NAC and DUID + for (i = 0; i < 3; i++) + { + dibit = getDibit (opts, state); + + bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 + index_bch_code++; + bch_code[index_bch_code] = 1 & dibit; // bit 0 + index_bch_code++; + } + // Intermission: read the status dibit + status_0 = getDibit (opts, state) + '0'; + // ... continue reading the BCH error correction data + for (i = 0; i < 20; i++) + { + dibit = getDibit (opts, state); + + bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 + index_bch_code++; + bch_code[index_bch_code] = 1 & dibit; // bit 0 + index_bch_code++; + } + + // Read the parity bit + dibit = getDibit (opts, state); + bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 + parity = (1 & dibit); // bit 0 + + // Check if the NID is correct + check_result = check_NID (bch_code, &new_nac, new_duid, parity); + if (check_result) { + if (new_nac != state->nac) { + // NAC fixed by error correction + state->nac = new_nac; + state->debug_header_errors++; + } + if (strcmp(new_duid, duid) != 0) { + // DUID fixed by error correction + //fprintf (stderr,"Fixing DUID %s -> %s\n", duid, new_duid); + duid[0] = new_duid[0]; + duid[1] = new_duid[1]; + state->debug_header_errors++; + } + } else { + // Check of NID failed and unable to recover its value + //fprintf (stderr,"NID error\n"); + duid[0] = 'E'; + duid[1] = 'E'; + state->debug_header_critical_errors++; + } + } + + if (strcmp (duid, "00") == 0) + { + // Header Data Unit + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," HDU\n"); + } + if (opts->mbe_out_dir[0] != 0) + { + closeMbeOutFile (opts, state); + openMbeOutFile (opts, state); + } + mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); + state->lastp25type = 2; + sprintf (state->fsubtype, " HDU "); + processHDU (opts, state); + } + else if (strcmp (duid, "11") == 0) + { + // Logical Link Data Unit 1 + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," LDU1 "); + } + if (opts->mbe_out_dir[0] != 0) + { + if (opts->mbe_out_f == NULL) + { + openMbeOutFile (opts, state); + } + } + state->lastp25type = 1; + sprintf (state->fsubtype, " LDU1 "); + state->numtdulc = 0; + processLDU1 (opts, state); + } + else if (strcmp (duid, "22") == 0) + { + // Logical Link Data Unit 2 + if (state->lastp25type != 1) + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," Ignoring LDU2 not preceeded by LDU1\n"); + } + state->lastp25type = 0; + sprintf (state->fsubtype, " "); + } + else + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," LDU2 "); + } + if (opts->mbe_out_dir[0] != 0) + { + if (opts->mbe_out_f == NULL) + { + openMbeOutFile (opts, state); + } + } + state->lastp25type = 2; + sprintf (state->fsubtype, " LDU2 "); + state->numtdulc = 0; + processLDU2 (opts, state); + } + } + else if (strcmp (duid, "33") == 0) + { + // Terminator with subsequent Link Control + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," TDULC\n"); + } + if (opts->mbe_out_dir[0] != 0) + { + closeMbeOutFile (opts, state); + } + mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); + state->lasttg = 0; + state->lastsrc = 0; + state->lastp25type = 0; + state->err_str[0] = 0; + sprintf (state->fsubtype, " TDULC "); + state->numtdulc++; + if ((opts->resume > 0) && (state->numtdulc > opts->resume)) + { + resumeScan (opts, state); + } + processTDULC (opts, state); + state->err_str[0] = 0; + } + else if (strcmp (duid, "03") == 0) + { + // Terminator without subsequent Link Control + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," TDU\n"); + } + if (opts->mbe_out_dir[0] != 0) + { + closeMbeOutFile (opts, state); + } + mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); + state->lasttg = 0; + state->lastsrc = 0; + state->lastp25type = 0; + state->err_str[0] = 0; + sprintf (state->fsubtype, " TDU "); + + processTDU (opts, state); + } + else if (strcmp (duid, "13") == 0) + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," TSDU\n"); + } + if (opts->resume > 0) + { + resumeScan (opts, state); + } + state->lasttg = 0; + state->lastsrc = 0; + state->lastp25type = 3; + sprintf (state->fsubtype, " TSDU "); + + // Now processing NID + + skipDibit (opts, state, 328-25); + } + else if (strcmp (duid, "30") == 0) + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," PDU\n"); + } + if (opts->resume > 0) + { + resumeScan (opts, state); + } + if (opts->mbe_out_dir[0] != 0) + { + if (opts->mbe_out_f == NULL) + { + openMbeOutFile (opts, state); + } + } + state->lastp25type = 4; + sprintf (state->fsubtype, " PDU "); + } + // try to guess based on previous frame if unknown type + else if (state->lastp25type == 1) + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr,"(LDU2) "); + } + if (opts->mbe_out_dir[0] != 0) + { + if (opts->mbe_out_f == NULL) + { + openMbeOutFile (opts, state); + } + } + //state->lastp25type = 0; + // Guess that the state is LDU2 + state->lastp25type = 2; + sprintf (state->fsubtype, "(LDU2) "); + state->numtdulc = 0; + processLDU2 (opts, state); + } + else if (state->lastp25type == 2) + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr,"(LDU1) "); + } + if (opts->mbe_out_dir[0] != 0) + { + if (opts->mbe_out_f == NULL) + { + openMbeOutFile (opts, state); + } + } + //state->lastp25type = 0; + // Guess that the state is LDU1 + state->lastp25type = 1; + sprintf (state->fsubtype, "(LDU1) "); + state->numtdulc = 0; + processLDU1 (opts, state); + } + else if (state->lastp25type == 3) + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," (TSDU)\n"); + } + //state->lastp25type = 0; + // Guess that the state is TSDU + state->lastp25type = 3; + sprintf (state->fsubtype, "(TSDU) "); + + // Now processing NID + + skipDibit (opts, state, 328-25); + } + else if (state->lastp25type == 4) + { + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," (PDU)\n"); + } + state->lastp25type = 0; + } + else + { + state->lastp25type = 0; + sprintf (state->fsubtype, " "); + if (opts->errorbars == 1) + { + printFrameInfo (opts, state); + fprintf (stderr," duid:%s *Unknown DUID*\n", duid); + } + } +} diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index f9a7f38..cf0420b 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -185,10 +185,13 @@ getFrameSync (dsd_opts * opts, dsd_state * state) while (sync == 0) { //fprintf (stderr,"now=%d\n", now); //okay, so this is incrementing as expected + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } if ( opts->monitor_input_audio == 1 && (time(NULL) - now) > 1 ) //okay, still something going on, still doing the read part for some reason { playRawAudio(opts, state); //this is on line 21 in dsd_audio.c - //fprintf( stderr, "Farts"); } t++; @@ -406,7 +409,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " P25 Phase 1 "); + sprintf (state->ftype, "P25 Phase 1"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +P25p1 ", synctest_pos + 1, modulation); @@ -421,7 +424,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " P25 Phase 1 "); + sprintf (state->ftype, "P25 Phase 1"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -P25p1 ", synctest_pos + 1, modulation); @@ -442,7 +445,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) if (opts->inverted_x2tdma == 0) { // data frame - sprintf (state->ftype, " X2-TDMA "); + sprintf (state->ftype, "X2-TDMA"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +X2-TDMA ", synctest_pos + 1, modulation); @@ -453,7 +456,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) else { // inverted voice frame - sprintf (state->ftype, " X2-TDMA "); + sprintf (state->ftype, "X2-TDMA"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -X2-TDMA ", synctest_pos + 1, modulation); @@ -476,7 +479,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) if (opts->inverted_x2tdma == 0) { // voice frame - sprintf (state->ftype, " X2-TDMA "); + sprintf (state->ftype, "X2-TDMA"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +X2-TDMA ", synctest_pos + 1, modulation); @@ -491,7 +494,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) else { // inverted data frame - sprintf (state->ftype, " X2-TDMA "); + sprintf (state->ftype, "X2-TDMA"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -X2-TDMA ", synctest_pos + 1, modulation); @@ -503,7 +506,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } if (opts->frame_dmr == 1) { - if ((strcmp (synctest, DMR_MS_DATA_SYNC) == 0) || (strcmp (synctest, DMR_BS_DATA_SYNC) == 0)) + if ((strcmp (synctest, DMR_MS_DATA_SYNC) == 0) || (strcmp (synctest, DMR_BS_DATA_SYNC) == 0) )//try this + //if ((strncmperr (synctest, DMR_MS_DATA_SYNC, 24, 1) == 0) || (strncmperr (synctest, DMR_MS_DATA_SYNC, 24, 1) == 0)) { now = time(NULL); state->carrier = 1; @@ -513,7 +517,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) if (opts->inverted_dmr == 0) { // data frame - sprintf (state->ftype, " DMR "); + sprintf (state->ftype, "DMR"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +DMR ", synctest_pos + 1, modulation); @@ -524,7 +528,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) else { // inverted voice frame - sprintf (state->ftype, " DMR "); + sprintf (state->ftype, "DMR"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -DMR ", synctest_pos + 1, modulation); @@ -538,6 +542,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } if ((strcmp (synctest, DMR_MS_VOICE_SYNC) == 0) || (strcmp (synctest, DMR_BS_VOICE_SYNC) == 0)) + //if ( strcmp (synctest, DMR_MS_VOICE_SYNC) == 0 || strcmp (synctest, DMR_BS_VOICE_SYNC) == 0 || strcmp (synctest, DMR_DIRECT_MODE_TS1_VOICE_SYNC) == 0 || strcmp (synctest, DMR_DIRECT_MODE_TS2_VOICE_SYNC) == 0 ) + //if ((strncmperr (synctest, DMR_MS_VOICE_SYNC, 24, 1) == 0) || (strncmperr (synctest, DMR_BS_VOICE_SYNC, 24, 1) == 0)) { now = time(NULL); state->carrier = 1; @@ -547,7 +553,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) if (opts->inverted_dmr == 0) { // voice frame - sprintf (state->ftype, " DMR "); + sprintf (state->ftype, "DMR"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +DMR ", synctest_pos + 1, modulation); @@ -562,7 +568,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) else { // inverted data frame - sprintf (state->ftype, " DMR "); + sprintf (state->ftype, "DMR"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -DMR ", synctest_pos + 1, modulation); @@ -582,7 +588,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " ProVoice "); + sprintf (state->ftype, "ProVoice"); if (opts->errorbars == 1) //if (opts->errorbars == 1 && (time(NULL) - now) > 2 ) { @@ -602,7 +608,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " ProVoice "); + sprintf (state->ftype, "ProVoice"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -ProVoice ", synctest_pos + 1, modulation); @@ -634,15 +640,17 @@ getFrameSync (dsd_opts * opts, dsd_state * state) if (state->samplesPerSymbol == 20) { - sprintf (state->ftype, " NXDN48 "); + //sprintf (state->ftype, " NXDN48 "); + sprintf (state->ftype, "NXDN48"); //get rid of spaces if (opts->errorbars == 1) { - printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation); + printFrameSync (opts, state, " +NXDN48", synctest_pos + 1, modulation); } } else { - sprintf (state->ftype, " NXDN96 "); + sprintf (state->ftype, "NXDN96"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation); @@ -675,15 +683,17 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->min = ((state->min) + lmin) / 2; if (state->samplesPerSymbol == 20) { - sprintf (state->ftype, " NXDN48 "); + //sprintf (state->ftype, " NXDN48 "); + sprintf (state->ftype, "NXDN48"); if (opts->errorbars == 1) { - printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation); + printFrameSync (opts, state, " -NXDN48", synctest_pos + 1, modulation); } } else { - sprintf (state->ftype, " NXDN96 "); + sprintf (state->ftype, "NXDN96"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation); @@ -714,15 +724,17 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->min = ((state->min) + lmin) / 2; if (state->samplesPerSymbol == 20) { - sprintf (state->ftype, " NXDN48 "); + //sprintf (state->ftype, " NXDN48 "); + sprintf (state->ftype, "NXDN48"); if (opts->errorbars == 1) { - printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation); + printFrameSync (opts, state, " +NXDN48", synctest_pos + 1, modulation); } } else { - sprintf (state->ftype, " NXDN96 "); + sprintf (state->ftype, "NXDN96"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation); @@ -751,10 +763,12 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " NXDN "); + //sprintf (state->ftype, " NXDN "); + sprintf (state->ftype, "NXDN"); if (state->samplesPerSymbol == 20) { - sprintf (state->ftype, " NXDN48 "); + sprintf (state->ftype, "NXDN48"); + //sprintf (state->ftype, "NXDN48"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation); @@ -762,7 +776,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } else { - sprintf (state->ftype, " NXDN96 "); + sprintf (state->ftype, "NXDN96"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation); @@ -792,7 +806,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " D-STAR "); + sprintf (state->ftype, "D-STAR"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +D-STAR ", synctest_pos + 1, modulation); @@ -811,7 +825,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " D-STAR "); + sprintf (state->ftype, "D-STAR"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -D-STAR ", synctest_pos + 1, modulation); @@ -830,7 +844,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " D-STAR_HD "); + sprintf (state->ftype, "D-STAR_HD"); if (opts->errorbars == 1) { printFrameSync (opts, state, " +D-STAR_HD ", synctest_pos + 1, modulation); @@ -849,7 +863,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, " D-STAR_HD "); + sprintf (state->ftype, "D-STAR_HD"); if (opts->errorbars == 1) { printFrameSync (opts, state, " -D-STAR_HD ", synctest_pos + 1, modulation); @@ -927,7 +941,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, "(X2-TDMA) "); + sprintf (state->ftype, "(X2-TDMA)"); if (opts->errorbars == 1) { printFrameSync (opts, state, "(+X2-TDMA) ", synctest_pos + 1, modulation); @@ -945,7 +959,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->offset = synctest_pos; state->max = ((state->max) + lmax) / 2; state->min = ((state->min) + lmin) / 2; - sprintf (state->ftype, "(DMR) "); + sprintf (state->ftype, "(DMR)"); if (opts->errorbars == 1) { printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation); diff --git a/src/dsd_main.c b/src/dsd_main.c index cfd5941..4bc11b4 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -293,6 +293,8 @@ initState (dsd_state * state) state->debug_header_errors = 0; state->debug_header_critical_errors = 0; + state->nxdn_last_ran = 0; + #ifdef TRACE_DSD state->debug_sample_index = 0; state->debug_label_file = NULL; @@ -787,7 +789,7 @@ main (int argc, char **argv) opts.frame_x2tdma = 1; opts.frame_p25p1 = 1; opts.frame_nxdn48 = 0; //turn it on, doesn't work due to symbol rate difference - opts.frame_nxdn96 = 0; //causes false positives, leave on 0 + opts.frame_nxdn96 = 0; //causes false positives, leave on 0 opts.frame_dmr = 1; opts.frame_provoice = 0; //turn it on, doesn't work due to symbol rate difference } @@ -877,7 +879,6 @@ main (int argc, char **argv) opts.mod_qpsk = 0; opts.mod_gfsk = 0; //was 1 state.rf_mod = 0; //was 2 - //fprintf (stderr,"Enabling only GFSK modulation optimizations.\n"); fprintf (stderr,"Enabling only C4FM modulation optimizations.\n"); fprintf (stderr,"Decoding only NXDN 9600 baud frames.\n"); } @@ -890,6 +891,9 @@ main (int argc, char **argv) opts.frame_nxdn96 = 0; opts.frame_dmr = 1; opts.frame_provoice = 0; + opts.mod_c4fm = 1; //just a test + opts.mod_qpsk = 0; + opts.mod_gfsk = 0; //was 1 fprintf (stderr,"Decoding only DMR/MOTOTRBO frames.\n"); } break; diff --git a/src/dsd_mbe.c b/src/dsd_mbe.c index 7fbd669..01f2d96 100644 --- a/src/dsd_mbe.c +++ b/src/dsd_mbe.c @@ -17,6 +17,8 @@ #include "dsd.h" +static void DecipherData(char * Input, char * KeyStream, char * Output, int NbData); + void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv) { @@ -73,12 +75,14 @@ playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv) void processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24]) { - + //comment out line below should return print back to normal + //strncpy (state->err_buf, state->err_str, sizeof(state->err_str)); //right at the very top before err_str gets returned? int i; char imbe_d[88]; char ambe_d[49]; -#ifdef AMBE_PACKET_OUT char ambe_d_str[50]; +#ifdef AMBE_PACKET_OUT + #endif for (i = 0; i < 88; i++) @@ -117,6 +121,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a { mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); #ifdef AMBE_PACKET_OUT + for(i=0; i<49; i++) { ambe_d_str[i] = ambe_d[i] + '0'; } @@ -124,7 +129,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a // print binary string fprintf (stderr, "\n?\t?\t%s\t", ambe_d_str); // print error data - fprintf (stderr, "E1: %d; E2: %d; S: %s", state->errs, state->errs2, state->err_str); + fprintf (stderr, "E1: %d; E2: %d; S: %s", state->errs, state->errs2, state->err_str);} #endif if (opts->mbe_out_f != NULL) { @@ -134,8 +139,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a if (opts->errorbars == 1) { - fprintf (stderr, "%s", state->err_str); - //printw("%s", state->err_str); + //state->err_buf = state->err_str; //make comy to compare, and only print when comparison differs?? THIS HERE HERE + //strncpy (state->err_buf, state->err_str, sizeof(state->err_str)); //is this the correct placement for this? want it just before err_str is set? + fprintf (stderr, "%s", state->err_str); //this the actual error 'bar' ==== printer, find way to keep this entire string from printing constantly unless err_str changes + //fprintf (stderr, "%s", state->err_buf); } state->debug_audio_errors += state->errs2; @@ -151,3 +158,128 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a playSynthesizedVoice (opts, state); } } + +void processMbeFrameEncrypted (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24], char ambe_keystream[49], char imbe_keystream[88]) +{ + + int i; + char imbe_d[88]; + char ambe_d[49]; +#ifdef AMBE_PACKET_OUT + char ambe_d_str[50]; +#endif + + for (i = 0; i < 88; i++) + { + imbe_d[i] = 0; + } + + if ((state->synctype == 0) || (state->synctype == 1)) + { + // 0 +P25p1 + // 1 -P25p1 + + mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); + + DecipherData(imbe_d, imbe_keystream, imbe_d, 88); + + if (opts->mbe_out_f != NULL) + { + saveImbe4400Data (opts, state, imbe_d); + } + } + else if ((state->synctype == 14) || (state->synctype == 15)) + { + mbe_processImbe7100x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe7100_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); + + DecipherData(imbe_d, imbe_keystream, imbe_d, 88); + + if (opts->mbe_out_f != NULL) + { + saveImbe4400Data (opts, state, imbe_d); + } + } + else if ((state->synctype == 6) || (state->synctype == 7)) + { + //mbe_processAmbe3600x2400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); + + state->errs = 0; + state->errs2 = 0; + state->errs = mbe_eccAmbe3600x2400C0 (ambe_fr); + mbe_demodulateAmbe3600x2400Data (ambe_fr); + state->errs2 = state->errs; + state->errs2 += mbe_eccAmbe3600x2400Data (ambe_fr, ambe_d); + + memcpy(state->ambe_ciphered, ambe_d, sizeof(state->ambe_ciphered)); + DecipherData(ambe_d, ambe_keystream, ambe_d, 49); + memcpy(state->ambe_deciphered, ambe_d, sizeof(state->ambe_deciphered)); + + mbe_processAmbe2400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); + + if (opts->mbe_out_f != NULL) + { + saveAmbe2450Data (opts, state, ambe_d); + } + } + else + { + //mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); + + state->errs = 0; + state->errs2 = 0; + state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr); + mbe_demodulateAmbe3600x2450Data (ambe_fr); + state->errs2 = state->errs; + state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d); + + memcpy(state->ambe_ciphered, ambe_d, sizeof(state->ambe_ciphered)); + DecipherData(ambe_d, ambe_keystream, ambe_d, 49); + memcpy(state->ambe_deciphered, ambe_d, sizeof(state->ambe_deciphered)); + + mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); + +#ifdef AMBE_PACKET_OUT + for(i=0; i<49; i++) { + ambe_d_str[i] = ambe_d[i] + '0'; + } + ambe_d_str[49] = '\0'; + // print binary string + fprintf(stderr, "\n?\t?\t%s\t", ambe_d_str); + // print error data + fprintf(stderr, "E1: %d; E2: %d; S: %s", state->errs, state->errs2, state->err_str); +#endif + if (opts->mbe_out_f != NULL) + { + saveAmbe2450Data (opts, state, ambe_d); + } + } + + if (opts->errorbars == 1) + { + fprintf(stderr, "%s", state->err_str); + } + + state->debug_audio_errors += state->errs2; + + processAudio (opts, state); + if (opts->wav_out_f != NULL) + { + writeSynthesizedVoice (opts, state); + } + + if (opts->audio_out == 1) + { + playSynthesizedVoice (opts, state); + } +} + +/* This function decipher/decrypt data */ +static void DecipherData(char * Input, char * KeyStream, char * Output, int NbData) +{ + int i; + + for(i = 0; i < NbData; i++) + { + Output[i] = Input[i] ^ KeyStream[i]; + } +} diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index deb3e66..d45a523 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -27,7 +27,28 @@ #include "dsd.h" #include "git_ver.h" +/* +short hexbuf; +unsigned long long sr_0 = 0; //64-bit shift registers for pushing decoded binary or dibit data +unsigned long long sr_1 = 0; //384 +unsigned long long sr_2 = 0; // +unsigned long long sr_3 = 0; // +unsigned long long sr_4 = 0; // +unsigned long long sr_5 = 0; // +unsigned long long sr_6 = 0; // +*/ +int tg; //last tg +int rd; //last rid +int rn; //last ran +int nc; //nac +int src; //last rid? double? +int lls = -1; //last last sync type +int dcc = 0; //initialize with 0 to prevent core dump +int i = 0; +char * s0last = " "; +char * s1last = " "; char versionstr[25]; +unsigned long long int call_matrix[33][6]; //0 - sync type; 1 - tg/ran; 2 - rid; 3 - slot; 4 - cc; 5 - time(NULL) ; char * FM_bannerN[9] = { " CTRL + C twice to exit", " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗", @@ -48,16 +69,16 @@ char * SyncTypes[20] = { "INV_X2TDMA_BS/MS_VOICE_SYNC", "DSTAR_SYNC", "INV_DSTAR_SYNC", - "NXDN_BS_VOICE_SYNC", //8 - "INV_NXDN_BS_VOICE_SYNC", //9 - "DMR_BS/MS_DATA_SYNC", - "INV_DMR_BS/MS_DATA_SYNC", - "DMR_BS/MS_VOICE_SYNC", - "INV_DMR_BS/MS_VOICE_SYNC", - "PROVOICE_SYNC", //14 - "INV_PROVOICE_SYNC", //15 - "NXDN_BS_DATA_SYNC", //16 - "INV_NXDN_BS_DATA_SYNC", //17 + "NXDN_BS_VOICE_SYNC", //8 + "INV_NXDN_BS_VOICE_SYNC", //9 + "DMR_BS/MS_DATA_SYNC", //10 + "DMR_MS/BS_VOICE_SYNC", //11 + "DMR_MS/BS_DATA_SYNC", //12 + "INV_DMR_BS/MS_VOICE_SYNC", //13 + "PROVOICE_SYNC", //14 + "INV_PROVOICE_SYNC", //15 + "NXDN_BS_DATA_SYNC", //16 + "INV_NXDN_BS_DATA_SYNC", //17 "DSTAR_HD", "INV_DSTAR_HD" @@ -82,7 +103,7 @@ char * getTimeN(void) //get pretty hh:mm:ss timestamp void ncursesOpen () { mbe_printVersion (versionstr); - setlocale(LC_ALL, ""); + //setlocale(LC_ALL, ""); initscr(); //Initialize NCURSES screen window start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style @@ -92,93 +113,339 @@ void ncursesOpen () init_pair(5, COLOR_MAGENTA, COLOR_BLACK); //Magenta for no frame sync/signal noecho(); cbreak(); + fprintf (stderr, "Opening NCurses Terminal. \n"); + //call_matrix[5-i][0] = 0; + //call_matrix[5-i][1] = 0; + //call_matrix[5-i][2] = 0; + //call_matrix[5-i][3] = 0; + //call_matrix[5-i][4] = 0; + //call_matrix[5-i][5] = time(NULL); } void ncursesPrinter (dsd_opts * opts, dsd_state * state) { int level; - level = (int) state->max / 164; + + //level = (int) state->max / 164; + level = 0; //start each cycle with 0 erase(); //disabling until wide support can be built for LM, etc. $(ncursesw5-config --cflags --libs) //printw ("%s \n", FM_bannerN[0]); //top line in white - //attron(COLOR_PAIR(4)); - //for (short int i = 1; i < 7; i++) { //following lines in cyan - //printw("%s \n", FM_bannerN[i]); } - //attroff(COLOR_PAIR(4)); - printw ("%s \n", FM_bannerN[7]); //http link - printw ("Digital Speech Decoder: Florida Man Edition\n"); - printw ("Github Build Version: %s \n", GIT_TAG); - printw ("mbelib version %s\n", versionstr); - printw ("Time: "); - printw ("%s ", getTimeN()); - if (SyncTypes[state->lastsynctype] != NULL) + attron(COLOR_PAIR(4)); + //for (short int i = 1; i < 7; i++) + //{ //following lines in cyan + //printw("%s \n", FM_bannerN[i]); + //} + attroff(COLOR_PAIR(4)); + printw ("--Build Info------------------------------------------------------------------\n"); + //printw ("| %s \n", FM_bannerN[7]); //http link + printw ("| Digital Speech Decoder: Florida Man Edition\n"); + printw ("| Github Build Version: %s \n", GIT_TAG); + printw ("| mbelib version %s\n", versionstr); + printw ("------------------------------------------------------------------------------\n"); + + + if ( (state->lastsynctype == 14 || state->lastsynctype == 15) ) //honestly have no idea how to do this for pV { - printw ("%s \n", SyncTypes[state->lastsynctype]); - //printw("%s ", state->ftype); //moved to front, some ftype strings have spaces in front of them, and others dont - /* Not sure if I'm going to use the error bars yet - if (opts->errorbars == 1) - { - printw("-"); //AFAIK, errorbars==1 is the internal value for if a system has inverted signal types, not at all misleading - } - else - { - printw("+"); - } + call_matrix[5][0] = lls; + call_matrix[5][1] = 1; + call_matrix[5][2] = 1; + call_matrix[5][3] = 1; + call_matrix[5][4] = 1; + call_matrix[5][5] = time(NULL); + } + + if ( (state->nxdn_last_rid != src && src > 0) || (state->nxdn_last_ran != rn && rn > 0) ) //find condition to make this work well, probably if last != local last variables + { + /* //save just in case + call_matrix[0][0] = call_matrix[1][0]; + call_matrix[0][1] = call_matrix[1][1]; + call_matrix[0][2] = call_matrix[1][2]; + call_matrix[0][3] = call_matrix[1][3]; + call_matrix[0][4] = call_matrix[1][4]; + call_matrix[0][5] = call_matrix[1][5]; + + call_matrix[1][0] = call_matrix[2][0]; + call_matrix[1][1] = call_matrix[2][1]; + call_matrix[1][2] = call_matrix[2][2]; + call_matrix[1][3] = call_matrix[2][3]; + call_matrix[1][4] = call_matrix[2][4]; + call_matrix[1][5] = call_matrix[2][5]; + + call_matrix[2][0] = call_matrix[3][0]; + call_matrix[2][1] = call_matrix[3][1]; + call_matrix[2][2] = call_matrix[3][2]; + call_matrix[2][3] = call_matrix[3][3]; + call_matrix[2][4] = call_matrix[3][4]; + call_matrix[2][5] = call_matrix[3][5]; + + call_matrix[3][0] = call_matrix[4][0]; + call_matrix[3][1] = call_matrix[4][1]; + call_matrix[3][2] = call_matrix[4][2]; + call_matrix[3][3] = call_matrix[4][3]; + call_matrix[3][4] = call_matrix[4][4]; + call_matrix[3][5] = call_matrix[4][5]; + + call_matrix[4][0] = call_matrix[5][0]; + call_matrix[4][1] = call_matrix[5][1]; + call_matrix[4][2] = call_matrix[5][2]; + call_matrix[4][3] = call_matrix[5][3]; + call_matrix[4][4] = call_matrix[5][4]; + call_matrix[4][5] = call_matrix[5][5]; */ - if (1 == 1){ //figure out method that will tell me when is active and when not active, maybe carrier but this doesn't print anyways unless activity - attron(COLOR_PAIR(3)); - } - printw ("%s %s\n", state->ftype, state->fsubtype); //some ftype strings have extra spaces in them - if (state->lasttg < 0) //triggers compiler warning: comparison between pointer and integer + for (short int k = 0; k < 5; k++) { - //sprintf(state->ftype, ) - //state->lasttg = state->ftype; //warning: assignment to ‘int’ from ‘char * - state->lasttg = 0; - } - printw ("TG [%7i] RID [%12i] \n", state->lasttg, state->lastsrc); //variables to fill with info from other system types too - //printw ("TG [%s] \n", state->lasttg); - //printw ("TDMA activity: %s %s \n", state->slot0light, state->slot1light); - printw("In Level: [%2i%%] ", level); - printw ("Voice Error [%s] \n", state->err_str); //no idea if this shows anything outside of TDMA or P1 or what - if (1 == 1){ //same as above - attroff(COLOR_PAIR(3)); + call_matrix[k][0] = call_matrix[k+1][0]; + call_matrix[k][1] = call_matrix[k+1][1]; + call_matrix[k][2] = call_matrix[k+1][2]; + call_matrix[k][3] = call_matrix[k+1][3]; + call_matrix[k][4] = call_matrix[k+1][4]; + call_matrix[k][5] = call_matrix[k+1][5]; } + call_matrix[5][0] = lls; + call_matrix[5][1] = rn; + call_matrix[5][2] = src; + call_matrix[5][3] = 0; + call_matrix[5][4] = 0; + call_matrix[5][5] = time(NULL); + } - /* - if (state->lastsynctype == 8 ||state->lastsynctype == 9 ||state->lastsynctype == 16 ||state->lastsynctype == 17) + if ( (lls == 0 || lls == 1) && state->lastsrc != rd && state->lastsrc > 0) //find condition to make this work well, probably if last != local last variables { - if (state->samplesPerSymbol == 20) - { - //sprintf (state->ftype, " NXDN48 "); - if (opts->errorbars == 1) - { - //printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation); - printw("NXDN48 "); - printw("%s \n", SyncTypes[state->lastsynctype]); - printw("%s ", state->ftype); - } - } - else - { - //sprintf (state->ftype, " NXDN96 "); - if (opts->errorbars == 1) - { - //printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation); - printw("NXDN96 "); - printw("%s ", SyncTypes[state->lastsynctype]); - printw("%s ", state->ftype); - } - } + for (short int k = 0; k < 5; k++) + { + call_matrix[k][0] = call_matrix[k+1][0]; + call_matrix[k][1] = call_matrix[k+1][1]; + call_matrix[k][2] = call_matrix[k+1][2]; + call_matrix[k][3] = call_matrix[k+1][3]; + call_matrix[k][4] = call_matrix[k+1][4]; + call_matrix[k][5] = call_matrix[k+1][5]; + } + + call_matrix[5][0] = lls; + call_matrix[5][1] = tg; + call_matrix[5][2] = rd; + call_matrix[5][3] = 0; + call_matrix[5][4] = nc; + call_matrix[5][5] = time(NULL); + //i++; + } + //printw ("Time: "); + //printw ("%s \n", getTimeN()); + attron(COLOR_PAIR(4)); + printw ("--Input Output----------------------------------------------------------------\n"); + if (opts->audio_in_type == 0) + { + printw ("| Pulse Audio Input [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_in, opts->pulse_digi_in_channels); + } + if (opts->audio_in_type == 1) + { + printw ("| STDIN - Input\n"); + } + if (opts->audio_in_type == 3) + { + printw ("| RTL2838 Device #[%d]", opts->rtl_dev_index); + printw (" [%i] dB", opts->rtl_gain_value); + printw (" [%i] Sq", opts->rtl_squelch_level); + printw (" [%i] kHz VFO\n", opts->rtl_bandwidth); + printw ("| Freq: [%lld] Hz", opts->rtlsdr_center_freq); + printw (" - Tuning available on UDP Port [%i]\n", opts->rtl_udp_port); + } + if (opts->audio_out_type == 0) + { + printw ("| Pulse Audio Output [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_out, opts->pulse_digi_out_channels); + } + if (opts->mbe_out_dir[0] != 0) + { + printw ("| Writing MBE data files to directory %s\n", opts->mbe_out_dir); + } + if (opts->wav_out_file[0] != 0) + { + printw ("| Writing audio wav to file %s\n", opts->wav_out_file); } - */ - printw("\n"); //line return + printw ("------------------------------------------------------------------------------\n"); + attroff(COLOR_PAIR(4)); + + if (state->carrier == 1){ //figure out method that will tell me when is active and when not active, maybe carrier but this doesn't print anyways unless activity + attron(COLOR_PAIR(3)); + level = (int) state->max / 164; //only update on carrier present + } + //if (state->carrier == 0){ //figure out method that will tell me when is active and when not active, maybe carrier but this doesn't print anyways unless activity + //attron(COLOR_PAIR(1)); + //0 - sync type; 1 - tg/ran; 2 - rid; 3 - slot; 4 - dcc; 5 - time(NULL) ; + //} + + printw ("--Audio Decode----------------------------------------------------------------\n"); + printw ("| In Level: [%3i%%] \n", level); + printw ("| Voice Error: [%i][%i] \n| Error Bars: [%s] \n", state->errs, state->errs2, state->err_str); // + printw ("------------------------------------------------------------------------------\n"); + + + printw ("--Call Info-------------------------------------------------------------------\n"); + if (state->lastsynctype != -1) //not sure if this will be okay + { + lls = state->lastsynctype; + } + if (state->nxdn_last_rid > 0 && state->nxdn_last_rid != src); + { + src = state->nxdn_last_rid; + //rn = state->nxdn_last_ran; + } + if (state->nxdn_last_ran > 0 && state->nxdn_last_rid != rn); + { + //src = state->nxdn_last_rid; + rn = state->nxdn_last_ran; + } + //if (state->lastsynctype == 8 || state->lastsynctype == 9 || state->lastsynctype == 16 || state->lastsynctype == 17) //change this to NXDN syncs later on + if (lls == 8 || lls == 9 || lls == 16 || lls == 17) + { + //printw ("| RAN: [%02d] \n", state->nxdn_last_ran); + printw ("| RAN: [%02d] \n", rn); + printw ("| RID: [%d] \n", src); //maybe change to nxdn_last_rid + } + + //printw ("Error?: [%i] [%i] \n", state->errs, state->errs2); //what are these? + + if (state->lasttg > 0 && state->lastsrc > 0) + { + tg = state->lasttg; + rd = state->lastsrc; + } + if (state->nac > 0) + { + nc = state->nac; + } + if ((lls == 0 || lls == 1)) //1 for P25 P1 Audio + { + printw("| TID:[%i] \n| RID:[%i] \n", tg, rd); + printw("| NAC: [0x%X] \n", nc); + } + //if (state->lastsynctype == 12 || state->lastsynctype == 13) //DMR Voice Types + if (lls == 11 || lls == 13) //DMR Voice Types + { + printw ("| DCC: [%i]\n", state->dmr_color_code); + //printw ("%s ", state->slot0light); + printw ("| SLOT 0 "); + if (state->currentslot == 0) //find out how to tell when slot0 has voice + { + s0last = "Voice"; + //printw("Voice"); + } + printw ("%s ", s0last); + + //printw ("%s ", state->slot1light); + printw ("SLOT 1 "); + if (state->currentslot == 1) //find out how to tell when slot1 has voice + { + s1last = "Voice"; + //printw("Voice"); + } + printw ("%s \n", s1last); + } + + if (state->dmr_color_code > 0 && (lls == 11 || lls == 13) ) //DMR VOice + { + dcc = state->dmr_color_code; + } + //if (state->lastsynctype == 10 || state->lastsynctype == 11) //DMR Data Types + if (lls == 10 || lls == 11) //DMR Data Types + { + printw ("| DCC: [%i]\n", dcc); + //printw ("%s ", state->slot0light); + printw ("| SLOT 0 "); + if (state->currentslot == 0) //find out how to tell when slot0 has voice + { + s0last = "Data "; + if (strcmp (state->fsubtype, " Slot idle ") == 0) + { + s0last = "Idle "; + } + } + printw ("%s ", s0last); + //printw ("%s ", state->slot1light); + printw ("SLOT 1 "); + if (state->currentslot == 1) //find out how to tell when slot1 has voice + { + s1last = "Data "; + if (strcmp (state->fsubtype, " Slot idle ") == 0) + { + s1last = "Idle "; + } + } + printw ("%s \n", s1last); + } + if (lls != -1) //is there a synctype 0? + { + printw ("| %s \n", SyncTypes[lls]); + } + printw ("------------------------------------------------------------------------------\n"); + //colors off + if (state->carrier == 1){ //same as above + attroff(COLOR_PAIR(3)); + } + //if (state->carrier == 0){ //same as above + //attroff(COLOR_PAIR(1)); + //} + + attron(COLOR_PAIR(4)); //cyan for history //add other interesting info to put here + //make Call_Matrix + //0 - sync type; 1 - tg/ran; 2 - rid; 3 - slot; 4 - cc; 5 - time(NULL) ; + printw ("--Call History----------------------------------------------------------------\n"); + for (short int j = 0; j < 6; j++) + { + if ( (time(NULL) - call_matrix[j][5]) < 9999) + //if (1 == 1) + { + printw ("| #%d %s ", 6-j, SyncTypes[call_matrix[j][0]]); + if (lls == 8 || lls == 9 || lls == 16 || lls == 17) + { + printw ("RAN [%2d] ", call_matrix[j][1]); + } + if (lls == 0 || lls == 1 || lls == 11 || lls == 13) //P25 P1 and DMR Voice + { + printw ("TID [%2d] ", call_matrix[j][1]); + } + + printw ("RID [%4d] ", call_matrix[j][2]); + //printw ("S %d - ", call_matrix[j][3]); + if (call_matrix[j][0] == 0 || call_matrix[j][0] == 1) //P25P1 Voice + { + printw ("NAC [0x%X] ", call_matrix[j][4]); + } + if (call_matrix[j][0] == 12 || call_matrix[j][0] == 13) //DMR Voice Types + { + printw ("DCC [%d] ", call_matrix[j][4]); + } + printw ("%d secs ago\n", time(NULL) - call_matrix[j][5]); + } + //printw("\n"); + } + printw ("------------------------------------------------------------------------------"); + attroff(COLOR_PAIR(4)); //cyan for history + //put sync type at very bottom + //printw ("%s %s\n", state->ftype, state->fsubtype); //some ftype strings have extra spaces in them + //if (state->lastsynctype != -1) //is there a synctype 0? + + + //debug sr printw + if (1==2) //disable this later on + { + + printw ("sr_0 = %16llX \n", state->sr_0); + printw ("sr_1 = %16llX \n", state->sr_1); + printw ("sr_2 = %16llX \n", state->sr_2); + printw ("sr_3 = %16llX \n", state->sr_3); + printw ("sr_4 = %16llX \n", state->sr_4); + printw ("sr_5 = %16llX \n", state->sr_5); + printw ("sr_6 = %16llX \n", state->sr_6); + + } refresh(); - } void ncursesClose () diff --git a/src/dsd_symbol.c b/src/dsd_symbol.c index a9a474e..131cf2f 100644 --- a/src/dsd_symbol.c +++ b/src/dsd_symbol.c @@ -27,7 +27,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) sum = 0; count = 0; - for (i = 0; i < state->samplesPerSymbol; i++) //right HERE, this is how many samples it will grab, depending on samplesPerSymbol and also rf_mod messing with it too + for (i = 0; i < state->samplesPerSymbol; i++) //right HERE { // timing control diff --git a/src/nxdn_data.c b/src/nxdn_data.c index 7eb3cbe..ad535f7 100644 --- a/src/nxdn_data.c +++ b/src/nxdn_data.c @@ -1,36 +1,105 @@ #include "dsd.h" +#include "nxdn_const.h" -void -processNXDNData (dsd_opts * opts, dsd_state * state) +//don't know why this doesn't work right in LEH, need to figure that out for him +//works just fien when ripped from his and into mine +//must be some random thing, I'll look at his when I have a chance +void processNXDNData (dsd_opts * opts, dsd_state * state) { - int i, dibit; + int i, dibit = 0; + unsigned char sacch_raw[72] = {0}; + unsigned char sacch_decoded[32] = {0}; /* 26 bit + 6 bit CRC */ + unsigned char *pr; + uint8_t CrcIsGood = 0; + uint8_t StructureField = 0; + uint8_t RAN = 0; + uint8_t PartOfFrame = 0; + + /* Remove compiler warning */ + //UNUSED_VARIABLE(dibit); if (opts->errorbars == 1) - { - fprintf (stderr, "DATA "); - } + { + fprintf(stderr, "DATA - "); + } + /* Start pseudo-random NXDN sequence after + * LITCH = 16 bit = 8 dibit + * ==> Index 8 */ + pr = (unsigned char *)(&nxdnpr2[8]); for (i = 0; i < 30; i++) - { - dibit = getDibit (opts, state); + { + dibit = getDibit (opts, state); + + /* Store and de-interleave directly SACCH bits */ + sacch_raw[(2*i)] = ((*pr) & 1) ^ (1 & (dibit >> 1)); // bit 1 + sacch_raw[(2*i)+1] = (1 & dibit); // bit 0 + pr++; #ifdef NXDN_DUMP - fprintf (stderr, "%c", dibit + 48); + fprintf(stderr, "%c", dibit + 48); #endif - } + } #ifdef NXDN_DUMP - fprintf (stderr, " "); + fprintf(stderr, " "); #endif + + /* Decode the SACCH fields */ + CrcIsGood = NXDN_SACCH_raw_part_decode(sacch_raw, sacch_decoded); + StructureField = (sacch_decoded[0]<<1 | sacch_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */ + RAN = (sacch_decoded[2]<<5 | sacch_decoded[3]<<4 | sacch_decoded[4]<<3 | sacch_decoded[5]<<2 | sacch_decoded[6]<<1 | sacch_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the SACCH) */ + + /* Compute the Part of Frame according to the structure field */ + if (StructureField == 3) PartOfFrame = 0; + else if(StructureField == 2) PartOfFrame = 1; + else if(StructureField == 1) PartOfFrame = 2; + else if(StructureField == 0) PartOfFrame = 3; + else PartOfFrame = 0; /* Normally we should never go here */ + + /* Fill the SACCH structure */ + state->NxdnSacchRawPart[PartOfFrame].CrcIsGood = CrcIsGood; + state->NxdnSacchRawPart[PartOfFrame].StructureField = StructureField; + state->NxdnSacchRawPart[PartOfFrame].RAN = RAN; + + memcpy(state->NxdnSacchRawPart[PartOfFrame].Data, &sacch_decoded[8], 18); /* Copy the 18 bits of SACCH content */ + + //fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); + if(CrcIsGood) + { + fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); + fprintf (stderr, " (OK) - "); + state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead + } + + else fprintf (stderr, "(CRC ERR) - "); + + + /* Decode the SACCH only when all 4 voice frame + * SACCH spare parts have been received */ + if(PartOfFrame == 3) + { + /* Decode the entire SACCH content */ + NXDN_SACCH_Full_decode(opts, state); + } + for (i = 0; i < 144; i++) - { - dibit = getDibit (opts, state); + { + dibit = getDibit (opts, state); #ifdef NXDN_DUMP - fprintf (stderr, "%c", dibit + 48); + fprintf(stderr, "%c", dibit + 48); #endif - } + } if (opts->errorbars == 1) - { - fprintf (stderr, "\n"); - } -} + { + fprintf(stderr, "\n"); + } + + /* Reset the SACCH CRCs when all 4 voice frame + * SACCH spare parts have been received */ + if(PartOfFrame == 3) + { + /* Reset all CRCs of the SACCH */ + for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0; + } +} /* End processNXDNData() */ diff --git a/src/nxdn_data.c.bkp b/src/nxdn_data.c.bkp new file mode 100644 index 0000000..5e212bd --- /dev/null +++ b/src/nxdn_data.c.bkp @@ -0,0 +1,41 @@ +#include "dsd.h" +#include "nxdn_const.h"//going to test pushing data frames through, but not throught he processMBE portion, want to get those get frames + +void +processNXDNData (dsd_opts * opts, dsd_state * state) +{ + int i, dibit; + //dibit = getDibit (opts, state); + //fprintf (stderr, "D %c \n", dibit + 48); //adding to see what dumps exactly + if (opts->errorbars == 1) + { + fprintf (stderr, "DATA "); + //dibit = getDibit (opts, state); + //fprintf (stderr, "DE %c \n", dibit + 48); //adding to see what dumps exactly + } + + for (i = 0; i < 30; i++) + { + dibit = getDibit (opts, state); +#ifdef NXDN_DUMP + fprintf (stderr, "%c", dibit + 48); +#endif + } +#ifdef NXDN_DUMP + fprintf (stderr, " "); +#endif + + for (i = 0; i < 144; i++) + { + dibit = getDibit (opts, state); + //fprintf (stderr, "%c", dibit + 48); +#ifdef NXDN_DUMP + fprintf (stderr, "%c", dibit + 48); +#endif + } + + if (opts->errorbars == 1) + { + fprintf (stderr, "\n"); + } +} diff --git a/src/nxdn_data.c.bkp2 b/src/nxdn_data.c.bkp2 new file mode 100644 index 0000000..fe3cddf --- /dev/null +++ b/src/nxdn_data.c.bkp2 @@ -0,0 +1,72 @@ +#include "dsd.h" +#include "nxdn_const.h" //test making this just like voice, but not processing MBEframes + +void +processNXDNData (dsd_opts * opts, dsd_state * state) +{ + int i, j, dibit, k, l; + char ambe_fr2[4][24]; + const int *w, *x, *y, *z; + const char *pr; + + if (opts->errorbars == 1) + { + fprintf (stderr,"DATA e:"); + } + + for (i = 0; i < 30; i++) + { + dibit = getDibit (opts, state); +#ifdef NXDN_DUMP + fprintf (stderr,"%c", dibit + 48); +#endif + } +#ifdef NXDN_DUMP + fprintf (stderr," "); +#endif + + pr = nxdnpr; + for (j = 0; j < 4; j++) + { + w = nW; + x = nX; + y = nY; + z = nZ; + for (i = 0; i < 36; i++) + { + dibit = getDibit (opts, state); + //fprintf (stderr,"%c", dibit + 48); //remove later +#ifdef NXDN_DUMP + fprintf (stderr,"%c", dibit + 48); +#endif + ambe_fr2[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1 + pr++; + ambe_fr2[*y][*z] = (1 & dibit); // bit 0 + w++; + x++; + y++; + z++; + //dump this whole lot, figure out what it all means + //fprintf (stderr, "%s\n%s\n", ambe_fr, pr); + } + for (k = 0; k < 36; k++) //was 36 + { + for (l = 0; l < 36; l++) //was 36 + { + //fprintf (stderr, "%X%X", ambe_fr[k][l]); + //fprintf (stderr, "%X", ambe_fr2[k][l]); + } + //fprintf (stderr, "\n"); + } + //processMbeFrame (opts, state, NULL, ambe_fr, NULL); +#ifdef NXDN_DUMP + fprintf (stderr," "); +#endif + + } + //fprintf (stderr, "\nD%s\n%s\n", ambe_fr, pr); + if (opts->errorbars == 1) + { + fprintf (stderr,"\n"); + } +} diff --git a/src/nxdn_lib.c b/src/nxdn_lib.c new file mode 100644 index 0000000..d96e1fd --- /dev/null +++ b/src/nxdn_lib.c @@ -0,0 +1,1084 @@ +/* + ============================================================================ + Name : nxdn_lib + Author : + Version : 1.0 + Date : 2018 December 26 + Copyright : No copyright + Description : NXDN decoding source lib + ============================================================================ + */ + + +/* Include ------------------------------------------------------------------*/ +#include "dsd.h" +#include "nxdn_const.h" + + +/* Global variables ---------------------------------------------------------*/ + + +/* Functions ----------------------------------------------------------------*/ + + +/* + * @brief : This function decodes the LICH + * + * @param InputLich : A 8 ASCII bytes buffer + * + * @param RFChannelType : Output of RF Channel Type + * parameter + * + * @param FunctionnalChannelType : Output of Functional + * Channel Type parameter + * + * @param Option : Output of Option parameter + * + * @param : CompleteLichBinaryFormat : The constitued LICH (7 bits) + * + * @param Direction : Output of Direction parameter + * + * @param Inverted : 1 = Inverted frame ; 0 = Normal frame + * + * @return 1 when LICH parity is good + * 0 when LICH parity is bad + * + */ + //borrowed from LEH my_lib.c file + uint32_t ConvertBitIntoBytes(uint8_t * BufferIn, uint32_t BitLength) + { + uint32_t Output = 0; + uint32_t i; + + for(i = 0; i < BitLength; i++) + { + Output <<= 1; + Output |= (uint32_t)(BufferIn[i] & 1); + } + + return Output; + } /* End ConvertBitIntoBytes() */ + + +uint8_t NXDN_decode_LICH(uint8_t InputLich[8], + uint8_t * RFChannelType, + uint8_t * FunctionnalChannelType, + uint8_t * Option, + uint8_t * Direction, + uint8_t * CompleteLichBinaryFormat, + uint8_t Inverted) +{ + uint8_t GoodParity = 0; + uint32_t i; + uint8_t LichDibits[8] = {0}; + uint8_t LichBits[8] = {0}; + uint8_t EvenParityComputed = 0; + uint8_t *pr; + uint8_t dibit; + uint8_t InvertionDibitValue; + uint8_t CompleteLich = 0; + + if(Inverted) InvertionDibitValue = 0x02; + else InvertionDibitValue = 0x00; + + pr = (uint8_t *)(&nxdnpr[0]); + + /* Recreate a 8 bits field + * 7 bits of LICH + 1 parity bit */ + for(i = 0; i < 8; i++) + { + /* Get the dibit value (convert ASCII to bin value) */ + dibit = ((InputLich[i] - '0') & 0x03) ^ InvertionDibitValue; + + /* Descramble the dibit */ + LichDibits[i] = dibit ^ ((*pr & 0x01) << 1); + + /* Increment pseudo-random pointer */ + pr++; + + /* Decode LICH dibit */ + switch(LichDibits[i]) + { + case 0: + { + LichBits[i] = 0; + break; + } + case 1: + { + LichBits[i] = 0; + break; + } + case 2: + { + LichBits[i] = 1; + break; + } + default: + { + LichBits[i] = 1; + break; + } + } /* End switch(LichDibits[i]) */ + + /* Parity should be even */ + EvenParityComputed += LichBits[i]; + + } /* End for(i = 0; i < 8; i++) */ + + /* Even parity = Good */ + if((EvenParityComputed % 2) == 0) + { + GoodParity = 1; + } + else + { + /* Odd parity = Wrong */ + } + + *RFChannelType = ((LichBits[0] & 0x01) << 1) | (LichBits[1] & 0x01); + *FunctionnalChannelType = ((LichBits[2] & 0x01) << 1) | (LichBits[3] & 0x01); + *Option = ((LichBits[4] & 0x01) << 1) | (LichBits[5] & 0x01); + *Direction = LichBits[6] & 0x01; + + CompleteLich = 0; + for(i = 0; i < 7; i++) + { + CompleteLich = ((CompleteLich << 1) | LichBits[i]) & 0x7F; + } + *CompleteLichBinaryFormat = CompleteLich; + + return GoodParity; +} /* End NXDN_decode_LICH() */ + + +/* + * @brief : This function decodes the RAW part of SACCH received when + * each voice frame starts. + * This is NOT the full SACCH but only 18 bits on 72. + * + * @param Input : A 60 bit (60 bytes) buffer pointer of input data + * + * @param Output : A 32 bit (26 bytes data + 6 bytes CRC) buffer where write output data + * + * @return 1 when CRC is good + * 0 when CRC is bad + * + */ +uint8_t NXDN_SACCH_raw_part_decode(uint8_t * Input, uint8_t * Output) +{ + uint32_t i; + uint8_t sacchRaw[60]; /* SACCH bits retrieved from RF channel */ + uint8_t sacch[72] = {0}; + uint8_t s0; + uint8_t s1; + uint8_t m_data[5] = {0}; /* SACCH bytes after de-convolution (36 bits) */ + uint8_t CRCComputed = 0; + uint8_t CRCExtracted = 0; + uint32_t index = 0; + uint32_t punctureIndex = 0; + uint8_t temp[90] = {0}; /* SACCH working area */ + //uint8_t RAN = 0; + //uint8_t StructureField = 0; + uint8_t GoodCrc = 0; + + //UNUSED_VARIABLE(sacch[0]); + + /* De-interleave */ + for(i = 0; i < 60; i++) + { + sacchRaw[DSDNXDN_SACCH_m_Interleave[i]] = Input[i]; + } + + /* Un-Punture */ + for (index = 0, punctureIndex = 0, i = 0; i < 60; i++) + { + if (index == (uint32_t)DSDNXDN_SACCH_m_PunctureList[punctureIndex]) + { + temp[index++] = 1; + punctureIndex++; + } + + temp[index++] = sacchRaw[i]<<1; // 0->0, 1->2 + } + + for (i = 0; i < 8; i++) + { + temp[index++] = 0; + } + + /* Convolutional decoding */ + CNXDNConvolution_start(); + for (i = 0U; i < 40U; i++) + { + s0 = temp[(2*i)]; + s1 = temp[(2*i)+1]; + + CNXDNConvolution_decode(s0, s1); + } + + CNXDNConvolution_chainback(m_data, 36U); + + + for(i = 0; i < 4; i++) + { + Output[(i*8)+0] = (m_data[i] >> 7) & 1; + Output[(i*8)+1] = (m_data[i] >> 6) & 1; + Output[(i*8)+2] = (m_data[i] >> 5) & 1; + Output[(i*8)+3] = (m_data[i] >> 4) & 1; + Output[(i*8)+4] = (m_data[i] >> 3) & 1; + Output[(i*8)+5] = (m_data[i] >> 2) & 1; + Output[(i*8)+6] = (m_data[i] >> 1) & 1; + Output[(i*8)+7] = (m_data[i] >> 0) & 1; + } + + /* Extract the 6 bit CRC */ + CRCExtracted = m_data[3] & 0x3F; + + /* Compute the 6 bit CRC */ + CRCComputed = CRC6BitNXDN(Output, 26); + + /* Compute the RAN (6 last bits of the SR Information in the SACCH) */ + //RAN = m_data[0] & 0x3F; + + /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */ + //StructureField = (m_data[0] >> 6) & 0x03; + + //fprintf(stderr, "RAN=%u ; StructureField=%u ; ", RAN, StructureField); + + //fprintf(stderr, "SACCH=0x%02X-0x%02X-0x%02X-0x%02X-0x%02X ; ", + // m_data[0], m_data[1], m_data[2], m_data[3], m_data[4]); + + //fprintf(stderr, "CRC Extracted=0x%02X ; CRC computed=0x%02X ; ", CRCExtracted, CRCComputed); + + /* Check CRCs */ + if(CRCExtracted == CRCComputed) + { + //fprintf(stderr, "OK !\n"); + GoodCrc = 1; + } + else + { + //fprintf(stderr, "ERROR !\n"); + GoodCrc = 0; + } + + return GoodCrc; +} /* NXDN_SACCH_raw_part_decode() */ + + +/* + * @brief : This function decodes the full SACCH (when 4 voice frame parts + * have been successfully received) + * + * @param opts : Option structure parameters pointer + * + * @param state : State structure parameters pointer + * + * @return None + * + */ +void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state) +{ + uint8_t SACCH[72]; + uint32_t i; + uint8_t CrcCorrect = 1; + + /* Consider all SACCH CRC parts as corrects */ + CrcCorrect = 1; + + /* Reconstitute the full 72 bits SACCH */ + for(i = 0; i < 4; i++) + { + memcpy(&SACCH[i * 18], state->NxdnSacchRawPart[i].Data, 18); + + /* Check CRC */ + if(state->NxdnSacchRawPart[i].CrcIsGood == 0) CrcCorrect = 0; + } + + /* Decodes the element content */ + NXDN_Elements_Content_decode(opts, state, CrcCorrect, SACCH); + +} /* End NXDN_SACCH_Full_decode() */ + + +/* + * @brief : This function decodes the RAW part of FACCH1 received when + * each voice frame starts. + * + * @param Input : A 144 bits (144 bytes) buffer pointer of input data + * + * @param Output : A 96 bits (80 bytes data + 12 bytes CRC + 4 bytes "Tail" all "0") buffer where write output data + * + * @return 1 when CRC is good + * 0 when CRC is bad + * + */ +uint8_t NXDN_FACCH1_decode(uint8_t * Input, uint8_t * Output) +{ + uint32_t i; + uint8_t GoodCrc = 0; + uint16_t CRCComputed = 0; + uint16_t CRCExtracted = 0; + uint8_t facch1Raw[144]; /* FACCH1 bits retrieved from RF channel */ + uint8_t s0; + uint8_t s1; + uint8_t m_data[12] = {0}; /* FACCH1 bytes after de-convolution (96 bits) */ + uint32_t index = 0; + uint32_t punctureIndex = 0; + uint8_t temp[210] = {0}; /* FACCH1 working area */ + + /* De-interleave */ + for(i = 0; i < 144; i++) + { + facch1Raw[DSDNXDN_FACCH1_m_Interleave[i]] = Input[i]; + } + + /* Un-Punture */ + for (index = 0, punctureIndex = 0, i = 0; i < 144; i++) + { + if (index == (uint32_t)DSDNXDN_FACCH1_m_PunctureList[punctureIndex]) + { + temp[index++] = 1; + punctureIndex++; + } + + temp[index++] = facch1Raw[i]<<1; // 0->0, 1->2 + } + + for (i = 0; i < 8; i++) + { + temp[index++] = 0; + } + + /* Convolutional decoding */ + CNXDNConvolution_start(); + for (i = 0U; i < 100U; i++) + { + s0 = temp[(2*i)]; + s1 = temp[(2*i)+1]; + + CNXDNConvolution_decode(s0, s1); + } + /* + fprintf (stderr, "\n"); + for (i = 0U; i < 100U; i++) + { + fprintf (stderr, "temp=%X", temp[i]); + } + fprintf (stderr, "\n"); + */ + CNXDNConvolution_chainback(m_data, 96U); + + /* Reconstitute L3 Data (Data 80 bits + CRC 12 bits + 4 tail bits = Total 96 bits = 12 bytes) */ + for(i = 0; i < 12; i++) + { + Output[(i*8)+0] = (m_data[i] >> 7) & 1; + Output[(i*8)+1] = (m_data[i] >> 6) & 1; + Output[(i*8)+2] = (m_data[i] >> 5) & 1; + Output[(i*8)+3] = (m_data[i] >> 4) & 1; + Output[(i*8)+4] = (m_data[i] >> 3) & 1; + Output[(i*8)+5] = (m_data[i] >> 2) & 1; + Output[(i*8)+6] = (m_data[i] >> 1) & 1; + Output[(i*8)+7] = (m_data[i] >> 0) & 1; + } + + /* Extract the 12 bits CRC */ + CRCExtracted = ((uint16_t)(m_data[10] << 4) | (uint16_t)(m_data[11] >> 4)) & 0x0FFF; + + /* Compute the 12 bits CRC */ + CRCComputed = CRC12BitNXDN(Output, 80); + + //fprintf(stderr, "\n"); + + //fprintf(stderr, "SACCH1 Data = "); + //for(i = 0; i < 12; i++) + //{ + // fprintf(stderr, "0x%02X - ", m_data[i]); + //} + //fprintf(stderr, "\n"); + + //fprintf(stderr, "CRC computed = 0x%03X - CRC extracted = 0x%03X\n", CRCComputed, CRCExtracted); + + /* Check CRCs */ + if(CRCExtracted == CRCComputed) + { + //fprintf(stderr, "OK !\n"); + GoodCrc = 1; + } + else + { + //fprintf(stderr, "ERROR !\n"); + GoodCrc = 0; + } + + return GoodCrc; +} /* End NXDN_FACCH1_decode() */ + + + +/* + * @brief : This function decodes the UDCH/FACCH2 received. + * + * @param Input : A 348 bits (348 bytes) buffer pointer of input data + * + * @param Output : A 203 bits (184 bytes data + 15 bytes CRC + 4 bytes "Tail" all "0") buffer where write output data + * + * @return 1 when CRC is good + * 0 when CRC is bad + * + */ +uint8_t NXDN_UDCH_decode(uint8_t * Input, uint8_t * Output) +{ + uint32_t i; + uint8_t GoodCrc = 0; + uint16_t CRCComputed = 0; + uint16_t CRCExtracted = 0; + uint8_t UdchRaw[348]; /* UDCH bits retrieved from RF channel */ + uint8_t s0; + uint8_t s1; + uint8_t m_data[26] = {0}; /* UDCH bytes after de-convolution (203 bits) */ + uint32_t index = 0; + uint32_t punctureIndex = 0; + uint8_t temp[420] = {0}; /* UDCH working area */ + + /* De-interleave */ + for(i = 0; i < 348; i++) + { + UdchRaw[DSDNXDN_UDCH_m_Interleave[i]] = Input[i]; + } + + /* Un-Punture */ + for (index = 0, punctureIndex = 0, i = 0; i < 348; i++) + { + if (index == (uint32_t)DSDNXDN_UDCH_m_PunctureList[punctureIndex]) + { + temp[index++] = 1; + punctureIndex++; + } + + temp[index++] = UdchRaw[i]<<1; // 0->0, 1->2 + } + + for (i = 0; i < 8; i++) + { + temp[index++] = 0; + } + + /* Convolutional decoding */ + CNXDNConvolution_start(); + for (i = 0U; i < 207U; i++) + { + s0 = temp[(2*i)]; + s1 = temp[(2*i)+1]; + + CNXDNConvolution_decode(s0, s1); + } + + CNXDNConvolution_chainback(m_data, 203U); + + /* Reconstitute L3 Data (Data 184 bits + CRC 15 bits + 4 tail bits = Total 203 bits = 26 bytes) */ + for(i = 0; i < 25; i++) + { + Output[(i*8)+0] = (m_data[i] >> 7) & 1; + Output[(i*8)+1] = (m_data[i] >> 6) & 1; + Output[(i*8)+2] = (m_data[i] >> 5) & 1; + Output[(i*8)+3] = (m_data[i] >> 4) & 1; + Output[(i*8)+4] = (m_data[i] >> 3) & 1; + Output[(i*8)+5] = (m_data[i] >> 2) & 1; + Output[(i*8)+6] = (m_data[i] >> 1) & 1; + Output[(i*8)+7] = (m_data[i] >> 0) & 1; + } + /* Get the 3 last bits */ + Output[200] = (m_data[25] >> 7) & 1; + Output[201] = (m_data[25] >> 6) & 1; + Output[202] = (m_data[25] >> 5) & 1; + + /* Extract the 15 bits CRC */ + CRCExtracted = ((uint16_t)(m_data[23] << 7) | (uint16_t)(m_data[24] >> 1)) & 0x7FFF; + + /* Compute the 15 bits CRC */ + CRCComputed = CRC15BitNXDN(Output, 184); + + //fprintf(stderr, "\n"); + + //fprintf(stderr, "FACCH2 Data = "); + //for(i = 0; i < 26; i++) + //{ + // fprintf(stderr, "0x%02X - ", m_data[i]); + //} + //fprintf(stderr, "\n"); + + //fprintf(stderr, "CRC computed = 0x%04X - CRC extracted = 0x%04X\n", CRCComputed, CRCExtracted); + + /* Check CRCs */ + if(CRCExtracted == CRCComputed) + { + //fprintf(stderr, "OK !\n"); + GoodCrc = 1; + } + else + { + //fprintf(stderr, "ERROR !\n"); + GoodCrc = 0; + } + + return GoodCrc; +} /* End NXDN_UDCH_decode() */ + + + +/* + * @brief : This function decodes the content of elements in : + * - Full SACCH (when 4 voice frame parts have been + * successfully received) + * + * @param opts : Option structure parameters pointer + * + * @param state : State structure parameters pointer + * + * @param CrcCorrect : The CRC status of the last element received + * 0 = CRC incorrect + * Oher = CRC correct + * + * @param ElementsContent : A 64 to 144 bits buffer containing the + * element content + * + * @return None + * + */ +void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state, + uint8_t CrcCorrect, uint8_t * ElementsContent) +{ + uint32_t i; + uint8_t MessageType; + uint64_t CurrentIV = 0; + + /* Get the "Message Type" field */ + MessageType = (ElementsContent[2] & 1) << 5; + MessageType |= (ElementsContent[3] & 1) << 4; + MessageType |= (ElementsContent[4] & 1) << 3; + MessageType |= (ElementsContent[5] & 1) << 2; + MessageType |= (ElementsContent[6] & 1) << 1; + MessageType |= (ElementsContent[7] & 1) << 0; + + /* Save the "F1" and "F2" flags */ + state->NxdnElementsContent.F1 = ElementsContent[0]; + state->NxdnElementsContent.F2 = ElementsContent[1]; + + /* Save the "Message Type" field */ + state->NxdnElementsContent.MessageType = MessageType; + + //fprintf(stderr, "Message Type = 0x%02X ", MessageType & 0xFF); + + /* Decode the right "Message Type" */ + switch(MessageType) + { + /* VCALL */ + case NXDN_VCALL: + { + /* Set the CRC state */ + state->NxdnElementsContent.VCallCrcIsGood = CrcCorrect; + + /* Decode the "VCALL" message */ + NXDN_decode_VCALL(opts, state, ElementsContent); + + /* Check the "Cipher Type" and the "Key ID" validity */ + if(CrcCorrect) + { + state->NxdnElementsContent.CipherParameterValidity = 1; + } + else state->NxdnElementsContent.CipherParameterValidity = 0; + break; + } /* End case NXDN_VCALL: */ + + /* VCALL_IV */ + case NXDN_VCALL_IV: + { + /* Set the CRC state */ + state->NxdnElementsContent.VCallIvCrcIsGood = CrcCorrect; + + /* Decode the "VCALL_IV" message */ + NXDN_decode_VCALL_IV(opts, state, ElementsContent); + + if(CrcCorrect) + { + /* CRC is correct, copy the next theorical IV to use directly from the + * received VCALL_IV */ + memcpy(state->NxdnElementsContent.NextIVComputed, state->NxdnElementsContent.IV, 8); + } + else + { + /* CRC is incorrect, compute the next IV to use */ + CurrentIV = 0; + + /* Convert the 8 bytes buffer into a 64 bits integer */ + for(i = 0; i < 8; i++) + { + CurrentIV |= state->NxdnElementsContent.NextIVComputed[i]; + CurrentIV = CurrentIV << 8; + } + + /* Encryption is not supported in the public version, + * so do not compute the next IV */ + } + break; + } /* End case NXDN_VCALL_IV: */ + + /* Unknown Message Type */ + default: + { + fprintf(stderr, "Unknown Message type "); + break; + } + } /* End switch(MessageType) */ + +} /* End NXDN_Elements_Content_decode() */ + + +/* + * @brief : This function decodes the VCALL message + * + * @param opts : Option structure parameters pointer + * + * @param state : State structure parameters pointer + * + * @param Message : A 64 bit buffer containing the VCALL message to decode + * + * @return None + * + */ +void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) +{ + //uint32_t i; + uint8_t CCOption = 0; + uint8_t CallType = 0; + uint8_t VoiceCallOption = 0; + uint16_t SourceUnitID = 0; + uint16_t DestinationID = 0; + uint8_t CipherType = 0; + uint8_t KeyID = 0; + uint8_t DuplexMode[32] = {0}; + uint8_t TransmissionMode[32] = {0}; + + //UNUSED_VARIABLE(opts); + //UNUSED_VARIABLE(state); + //UNUSED_VARIABLE(DuplexMode[0]); + //UNUSED_VARIABLE(TransmissionMode[0]); + + /* Message[0..7] contains : + * - The "F1" and "F2" flags + * - The "Message Type" (already decoded before calling this function) + * + * So no need to decode it a second time + */ + + /* Decode "CC Option" */ + CCOption = (uint8_t)ConvertBitIntoBytes(&Message[8], 8); + state->NxdnElementsContent.CCOption = CCOption; + + /* Decode "Call Type" */ + CallType = (uint8_t)ConvertBitIntoBytes(&Message[16], 3); + state->NxdnElementsContent.CallType = CallType; + + /* Decode "Voice Call Option" */ + VoiceCallOption = (uint8_t)ConvertBitIntoBytes(&Message[19], 5); + state->NxdnElementsContent.VoiceCallOption = VoiceCallOption; + + /* Decode "Source Unit ID" */ + SourceUnitID = (uint16_t)ConvertBitIntoBytes(&Message[24], 16); + state->NxdnElementsContent.SourceUnitID = SourceUnitID; + + /* Decode "Destination ID" */ + DestinationID = (uint16_t)ConvertBitIntoBytes(&Message[40], 16); + state->NxdnElementsContent.DestinationID = DestinationID; + + /* Decode the "Cipher Type" */ + CipherType = (uint8_t)ConvertBitIntoBytes(&Message[56], 2); + state->NxdnElementsContent.CipherType = CipherType; + + /* Decode the "Key ID" */ + KeyID = (uint8_t)ConvertBitIntoBytes(&Message[58], 6); + state->NxdnElementsContent.KeyID = KeyID; + + /* Print the "CC Option" */ + if(CCOption & 0x80) fprintf(stderr, "Emergency "); + if(CCOption & 0x40) fprintf(stderr, "Visitor "); + if(CCOption & 0x20) fprintf(stderr, "Priority Paging "); + + /* On an AES or DES encrypted frame one IV is used on two + * superframe. + * The first superframe contains a VCALL message inside + * the SACCH and the second superframe contains the next IV + * to use. + * + * Set the correct part of encrypted frame flag. + */ + if((CipherType == 2) || (CipherType == 3)) + { + state->NxdnElementsContent.PartOfCurrentEncryptedFrame = 1; + state->NxdnElementsContent.PartOfNextEncryptedFrame = 2; + } + else + { + state->NxdnElementsContent.PartOfCurrentEncryptedFrame = 1; + state->NxdnElementsContent.PartOfNextEncryptedFrame = 1; + } + + /* Print the "Call Type" */ + fprintf(stderr, "%s - ", NXDN_Call_Type_To_Str(CallType)); + + /* Print the "Voice Call Option" */ + NXDN_Voice_Call_Option_To_Str(VoiceCallOption, DuplexMode, TransmissionMode); + fprintf(stderr, "%s %s - ", DuplexMode, TransmissionMode); + + /* Print the "Cipher Type" */ + if(CipherType != 0) fprintf(stderr, "%s - ", NXDN_Cipher_Type_To_Str(CipherType)); + + /* Print the Key ID */ + if(CipherType != 0) fprintf(stderr, "Key ID %u - ", KeyID & 0xFF); + + /* Print Source ID and Destination ID (Talk Group or Unit ID) */ + fprintf(stderr, "Src=%u - Dst/TG=%u ", SourceUnitID & 0xFFFF, DestinationID & 0xFFFF); + + if(state->NxdnElementsContent.VCallCrcIsGood) + { + if ( (SourceUnitID & 0xFFFF) > 0 ) + { + state->nxdn_last_rid = SourceUnitID & 0xFFFF; //only grab if CRC is okay + } + fprintf(stderr, " (OK) - "); + } + //fprintf(stderr, " (OK) - "); + else fprintf(stderr, "(CRC ERR) - "); + + //fprintf(stderr, "\nVCALL = "); + + //for(i = 0; i < 8; i++) + //{ + // fprintf(stderr, "0x%02X, ", ConvertBitIntoBytes(&Message[i * 8], 8) & 0xFF); + //} + //fprintf(stderr, "\n"); + +} /* End NXDN_decode_VCALL() */ + + +/* + * @brief : This function decodes the VCALL_IV message + * + * @param opts : Option structure parameters pointer + * + * @param state : State structure parameters pointer + * + * @param Message : A 72 bit buffer containing the VCALL_IV message to decode + * + * @return None + * + */ +void NXDN_decode_VCALL_IV(dsd_opts * opts, dsd_state * state, uint8_t * Message) +{ + uint32_t i; + + //UNUSED_VARIABLE(opts); + //UNUSED_VARIABLE(state); + + /* Message[0..7] contains : + * - The "F1" and "F2" flags + * - The "Message Type" (already decoded before calling this function) + * + * So no need to decode it a second time + * + * Message[8..71] contains : The 64 bits IV + */ + + /* Extract the IV from the VCALL_IV message */ + for(i = 0; i < 8; i++) + { + state->NxdnElementsContent.IV[i] = (uint8_t)ConvertBitIntoBytes(&Message[(i + 1) * 8], 8); + } + + /* On an AES or DES encrypted frame one IV is used on two + * superframe. + * The first superframe contains a VCALL message inside + * the SACCH and the second superframe contains the next IV + * to use. + * + * Set the correct part of encrypted frame flag. + */ + state->NxdnElementsContent.PartOfCurrentEncryptedFrame = 2; + state->NxdnElementsContent.PartOfNextEncryptedFrame = 1; + +} /* End NXDN_decode_VCALL_IV() */ + + +/* + * @brief : This function decodes the "Call Type" and return the + * ASCII string corresponding to it. + * + * @param CallType : The call type parameter to decode + * + * @return An ASCII string of the "Call Type" + * + */ +char * NXDN_Call_Type_To_Str(uint8_t CallType) +{ + char * Ptr = NULL; + + switch(CallType) + { + case 0: Ptr = "Broadcast Call"; break; + case 1: Ptr = "Group Call"; break; + case 2: Ptr = "Unspecified Call"; break; + case 3: Ptr = "Reserved"; break; + case 4: Ptr = "Individual Call"; break; + case 5: Ptr = "Reserved"; break; + case 6: Ptr = "Interconnect Call"; break; + case 7: Ptr = "Speed Dial Call"; break; + default: Ptr = "Unknown Call Type"; break; + } + + return Ptr; +} /* End NXDN_Call_Type_To_Str() */ + + +/* + * @brief : This function decodes the "Voice Call Option" and return the + * ASCII string corresponding to it. + * + * @param VoiceCallOption : The call type parameter to decode + * + * @param Duplex : A 32 bytes ASCII buffer pointer where store + * the Duplex/Half duplex mode + * + * @param TransmissionMode : A 32 bytes ASCII buffer pointer where store + * the transmission mode (bit rate) + * + * @return An ASCII string of the "Voice Call Option" + * + */ +void NXDN_Voice_Call_Option_To_Str(uint8_t VoiceCallOption, uint8_t * Duplex, uint8_t * TransmissionMode) +{ + char * Ptr = NULL; + + Duplex[0] = 0; + TransmissionMode[0] = 0; + + if(VoiceCallOption & 0x10) strcpy((char *)Duplex, "Duplex"); + else strcpy((char *)Duplex, "Half Duplex"); + + switch(VoiceCallOption & 0x17) + { + case 0: Ptr = "4800bps/EHR"; break; + case 2: Ptr = "9600bps/EHR"; break; + case 3: Ptr = "9600bps/EFR"; break; + default: Ptr = "Reserved Voice Call Option"; break; + } + + strcpy((char *)TransmissionMode, Ptr); +} /* End NXDN_Voice_Call_Option_To_Str() */ + + +/* + * @brief : This function decodes the "Cipher Type" and return the + * ASCII string corresponding to it. + * + * @param CipherType : The cipher type parameter to decode + * + * @return An ASCII string of the "Cipher Type" + * + */ +char * NXDN_Cipher_Type_To_Str(uint8_t CipherType) +{ + char * Ptr = NULL; + + switch(CipherType) + { + case 0: Ptr = ""; break; /* Non-ciphered mode / clear call */ + case 1: Ptr = "Scrambler"; break; + case 2: Ptr = "DES"; break; + case 3: Ptr = "AES"; break; + default: Ptr = "Unknown Cipher Type"; break; + } + + return Ptr; +} /* End NXDN_Cipher_Type_To_Str() */ + + +/* CRC 15 bits computation with the following polynomial : + * X^15 + X^14 + X^11 + X^10 + X^7 + X^6 + X^2 + 1 + * + * X^15 + (1X^14 + 0X^13 + 0X^12 + 1X^11 + 1X^10 + 0X^9 + 0X^8 + 1X^7 + 1X^6 + 0X^5 + 0X^4 + 0X^3 + 1X^2 + 0X^1 + 1X^0) + * => Polynomial = 0b100110011000101 = 0x4CC5 + */ +uint16_t CRC15BitNXDN(uint8_t * BufferIn, uint32_t BitLength) +{ + uint16_t CRC = 0x7FFF; /* Initial value = All bit to '1' (only 15 LSBit are used) */ + uint16_t Polynome = 0x4CC5; /* X^15 + X^14 + X^11 + X^10 + X^7 + X^6 + X^2 + 1 */ + uint32_t i; + + for(i = 0; i < BitLength; i++) + { + if(((CRC >> 14) & 1) ^ (BufferIn[i] & 1)) + { + CRC = ((CRC << 1) ^ Polynome) & 0x7FFF; + } + else + { + CRC = (CRC << 1) & 0x7FFF; + } + } + + return CRC; +} /* End CRC15BitNXDN() */ + + +/* CRC 12 bits computation with the following polynomial : + * X^12 + X^11 + X^3 + X^2 + X + 1 + * + * X^12 + (1X^11 + 0X^10 + 0X^9 + 0X^8 + 0X^7 + 0X^6 + 0X^5 + 0X^4 + 1X^3 + 1X^2 + 1X^1 + 1X^0) + * => Polynomial = 0b100000001111 = 0x80F + */ +uint16_t CRC12BitNXDN(uint8_t * BufferIn, uint32_t BitLength) +{ + uint16_t CRC = 0x0FFF; /* Initial value = All bit to '1' (only 12 LSBit are used) */ + uint16_t Polynome = 0x80F; /* X^12 + X^11 + X^3 + X^2 + X + 1 */ + uint32_t i; + + for(i = 0; i < BitLength; i++) + { + if(((CRC >> 11) & 1) ^ (BufferIn[i] & 1)) + { + CRC = ((CRC << 1) ^ Polynome) & 0x0FFF; + } + else + { + CRC = (CRC << 1) & 0x0FFF; + } + } + + return CRC; +} /* End CRC12BitNXDN() */ + + +/* CRC 6 bit computation with the following + * polynomial : X^6 + X^5 + X^2 + X + 1 + * + * X^6 + (1X^5 + 0X^4 + 0X^3 + 1X^2 + 1X^1 + 1X^0) + * => Polynomial = 0b100111 = 0x27 + */ +uint8_t CRC6BitNXDN(uint8_t * BufferIn, uint32_t BitLength) +{ + uint8_t CRC = 0x3F; /* Initial value = All bit to '1' (only 6 LSBit are used) */ + uint8_t Polynome = 0x27; /* X^6 + X^5 + X^2 + X + 1 */ + uint32_t i; + + for(i = 0; i < BitLength; i++) + { + if(((CRC >> 5) & 1) ^ (BufferIn[i] & 1)) + { + CRC = ((CRC << 1) ^ Polynome) & 0x3F; + } + else + { + CRC = (CRC << 1) & 0x3F; + } + } + + return CRC; +} /* End CRC6BitNXDN() */ + + +/* Scrambler used for NXDN transmission (different of the + * voice encryption scrambler), see NXDN Part1-A Common Air Interface chapter + * 4.6 for the polynomial description. + * It is a X^9 + X^4 + 1 polynomial used as pseudo-random generator */ +void ScrambledNXDNVoiceBit(int * LfsrValue, char * BufferIn, char * BufferOut, int NbOfBitToScramble) +{ + uint32_t i; + uint32_t LFSR; + uint8_t bit; + + /* Load the initial LFSR value + * LFSR = 0x0E4 at starting value */ + LFSR = (uint32_t)*LfsrValue; + + for(i = 0; i < (uint32_t)NbOfBitToScramble; i++) + { + /* Bit 0 of LFSR is used to scramble data */ + BufferOut[i] = (BufferIn[i] ^ (LFSR & 1)) & 1; + + /* Compute bit = X^0 + X^4 */ + bit = ((LFSR & 1) ^ ((LFSR >> 4) & 1)) & 1; + + /* Insert bit on the 9th bit (X^9) */ + LFSR = ((LFSR >> 1) & 0xFF) | ((bit << 8) & 0x100); + } + + *LfsrValue = (int)LFSR; +} /* End ScrambledNXDNVoiceBit() */ + + +void NxdnEncryptionStreamGeneration (dsd_opts* opts, dsd_state* state, uint8_t KeyStream[1664]) +{ + uint32_t i = 0, j = 0, k = 0; + uint32_t LFSR = 0; + uint64_t CurrentIV = 0; + uint64_t NextIV = 0; + uint64_t TempIV = 0; + uint8_t Temp = 0; + + /* Remove compiler warning */ + /* + UNUSED_VARIABLE(opts); + UNUSED_VARIABLE(state); + UNUSED_VARIABLE(i); + UNUSED_VARIABLE(j); + UNUSED_VARIABLE(k); + UNUSED_VARIABLE(LFSR); + UNUSED_VARIABLE(CurrentIV); + UNUSED_VARIABLE(NextIV); + UNUSED_VARIABLE(TempIV); + UNUSED_VARIABLE(Temp); + */ + if((state->NxdnElementsContent.CipherParameterValidity)) + { + //fprintf(stderr, "Scrambler Encryption "); + + /* Scrambler encryption mode */ + if(state->NxdnElementsContent.CipherType == 0x01) + { + /* Encryption not supported in the public version + * Set the keystream to 0 */ + memset(KeyStream, 0, sizeof(uint8_t) * 1664); + + } /* End if(state->NxdnElementsContent.CipherType == 0x01) - Scrambler */ + /* DES Mode */ + else if(state->NxdnElementsContent.CipherType == 0x02) + { + /* Encryption not supported in the public version + * Set the keystream to 0 */ + memset(KeyStream, 0, sizeof(uint8_t) * 1664); + } /* End else if(state->NxdnElementsContent.CipherType == 0x02) - DES mode */ + /* AES Mode */ + else if(state->NxdnElementsContent.CipherType == 0x03) + { + /* Encryption not supported in the public version + * Set the keystream to 0 */ + memset(KeyStream, 0, sizeof(uint8_t) * 1664); + } /* End else if(state->NxdnElementsContent.CipherType == 0x03) - AES mode */ + else + { + /* No encryption required, simply set the keystream to "0" */ + memset(KeyStream, 0, sizeof(uint8_t) * 1664); + } + } + else + { + /* No encryption required or error, simply set the keystream to "0" */ + memset(KeyStream, 0, sizeof(uint8_t) * 1664); + } + +} /* End NxdnEncryptionStreamGeneration() */ + + +/* End of file */ diff --git a/src/nxdn_voice.c b/src/nxdn_voice.c index 7ef59d2..8f7486d 100644 --- a/src/nxdn_voice.c +++ b/src/nxdn_voice.c @@ -1,59 +1,181 @@ #include "dsd.h" #include "nxdn_const.h" -void -processNXDNVoice (dsd_opts * opts, dsd_state * state) +//don't know why this doesn't work right in LEH, need to figure that out for him +//works just fien when ripped from his and into mine +//must be some random thing, I'll look at his when I have a chance +void processNXDNVoice (dsd_opts * opts, dsd_state * state) { int i, j, dibit; char ambe_fr[4][24]; + unsigned char sacch_raw[72] = {0}; + unsigned char sacch_decoded[32] = {0}; /* 26 bit + 6 bit CRC */ const int *w, *x, *y, *z; - const char *pr; + unsigned char *pr; + uint8_t CrcIsGood = 0; + uint8_t StructureField = 0; + uint8_t RAN = 0; + uint8_t PartOfFrame = 0; + uint8_t KeyStream[1664] = {0}; + char ambe7bytesArray[7] = {0}; + int PartOfEncryptedSuperFrame = 0; if (opts->errorbars == 1) - { - fprintf (stderr,"VOICE e:"); - } + { + fprintf(stderr, "VOICE - "); + } + /* Start pseudo-random NXDN sequence after + * LITCH = 16 bit = 8 dibit + * ==> Index 8 */ + pr = (unsigned char *)(&nxdnpr2[8]); for (i = 0; i < 30; i++) + { + dibit = getDibit (opts, state); + + /* Store and de-interleave directly SACCH bits */ + sacch_raw[(2*i)] = ((*pr) & 1) ^ (1 & (dibit >> 1)); // bit 1 + sacch_raw[(2*i)+1] = (1 & dibit); // bit 0 + +// TODO : Deinterleave is done in the "NXDN_SACCH_decode" function +// /* Store and de-interleave directly SACCH bits */ +// sacch_raw[nsW[2*i]] = *pr ^ (1 & (dibit >> 1)); // bit 1 +// sacch_raw[nsW[2*i+1]] = (1 & dibit); // bit 0 + pr++; +#ifdef NXDN_DUMP + fprintf(stderr, "%c", dibit + 48); +#endif + } +#ifdef NXDN_DUMP + fprintf(stderr, " "); +#endif + +// TODO : Unpuncture is done in the "NXDN_SACCH_decode" function +// /* For the sake of simplicity, handle the re-insertion of punctured bits here. +// * This makes the actual Viterbi decoder code a LOT simpler. */ +// for (i = 30; i < 36; i++) +// { +// sacch_raw[nsW[2*i]] = 0; +// sacch_raw[nsW[2*i+1]] = 0; +// } + + /* Decode the SACCH fields */ + CrcIsGood = NXDN_SACCH_raw_part_decode(sacch_raw, sacch_decoded); + StructureField = (sacch_decoded[0]<<1 | sacch_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */ + RAN = (sacch_decoded[2]<<5 | sacch_decoded[3]<<4 | sacch_decoded[4]<<3 | sacch_decoded[5]<<2 | sacch_decoded[6]<<1 | sacch_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the SACCH) */ + + /* Compute the Part of Frame according to the structure field */ + if (StructureField == 3) PartOfFrame = 0; + else if(StructureField == 2) PartOfFrame = 1; + else if(StructureField == 1) PartOfFrame = 2; + else if(StructureField == 0) PartOfFrame = 3; + else PartOfFrame = 0; /* Normally we should never go here */ + + /* Fill the SACCH structure */ + state->NxdnSacchRawPart[PartOfFrame].CrcIsGood = CrcIsGood; + state->NxdnSacchRawPart[PartOfFrame].StructureField = StructureField; + state->NxdnSacchRawPart[PartOfFrame].RAN = RAN; + memcpy(state->NxdnSacchRawPart[PartOfFrame].Data, &sacch_decoded[8], 18); /* Copy the 18 bits of SACCH content */ + + //fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); + //if(CrcIsGood) fprintf(stderr, " (OK) - "); + if(CrcIsGood) + { + fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); + fprintf (stderr, " (OK) - "); + state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead + } + else fprintf(stderr, "(CRC ERR) - "); + + /* Generate the key stream */ + NxdnEncryptionStreamGeneration(opts, state, KeyStream); + + //fprintf(stderr, "\nKeyStream = "); + //for(i = 0; i < 49; i++) fprintf(stderr, "%d", KeyStream[i]); + //fprintf(stderr, "\n"); + + + /* Determine the current part of superframe + * (in an AES or DES encrypted frame, two superframes + * are used with the same IV, so to decipher the sound + * correctly we must know the current superframe part) */ + if(state->NxdnElementsContent.PartOfNextEncryptedFrame == 1) PartOfEncryptedSuperFrame = 0; + else if(state->NxdnElementsContent.PartOfNextEncryptedFrame == 2) PartOfEncryptedSuperFrame = 1; + else PartOfEncryptedSuperFrame = 0; + + /* Decode the SACCH only when all 4 voice frame + * SACCH spare parts have been received */ + if(PartOfFrame == 3) + { + /* Decode the entire SACCH content */ + NXDN_SACCH_Full_decode(opts, state); + } + + + if (opts->errorbars == 1) + { + fprintf(stderr, "e:"); + } + + /* Start pseudo-random NXDN sequence after + * LITCH = 16 bit = 8 dibit + + * SACCH = 60 bit = 30 dibit + * = 76 bit = 38 dibit + * ==> Index 38 */ + pr = (unsigned char *)(&nxdnpr2[38]); + for (j = 0; j < 4; j++) + { + w = nW; + x = nX; + y = nY; + z = nZ; + for (i = 0; i < 36; i++) { dibit = getDibit (opts, state); #ifdef NXDN_DUMP - fprintf (stderr,"%c", dibit + 48); -#endif - } -#ifdef NXDN_DUMP - fprintf (stderr," "); + fprintf(stderr, "%c", dibit + 48); #endif + ambe_fr[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1 + pr++; + ambe_fr[*y][*z] = (1 & dibit); // bit 0 - pr = nxdnpr; - for (j = 0; j < 4; j++) - { - w = nW; - x = nX; - y = nY; - z = nZ; - for (i = 0; i < 36; i++) - { - dibit = getDibit (opts, state); -#ifdef NXDN_DUMP - fprintf (stderr,"%c", dibit + 48); -#endif - ambe_fr[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1 - pr++; - ambe_fr[*y][*z] = (1 & dibit); // bit 0 - w++; - x++; - y++; - z++; - } - processMbeFrame (opts, state, NULL, ambe_fr, NULL); -#ifdef NXDN_DUMP - fprintf (stderr," "); -#endif + w++; + x++; + y++; + z++; } + //processMbeFrame (opts, state, NULL, ambe_fr, NULL); + processMbeFrameEncrypted(opts, state, NULL, ambe_fr, NULL, (char *)&KeyStream[(PartOfEncryptedSuperFrame * 4 * 4 * 49) + (PartOfFrame * 4 * 49) + (j * 49)], NULL); + + +#ifdef BUILD_DSD_WITH_FRAME_CONTENT_DISPLAY + if(state->printNXDNAmbeVoiceSampleHex) + { + /* Display AMBE frame content */ + /* Convert the 49 bit AMBE frame into 7 bytes */ + Convert49BitSampleInto7Bytes(state->ambe_deciphered, ambe7bytesArray); + fprintf(stderr, "\nVoice Frame %d/4 : ", j + 1); + fprintf(stderr, "E1 = %d ; E2 = %d ; Content = ", state->errs, state->errs2); + for(i = 0; i < 7; i++) fprintf(stderr, "0x%02X, ", ambe7bytesArray[i] & 0xFF); + //fprintf(stderr, "\n"); + } +#endif /* BUILD_DSD_WITH_FRAME_CONTENT_DISPLAY */ + +#ifdef NXDN_DUMP + fprintf(stderr, " "); +#endif + } /* End for (j = 0; j < 4; j++) */ if (opts->errorbars == 1) - { - fprintf (stderr,"\n"); - } -} + { + fprintf(stderr, "\n"); + } + + /* Reset the SACCH CRCs when all 4 voice frame + * SACCH spare parts have been received */ + if(PartOfFrame == 3) + { + /* Reset all CRCs of the SACCH */ + for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0; + } +} /* End processNXDNVoice() */ diff --git a/src/nxdn_voice.c.bkp3 b/src/nxdn_voice.c.bkp3 new file mode 100644 index 0000000..3c79ef4 --- /dev/null +++ b/src/nxdn_voice.c.bkp3 @@ -0,0 +1,118 @@ +#include "dsd.h" +#include "nxdn_const.h" + +void +processNXDNVoice (dsd_opts * opts, dsd_state * state) +{ + int i, j, dibit, k, l; + char ambe_fr[4][24]; + const int *w, *x, *y, *z; + const char *pr; + //borrow from LEH data + unsigned char sacch_raw[72] = {0}; + unsigned char sacch_decoded[32] = {0}; /* 26 bit + 6 bit CRC */ + unsigned char *pr2; //change this to pr2 to differentiate + uint8_t CrcIsGood = 0; + uint8_t StructureField = 0; + uint8_t RAN = 0; + uint8_t PartOfFrame = 0; + + if (opts->errorbars == 1) + { + fprintf (stderr,"VOICE e:"); + } + + for (i = 0; i < 30; i++) + { + dibit = getDibit (opts, state); +#ifdef NXDN_DUMP + fprintf (stderr,"%c", dibit + 48); +#endif + } +#ifdef NXDN_DUMP + fprintf (stderr," "); +#endif + + pr = nxdnpr; + pr2 = (unsigned char *)(&nxdnpr2[8]); //from LEH data + + for (j = 0; j < 4; j++) + { + w = nW; + x = nX; + y = nY; + z = nZ; + for (i = 0; i < 36; i++) + { + dibit = getDibit (opts, state); + //fprintf (stderr,"%c", dibit + 48); //remove later + if (i < 30){ + sacch_raw[(2*i)] = ((*pr2) & 1) ^ (1 & (dibit >> 1)); // bit 1 + sacch_raw[(2*i)+1] = (1 & dibit); // bit 0 + } + +#ifdef NXDN_DUMP + fprintf (stderr,"%c", dibit + 48); +#endif + ambe_fr[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1 + pr++; + ambe_fr[*y][*z] = (1 & dibit); // bit 0 + w++; + x++; + y++; + z++; + } + processMbeFrame (opts, state, NULL, ambe_fr, NULL); + //from LEH data + /* Decode the SACCH fields */ + CrcIsGood = NXDN_SACCH_raw_part_decode(sacch_raw, sacch_decoded); + StructureField = (sacch_decoded[0]<<1 | sacch_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */ + RAN = (sacch_decoded[2]<<5 | sacch_decoded[3]<<4 | sacch_decoded[4]<<3 | sacch_decoded[5]<<2 | sacch_decoded[6]<<1 | sacch_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the SACCH) */ + + /* Compute the Part of Frame according to the structure field */ + if (StructureField == 3) PartOfFrame = 0; + else if(StructureField == 2) PartOfFrame = 1; + else if(StructureField == 1) PartOfFrame = 2; + else if(StructureField == 0) PartOfFrame = 3; + else PartOfFrame = 0; /* Normally we should never go here */ + + /* Fill the SACCH structure */ + state->NxdnSacchRawPart[PartOfFrame].CrcIsGood = CrcIsGood; + state->NxdnSacchRawPart[PartOfFrame].StructureField = StructureField; + state->NxdnSacchRawPart[PartOfFrame].RAN = RAN; + + memcpy(state->NxdnSacchRawPart[PartOfFrame].Data, &sacch_decoded[8], 18); /* Copy the 18 bits of SACCH content */ + + //fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); + if(CrcIsGood) + { + //fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); + //fprintf (stderr, " (OK) - "); + state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead + } + + else fprintf (stderr, "(CRC ERR) - "); + + if(PartOfFrame == 3) + { + /* Decode the entire SACCH content */ + NXDN_SACCH_Full_decode(opts, state); + } + + /* Reset the SACCH CRCs when all 4 voice frame + * SACCH spare parts have been received */ + if(PartOfFrame == 3) + { + /* Reset all CRCs of the SACCH */ + for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0; + } +#ifdef NXDN_DUMP + fprintf (stderr," "); +#endif + } + //fprintf (stderr, "\nV%c\n%c\n", ambe_fr, pr); + if (opts->errorbars == 1) + { + fprintf (stderr,"\n"); + } +} diff --git a/src/nxdnconvolution.c b/src/nxdnconvolution.c new file mode 100644 index 0000000..082103b --- /dev/null +++ b/src/nxdnconvolution.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2009-2016,2018 by Jonathan Naylor G4KLX + * + * Copyright (C) 2018 by Edouard Griffiths F4EXB: + * - Cosmetic changes to integrate with DSDcc + * + * Copyright (C) 2018 by Louis HERVE F4HUZ: + * - Transform C++ lib into C lib to integrate with DSD + * + * 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; either version 2 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* Include ------------------------------------------------------------------*/ +//#include "nxdnconvolution.h" + +#include +//#include +#include +#include +#include +#include + + +/* Define -------------------------------------------------------------------*/ + + +/* Global variables ---------------------------------------------------------*/ +static const uint8_t CNXDNConvolution_BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | CNXDNConvolution_BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~CNXDNConvolution_BIT_MASK_TABLE[(i)&7]) +#define READ_BIT1(p,i) (p[(i)>>3] & CNXDNConvolution_BIT_MASK_TABLE[(i)&7]) + +static const uint8_t CNXDNConvolution_BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U}; +static const uint8_t CNXDNConvolution_BRANCH_TABLE2[] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U}; + +static const unsigned int CNXDNConvolution_NUM_OF_STATES_D2 = 8U; +static const unsigned int CNXDNConvolution_NUM_OF_STATES = 16U; +static const uint32_t CNXDNConvolution_M = 4U; +static const unsigned int CNXDNConvolution_K = 5U; + +static uint16_t m_metrics1[16U] = {0}; +static uint16_t m_metrics2[16U] = {0}; +static uint64_t m_decisions[300U] = {0}; +static uint16_t * m_oldMetrics = NULL; +static uint16_t * m_newMetrics = NULL; +static uint64_t * m_dp = NULL; + + +/* Functions ----------------------------------------------------------------*/ + +void CNXDNConvolution_start(void) +{ + memset(m_metrics1, 0x00U, CNXDNConvolution_NUM_OF_STATES * sizeof(uint16_t)); + memset(m_metrics2, 0x00U, CNXDNConvolution_NUM_OF_STATES * sizeof(uint16_t)); + + m_oldMetrics = m_metrics1; + m_newMetrics = m_metrics2; + m_dp = m_decisions; +} + + +void CNXDNConvolution_decode(uint8_t s0, uint8_t s1) +{ + uint8_t i = 0; + uint8_t j = 0; + uint8_t decision0 = 0; + uint8_t decision1 = 0; + uint16_t metric = 0; + uint16_t m0 = 0; + uint16_t m1 = 0; + uint16_t * tmp = NULL; + + *m_dp = 0U; + + for (i = 0U; i < CNXDNConvolution_NUM_OF_STATES_D2; i++) + { + j = i * 2U; + + metric = abs(CNXDNConvolution_BRANCH_TABLE1[i] - s0) + abs(CNXDNConvolution_BRANCH_TABLE2[i] - s1); + + m0 = m_oldMetrics[i] + metric; + m1 = m_oldMetrics[i + CNXDNConvolution_NUM_OF_STATES_D2] + (CNXDNConvolution_M - metric); + decision0 = (m0 >= m1) ? 1U : 0U; + m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0; + + m0 = m_oldMetrics[i] + (CNXDNConvolution_M - metric); + m1 = m_oldMetrics[i + CNXDNConvolution_NUM_OF_STATES_D2] + metric; + decision1 = (m0 >= m1) ? 1U : 0U; + m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0; + + *m_dp |= ((uint64_t)(decision1) << (j + 1U)) | ((uint64_t)(decision0) << (j + 0U)); + } + + ++m_dp; + + //assert((m_dp - m_decisions) <= 300); + + tmp = m_oldMetrics; + m_oldMetrics = m_newMetrics; + m_newMetrics = tmp; +} + +void CNXDNConvolution_chainback(unsigned char* out, unsigned int nBits) +{ + //assert(out != 0); + + uint32_t state = 0U; + uint32_t i = 0; + uint8_t bit = 0; + + while (nBits-- > 0) + { + --m_dp; + + i = state >> (9 - CNXDNConvolution_K); + bit = (uint8_t)(*m_dp >> i) & 1; + state = (bit << 7) | (state >> 1); + + WRITE_BIT1(out, nBits, bit != 0U); + } +} + +void CNXDNConvolution_encode(const unsigned char* in, unsigned char* out, unsigned int nBits) +{ + //assert(in != 0); + //assert(out != 0); + //assert(nBits > 0U); + + uint8_t g1 = 0U; + uint8_t g2 = 0U; + uint8_t d = 0U; + uint8_t d1 = 0U; + uint8_t d2 = 0U; + uint8_t d3 = 0U; + uint8_t d4 = 0U; + uint32_t k = 0U; + unsigned int i = 0U; + + for (i = 0U; i < nBits; i++) + { + d = READ_BIT1(in, i) ? 1U : 0U; + + g1 = (d + d3 + d4) & 1; + g2 = (d + d1 + d2 + d4) & 1; + + d4 = d3; + d3 = d2; + d2 = d1; + d1 = d; + + WRITE_BIT1(out, k, g1 != 0U); + k++; + + WRITE_BIT1(out, k, g2 != 0U); + k++; + } +} + From 409321eb43afbb5d8f287a9aa163925db808b664 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 05:55:13 -0500 Subject: [PATCH 02/14] NCurses wide support and cmake NCurses wide support and cmake --- cmake/FindCURSES.cmake | 288 +++++++++++++++++++++++++++++++++++-- cmake/FindCURSES.cmake.bkp | 16 +++ src/dsd_main.c | 2 + src/dsd_ncurses.c | 27 ++-- src/rtl_sdr_fm.cpp | 3 +- 5 files changed, 313 insertions(+), 23 deletions(-) create mode 100644 cmake/FindCURSES.cmake.bkp diff --git a/cmake/FindCURSES.cmake b/cmake/FindCURSES.cmake index 29818ba..bfa1d6f 100644 --- a/cmake/FindCURSES.cmake +++ b/cmake/FindCURSES.cmake @@ -1,16 +1,276 @@ -# - Try to find NCURSES -# Once done this will define -# -# ITPP_FOUND - System has ITPP -# ITPP_INCLUDE_DIR - The ITPP include directory -# ITPP_LIBRARY - The library needed to use ITPP -# -set(CURSES_LIBRARY "/opt/lib/libncurses.so") -set(CURSES_INCLUDE_PATH "/opt/include") -find_path(CURSES_INCLUDE_DIR /usr/ncurses.h) +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. -set(CURSES_NAMES ${CURSES_NAMES} curses.h curses curses5w curses6w curses6 curses5 libncursesw) -FIND_LIBRARY(CURSES_LIBRARY NAMES ${CURSES_NAMES}) +#[=======================================================================[.rst: +FindCurses +---------- -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(CURSES DEFAULT_MSG NCURSES_LIBRARY CURSES_INCLUDE_DIR) +Find the curses or ncurses include file and library. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +``CURSES_FOUND`` + True if Curses is found. +``CURSES_INCLUDE_DIRS`` + The include directories needed to use Curses. +``CURSES_LIBRARIES`` + The libraries needed to use Curses. +``CURSES_CFLAGS`` + .. versionadded:: 3.16 + + Parameters which ought be given to C/C++ compilers when using Curses. +``CURSES_HAVE_CURSES_H`` + True if curses.h is available. +``CURSES_HAVE_NCURSES_H`` + True if ncurses.h is available. +``CURSES_HAVE_NCURSES_NCURSES_H`` + True if ``ncurses/ncurses.h`` is available. +``CURSES_HAVE_NCURSES_CURSES_H`` + True if ``ncurses/curses.h`` is available. + +Set ``CURSES_NEED_NCURSES`` to ``TRUE`` before the +``find_package(Curses)`` call if NCurses functionality is required. + +.. versionadded:: 3.10 + Set ``CURSES_NEED_WIDE`` to ``TRUE`` before the + ``find_package(Curses)`` call if unicode functionality is required. + +Backward Compatibility +^^^^^^^^^^^^^^^^^^^^^^ + +The following variable are provided for backward compatibility: + +``CURSES_INCLUDE_DIR`` + Path to Curses include. Use ``CURSES_INCLUDE_DIRS`` instead. +``CURSES_LIBRARY`` + Path to Curses library. Use ``CURSES_LIBRARIES`` instead. +#]=======================================================================] + +include(${CMAKE_CURRENT_LIST_DIR}/CheckLibraryExists.cmake) + +# we don't know anything about cursesw, so only ncurses +# may be ncursesw +if(NOT CURSES_NEED_WIDE) + set(NCURSES_LIBRARY_NAME "ncurses") + set(CURSES_FORM_LIBRARY_NAME "form") +else() + set(NCURSES_LIBRARY_NAME "ncursesw") + set(CURSES_FORM_LIBRARY_NAME "formw") + # Also, if we are searching for wide curses - we are actually searching + # for ncurses, we don't know about any other unicode version. + set(CURSES_NEED_NCURSES TRUE) +endif() + +find_library(CURSES_CURSES_LIBRARY NAMES curses) + +find_library(CURSES_NCURSES_LIBRARY NAMES "${NCURSES_LIBRARY_NAME}" ) +set(CURSES_USE_NCURSES FALSE) + +if(CURSES_NCURSES_LIBRARY AND ((NOT CURSES_CURSES_LIBRARY) OR CURSES_NEED_NCURSES)) + set(CURSES_USE_NCURSES TRUE) +endif() +# http://cygwin.com/ml/cygwin-announce/2010-01/msg00002.html +# cygwin ncurses stopped providing curses.h symlinks see above +# message. Cygwin is an ncurses package, so force ncurses on +# cygwin if the curses.h is missing +if(CURSES_NCURSES_LIBRARY AND CYGWIN) + if (CURSES_NEED_WIDE) + if(NOT EXISTS /usr/include/ncursesw/curses.h) + set(CURSES_USE_NCURSES TRUE) + endif() + else() + if(NOT EXISTS /usr/include/curses.h) + set(CURSES_USE_NCURSES TRUE) + endif() + endif() +endif() + + +# Not sure the logic is correct here. +# If NCurses is required, use the function wsyncup() to check if the library +# has NCurses functionality (at least this is where it breaks on NetBSD). +# If wsyncup is in curses, use this one. +# If not, try to find ncurses and check if this has the symbol. +# Once the ncurses library is found, search the ncurses.h header first, but +# some web pages also say that even with ncurses there is not always a ncurses.h: +# http://osdir.com/ml/gnome.apps.mc.devel/2002-06/msg00029.html +# So at first try ncurses.h, if not found, try to find curses.h under the same +# prefix as the library was found, if still not found, try curses.h with the +# default search paths. +if(CURSES_CURSES_LIBRARY AND CURSES_NEED_NCURSES) + include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET ${Curses_FIND_QUIETLY}) + CHECK_LIBRARY_EXISTS("${CURSES_CURSES_LIBRARY}" + wsyncup "" CURSES_CURSES_HAS_WSYNCUP) + + if(CURSES_NCURSES_LIBRARY AND NOT CURSES_CURSES_HAS_WSYNCUP) + CHECK_LIBRARY_EXISTS("${CURSES_NCURSES_LIBRARY}" + wsyncup "" CURSES_NCURSES_HAS_WSYNCUP) + if( CURSES_NCURSES_HAS_WSYNCUP) + set(CURSES_USE_NCURSES TRUE) + endif() + endif() + cmake_pop_check_state() + +endif() + +if(CURSES_USE_NCURSES) + get_filename_component(_cursesLibDir "${CURSES_NCURSES_LIBRARY}" PATH) + get_filename_component(_cursesParentDir "${_cursesLibDir}" PATH) + + # Use CURSES_NCURSES_INCLUDE_PATH if set, for compatibility. + if(CURSES_NCURSES_INCLUDE_PATH) + if (CURSES_NEED_WIDE) + find_path(CURSES_INCLUDE_PATH + NAMES ncursesw/ncurses.h ncursesw/curses.h ncursesw.h cursesw.h + PATHS ${CURSES_NCURSES_INCLUDE_PATH} + NO_DEFAULT_PATH + ) + else() + find_path(CURSES_INCLUDE_PATH + NAMES ncurses/ncurses.h ncurses/curses.h ncurses.h curses.h + PATHS ${CURSES_NCURSES_INCLUDE_PATH} + NO_DEFAULT_PATH + ) + endif() + endif() + + if (CURSES_NEED_WIDE) + set(CURSES_TINFO_LIBRARY_NAME tinfow) + find_path(CURSES_INCLUDE_PATH + NAMES ncursesw/ncurses.h ncursesw/curses.h ncursesw.h cursesw.h + HINTS "${_cursesParentDir}/include" + ) + else() + set(CURSES_TINFO_LIBRARY_NAME tinfo) + find_path(CURSES_INCLUDE_PATH + NAMES ncurses/ncurses.h ncurses/curses.h ncurses.h curses.h + HINTS "${_cursesParentDir}/include" + ) + endif() + + # Previous versions of FindCurses provided these values. + if(NOT DEFINED CURSES_LIBRARY) + set(CURSES_LIBRARY "${CURSES_NCURSES_LIBRARY}") + endif() + + CHECK_LIBRARY_EXISTS("${CURSES_NCURSES_LIBRARY}" + cbreak "" CURSES_NCURSES_HAS_CBREAK) + CHECK_LIBRARY_EXISTS("${CURSES_NCURSES_LIBRARY}" + nodelay "" CURSES_NCURSES_HAS_NODELAY) + if(NOT CURSES_NCURSES_HAS_CBREAK OR NOT CURSES_NCURSES_HAS_NODELAY) + find_library(CURSES_EXTRA_LIBRARY "${CURSES_TINFO_LIBRARY_NAME}" HINTS "${_cursesLibDir}") + find_library(CURSES_EXTRA_LIBRARY "${CURSES_TINFO_LIBRARY_NAME}" ) + + mark_as_advanced( + CURSES_EXTRA_LIBRARY + ) + endif() +else() + get_filename_component(_cursesLibDir "${CURSES_CURSES_LIBRARY}" PATH) + get_filename_component(_cursesParentDir "${_cursesLibDir}" PATH) + + #We can't find anything with CURSES_NEED_WIDE because we know + #only about ncursesw unicode curses version + if(NOT CURSES_NEED_WIDE) + find_path(CURSES_INCLUDE_PATH + NAMES curses.h + HINTS "${_cursesParentDir}/include" + ) + endif() + + # Previous versions of FindCurses provided these values. + if(NOT DEFINED CURSES_CURSES_H_PATH) + set(CURSES_CURSES_H_PATH "${CURSES_INCLUDE_PATH}") + endif() + if(NOT DEFINED CURSES_LIBRARY) + set(CURSES_LIBRARY "${CURSES_CURSES_LIBRARY}") + endif() +endif() + +# Report whether each possible header name exists in the include directory. +if(NOT DEFINED CURSES_HAVE_NCURSES_NCURSES_H) + if(CURSES_NEED_WIDE) + if(EXISTS "${CURSES_INCLUDE_PATH}/ncursesw/ncurses.h") + set(CURSES_HAVE_NCURSES_NCURSES_H "${CURSES_INCLUDE_PATH}/ncursesw/ncurses.h") + endif() + elseif(EXISTS "${CURSES_INCLUDE_PATH}/ncurses/ncurses.h") + set(CURSES_HAVE_NCURSES_NCURSES_H "${CURSES_INCLUDE_PATH}/ncurses/ncurses.h") + endif() + if(NOT DEFINED CURSES_HAVE_NCURSES_NCURSES_H) + set(CURSES_HAVE_NCURSES_NCURSES_H "CURSES_HAVE_NCURSES_NCURSES_H-NOTFOUND") + endif() +endif() +if(NOT DEFINED CURSES_HAVE_NCURSES_CURSES_H) + if(CURSES_NEED_WIDE) + if(EXISTS "${CURSES_INCLUDE_PATH}/ncursesw/curses.h") + set(CURSES_HAVE_NCURSES_CURSES_H "${CURSES_INCLUDE_PATH}/ncursesw/curses.h") + endif() + elseif(EXISTS "${CURSES_INCLUDE_PATH}/ncurses/curses.h") + set(CURSES_HAVE_NCURSES_CURSES_H "${CURSES_INCLUDE_PATH}/ncurses/curses.h") + endif() + if(NOT DEFINED CURSES_HAVE_NCURSES_CURSES_H) + set(CURSES_HAVE_NCURSES_CURSES_H "CURSES_HAVE_NCURSES_CURSES_H-NOTFOUND") + endif() +endif() +if(NOT CURSES_NEED_WIDE) + #ncursesw can't be found for this paths + if(NOT DEFINED CURSES_HAVE_NCURSES_H) + if(EXISTS "${CURSES_INCLUDE_PATH}/ncurses.h") + set(CURSES_HAVE_NCURSES_H "${CURSES_INCLUDE_PATH}/ncurses.h") + else() + set(CURSES_HAVE_NCURSES_H "CURSES_HAVE_NCURSES_H-NOTFOUND") + endif() + endif() + if(NOT DEFINED CURSES_HAVE_CURSES_H) + if(EXISTS "${CURSES_INCLUDE_PATH}/curses.h") + set(CURSES_HAVE_CURSES_H "${CURSES_INCLUDE_PATH}/curses.h") + else() + set(CURSES_HAVE_CURSES_H "CURSES_HAVE_CURSES_H-NOTFOUND") + endif() + endif() +endif() + +find_library(CURSES_FORM_LIBRARY "${CURSES_FORM_LIBRARY_NAME}" HINTS "${_cursesLibDir}") +find_library(CURSES_FORM_LIBRARY "${CURSES_FORM_LIBRARY_NAME}" ) + +# Previous versions of FindCurses provided these values. +if(NOT DEFINED FORM_LIBRARY) + set(FORM_LIBRARY "${CURSES_FORM_LIBRARY}") +endif() + +# Need to provide the *_LIBRARIES +set(CURSES_LIBRARIES ${CURSES_LIBRARY}) + +if(CURSES_EXTRA_LIBRARY) + set(CURSES_LIBRARIES ${CURSES_LIBRARIES} ${CURSES_EXTRA_LIBRARY}) +endif() + +if(CURSES_FORM_LIBRARY) + set(CURSES_LIBRARIES ${CURSES_LIBRARIES} ${CURSES_FORM_LIBRARY}) +endif() + +# Provide the *_INCLUDE_DIRS and *_CFLAGS results. +set(CURSES_INCLUDE_DIRS ${CURSES_INCLUDE_PATH}) +set(CURSES_INCLUDE_DIR ${CURSES_INCLUDE_PATH}) # compatibility + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(NCURSES QUIET ${NCURSES_LIBRARY_NAME}) + set(CURSES_CFLAGS ${NCURSES_CFLAGS_OTHER}) +endif() + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Curses DEFAULT_MSG + CURSES_LIBRARY CURSES_INCLUDE_PATH) + +mark_as_advanced( + CURSES_INCLUDE_PATH + CURSES_CURSES_LIBRARY + CURSES_NCURSES_LIBRARY + CURSES_FORM_LIBRARY + ) diff --git a/cmake/FindCURSES.cmake.bkp b/cmake/FindCURSES.cmake.bkp new file mode 100644 index 0000000..29818ba --- /dev/null +++ b/cmake/FindCURSES.cmake.bkp @@ -0,0 +1,16 @@ +# - Try to find NCURSES +# Once done this will define +# +# ITPP_FOUND - System has ITPP +# ITPP_INCLUDE_DIR - The ITPP include directory +# ITPP_LIBRARY - The library needed to use ITPP +# +set(CURSES_LIBRARY "/opt/lib/libncurses.so") +set(CURSES_INCLUDE_PATH "/opt/include") +find_path(CURSES_INCLUDE_DIR /usr/ncurses.h) + +set(CURSES_NAMES ${CURSES_NAMES} curses.h curses curses5w curses6w curses6 curses5 libncursesw) +FIND_LIBRARY(CURSES_LIBRARY NAMES ${CURSES_NAMES}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CURSES DEFAULT_MSG NCURSES_LIBRARY CURSES_INCLUDE_DIR) diff --git a/src/dsd_main.c b/src/dsd_main.c index 4bc11b4..3e20d69 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -557,6 +557,8 @@ sigfun (int sig) { exitflag = 1; signal (SIGINT, SIG_DFL); + ncursesClose (); + #ifdef USE_RTLSDR rtlsdr_sighandler(); #endif diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index d45a523..9371579 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -37,6 +37,7 @@ unsigned long long sr_4 = 0; // unsigned long long sr_5 = 0; // unsigned long long sr_6 = 0; // */ +char c; //getch key int tg; //last tg int rd; //last rid int rn; //last ran @@ -103,7 +104,7 @@ char * getTimeN(void) //get pretty hh:mm:ss timestamp void ncursesOpen () { mbe_printVersion (versionstr); - //setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); initscr(); //Initialize NCURSES screen window start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style @@ -131,15 +132,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) level = 0; //start each cycle with 0 erase(); //disabling until wide support can be built for LM, etc. $(ncursesw5-config --cflags --libs) - //printw ("%s \n", FM_bannerN[0]); //top line in white + printw ("%s \n", FM_bannerN[0]); //top line in white attron(COLOR_PAIR(4)); - //for (short int i = 1; i < 7; i++) - //{ //following lines in cyan - //printw("%s \n", FM_bannerN[i]); - //} + for (short int i = 1; i < 7; i++) //following lines in cyan + { + printw("%s \n", FM_bannerN[i]); + } attroff(COLOR_PAIR(4)); printw ("--Build Info------------------------------------------------------------------\n"); - //printw ("| %s \n", FM_bannerN[7]); //http link + printw ("| %s \n", FM_bannerN[7]); //http link printw ("| Digital Speech Decoder: Florida Man Edition\n"); printw ("| Github Build Version: %s \n", GIT_TAG); printw ("| mbelib version %s\n", versionstr); @@ -431,7 +432,17 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //printw ("%s %s\n", state->ftype, state->fsubtype); //some ftype strings have extra spaces in them //if (state->lastsynctype != -1) //is there a synctype 0? - + //while((c = getch()) != '~') { + // printw ("%c\n",c);} + //c = getch(); + /* + if (c = getch() != '~') + { + printf ("%c\n",c); + printf ("closing NCurses"); + ncursesClose(); + } + */ //debug sr printw if (1==2) //disable this later on { diff --git a/src/rtl_sdr_fm.cpp b/src/rtl_sdr_fm.cpp index a5989f4..1c84320 100644 --- a/src/rtl_sdr_fm.cpp +++ b/src/rtl_sdr_fm.cpp @@ -1043,6 +1043,7 @@ void rtlsdr_sighandler() { fprintf (stderr, "Signal caught, exiting!\n"); fprintf (stderr, "Press CTRL + C again to close. Thanks. \n"); //Kindly remind user to double tap CTRL + C + rtlsdr_cancel_async(dongle.dev); //cleanup_rtlsdr_stream(); //thank the wraith for this one...if it works...didn't work //_Exit(1); @@ -1155,7 +1156,7 @@ void cleanup_rtlsdr_stream() demod_cleanup(&demod); output_cleanup(&output); controller_cleanup(&controller); - + rtlsdr_close(dongle.dev); } From 9751eb165f2efba3b5723fbf9c91e91b80b811fa Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 06:09:35 -0500 Subject: [PATCH 03/14] set(CURSES_NEED_WIDE TRUE) set(CURSES_NEED_WIDE TRUE) --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 42d0a7f..60fbc5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,9 +19,10 @@ find_package(PULSEAUDIO) #include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR}) #set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) #remove CURSES from 'required' set up top AFTER switching all commands to ifdef in dsd_main, dsd_framesync, and dsd_ncurses.c -#also, figure out how to make it build for wide character support in Linux Mint etc, like this -- $(ncursesw5-config --cflags --libs) +#also, figure out how to make it build for wide character support in Linux Mint etc, like this -- $(ncursesw5-config --cflags --libs) include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR}) set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) +set(CURSES_NEED_WIDE TRUE) if(Curses_FOUND) include_directories(SYSTEM ${CURSES_INCLUDE_PATH}) From c3c4956ebb3203a4949058e90e805ba92c7cc43d Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 06:13:07 -0500 Subject: [PATCH 04/14] set(CURSES_NEED_WIDE TRUE) set(CURSES_NEED_WIDE TRUE) --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60fbc5e..03495c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,9 +22,10 @@ find_package(PULSEAUDIO) #also, figure out how to make it build for wide character support in Linux Mint etc, like this -- $(ncursesw5-config --cflags --libs) include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR}) set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) -set(CURSES_NEED_WIDE TRUE) + if(Curses_FOUND) + set(CURSES_NEED_WIDE TRUE) include_directories(SYSTEM ${CURSES_INCLUDE_PATH}) list(APPEND LIBS ${CURSES_LIBRARY}) add_definitions(-DUSE_CURSES) From 48c9ae4b285089cb0a8d03ce80adaeaf806bd6ed Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 06:20:19 -0500 Subject: [PATCH 05/14] disable FM_banner disable FM_banner on ncurses terminal, still can't figure out ncursesw support in cmake --- src/dsd_ncurses.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 9371579..1b545d0 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -104,7 +104,7 @@ char * getTimeN(void) //get pretty hh:mm:ss timestamp void ncursesOpen () { mbe_printVersion (versionstr); - setlocale(LC_ALL, ""); + //setlocale(LC_ALL, ""); initscr(); //Initialize NCURSES screen window start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style @@ -132,15 +132,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) level = 0; //start each cycle with 0 erase(); //disabling until wide support can be built for LM, etc. $(ncursesw5-config --cflags --libs) - printw ("%s \n", FM_bannerN[0]); //top line in white + //printw ("%s \n", FM_bannerN[0]); //top line in white attron(COLOR_PAIR(4)); - for (short int i = 1; i < 7; i++) //following lines in cyan - { - printw("%s \n", FM_bannerN[i]); - } + //for (short int i = 1; i < 7; i++) //following lines in cyan + //{ + //printw("%s \n", FM_bannerN[i]); + //} attroff(COLOR_PAIR(4)); printw ("--Build Info------------------------------------------------------------------\n"); - printw ("| %s \n", FM_bannerN[7]); //http link + //printw ("| %s \n", FM_bannerN[7]); //http link printw ("| Digital Speech Decoder: Florida Man Edition\n"); printw ("| Github Build Version: %s \n", GIT_TAG); printw ("| mbelib version %s\n", versionstr); From 9acff308b96ef553355bfd576880d05746b46400 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 06:35:39 -0500 Subject: [PATCH 06/14] OCD change OCD change to how rtl info is presented in ncurses window --- src/dsd_ncurses.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 1b545d0..673dfc8 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -248,9 +248,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (opts->audio_in_type == 3) { printw ("| RTL2838 Device #[%d]", opts->rtl_dev_index); - printw (" [%i] dB", opts->rtl_gain_value); - printw (" [%i] Sq", opts->rtl_squelch_level); - printw (" [%i] kHz VFO\n", opts->rtl_bandwidth); + printw (" Gain [%i] dB -", opts->rtl_gain_value); + printw (" Squelch [%i]", opts->rtl_squelch_level); + printw (" VFO [%i] kHz\n", opts->rtl_bandwidth); printw ("| Freq: [%lld] Hz", opts->rtlsdr_center_freq); printw (" - Tuning available on UDP Port [%i]\n", opts->rtl_udp_port); } From 417a48cc71c6f1021466819c8673c02087b0e89f Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 10:42:55 -0500 Subject: [PATCH 07/14] resetState and Minor Ncurses Printer tweak resetState and Minor Ncurses Printer tweak don't run with -n yet, resets state, using to test to fix when input type changes, but won't decode properly --- include/dsd.h | 2 + src/dsd_frame_sync.c | 13 +++++- src/dsd_main.c | 5 +- src/dsd_ncurses.c | 10 ++-- src/dsd_reset.c | 107 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 src/dsd_reset.c diff --git a/include/dsd.h b/include/dsd.h index 8d2175d..a24cfd0 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -238,6 +238,7 @@ typedef struct pa_simple *pulse_digi_dev_in; pa_simple *pulse_digi_dev_out; int use_ncurses_terminal; + int reset_state; } dsd_opts; @@ -535,6 +536,7 @@ void NxdnEncryptionStreamGeneration (dsd_opts* opts, dsd_state* state, uint8_t K void processMbeFrameEncrypted (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24], char ambe_keystream[49], char imbe_keystream[88]); //end borrow from LEH +void resetState (dsd_state * state); #ifdef __cplusplus extern "C" { diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index cf0420b..3b37932 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -193,7 +193,12 @@ getFrameSync (dsd_opts * opts, dsd_state * state) { playRawAudio(opts, state); //this is on line 21 in dsd_audio.c } - + /* + if (opts->reset_state == 1 && state->carrier == 0) + { + resetState (state); + } + */ t++; symbol = getSymbol (opts, state, 0); @@ -1020,6 +1025,12 @@ getFrameSync (dsd_opts * opts, dsd_state * state) fprintf (stderr,"Press CTRL + C to close.\n"); //Kindly remind user to double tap CTRL + C } noCarrier (opts, state); + /* + if (opts->reset_state == 1) + { + resetState (state); + } + */ return (-1); } } diff --git a/src/dsd_main.c b/src/dsd_main.c index 3e20d69..1c70081 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -764,8 +764,9 @@ main (int argc, char **argv) } break; case 'n': - opts.audio_out = 0; - fprintf (stderr,"Disabling audio output to soundcard.\n"); + //opts.audio_out = 0; + //fprintf (stderr,"Disabling audio output to soundcard.\n"); + opts.reset_state = 1; break; case 'w': strncpy(opts.wav_out_file, optarg, 1023); diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 673dfc8..461609c 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -274,14 +274,16 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) attron(COLOR_PAIR(3)); level = (int) state->max / 164; //only update on carrier present } - //if (state->carrier == 0){ //figure out method that will tell me when is active and when not active, maybe carrier but this doesn't print anyways unless activity - //attron(COLOR_PAIR(1)); - //0 - sync type; 1 - tg/ran; 2 - rid; 3 - slot; 4 - dcc; 5 - time(NULL) ; - //} + if (state->carrier == 0 && opts->reset_state == 1) + { + resetState (state); + } + printw ("--Audio Decode----------------------------------------------------------------\n"); printw ("| In Level: [%3i%%] \n", level); printw ("| Voice Error: [%i][%i] \n| Error Bars: [%s] \n", state->errs, state->errs2, state->err_str); // + printw ("| Carrier = %i\n", state->carrier); printw ("------------------------------------------------------------------------------\n"); diff --git a/src/dsd_reset.c b/src/dsd_reset.c new file mode 100644 index 0000000..3dc1663 --- /dev/null +++ b/src/dsd_reset.c @@ -0,0 +1,107 @@ + +#include "dsd.h" +#include "p25p1_heuristics.h" + +void +resetState (dsd_state * state) +{ + + int i, j; + + state->dibit_buf = malloc (sizeof (int) * 1000000); + state->dibit_buf_p = state->dibit_buf + 200; + memset (state->dibit_buf, 0, sizeof (int) * 200); + state->repeat = 0; //not sure yet + //state->audio_out_buf = malloc (sizeof (short) * 1000000); + //memset (state->audio_out_buf, 0, 100 * sizeof (short)); + //state->audio_out_buf_p = state->audio_out_buf + 100; + //state->audio_out_float_buf = malloc (sizeof (float) * 1000000); + //memset (state->audio_out_float_buf, 0, 100 * sizeof (float)); + //state->audio_out_float_buf_p = state->audio_out_float_buf + 100; + //state->audio_out_idx = 0; + //state->audio_out_idx2 = 0; + //state->audio_out_temp_buf_p = state->audio_out_temp_buf; + //state->wav_out_bytes = 0; + state->center = 0; + state->jitter = -1; + state->synctype = -1; + state->min = -15000; + state->max = 15000; + state->lmid = 0; + state->umid = 0; + state->minref = -12000; + state->maxref = 12000; + state->lastsample = 0; + for (i = 0; i < 128; i++) + { + state->sbuf[i] = 0; + } + state->sidx = 0; + for (i = 0; i < 1024; i++) + { + state->maxbuf[i] = 15000; + } + for (i = 0; i < 1024; i++) + { + state->minbuf[i] = -15000; + } + state->midx = 0; + state->err_str[0] = 0; + sprintf (state->fsubtype, " "); + sprintf (state->ftype, " "); + state->symbolcnt = 0; + state->rf_mod = 0; + state->numflips = 0; + state->lastsynctype = -1; + state->lastp25type = 0; + state->offset = 0; + state->carrier = 0; + for (i = 0; i < 25; i++) + { + for (j = 0; j < 16; j++) + { + state->tg[i][j] = 48; + } + } + state->tgcount = 0; + state->lasttg = 0; + state->lastsrc = 0; + state->nac = 0; + state->errs = 0; + state->errs2 = 0; + state->mbe_file_type = -1; + state->optind = 0; + state->numtdulc = 0; + state->firstframe = 0; + sprintf (state->slot0light, " slot0 "); + sprintf (state->slot1light, " slot1 "); + state->aout_gain = 25; + memset (state->aout_max_buf, 0, sizeof (float) * 200); + state->aout_max_buf_p = state->aout_max_buf; + state->aout_max_buf_idx = 0; + state->samplesPerSymbol = 10; + state->symbolCenter = 4; + sprintf (state->algid, "________"); + sprintf (state->keyid, "________________"); + state->currentslot = 0; + state->cur_mp = malloc (sizeof (mbe_parms)); + state->prev_mp = malloc (sizeof (mbe_parms)); + state->prev_mp_enhanced = malloc (sizeof (mbe_parms)); + mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); + state->p25kid = 0; + + state->debug_audio_errors = 0; + state->debug_header_errors = 0; + state->debug_header_critical_errors = 0; + + state->nxdn_last_ran = 0; + +//#ifdef TRACE_DSD +// state->debug_sample_index = 0; +// state->debug_label_file = NULL; +// state->debug_label_dibit_file = NULL; +// state->debug_label_imbe_file = NULL; +//#endif + + initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not +} From 4404c1afed3cf58c1923a2dd07a60823eafd17a0 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 10:47:52 -0500 Subject: [PATCH 08/14] remove printw carrier remove printw carrier only had that in as a quick test, forgot to disable it --- src/dsd_ncurses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 461609c..8350c0a 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -283,7 +283,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("--Audio Decode----------------------------------------------------------------\n"); printw ("| In Level: [%3i%%] \n", level); printw ("| Voice Error: [%i][%i] \n| Error Bars: [%s] \n", state->errs, state->errs2, state->err_str); // - printw ("| Carrier = %i\n", state->carrier); + //printw ("| Carrier = %i\n", state->carrier); printw ("------------------------------------------------------------------------------\n"); From af401a7e5be7c66a2815ca3a15478100bf836451 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sat, 19 Feb 2022 19:44:56 -0500 Subject: [PATCH 09/14] More NCURSES tweaking More NCURSES tweaking resetState memory leak mitigation --- src/dsd_ncurses.c | 50 ++++++---------------------------------------- src/dsd_reset.c | 2 +- src/rtl_sdr_fm.cpp | 3 ++- 3 files changed, 9 insertions(+), 46 deletions(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 8350c0a..fb69582 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -37,6 +37,7 @@ unsigned long long sr_4 = 0; // unsigned long long sr_5 = 0; // unsigned long long sr_6 = 0; // */ +int reset = 0; char c; //getch key int tg; //last tg int rd; //last rid @@ -115,12 +116,7 @@ void ncursesOpen () noecho(); cbreak(); fprintf (stderr, "Opening NCurses Terminal. \n"); - //call_matrix[5-i][0] = 0; - //call_matrix[5-i][1] = 0; - //call_matrix[5-i][2] = 0; - //call_matrix[5-i][3] = 0; - //call_matrix[5-i][4] = 0; - //call_matrix[5-i][5] = time(NULL); + } void @@ -159,42 +155,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if ( (state->nxdn_last_rid != src && src > 0) || (state->nxdn_last_ran != rn && rn > 0) ) //find condition to make this work well, probably if last != local last variables { - /* //save just in case - call_matrix[0][0] = call_matrix[1][0]; - call_matrix[0][1] = call_matrix[1][1]; - call_matrix[0][2] = call_matrix[1][2]; - call_matrix[0][3] = call_matrix[1][3]; - call_matrix[0][4] = call_matrix[1][4]; - call_matrix[0][5] = call_matrix[1][5]; - - call_matrix[1][0] = call_matrix[2][0]; - call_matrix[1][1] = call_matrix[2][1]; - call_matrix[1][2] = call_matrix[2][2]; - call_matrix[1][3] = call_matrix[2][3]; - call_matrix[1][4] = call_matrix[2][4]; - call_matrix[1][5] = call_matrix[2][5]; - - call_matrix[2][0] = call_matrix[3][0]; - call_matrix[2][1] = call_matrix[3][1]; - call_matrix[2][2] = call_matrix[3][2]; - call_matrix[2][3] = call_matrix[3][3]; - call_matrix[2][4] = call_matrix[3][4]; - call_matrix[2][5] = call_matrix[3][5]; - - call_matrix[3][0] = call_matrix[4][0]; - call_matrix[3][1] = call_matrix[4][1]; - call_matrix[3][2] = call_matrix[4][2]; - call_matrix[3][3] = call_matrix[4][3]; - call_matrix[3][4] = call_matrix[4][4]; - call_matrix[3][5] = call_matrix[4][5]; - - call_matrix[4][0] = call_matrix[5][0]; - call_matrix[4][1] = call_matrix[5][1]; - call_matrix[4][2] = call_matrix[5][2]; - call_matrix[4][3] = call_matrix[5][3]; - call_matrix[4][4] = call_matrix[5][4]; - call_matrix[4][5] = call_matrix[5][5]; - */ for (short int k = 0; k < 5; k++) { call_matrix[k][0] = call_matrix[k+1][0]; @@ -264,7 +224,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } if (opts->wav_out_file[0] != 0) { - printw ("| Writing audio wav to file %s\n", opts->wav_out_file); + printw ("| Writing Audio WAV to file %s\n", opts->wav_out_file); } printw ("------------------------------------------------------------------------------\n"); @@ -273,10 +233,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (state->carrier == 1){ //figure out method that will tell me when is active and when not active, maybe carrier but this doesn't print anyways unless activity attron(COLOR_PAIR(3)); level = (int) state->max / 164; //only update on carrier present + reset = 1; } - if (state->carrier == 0 && opts->reset_state == 1) + if (state->carrier == 0 && opts->reset_state == 1 && reset == 1) { resetState (state); + reset = 0; } diff --git a/src/dsd_reset.c b/src/dsd_reset.c index 3dc1663..e794701 100644 --- a/src/dsd_reset.c +++ b/src/dsd_reset.c @@ -103,5 +103,5 @@ resetState (dsd_state * state) // state->debug_label_imbe_file = NULL; //#endif - initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not + initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not, currently seems to cause memory leak when running over and over } diff --git a/src/rtl_sdr_fm.cpp b/src/rtl_sdr_fm.cpp index 1c84320..75fb919 100644 --- a/src/rtl_sdr_fm.cpp +++ b/src/rtl_sdr_fm.cpp @@ -953,6 +953,7 @@ static void *socket_thread_fn(void *arg) { if(buffer[0] == 0) { new_freq = chars_to_int(buffer); dongle.freq = new_freq; // + //opts->rtlsdr_center_freq = new_freq; //or dongle.freq, this should update the freq displayed in ncurses terminal hopefully and not do anything naughty optimal_settings(new_freq, demod.rate_in); rtlsdr_set_center_freq(dongle.dev, dongle.freq); //fprintf (stderr, "Tuning to: %d [Hz] (central freq: %d [Hz])\n", new_freq, new_freq + freq_offset); @@ -1156,7 +1157,7 @@ void cleanup_rtlsdr_stream() demod_cleanup(&demod); output_cleanup(&output); controller_cleanup(&controller); - + rtlsdr_close(dongle.dev); } From 387f2253b1f8aeb5129808b168850773c869de75 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sun, 20 Feb 2022 15:41:28 -0500 Subject: [PATCH 10/14] More NCURSES Tweaking More NCURSES Tweaking -tweak array, seems to update smoother now, immediate -more concise, cleaner names for sync types -array updates on DMR, P25P1, NXDN, PV types only currenlty (no dstar etc yet) More P25 resetState tweaking/testing Other under the hood tweaking --- CMakeLists.txt | 2 +- src/dsd_file.c | 24 +++++- src/dsd_main.c | 10 ++- src/dsd_ncurses.c | 185 +++++++++++++++++++++++++++++----------------- src/dsd_reset.c | 2 +- 5 files changed, 153 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03495c9..1e36638 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ find_package(RTLSDR) #more messing around #find_package(Curses) find_package(Curses REQUIRED) #making this required until I can fix all instances of it being called to ifdef lines -find_package(PULSEAUDIO) +find_package(PulseAudio) #include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR}) #set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) diff --git a/src/dsd_file.c b/src/dsd_file.c index b27b67a..9a0dc32 100644 --- a/src/dsd_file.c +++ b/src/dsd_file.c @@ -16,7 +16,7 @@ */ #include "dsd.h" - +int payload = 0; void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d) { @@ -28,17 +28,28 @@ saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d) fputc (err, opts->mbe_out_f); k = 0; + if (payload == 1) //make opt variable later on to toggle this + { + fprintf(stderr, "\n"); + } + for (i = 0; i < 11; i++) { b = 0; + for (j = 0; j < 8; j++) { b = b << 1; b = b + imbe_d[k]; k++; } + if (payload == 1) //make opt variable later on to toggle this + { + fprintf (stderr, "[%2X] ", b); + } fputc (b, opts->mbe_out_f); } + //fprintf(stderr, "\n"); fflush (opts->mbe_out_f); } @@ -53,17 +64,28 @@ saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d) fputc (err, opts->mbe_out_f); k = 0; + if (payload == 1) //make opt variable later on to toggle this + { + fprintf(stderr, "\n"); + } for (i = 0; i < 6; i++) { b = 0; + for (j = 0; j < 8; j++) { b = b << 1; b = b + ambe_d[k]; k++; } + if (payload == 1) //make opt variable later on to toggle this + { + fprintf (stderr, "[%2X] ", b); + } + fputc (b, opts->mbe_out_f); } + //fprintf(stderr, "\n"); b = ambe_d[48]; fputc (b, opts->mbe_out_f); fflush (opts->mbe_out_f); diff --git a/src/dsd_main.c b/src/dsd_main.c index 1c70081..8f74c25 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -334,7 +334,7 @@ usage () fprintf (stderr," -d Create mbe data files, use this directory\n"); fprintf (stderr," -r Read/Play saved mbe data from file(s)\n"); fprintf (stderr," -g Audio output gain (default = 0 = auto, disable = -1)\n"); - fprintf (stderr," -n Do not send synthesized speech to audio output device\n"); + //fprintf (stderr," -n Do not send synthesized speech to audio output device\n"); fprintf (stderr," -w Output synthesized speech to a .wav file\n"); fprintf (stderr," -a Display port audio devices\n"); fprintf (stderr," -W Monitor Source Audio When No Sync Detected (WIP!)\n"); @@ -381,6 +381,9 @@ usage () fprintf (stderr," (default=36)\n"); fprintf (stderr," -M Min/Max buffer size for QPSK decision point tracking\n"); fprintf (stderr," (default=15)\n"); + fprintf (stderr," -n Reset P25 Heuristics and initState variables on mixed decoding signal\n"); + fprintf (stderr," Helps when decoding multiple signal types at same time\n"); + fprintf (stderr," (WiP! May Cause Slow Memory Leak - Experimental)\n"); fprintf (stderr,"\n"); fprintf (stderr,"Report bugs to: https://github.com/lwvmobile/dsd-fme/issues \n"); exit (0); @@ -715,6 +718,7 @@ main (int argc, char **argv) case 'N': opts.use_ncurses_terminal = 1; fprintf (stderr,"Enabling NCurses Terminal.\n"); + fprintf (stderr," - may need to issue 'reset' command in terminal after use\n"); break; case 'z': @@ -767,6 +771,9 @@ main (int argc, char **argv) //opts.audio_out = 0; //fprintf (stderr,"Disabling audio output to soundcard.\n"); opts.reset_state = 1; + fprintf (stderr,"Enabling Automatic Reset of P25 states\n"); + fprintf (stderr," -Helps with multiple signal type decoding\n"); + fprintf (stderr," -(WiP! May cause slow memory leak)\n"); break; case 'w': strncpy(opts.wav_out_file, optarg, 1023); @@ -1090,6 +1097,7 @@ main (int argc, char **argv) else { liveScanner (&opts, &state); + } if (opts.use_ncurses_terminal == 1){ ncursesClose (); diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index fb69582..037e9dc 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -27,16 +27,7 @@ #include "dsd.h" #include "git_ver.h" -/* -short hexbuf; -unsigned long long sr_0 = 0; //64-bit shift registers for pushing decoded binary or dibit data -unsigned long long sr_1 = 0; //384 -unsigned long long sr_2 = 0; // -unsigned long long sr_3 = 0; // -unsigned long long sr_4 = 0; // -unsigned long long sr_5 = 0; // -unsigned long long sr_6 = 0; // -*/ + int reset = 0; char c; //getch key int tg; //last tg @@ -62,6 +53,7 @@ char * FM_bannerN[9] = { "https://github.com/lwvmobile/dsd-fme/tree/pulseaudio " }; +/* char * SyncTypes[20] = { "P25P1_SYNC", "INV_P25P1_SYNC", @@ -84,6 +76,30 @@ char * SyncTypes[20] = { "DSTAR_HD", "INV_DSTAR_HD" +}; +*/ +char * SyncTypes[20] = { + "+P25P1", + "-P25P1", + "+X2TDMA DATA", + "-X2TDMA DATA", + "+X2TDMA VOICE", + "-X2TDMA VOICE", + "+DSTARC", + "-DSTAR", + "+NXDN VOICE", //8 + "-NXDN VOICE", //9 + "+DMR DATA", //10 + "-DMR VOICE", //11 + "+DMR DATA", //12 + "-DMR VOICE", //13 + "+PROVOICE", //14 + "-PROVOICE", //15 + "+NXDN DATA", //16 + "-NXDN DATA", //17 + "+DSTAR HD", + "-DSTAR HD" + }; time_t nowN; @@ -115,7 +131,7 @@ void ncursesOpen () init_pair(5, COLOR_MAGENTA, COLOR_BLACK); //Magenta for no frame sync/signal noecho(); cbreak(); - fprintf (stderr, "Opening NCurses Terminal. \n"); + //fprintf (stderr, "Opening NCurses Terminal. \n"); } @@ -143,39 +159,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("------------------------------------------------------------------------------\n"); - if ( (state->lastsynctype == 14 || state->lastsynctype == 15) ) //honestly have no idea how to do this for pV + if ( (lls == 14 || lls == 15) && (time(NULL) - call_matrix[9][5] > 5) ) //honestly have no idea how to do this for pV, just going time based? { - call_matrix[5][0] = lls; - call_matrix[5][1] = 1; - call_matrix[5][2] = 1; - call_matrix[5][3] = 1; - call_matrix[5][4] = 1; - call_matrix[5][5] = time(NULL); - } - - if ( (state->nxdn_last_rid != src && src > 0) || (state->nxdn_last_ran != rn && rn > 0) ) //find condition to make this work well, probably if last != local last variables - { - for (short int k = 0; k < 5; k++) - { - call_matrix[k][0] = call_matrix[k+1][0]; - call_matrix[k][1] = call_matrix[k+1][1]; - call_matrix[k][2] = call_matrix[k+1][2]; - call_matrix[k][3] = call_matrix[k+1][3]; - call_matrix[k][4] = call_matrix[k+1][4]; - call_matrix[k][5] = call_matrix[k+1][5]; - } - call_matrix[5][0] = lls; - call_matrix[5][1] = rn; - call_matrix[5][2] = src; - call_matrix[5][3] = 0; - call_matrix[5][4] = 0; - call_matrix[5][5] = time(NULL); - - } - - if ( (lls == 0 || lls == 1) && state->lastsrc != rd && state->lastsrc > 0) //find condition to make this work well, probably if last != local last variables - { - for (short int k = 0; k < 5; k++) + for (short int k = 0; k < 9; k++) { call_matrix[k][0] = call_matrix[k+1][0]; call_matrix[k][1] = call_matrix[k+1][1]; @@ -185,12 +171,79 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) call_matrix[k][5] = call_matrix[k+1][5]; } - call_matrix[5][0] = lls; - call_matrix[5][1] = tg; - call_matrix[5][2] = rd; - call_matrix[5][3] = 0; - call_matrix[5][4] = nc; - call_matrix[5][5] = time(NULL); + call_matrix[9][0] = lls; + call_matrix[9][1] = 1; + call_matrix[9][2] = 1; + call_matrix[9][3] = 1; + call_matrix[9][4] = 1; + call_matrix[9][5] = time(NULL); + //nowN = time(NULL); + } + + //if ( (state->nxdn_last_rid != src && src > 0) || (state->nxdn_last_ran != rn && rn > 0) ) //find condition to make this work well, probably if last != local last variables + //if ( (call_matrix[9][2] != src && src > 0) || (call_matrix[9][1] != rn && rn > 0) ) //NXDN working well now with this, updates immediately and only once + if ( call_matrix[9][2] != src && src > 0 && rn > 0 ) //NXDN working well now with this, updates immediately and only once + { + for (short int k = 0; k < 9; k++) + { + call_matrix[k][0] = call_matrix[k+1][0]; + call_matrix[k][1] = call_matrix[k+1][1]; + call_matrix[k][2] = call_matrix[k+1][2]; + call_matrix[k][3] = call_matrix[k+1][3]; + call_matrix[k][4] = call_matrix[k+1][4]; + call_matrix[k][5] = call_matrix[k+1][5]; + } + call_matrix[9][0] = lls; + call_matrix[9][1] = rn; + call_matrix[9][2] = src; + call_matrix[9][3] = 0; + call_matrix[9][4] = 0; + call_matrix[9][5] = time(NULL); + + } + + //if (state->dmr_color_code != dcc && (lls == 11 || lls == 13 || lls == 10 || lls == 12) ) //DMR Voice + last two is data + if ( (call_matrix[9][4] != dcc || call_matrix[9][2] != rd) && (lls == 11 || lls == 13 || lls == 10 || lls == 12) ) //DMR Voice + last two is data + { + //dcc = state->dmr_color_code; + for (short int k = 0; k < 9; k++) + { + call_matrix[k][0] = call_matrix[k+1][0]; + call_matrix[k][1] = call_matrix[k+1][1]; + call_matrix[k][2] = call_matrix[k+1][2]; + call_matrix[k][3] = call_matrix[k+1][3]; + call_matrix[k][4] = call_matrix[k+1][4]; + call_matrix[k][5] = call_matrix[k+1][5]; + } + + call_matrix[9][0] = lls; + call_matrix[9][1] = tg; + call_matrix[9][2] = rd; + call_matrix[9][3] = 0; + call_matrix[9][4] = dcc; + call_matrix[9][5] = time(NULL); + //i++; + } + + //if ( (lls == 0 || lls == 1) && state->lastsrc != rd && state->lastsrc > 0) //find condition to make this work well, probably if last != local last variables + if ( (lls == 0 || lls == 1) && call_matrix[9][2] != rd && nc > 0 && tg > 0) //P25 + { + for (short int k = 0; k < 9; k++) + { + call_matrix[k][0] = call_matrix[k+1][0]; + call_matrix[k][1] = call_matrix[k+1][1]; + call_matrix[k][2] = call_matrix[k+1][2]; + call_matrix[k][3] = call_matrix[k+1][3]; + call_matrix[k][4] = call_matrix[k+1][4]; + call_matrix[k][5] = call_matrix[k+1][5]; + } + + call_matrix[9][0] = lls; + call_matrix[9][1] = tg; + call_matrix[9][2] = rd; + call_matrix[9][3] = 0; + call_matrix[9][4] = nc; + call_matrix[9][5] = time(NULL); //i++; } //printw ("Time: "); @@ -199,7 +252,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("--Input Output----------------------------------------------------------------\n"); if (opts->audio_in_type == 0) { - printw ("| Pulse Audio Input [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_in, opts->pulse_digi_in_channels); + printw ("| Pulse Audio Input [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_in/1000, opts->pulse_digi_in_channels); } if (opts->audio_in_type == 1) { @@ -216,7 +269,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } if (opts->audio_out_type == 0) { - printw ("| Pulse Audio Output [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_out, opts->pulse_digi_out_channels); + printw ("| Pulse Audio Output [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels); } if (opts->mbe_out_dir[0] != 0) { @@ -311,7 +364,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("%s \n", s1last); } - if (state->dmr_color_code > 0 && (lls == 11 || lls == 13) ) //DMR VOice + if (state->dmr_color_code > 0 && (lls == 11 || lls == 13 || lls == 10 || lls == 12) ) //DMR Voice + last two is data { dcc = state->dmr_color_code; } @@ -361,36 +414,36 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //0 - sync type; 1 - tg/ran; 2 - rid; 3 - slot; 4 - cc; 5 - time(NULL) ; printw ("--Call History----------------------------------------------------------------\n"); - for (short int j = 0; j < 6; j++) + for (short int j = 0; j < 10; j++) { - if ( (time(NULL) - call_matrix[j][5]) < 9999) + if ( ((time(NULL) - call_matrix[9-j][5]) < 9999) ) //if (1 == 1) { - printw ("| #%d %s ", 6-j, SyncTypes[call_matrix[j][0]]); + printw ("| #%d %s ", j, SyncTypes[call_matrix[9-j][0]]); if (lls == 8 || lls == 9 || lls == 16 || lls == 17) { - printw ("RAN [%2d] ", call_matrix[j][1]); + printw ("RAN [%2d] ", call_matrix[9-j][1]); } if (lls == 0 || lls == 1 || lls == 11 || lls == 13) //P25 P1 and DMR Voice { - printw ("TID [%2d] ", call_matrix[j][1]); + printw ("TID [%2d] ", call_matrix[9-j][1]); } - printw ("RID [%4d] ", call_matrix[j][2]); + printw ("RID [%4d] ", call_matrix[9-j][2]); //printw ("S %d - ", call_matrix[j][3]); - if (call_matrix[j][0] == 0 || call_matrix[j][0] == 1) //P25P1 Voice + if (call_matrix[9-j][0] == 0 || call_matrix[9-j][0] == 1) //P25P1 Voice { - printw ("NAC [0x%X] ", call_matrix[j][4]); + printw ("NAC [0x%X] ", call_matrix[9-j][4]); } - if (call_matrix[j][0] == 12 || call_matrix[j][0] == 13) //DMR Voice Types + if (call_matrix[9-j][0] == 12 || call_matrix[9-j][0] == 13 || call_matrix[9-j][0] == 10 || call_matrix[9-j][0] == 11 ) //DMR Voice Types { - printw ("DCC [%d] ", call_matrix[j][4]); + printw ("DCC [%d] ", call_matrix[9-j][4]); } - printw ("%d secs ago\n", time(NULL) - call_matrix[j][5]); + printw ("%d secs ago\n", time(NULL) - call_matrix[9-j][5]); } //printw("\n"); } - printw ("------------------------------------------------------------------------------"); + printw ("------------------------------------------------------------------------------\n"); attroff(COLOR_PAIR(4)); //cyan for history //put sync type at very bottom //printw ("%s %s\n", state->ftype, state->fsubtype); //some ftype strings have extra spaces in them @@ -425,7 +478,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) void ncursesClose () { - erase(); - refresh(); + //erase(); + //refresh(); endwin(); } diff --git a/src/dsd_reset.c b/src/dsd_reset.c index e794701..e8aa893 100644 --- a/src/dsd_reset.c +++ b/src/dsd_reset.c @@ -103,5 +103,5 @@ resetState (dsd_state * state) // state->debug_label_imbe_file = NULL; //#endif - initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not, currently seems to cause memory leak when running over and over + initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not, currently seems to cause memory leak when running over and over, mitigated with a reset flag } From 7e9eadaea5736e799d1cdfc27ab1a40599c55175 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sun, 20 Feb 2022 16:24:45 -0500 Subject: [PATCH 11/14] Delete dsd_frame.c.bkp --- src/dsd_frame.c.bkp | 571 -------------------------------------------- 1 file changed, 571 deletions(-) delete mode 100644 src/dsd_frame.c.bkp diff --git a/src/dsd_frame.c.bkp b/src/dsd_frame.c.bkp deleted file mode 100644 index e89cfa3..0000000 --- a/src/dsd_frame.c.bkp +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright (C) 2010 DSD Author - * GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0) - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include "dsd.h" -#if !defined(NULL) -#define NULL 0 -#endif - -#include "p25p1_check_nid.h" - -void -printFrameInfo (dsd_opts * opts, dsd_state * state) -{ - - int level; - - level = (int) state->max / 164; - if (opts->verbose > 0) - { - fprintf (stderr,"inlvl: %2i%% ", level); - } - if (state->nac != 0) - { - fprintf (stderr,"nac: %4X ", state->nac); - } - - if (opts->verbose > 1) - { - fprintf (stderr,"src: %8i ", state->lastsrc); - } - fprintf (stderr,"tg: %5i ", state->lasttg); -} - -void -processFrame (dsd_opts * opts, dsd_state * state) -{ - - int i, j, dibit; - char duid[3]; - char nac[13]; - int level; - - char status_0; - char bch_code[63]; - int index_bch_code; - unsigned char parity; - char v; - int new_nac; - char new_duid[3]; - int check_result; - - nac[12] = 0; - duid[2] = 0; - j = 0; - - if (state->rf_mod == 1) - { - state->maxref = (int)(state->max * 0.80F); - state->minref = (int)(state->min * 0.80F); - } - else - { - state->maxref = state->max; - state->minref = state->min; - } - - if ((state->synctype == 8) || (state->synctype == 9)) //lets make this NOT do this...maybe... - { - //state->rf_mod = 2; //wrong type of modulation HERE HERE - state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; - if (opts->errorbars == 1) - { - if (opts->verbose > 0) - { - level = (int) state->max / 164; - fprintf (stderr,"inlvl: %2i%% ", level); - } - } - state->nac = 0; - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) - { - openMbeOutFile (opts, state); - } - sprintf (state->fsubtype, " VOICE "); - processNXDNVoice (opts, state); - return; - } - else if ((state->synctype == 16) || (state->synctype == 17)) - { - //state->rf_mod = 2; - state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; - if (opts->errorbars == 1) - { - if (opts->verbose > 0) - { - level = (int) state->max / 164; - fprintf (stderr, "inlvl: %2i%% ", level); - } - } - state->nac = 0; - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) - { - openMbeOutFile (opts, state); - } - sprintf (state->fsubtype, " DATA "); - processNXDNData (opts, state); - return; - } - else if ((state->synctype == 6) || (state->synctype == 7)) - { - state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; - if (opts->errorbars == 1) - { - if (opts->verbose > 0) - { - level = (int) state->max / 164; - fprintf (stderr,"inlvl: %2i%% ", level); - } - } - state->nac = 0; - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) - { - openMbeOutFile (opts, state); - } - sprintf (state->fsubtype, " VOICE "); - processDSTAR (opts, state); - return; - } - else if ((state->synctype == 18) || (state->synctype == 19)) - { - state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; - if (opts->errorbars == 1) - { - if (opts->verbose > 0) - { - level = (int) state->max / 164; - fprintf (stderr,"inlvl: %2i%% ", level); - } - } - state->nac = 0; - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) - { - openMbeOutFile (opts, state); - } - sprintf (state->fsubtype, " DATA "); - processDSTAR_HD (opts, state); - return; - } - - else if ((state->synctype >= 10) && (state->synctype <= 13)) - { - state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; - if (opts->errorbars == 1) - { - if (opts->verbose > 0) - { - level = (int) state->max / 164; - fprintf (stderr,"inlvl: %2i%% ", level); - } - } - if ((state->synctype == 11) || (state->synctype == 12)) - { - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) - { - openMbeOutFile (opts, state); - } - sprintf (state->fsubtype, " VOICE "); - processDMRvoice (opts, state); - } - else - { - closeMbeOutFile (opts, state); - state->err_str[0] = 0; - processDMRdata (opts, state); - } - return; - } - else if ((state->synctype >= 2) && (state->synctype <= 5)) - { - state->nac = 0; - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - } - if ((state->synctype == 3) || (state->synctype == 4)) - { - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) - { - openMbeOutFile (opts, state); - } - sprintf (state->fsubtype, " VOICE "); - processX2TDMAvoice (opts, state); - } - else - { - closeMbeOutFile (opts, state); - state->err_str[0] = 0; - processX2TDMAdata (opts, state); - } - return; - } - else if ((state->synctype == 14) || (state->synctype == 15)) - { - state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; - if (opts->errorbars == 1) - { - if (opts->verbose > 0) - { - level = (int) state->max / 164; - fprintf (stderr,"inlvl: %2i%% ", level); - } - } - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) - { - openMbeOutFile (opts, state); - } - sprintf (state->fsubtype, " VOICE "); - processProVoice (opts, state); - return; - } - else - { - // Read the NAC, 12 bits - j = 0; - index_bch_code = 0; - for (i = 0; i < 6; i++) - { - dibit = getDibit (opts, state); - - v = 1 & (dibit >> 1); // bit 1 - nac[j] = v + '0'; - j++; - bch_code[index_bch_code] = v; - index_bch_code++; - - v = 1 & dibit; // bit 0 - nac[j] = v + '0'; - j++; - bch_code[index_bch_code] = v; - index_bch_code++; - } - state->nac = strtol (nac, NULL, 2); - - // Read the DUID, 4 bits - for (i = 0; i < 2; i++) - { - dibit = getDibit (opts, state); - duid[i] = dibit + '0'; - - bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 - index_bch_code++; - bch_code[index_bch_code] = 1 & dibit; // bit 0 - index_bch_code++; - } - - // Read the BCH data for error correction of NAC and DUID - for (i = 0; i < 3; i++) - { - dibit = getDibit (opts, state); - - bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 - index_bch_code++; - bch_code[index_bch_code] = 1 & dibit; // bit 0 - index_bch_code++; - } - // Intermission: read the status dibit - status_0 = getDibit (opts, state) + '0'; - // ... continue reading the BCH error correction data - for (i = 0; i < 20; i++) - { - dibit = getDibit (opts, state); - - bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 - index_bch_code++; - bch_code[index_bch_code] = 1 & dibit; // bit 0 - index_bch_code++; - } - - // Read the parity bit - dibit = getDibit (opts, state); - bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1 - parity = (1 & dibit); // bit 0 - - // Check if the NID is correct - check_result = check_NID (bch_code, &new_nac, new_duid, parity); - if (check_result) { - if (new_nac != state->nac) { - // NAC fixed by error correction - state->nac = new_nac; - state->debug_header_errors++; - } - if (strcmp(new_duid, duid) != 0) { - // DUID fixed by error correction - //fprintf (stderr,"Fixing DUID %s -> %s\n", duid, new_duid); - duid[0] = new_duid[0]; - duid[1] = new_duid[1]; - state->debug_header_errors++; - } - } else { - // Check of NID failed and unable to recover its value - //fprintf (stderr,"NID error\n"); - duid[0] = 'E'; - duid[1] = 'E'; - state->debug_header_critical_errors++; - } - } - - if (strcmp (duid, "00") == 0) - { - // Header Data Unit - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," HDU\n"); - } - if (opts->mbe_out_dir[0] != 0) - { - closeMbeOutFile (opts, state); - openMbeOutFile (opts, state); - } - mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); - state->lastp25type = 2; - sprintf (state->fsubtype, " HDU "); - processHDU (opts, state); - } - else if (strcmp (duid, "11") == 0) - { - // Logical Link Data Unit 1 - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," LDU1 "); - } - if (opts->mbe_out_dir[0] != 0) - { - if (opts->mbe_out_f == NULL) - { - openMbeOutFile (opts, state); - } - } - state->lastp25type = 1; - sprintf (state->fsubtype, " LDU1 "); - state->numtdulc = 0; - processLDU1 (opts, state); - } - else if (strcmp (duid, "22") == 0) - { - // Logical Link Data Unit 2 - if (state->lastp25type != 1) - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," Ignoring LDU2 not preceeded by LDU1\n"); - } - state->lastp25type = 0; - sprintf (state->fsubtype, " "); - } - else - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," LDU2 "); - } - if (opts->mbe_out_dir[0] != 0) - { - if (opts->mbe_out_f == NULL) - { - openMbeOutFile (opts, state); - } - } - state->lastp25type = 2; - sprintf (state->fsubtype, " LDU2 "); - state->numtdulc = 0; - processLDU2 (opts, state); - } - } - else if (strcmp (duid, "33") == 0) - { - // Terminator with subsequent Link Control - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," TDULC\n"); - } - if (opts->mbe_out_dir[0] != 0) - { - closeMbeOutFile (opts, state); - } - mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); - state->lasttg = 0; - state->lastsrc = 0; - state->lastp25type = 0; - state->err_str[0] = 0; - sprintf (state->fsubtype, " TDULC "); - state->numtdulc++; - if ((opts->resume > 0) && (state->numtdulc > opts->resume)) - { - resumeScan (opts, state); - } - processTDULC (opts, state); - state->err_str[0] = 0; - } - else if (strcmp (duid, "03") == 0) - { - // Terminator without subsequent Link Control - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," TDU\n"); - } - if (opts->mbe_out_dir[0] != 0) - { - closeMbeOutFile (opts, state); - } - mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); - state->lasttg = 0; - state->lastsrc = 0; - state->lastp25type = 0; - state->err_str[0] = 0; - sprintf (state->fsubtype, " TDU "); - - processTDU (opts, state); - } - else if (strcmp (duid, "13") == 0) - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," TSDU\n"); - } - if (opts->resume > 0) - { - resumeScan (opts, state); - } - state->lasttg = 0; - state->lastsrc = 0; - state->lastp25type = 3; - sprintf (state->fsubtype, " TSDU "); - - // Now processing NID - - skipDibit (opts, state, 328-25); - } - else if (strcmp (duid, "30") == 0) - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," PDU\n"); - } - if (opts->resume > 0) - { - resumeScan (opts, state); - } - if (opts->mbe_out_dir[0] != 0) - { - if (opts->mbe_out_f == NULL) - { - openMbeOutFile (opts, state); - } - } - state->lastp25type = 4; - sprintf (state->fsubtype, " PDU "); - } - // try to guess based on previous frame if unknown type - else if (state->lastp25type == 1) - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr,"(LDU2) "); - } - if (opts->mbe_out_dir[0] != 0) - { - if (opts->mbe_out_f == NULL) - { - openMbeOutFile (opts, state); - } - } - //state->lastp25type = 0; - // Guess that the state is LDU2 - state->lastp25type = 2; - sprintf (state->fsubtype, "(LDU2) "); - state->numtdulc = 0; - processLDU2 (opts, state); - } - else if (state->lastp25type == 2) - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr,"(LDU1) "); - } - if (opts->mbe_out_dir[0] != 0) - { - if (opts->mbe_out_f == NULL) - { - openMbeOutFile (opts, state); - } - } - //state->lastp25type = 0; - // Guess that the state is LDU1 - state->lastp25type = 1; - sprintf (state->fsubtype, "(LDU1) "); - state->numtdulc = 0; - processLDU1 (opts, state); - } - else if (state->lastp25type == 3) - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," (TSDU)\n"); - } - //state->lastp25type = 0; - // Guess that the state is TSDU - state->lastp25type = 3; - sprintf (state->fsubtype, "(TSDU) "); - - // Now processing NID - - skipDibit (opts, state, 328-25); - } - else if (state->lastp25type == 4) - { - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," (PDU)\n"); - } - state->lastp25type = 0; - } - else - { - state->lastp25type = 0; - sprintf (state->fsubtype, " "); - if (opts->errorbars == 1) - { - printFrameInfo (opts, state); - fprintf (stderr," duid:%s *Unknown DUID*\n", duid); - } - } -} From 455a7a9329296c43d7dfaee55d74df59b7504d9c Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sun, 20 Feb 2022 16:24:55 -0500 Subject: [PATCH 12/14] Delete nxdn_data.c.bkp --- src/nxdn_data.c.bkp | 41 ----------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 src/nxdn_data.c.bkp diff --git a/src/nxdn_data.c.bkp b/src/nxdn_data.c.bkp deleted file mode 100644 index 5e212bd..0000000 --- a/src/nxdn_data.c.bkp +++ /dev/null @@ -1,41 +0,0 @@ -#include "dsd.h" -#include "nxdn_const.h"//going to test pushing data frames through, but not throught he processMBE portion, want to get those get frames - -void -processNXDNData (dsd_opts * opts, dsd_state * state) -{ - int i, dibit; - //dibit = getDibit (opts, state); - //fprintf (stderr, "D %c \n", dibit + 48); //adding to see what dumps exactly - if (opts->errorbars == 1) - { - fprintf (stderr, "DATA "); - //dibit = getDibit (opts, state); - //fprintf (stderr, "DE %c \n", dibit + 48); //adding to see what dumps exactly - } - - for (i = 0; i < 30; i++) - { - dibit = getDibit (opts, state); -#ifdef NXDN_DUMP - fprintf (stderr, "%c", dibit + 48); -#endif - } -#ifdef NXDN_DUMP - fprintf (stderr, " "); -#endif - - for (i = 0; i < 144; i++) - { - dibit = getDibit (opts, state); - //fprintf (stderr, "%c", dibit + 48); -#ifdef NXDN_DUMP - fprintf (stderr, "%c", dibit + 48); -#endif - } - - if (opts->errorbars == 1) - { - fprintf (stderr, "\n"); - } -} From 291f9ed963053b78ccad5ad9670f3548cfa3a59e Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sun, 20 Feb 2022 16:25:03 -0500 Subject: [PATCH 13/14] Delete nxdn_data.c.bkp2 --- src/nxdn_data.c.bkp2 | 72 -------------------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 src/nxdn_data.c.bkp2 diff --git a/src/nxdn_data.c.bkp2 b/src/nxdn_data.c.bkp2 deleted file mode 100644 index fe3cddf..0000000 --- a/src/nxdn_data.c.bkp2 +++ /dev/null @@ -1,72 +0,0 @@ -#include "dsd.h" -#include "nxdn_const.h" //test making this just like voice, but not processing MBEframes - -void -processNXDNData (dsd_opts * opts, dsd_state * state) -{ - int i, j, dibit, k, l; - char ambe_fr2[4][24]; - const int *w, *x, *y, *z; - const char *pr; - - if (opts->errorbars == 1) - { - fprintf (stderr,"DATA e:"); - } - - for (i = 0; i < 30; i++) - { - dibit = getDibit (opts, state); -#ifdef NXDN_DUMP - fprintf (stderr,"%c", dibit + 48); -#endif - } -#ifdef NXDN_DUMP - fprintf (stderr," "); -#endif - - pr = nxdnpr; - for (j = 0; j < 4; j++) - { - w = nW; - x = nX; - y = nY; - z = nZ; - for (i = 0; i < 36; i++) - { - dibit = getDibit (opts, state); - //fprintf (stderr,"%c", dibit + 48); //remove later -#ifdef NXDN_DUMP - fprintf (stderr,"%c", dibit + 48); -#endif - ambe_fr2[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1 - pr++; - ambe_fr2[*y][*z] = (1 & dibit); // bit 0 - w++; - x++; - y++; - z++; - //dump this whole lot, figure out what it all means - //fprintf (stderr, "%s\n%s\n", ambe_fr, pr); - } - for (k = 0; k < 36; k++) //was 36 - { - for (l = 0; l < 36; l++) //was 36 - { - //fprintf (stderr, "%X%X", ambe_fr[k][l]); - //fprintf (stderr, "%X", ambe_fr2[k][l]); - } - //fprintf (stderr, "\n"); - } - //processMbeFrame (opts, state, NULL, ambe_fr, NULL); -#ifdef NXDN_DUMP - fprintf (stderr," "); -#endif - - } - //fprintf (stderr, "\nD%s\n%s\n", ambe_fr, pr); - if (opts->errorbars == 1) - { - fprintf (stderr,"\n"); - } -} From ad13d06accce3068bf2f78d8a1eb4c097628ae8d Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sun, 20 Feb 2022 16:25:18 -0500 Subject: [PATCH 14/14] Delete nxdn_voice.c.bkp3 --- src/nxdn_voice.c.bkp3 | 118 ------------------------------------------ 1 file changed, 118 deletions(-) delete mode 100644 src/nxdn_voice.c.bkp3 diff --git a/src/nxdn_voice.c.bkp3 b/src/nxdn_voice.c.bkp3 deleted file mode 100644 index 3c79ef4..0000000 --- a/src/nxdn_voice.c.bkp3 +++ /dev/null @@ -1,118 +0,0 @@ -#include "dsd.h" -#include "nxdn_const.h" - -void -processNXDNVoice (dsd_opts * opts, dsd_state * state) -{ - int i, j, dibit, k, l; - char ambe_fr[4][24]; - const int *w, *x, *y, *z; - const char *pr; - //borrow from LEH data - unsigned char sacch_raw[72] = {0}; - unsigned char sacch_decoded[32] = {0}; /* 26 bit + 6 bit CRC */ - unsigned char *pr2; //change this to pr2 to differentiate - uint8_t CrcIsGood = 0; - uint8_t StructureField = 0; - uint8_t RAN = 0; - uint8_t PartOfFrame = 0; - - if (opts->errorbars == 1) - { - fprintf (stderr,"VOICE e:"); - } - - for (i = 0; i < 30; i++) - { - dibit = getDibit (opts, state); -#ifdef NXDN_DUMP - fprintf (stderr,"%c", dibit + 48); -#endif - } -#ifdef NXDN_DUMP - fprintf (stderr," "); -#endif - - pr = nxdnpr; - pr2 = (unsigned char *)(&nxdnpr2[8]); //from LEH data - - for (j = 0; j < 4; j++) - { - w = nW; - x = nX; - y = nY; - z = nZ; - for (i = 0; i < 36; i++) - { - dibit = getDibit (opts, state); - //fprintf (stderr,"%c", dibit + 48); //remove later - if (i < 30){ - sacch_raw[(2*i)] = ((*pr2) & 1) ^ (1 & (dibit >> 1)); // bit 1 - sacch_raw[(2*i)+1] = (1 & dibit); // bit 0 - } - -#ifdef NXDN_DUMP - fprintf (stderr,"%c", dibit + 48); -#endif - ambe_fr[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1 - pr++; - ambe_fr[*y][*z] = (1 & dibit); // bit 0 - w++; - x++; - y++; - z++; - } - processMbeFrame (opts, state, NULL, ambe_fr, NULL); - //from LEH data - /* Decode the SACCH fields */ - CrcIsGood = NXDN_SACCH_raw_part_decode(sacch_raw, sacch_decoded); - StructureField = (sacch_decoded[0]<<1 | sacch_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */ - RAN = (sacch_decoded[2]<<5 | sacch_decoded[3]<<4 | sacch_decoded[4]<<3 | sacch_decoded[5]<<2 | sacch_decoded[6]<<1 | sacch_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the SACCH) */ - - /* Compute the Part of Frame according to the structure field */ - if (StructureField == 3) PartOfFrame = 0; - else if(StructureField == 2) PartOfFrame = 1; - else if(StructureField == 1) PartOfFrame = 2; - else if(StructureField == 0) PartOfFrame = 3; - else PartOfFrame = 0; /* Normally we should never go here */ - - /* Fill the SACCH structure */ - state->NxdnSacchRawPart[PartOfFrame].CrcIsGood = CrcIsGood; - state->NxdnSacchRawPart[PartOfFrame].StructureField = StructureField; - state->NxdnSacchRawPart[PartOfFrame].RAN = RAN; - - memcpy(state->NxdnSacchRawPart[PartOfFrame].Data, &sacch_decoded[8], 18); /* Copy the 18 bits of SACCH content */ - - //fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); - if(CrcIsGood) - { - //fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); - //fprintf (stderr, " (OK) - "); - state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead - } - - else fprintf (stderr, "(CRC ERR) - "); - - if(PartOfFrame == 3) - { - /* Decode the entire SACCH content */ - NXDN_SACCH_Full_decode(opts, state); - } - - /* Reset the SACCH CRCs when all 4 voice frame - * SACCH spare parts have been received */ - if(PartOfFrame == 3) - { - /* Reset all CRCs of the SACCH */ - for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0; - } -#ifdef NXDN_DUMP - fprintf (stderr," "); -#endif - } - //fprintf (stderr, "\nV%c\n%c\n", ambe_fr, pr); - if (opts->errorbars == 1) - { - fprintf (stderr,"\n"); - } -}