diff --git a/include/dsd.h b/include/dsd.h index 48319a0..5fd5ad5 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -17,6 +17,17 @@ * PERFORMANCE OF THIS SOFTWARE. */ + //pretty pretty colors + + #define KNRM "\x1B[0m" + #define KRED "\x1B[31m" + #define KGRN "\x1B[32m" + #define KYEL "\x1B[33m" + #define KBLU "\x1B[34m" + #define KMAG "\x1B[35m" + #define KCYN "\x1B[36m" + #define KWHT "\x1B[37m" + #include "config.h" #include #include @@ -67,13 +78,11 @@ //look into making this not required by doing ifdef, make new c file for methods, and CLI case option for ncurses terminal #include //move this stuff to dsd.h #include //move this stuff to dsd.h -/* - * global variables - */ +// +// static volatile int exitflag; -//borrow from LEH typedef struct { uint8_t RFChannelType; @@ -148,8 +157,6 @@ typedef struct } NxdnElementsContent_t; -//LEH DMR - enum { MODE_UNENCRYPTED, @@ -230,8 +237,8 @@ typedef struct FullLinkControlPDU_t FullLC; } TimeSlotVoiceSuperFrame_t; -//end borrow from LEH -//LEH dPMR + +//dPMR /* Could only be 2 or 4 */ #define NB_OF_DPMR_VOICE_FRAME_TO_DECODE 2 @@ -293,11 +300,13 @@ typedef struct int audio_out_type; // 0 for device, 1 for file, 2 for portaudio int split; int playoffset; + int playoffsetR; char mbe_out_dir[1024]; char mbe_out_file[1024]; char mbe_out_path[1024]; FILE *mbe_out_f; float audio_gain; + float audio_gainR; int audio_out; char wav_out_file[1024]; SNDFILE *wav_out_f; @@ -337,27 +346,34 @@ typedef struct int pulse_raw_rate_out; int pulse_digi_rate_in; int pulse_digi_rate_out; + //int pulse_digi_rate_outR; int pulse_raw_in_channels; int pulse_raw_out_channels; int pulse_digi_in_channels; int pulse_digi_out_channels; + //int pulse_digi_out_channelsR; int pulse_flush; pa_simple *pulse_raw_dev_in; pa_simple *pulse_raw_dev_out; pa_simple *pulse_digi_dev_in; pa_simple *pulse_digi_dev_out; + pa_simple *pulse_digi_dev_outR; int use_ncurses_terminal; int reset_state; int payload; char output_name[1024]; - //LEH DMR Stuff + int EncryptionMode; - //LEH dPMR stuff unsigned int dPMR_curr_frame_is_encrypted; int dPMR_next_part_of_superframe; int inverted_dpmr; int frame_dpmr; + // + short int dmr_stereo; + // + int frame_ysf; + int inverted_ysf; //not sure if ysf comes in inverted or not, but signal could if IQ flipped } dsd_opts; @@ -365,6 +381,8 @@ typedef struct { int *dibit_buf; int *dibit_buf_p; + int *dmr_payload_buf; //try loading up a small amount to buffer, 144 or 288? + int *dmr_payload_p; //position for payload buffer int repeat; short *audio_out_buf; short *audio_out_buf_p; @@ -418,6 +436,8 @@ typedef struct int nac; int errs; int errs2; + int errsR; + int errs2R; int mbe_file_type; int optind; int numtdulc; @@ -425,17 +445,25 @@ typedef struct char slot0light[8]; //char slot1light[8]; float aout_gain; + float aout_gainR; float aout_max_buf[200]; + float aout_max_bufR[200]; float *aout_max_buf_p; + float *aout_max_buf_pR; int aout_max_buf_idx; + int aout_max_buf_idxR; int samplesPerSymbol; int symbolCenter; char algid[9]; char keyid[17]; int currentslot; + int hardslot; mbe_parms *cur_mp; mbe_parms *prev_mp; mbe_parms *prev_mp_enhanced; + mbe_parms *cur_mp2; + mbe_parms *prev_mp2; + mbe_parms *prev_mp_enhanced2; int p25kid; int payload_algid; int payload_keyid; @@ -444,6 +472,7 @@ typedef struct unsigned long long int K; unsigned int debug_audio_errors; + unsigned int debug_audio_errorsR; unsigned int debug_header_errors; unsigned int debug_header_critical_errors; @@ -478,10 +507,9 @@ typedef struct unsigned int nxdn_cipher_type; unsigned int nxdn_key; char nxdn_call_type[1024]; - char dmr_callsign[4][99]; //plenty of room in case of overflow; + char dmr_callsign[6][99]; //plenty of room in case of overflow; char dmr_lrrp[6][9999]; - //borrow from LEH NxdnSacchRawPart_t NxdnSacchRawPart[4]; NxdnFacch1RawPart_t NxdnFacch1RawPart[2]; NxdnFacch2RawPart_t NxdnFacch2RawPart; @@ -492,8 +520,7 @@ typedef struct char ambe_ciphered[49]; char ambe_deciphered[49]; - //end borrow - //LEH DMR struff + unsigned int color_code; unsigned int color_code_ok; unsigned int PI; @@ -511,10 +538,13 @@ typedef struct TimeSlotVoiceSuperFrame_t TS2SuperFrame; char dmr_branding[25]; - uint8_t dmr_12_rate_sf[36]; //going three frames deep - uint8_t dmr_34_rate_sf[54]; //going three frames deep + uint8_t dmr_12_rate_sf[2][60]; //going five frames deep by 12 bytes //[slot][value] + uint8_t dmr_34_rate_sf[2][64]; //going four frames deep by 16 bytes //[slot][value] + //char dmr_stereo_payload[144]; //load up 144 dibit buffer for every single DMR TDMA frame + //char dmr_msmode_payload[144]; + int dmr_stereo_payload[144]; //load up 144 dibit buffer for every single DMR TDMA frame + - //LEH dPMR stuff dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame; //These flags are used to known the DMR frame @@ -539,6 +569,10 @@ typedef struct unsigned char * dpmr_target_id; int dpmr_color_code; + short int dmr_stereo; //need state variable for upsample function + short int dmr_ms_rc; + short int dmr_ms_mode; + #ifdef TRACE_DSD char debug_prefix; char debug_prefix_2; @@ -555,6 +589,10 @@ typedef struct /* * Frame sync patterns */ + +#define FUSION_SYNC "31111311313113131131" //HA! +#define INV_FUSION_SYNC "13333133131331313313" //HA! + #define INV_P25P1_SYNC "333331331133111131311111" #define P25P1_SYNC "111113113311333313133333" @@ -568,14 +606,6 @@ typedef struct #define DSTAR_SYNC "313131313133131113313111" #define INV_DSTAR_SYNC "131313131311313331131333" -//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 INV_NXDN_BS_DATA_SYNC "131311331313333131" @@ -589,64 +619,52 @@ typedef struct #define DMR_BS_VOICE_SYNC "131111333113313313113313" #define DMR_MS_DATA_SYNC "311131133313133331131113" #define DMR_MS_VOICE_SYNC "133313311131311113313331" -//borrow extra syncs from LEH + +//inversion testing on MS +//#define DMR_MS_DATA_SYNC "133313311131311113313331" +//#define DMR_MS_VOICE_SYNC "311131133313133331131113" + +#define DMR_RC_DATA_SYNC "131331111133133133311313" + #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" #define PROVOICE_EA_SYNC "31131311331331111133131311311133" -//LEH dPMR -/* dPMR Frame Sync 1 - 48 bits sequence - * HEX : 57 FF 5F 75 D5 77 - * Binary : 0101 0111 1111 1111 0101 1111 0111 0101 1101 0101 0111 0111 - * Dibit : 1 1 1 3 3 3 3 3 1 1 3 3 1 3 1 1 3 1 1 1 1 3 1 3 */ - #define DPMR_FRAME_SYNC_1 "111333331133131131111313" - -/* dPMR Frame Sync 2 - 24 bits sequence - * HEX : 5F F7 7D - * Binary : 0101 1111 1111 0111 0111 1101 - * Dibit : 1 1 3 3 3 3 1 3 1 3 3 1 */ #define DPMR_FRAME_SYNC_2 "113333131331" - -/* dPMR Frame Sync 3 - 24 bits sequence - * HEX : 7D DF F5 - * Binary : 0111 1101 1101 1111 1111 0101 - * Dibit : 1 3 3 1 3 1 3 3 3 3 1 1 */ #define DPMR_FRAME_SYNC_3 "133131333311" - -/* dPMR Frame Sync 4 - 48 bits sequence - * HEX : FD 55 F5 DF 7F DD - * Binary : 1111 1101 0101 0101 1111 0101 1101 1111 0111 1111 1101 1101 - * Dibit : 3 3 3 1 1 1 1 1 3 3 1 1 3 1 3 3 1 3 3 3 3 1 3 1 */ #define DPMR_FRAME_SYNC_4 "333111113311313313333131" -//#define DPMR_FRAME_SYNC_4 "111333331133131131111313" /* dPMR Frame Sync 1 to 4 - Inverted */ #define INV_DPMR_FRAME_SYNC_1 "333111113311313313333131" #define INV_DPMR_FRAME_SYNC_2 "331111313113" #define INV_DPMR_FRAME_SYNC_3 "311313111133" #define INV_DPMR_FRAME_SYNC_4 "111333331133131131111313" -//#define INV_DPMR_FRAME_SYNC_4 "333111113311313313333131" -// /* * function prototypes */ void processDMRdata (dsd_opts * opts, dsd_state * state); void processDMRvoice (dsd_opts * opts, dsd_state * state); +void dmrBSBootstrap (dsd_opts * opts, dsd_state * state); +void dmrBS (dsd_opts * opts, dsd_state * state); +void dmrMS (dsd_opts * opts, dsd_state * state); +void dmrMSData (dsd_opts * opts, dsd_state * state); +void dmrMSBootstrap (dsd_opts * opts, dsd_state * state); void processdPMRvoice (dsd_opts * opts, dsd_state * state); void processAudio (dsd_opts * opts, dsd_state * state); -void playRawAudio (dsd_opts * opts, dsd_state * state); //added this one HERE HERE +void processAudioR (dsd_opts * opts, dsd_state * state); void openPulseInput (dsd_opts * opts); //not sure if we need to just pass opts, or opts and state yet void openPulseOutput (dsd_opts * opts); //not sure if we need to just pass opts, or opts and state yet void writeSynthesizedVoice (dsd_opts * opts, dsd_state * state); void playSynthesizedVoice (dsd_opts * opts, dsd_state * state); +void playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state); void openAudioOutDevice (dsd_opts * opts, int speed); void openAudioInDevice (dsd_opts * opts); @@ -695,10 +713,11 @@ void processProVoice (dsd_opts * opts, dsd_state * state); void processX2TDMAdata (dsd_opts * opts, dsd_state * state); void processX2TDMAvoice (dsd_opts * opts, dsd_state * state); void processDSTAR_HD (dsd_opts * opts, dsd_state * state); +void processYSF(dsd_opts * opts, dsd_state * state); //YSF short dmr_filter(short sample); 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); @@ -711,7 +730,7 @@ 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); @@ -722,7 +741,7 @@ 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); @@ -751,7 +770,7 @@ 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); -//LEH dPMR + void dPMRVoiceFrameProcess(dsd_opts * opts, dsd_state * state); void printdPMRAmbeVoiceSample(dsd_opts * opts, dsd_state * state); void printdPMRRawVoiceFrame (dsd_opts * opts, dsd_state * state); @@ -762,7 +781,7 @@ uint8_t CRC7BitdPMR(uint8_t * BufferIn, uint32_t BitLength); uint8_t CRC8BitdPMR(uint8_t * BufferIn, uint32_t BitLength); void ConvertAirInterfaceID(uint32_t AI_ID, uint8_t ID[8]); int32_t GetdPmrColorCode(uint8_t ChannelCodeBit[24]); -//LEH DMR + void ProcessDMR (dsd_opts * opts, dsd_state * state); void DMRDataFrameProcess(dsd_opts * opts, dsd_state * state); void DMRVoiceFrameProcess(dsd_opts * opts, dsd_state * state); @@ -797,6 +816,7 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] void ProcessMBCData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]); void ProcessMBChData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]); void ProcessWTFData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]); +void ProcessUnifiedData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]); void Hamming_7_4_init(); @@ -836,9 +856,6 @@ void QR_16_7_6_encode(unsigned char *origBits, unsigned char *encodedBits); bool QR_16_7_6_decode(unsigned char *rxBits); void InitAllFecFunction(void); - -//end borrow from LEH - void resetState (dsd_state * state); #ifdef __cplusplus @@ -860,6 +877,8 @@ void CDMRTrellisPointsToDibits(const unsigned char* points, signed char* dibits) void CDMRTrellisBitsToTribits(const unsigned char* payload, unsigned char* tribits); bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload); + + #ifdef __cplusplus } #endif diff --git a/src/dmr_bs.c b/src/dmr_bs.c new file mode 100644 index 0000000..7d3c70d --- /dev/null +++ b/src/dmr_bs.c @@ -0,0 +1,462 @@ +#include "dsd.h" +#include "dmr_const.h" + +//A subroutine for processing each TDMA frame individually to allow for +//processing voice and/or data on both BS slots (channels) simultaneously +void dmrBS (dsd_opts * opts, dsd_state * state) +{ + int i, j, k, l, dibit; + int *dibit_p; + char ambe_fr[4][24] = {0}; + char ambe_fr2[4][24] = {0}; + char ambe_fr3[4][24] = {0}; + char t_ambe_fr[4][24] = {9}; + char t_ambe_fr2[4][24] = {9}; + char t_ambe_fr3[4][24] = {9}; + const int *w, *x, *y, *z; + char sync[25]; + char syncdata[48]; + char cachdata[13] = {0}; + int mutecurrentslot; + int msMode; + char cc[4]; + unsigned char EmbeddedSignalling[16]; + int EmbeddedSignallingOk; + unsigned int internalcolorcode; + int internalslot; + char redundancyA[36]; + char redundancyB[36]; + unsigned short int vc1; + unsigned short int vc2; + + //add time to mirror printFrameSync + time_t now; + char * getTime(void) //get pretty hh:mm:ss timestamp + { + time_t t = time(NULL); + + char * curr; + char * stamp = asctime(localtime( & t)); + + curr = strtok(stamp, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + + return curr; + } + + //Init the superframe buffers + //memset(&state->TS1SuperFrame, 0, sizeof(TimeSlotVoiceSuperFrame_t)); + //memset(&state->TS2SuperFrame, 0, sizeof(TimeSlotVoiceSuperFrame_t)); + + //Init the color code status + state->color_code_ok = 0; + + vc1 = 2; + vc2 = 2; + + short int loop = 1; + short int skipcount = 0; + + //Run Loop while the getting is good + while (loop == 1) { + + // CACH + internalslot = -1; //reset here so we know if this value is being set properly + for(i = 0; i < 12; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + cachdata[i] = dibit; + state->dmr_stereo_payload[i] = dibit; + if(i == 2) + { + state->currentslot = (1 & (dibit >> 1)); + internalslot = (1 & (dibit >> 1)); + } + } + + //Setup for first AMBE Frame + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //First AMBE Frame, Full 36 + for(i = 0; i < 36; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+12] = dibit; + redundancyA[i] = dibit; + ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //check for repetitive data if caught in a 'no carrier' loop? Just picking random values. + //this will test for no carrier (input signal) and return us to no sync state if necessary + if (redundancyA[16] == redundancyB[16] && redundancyA[27] == redundancyB[27] && + redundancyA[01] == redundancyB[01] && redundancyA[32] == redundancyB[32] && + redundancyA[03] == redundancyB[03] && redundancyA[33] == redundancyB[33] && + redundancyA[13] == redundancyB[13] && redundancyA[07] == redundancyB[07] ) + { + goto END; + } + // end redundancy test, set B to A + for(i = 0; i < 36; i++) + { + redundancyB[i] = redundancyA[i]; + } + + //Setup for Second AMBE Frame + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //Second AMBE Frame, First Half 18 dibits just before Sync or EmbeddedSignalling + for(i = 0; i < 18; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+48] = dibit; + ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr2[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //short int l = 0; //do I still use this? + // signaling data or sync + for(i = 0; i < 24; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+66] = dibit; + syncdata[(2*i)] = (1 & (dibit >> 1)); // bit 1 + syncdata[(2*i)+1] = (1 & dibit); // bit 0 + sync[i] = (dibit | 1) + 48; + + if (i < 4 || i > 19) // + { + EmbeddedSignalling[2*i] = (1 & (dibit >> 1)); // bit 1 + EmbeddedSignalling[2*i+1] = (1 & dibit); // bit 0 + } + + //Used for ProcessVoiceBurstSync + if(internalslot == 0 && vc1 > 1 && vc1 < 6) //grab on vc1 values 2-5 B C D and E + { + /* Time slot 1 superframe buffer filling => SYNC data */ + state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2] = (1 & (dibit >> 1)); // bit 1 + state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2+1] = (1 & dibit); // bit 0 + } + if(internalslot == 1 && vc2 > 1 && vc2 < 6) //grab on vc2 values 2-5 B C D and E + { + /* Time slot 2 superframe buffer filling => SYNC data */ + state->TS2SuperFrame.TimeSlotRawVoiceFrame[vc2-1].Sync[i*2] = (1 & (dibit >> 1)); // bit 1 + state->TS2SuperFrame.TimeSlotRawVoiceFrame[vc2-1].Sync[i*2+1] = (1 & dibit); // bit 0 + } + + } + + sync[24] = 0; + EmbeddedSignallingOk = -1; + if(QR_16_7_6_decode(EmbeddedSignalling)) + { + EmbeddedSignallingOk = 1; + } + + internalcolorcode = 69; //set so we know if this value is being set properly + if(EmbeddedSignallingOk == 1) + { + state->color_code = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); + internalcolorcode = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); + state->color_code_ok = EmbeddedSignallingOk; + + //Power Indicator, not the other PI (header) + state->PI = (unsigned int)EmbeddedSignalling[4]; + state->PI_ok = EmbeddedSignallingOk; + + //Link Control Start Stop Indicator + state->LCSS = (unsigned int)((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]); + state->LCSS_ok = EmbeddedSignallingOk; + + } + else skipcount++; + + //Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling + for(i = 0; i < 18; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+90] = dibit; + ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr2[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //Setup for Third AMBE Frame + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //Third AMBE Frame, Full 36 + for(i = 0; i < 36; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+108] = dibit; + ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr3[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //reset vc counters to 1 if new voice sync frame on each slot + if ( (strcmp (sync, DMR_BS_VOICE_SYNC) == 0) ) + { + if (internalslot == 0) + { + vc1 = 1; + } + if (internalslot == 1) + { + vc2 = 1; + } + } + + //check for sync pattern here after collected the rest of the payload, decide what to do with it + if ( (strcmp (sync, DMR_BS_DATA_SYNC) == 0) ) + { + fprintf (stderr,"%s ", getTime()); + if (internalslot == 0) + { + sprintf(state->slot1light, "[slot1]"); + sprintf(state->slot2light, " slot2 "); + //fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | Data ", state->color_code); + fprintf (stderr,"Sync: +DMR "); + //constantly reset the vc counter to 1 each data frame in anticipation of new voice frame + vc1 = 1; + } + if (internalslot == 1) + { + sprintf(state->slot2light, "[slot2]"); + sprintf(state->slot1light, " slot1 "); + //fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | Data ", state->color_code); + fprintf (stderr,"Sync: +DMR "); + //constantly reset the vc counter to 1 each data frame in anticipation of new voice frame + vc2 = 1; + } + processDMRdata (opts, state); + skipcount++; //after 6 data frames, drop back to getFrameSync and process subsequent data with processDMRdata + goto SKIP; + } + + if( (strcmp (sync, DMR_BS_DATA_SYNC) != 0) ) //only play voice no data sync // || (strcmp (sync, DMR_MS_DATA_SYNC) != 0) + { + if (EmbeddedSignallingOk == 0) + { + //goto END; + } + skipcount = 0; //reset skip count if processing voice frames + fprintf (stderr,"%s ", getTime()); + if (internalslot == 0) + { + fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc1); + } + + if (internalslot == 1) + { + fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc2); + } + if (internalslot == 0 && vc1 == 6) //presumably when full (and no sync issues) + { + //process voice burst + ProcessVoiceBurstSync(opts, state); + fprintf (stderr, "\n"); + } + if (internalslot == 1 && vc2 == 6) //presumably when full (and no sync issues) + { + //process voice burst + ProcessVoiceBurstSync(opts, state); + fprintf (stderr, "\n"); + } + processMbeFrame (opts, state, NULL, ambe_fr, NULL); + processMbeFrame (opts, state, NULL, ambe_fr2, NULL); + processMbeFrame (opts, state, NULL, ambe_fr3, NULL); + if (internalslot == 0) + { + vc1++; + } + if (internalslot == 1) + { + vc2++; + } + } + + // recalibrate center/umid/lmid, not sure this helps or does anything particularly in this case + state->center = ((state->max) + (state->min)) / 2; + state->umid = (((state->max) - state->center) * 5 / 8) + state->center; + state->lmid = (((state->min) - state->center) * 5 / 8) + state->center; + + //Escape conditions to break the loop + //7 seems optimal, allows for an extra frame each in case of late entry on dual voices + if ( (vc1 > 7 && vc2 > 7) ) + { + goto END; + } + //14 probably allows a few more in case of a bit of jitter but eventually breaks loop (1 second?) + if ( (vc1 > 14 || vc2 > 14) ) + { + goto END; + } + //using these conditions may cause excessive resyncs IF bad signal, + //but still better than getting stuck in a wonk wonk loop for too long. + //maybe consider making a opt variable for loose or aggressive resyncing for this sort of thing? + if (1 == 1) //set for more aggressive or less aggressive resync during accumulated playback errs + { + //errors caused due to playing MBE files out of sync, break loop + if (state->errs > 2 || state->errsR > 2) + { + //goto END; // + } + //errors caused due to playing MBE files out of sync, break loop + if (state->errs2 > 4 || state->errs2R > 4) + { + goto END; // + } + } + + //earlier skip conditions teleport us here to process further skip conditions before restarting while loop + SKIP: + if (skipcount > 2) //after 2 consecutive data frames, drop back to getFrameSync and process with processDMRdata + { + goto END; + } + + //since we are in a while loop, run ncursesPrinter here. + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } + + } // while loop + //Teleport here on END condition, set or reset variables and return to look for new frame sync + END: + state->dmr_stereo = 0; + state->errs2R = 0; + state->errs2 = 0; +} + +//Only process 2nd half voice payload (3rd frame) and then jump to full BS decoding +void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) +{ + int i, j, k, l, dibit; + int *dibit_p; + char ambe_fr[4][24] = {0}; + char ambe_fr2[4][24] = {0}; + char ambe_fr3[4][24] = {0}; + const int *w, *x, *y, *z; + char sync[25]; + char syncdata[48]; + char cachdata[13] = {0}; + int mutecurrentslot; + int msMode; + char cc[4]; + unsigned char EmbeddedSignalling[16]; + unsigned int EmbeddedSignallingOk; + + //add time to mirror printFrameSync + time_t now; + char * getTime(void) //get pretty hh:mm:ss timestamp + { + time_t t = time(NULL); + + char * curr; + char * stamp = asctime(localtime( & t)); + + curr = strtok(stamp, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + + return curr; + } + + //skip the 18 dibits of the 2nd frame, since we can't play only half a frame + skipDibit (opts, state, 18); + + //Setup for Third AMBE Frame + + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //Third AMBE Frame, Full 36 + for(i = 0; i < 36; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr3[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + fprintf (stderr,"\n%s ", getTime()); + fprintf (stderr,"Sync: +DMR | Frame Sync | DMRSTEREO | VC1 FS \n"); + processMbeFrame (opts, state, NULL, ambe_fr3, NULL); + dmrBS (opts, state); //bootstrap into full TDMA frame for BS mode + +} diff --git a/src/dmr_data.c b/src/dmr_data.c index d086880..d747695 100644 --- a/src/dmr_data.c +++ b/src/dmr_data.c @@ -49,6 +49,12 @@ processDMRdata (dsd_opts * opts, dsd_state * state) bursttype[4] = 0; dibit_p = state->dibit_buf_p - 90; + //using the estimate_symbol method for the dmr_payload_p buffer causes sync + //issues with P25, so only do it when frame_p25p1 == 0, or -fr option + if (opts->frame_p25p1 != 1) + { + dibit_p = state->dmr_payload_p - 90; + } // CACH for (i = 0; i < 12; i++) @@ -59,6 +65,11 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[i]; + } + //fprintf(stderr, "%X", dibit); cachdata[i] = dibit; if (i == 2) { @@ -79,6 +90,15 @@ processDMRdata (dsd_opts * opts, dsd_state * state) state->slot1light[0] = ' '; state->slot1light[6] = ' '; } + //method to only see data from one slot or the other when data occupies both slots or gets cooked by sync + state->hardslot = 9; //0 to only listen to slot 0 voice, 1 for slot 1, 9 for both + if(state->hardslot != 9 && state->hardslot != state->currentslot) + //if(1==1) + { + fprintf (stderr, " Current Slot = %d", state->currentslot + 1); + fprintf (stderr, "\n"); //line break after breaking out of jail + //goto JUMP; + } } } cachdata[12] = 0; @@ -107,6 +127,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[i+12]; + } trellisdibits[i] = dibit; info[2*i] = (1 & (dibit >> 1)); // bit 1 info[(2*i)+1] = (1 & dibit); // bit 0 @@ -119,6 +143,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[61]; //61, not i+61 + } cc[0] = (1 & (dibit >> 1)); // bit 1 cc[1] = (1 & dibit); // bit 0 SlotType[0] = (1 & (dibit >> 1)); // bit 1 @@ -130,6 +158,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[62]; + } cc[2] = (1 & (dibit >> 1)); // bit 1 cc[3] = (1 & dibit); // bit 0 SlotType[2] = (1 & (dibit >> 1)); // bit 1 @@ -147,6 +179,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) //state + { + dibit = (int)state->dmr_stereo_payload[63]; //(int) + } // burst = (unsigned int)((1 & (dibit >> 1)) << 3); // burst |= (unsigned int)((1 & (dibit >> 0)) << 2); // bursttype[0] = (1 & (dibit >> 1)) + 48; // bit 1 @@ -160,6 +196,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) //state + { + dibit = (int)state->dmr_stereo_payload[64]; //(int) + } // burst |= (unsigned int)((1 & (dibit >> 1)) << 1); // burst |= (unsigned int)((1 & (dibit >> 0)) << 0); // bursttype[2] = (1 & (dibit >> 1)) + 48; // bit 1 @@ -174,6 +214,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[65]; + } SlotType[8] = (1 & (dibit >> 1)); // bit 1 SlotType[9] = (1 & dibit); // bit 0 @@ -186,6 +230,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[i+66]; //double check these i+ values make sure we are on the right ones + } syncdata[2*i] = (1 & (dibit >> 1)); // bit 1 syncdata[(2*i)+1] = (1 & dibit); // bit 0 sync[i] = (dibit | 1) + 48; @@ -216,6 +264,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) sprintf(state->slot2light, "[slot2]"); } } + else if(strcmp (sync, DMR_DIRECT_MODE_TS1_DATA_SYNC) == 0) { state->currentslot = 0; @@ -236,11 +285,18 @@ processDMRdata (dsd_opts * opts, dsd_state * state) // Slot type - Second part - Parity bit for (i = 0; i < 5; i++) { - dibit = getDibit(opts, state); + if (state->dmr_stereo == 0) //only get dibits if not using dmr_stereo method + { + dibit = getDibit(opts, state); + } if (opts->inverted_dmr == 1) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[i+90]; //double checked these i+ values make sure we are on the right ones + } SlotType[(i*2) + 10] = (1 & (dibit >> 1)); // bit 1 SlotType[(i*2) + 11] = (1 & dibit); // bit 0 } @@ -250,8 +306,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) else SlotTypeOk = 0; /* Slot Type parity checked => Fill the color code */ - state->color_code = (unsigned int)((cc[0] << 3) + (cc[1] << 2) + (cc[2] << 1) + cc[3]); + //state->color_code = (unsigned int)((cc[0] << 3) + (cc[1] << 2) + (cc[2] << 1) + cc[3]); + state->color_code = (SlotType[0] << 3) + (SlotType[1] << 2) +(SlotType[2] << 1) + (SlotType[3] << 0); state->color_code_ok = SlotTypeOk; + //fprintf(stderr, "| Color Code=%02d ", (int)state->color_code); /* Reconstitute the burst type */ burst = (unsigned int)((SlotType[4] << 3) + (SlotType[5] << 2) + (SlotType[6] << 1) + SlotType[7]); @@ -263,13 +321,55 @@ processDMRdata (dsd_opts * opts, dsd_state * state) bursttype[3] = SlotType[7] + '0'; bursttype[4] = '\0'; + /* //delete this chunk later + if (state->dmr_stereo == 3) //may not need this any longer + { + burst = (state->dmr_stereo_payload[63] << 2) | (state->dmr_stereo_payload[64]); + //this whole split for getting burst and burst type is makes no sense + //why not just use burst + bursttype[0] = (((state->dmr_stereo_payload[63] >> 1) & 1) + '0'); + bursttype[1] = (((state->dmr_stereo_payload[63] >> 0) & 1) + '0'); + bursttype[2] = (((state->dmr_stereo_payload[64] >> 1) & 1) + '0'); + bursttype[3] = (((state->dmr_stereo_payload[64] >> 0) & 1) + '0'); + bursttype[4] = '\0'; + //fprintf(stderr, "BURST1 = %04b ", burst); + } + //figure out why the sync is wrong when dumping the payload to processDMRdata for MS Data + //I think its a conversion issue with the payload(chat) from the dibit buffer (int *) + //actually, its the dibit buffer storing as 1 and 3 only (GFSK) when sync drops + //made a seperate dmr buffer, but still, when sync loss and regain, takes a few syncs to calibrate center/umid/lmid properly + //getting accurate MS data AND leading BS data may be impossible without saving the symbols, calibrating, then going back + //and running the buffer payload, but I honestly don't know right now, probably easier to start from stratch than fix this + if (state->dmr_ms_mode == 7) + { + burst = (unsigned int)((SlotType[4] << 3) | (SlotType[5] << 2) | (SlotType[6] << 1) | SlotType[7]); + bursttype[0] = SlotType[4] + '0'; + bursttype[1] = SlotType[5] + '0'; + bursttype[2] = SlotType[6] + '0'; + bursttype[3] = SlotType[7] + '0'; + bursttype[4] = '\0'; + //fprintf(stderr, "BURST1 = %04b ", burst); + } + + if (state->dmr_stereo == 3) + { + fprintf(stderr, "BURST2 = %b%b%b%b Slot Dump ", SlotType[4], SlotType[5], SlotType[6], SlotType[7] ); + fprintf(stderr, " Slot Dump = "); + for (i = 0; i < 20; i++) + { + fprintf(stderr, "%b", SlotType[i]); + } + fprintf(stderr, "\n "); + } + */ + if (strcmp (bursttype, "0000") == 0) { sprintf(state->fsubtype, " PI Header "); } else if (strcmp (bursttype, "0001") == 0) { - sprintf(state->fsubtype, " VOICE Header "); + sprintf(state->fsubtype, " VOICE LC Header "); } else if (strcmp (bursttype, "0010") == 0) { @@ -316,31 +416,55 @@ processDMRdata (dsd_opts * opts, dsd_state * state) //trellis for (i = 0; i < 49; i++) { - dibit = getDibit(opts, state); + if (state->dmr_stereo == 0) //only get dibits if not using dmr_stereo method + { + dibit = getDibit(opts, state); + } if (opts->inverted_dmr == 1) { dibit = (dibit ^ 2); } + if (state->dmr_stereo == 1) + { + dibit = (int)state->dmr_stereo_payload[i+95]; //double checked these i+ values make sure we are on the right ones + } trellisdibits[i+49] = dibit; info[(2*i) + 98] = (1 & (dibit >> 1)); // bit 1 info[(2*i) + 99] = (1 & dibit); // bit 0 } // Skip cach (24 bit = 12 dibit) and next slot 1st half (98 + 10 bit = 49 + 5 dibit) - skipDibit (opts, state, 12 + 49 + 5); + if (state->dmr_stereo == 0) + { + skipDibit (opts, state, 12 + 49 + 5); + } if (opts->errorbars == 1) { /* Print the color code */ - fprintf(stderr, "| Color Code=%02d ", (int)state->color_code); + //if (burst == 0b1001 && state->color_code_ok) //only print on idle for data types, otherwise prints on voice frames. + if (SlotTypeOk == 1) + { + fprintf (stderr, "%s", KCYN); + fprintf(stderr, "| Color Code=%02d ", (int)state->color_code); + fprintf (stderr, "%s", KNRM); + //state->dmr_color_code = state->color_code; + } + else fprintf(stderr, "| "); //if(state->color_code_ok) fprintf(stderr, "(OK) |"); - if(state->color_code_ok) fprintf(stderr, "(CRC OK ) |"); //add line break - else fprintf(stderr, "(CRC ERR) |"); //add line break + if(state->color_code_ok) fprintf(stderr, "| (CRC OK ) |"); //add line break + else + { + fprintf (stderr, "%s", KRED); + fprintf(stderr, "| (CRC ERR) |"); + fprintf (stderr, "%s", KNRM); + } //fprintf (stderr, "\n"); //print line break if (strcmp (state->fsubtype, " ") == 0) { - fprintf(stderr, " Unknown burst type: %s", bursttype); + //fprintf(stderr, " Unknown burst type: %s", bursttype); + fprintf(stderr, " Unknown"); } else { @@ -368,6 +492,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) /* Burst = TLC */ case 0b0010: { + //Not sure if I really care about this in the context of what it shows ProcessDmrTerminaisonLC(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType); break; } @@ -375,6 +500,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) /* Burst = CSBK */ case 0b0011: { + //going to disable until I can find more useful info to present ProcessCSBK(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType); break; } @@ -386,7 +512,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) break; } - /* Burst = MBC */ + /* Burst = MBC Continuation*/ case 0b0101: { //ProcessMBCData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType); @@ -410,14 +536,15 @@ processDMRdata (dsd_opts * opts, dsd_state * state) /* Burst = RATE 3/4 DATA */ case 0b1000: { - //disabled until a viable viterbi/trellis decoding solution is worked out - //Process34Data(opts, state, trellisdibits, (uint8_t *)syncdata, (uint8_t *)SlotType); + //need to keep working on improving the trellis decode, but is partially viable now + Process34Data(opts, state, trellisdibits, (uint8_t *)syncdata, (uint8_t *)SlotType); break; } /* Burst = Slot idle */ case 0b1001: { + if(state->color_code_ok) state->dmr_color_code = state->color_code; //try setting this on idle if crc ok break; } @@ -428,10 +555,10 @@ processDMRdata (dsd_opts * opts, dsd_state * state) break; } - /* Burst = WTF 1101 Type DATA */ + /* Burst = Unified Single Block DATA */ case 0b1101: { - //ProcessWTFData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType); + //ProcessUnifiedData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType); break; } @@ -448,5 +575,5 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { fprintf(stderr, "\n"); } - + //JUMP: } /* End processDMRdata() */ diff --git a/src/dmr_ms.c b/src/dmr_ms.c new file mode 100644 index 0000000..e8dc69d --- /dev/null +++ b/src/dmr_ms.c @@ -0,0 +1,672 @@ +#include "dsd.h" +#include "dmr_const.h" + +//A subroutine for processing MS voice +void dmrMS (dsd_opts * opts, dsd_state * state) +{ + //fprintf (stderr, "\n Quick DMR Voice Testing\n"); + int i, j, k, l, dibit; + int *dibit_p; + char ambe_fr[4][24] = {0}; + char ambe_fr2[4][24] = {0}; + char ambe_fr3[4][24] = {0}; + char t_ambe_fr[4][24] = {9}; + char t_ambe_fr2[4][24] = {9}; + char t_ambe_fr3[4][24] = {9}; + const int *w, *x, *y, *z; + char sync[25]; + char syncdata[48]; + //standalone inbound rc sync exists on dibits 48-96? + //or 44-92? of each potential payload, middle 10 ms or 30 ms frame + char rcsync[25]; + char rcsyncdata[96]; //96 bit RC sync data + char cachdata[13] = {0}; + int mutecurrentslot; + int msMode; + char cc[4]; + unsigned char EmbeddedSignalling[16]; + int EmbeddedSignallingOk; + unsigned int internalcolorcode; + int internalslot; + int activeslot; + char redundancyA[36]; + char redundancyB[36]; + unsigned short int vc1; + unsigned short int vc2; + //add time to mirror printFrameSync + time_t now; + char * getTime(void) //get pretty hh:mm:ss timestamp + { + time_t t = time(NULL); + + char * curr; + char * stamp = asctime(localtime( & t)); + + curr = strtok(stamp, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + + return curr; + } + + //Init the color code status + state->color_code_ok = 0; + + vc1 = 2; + vc2 = 2; + + short int loop = 1; + short int skipcount = 0; + + //Hardset variables for MS + state->currentslot = 0; + internalslot = 0; + activeslot = 0; + + //Run Loop while the getting is good + while (loop == 1) { + + // No CACH in MS Mode? + for(i = 0; i < 12; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + cachdata[i] = dibit; + state->dmr_stereo_payload[i] = dibit; + if(i == 2) + { + //state->currentslot = (1 & (dibit >> 1)); + //internalslot = (1 & (dibit >> 1)); + } + } + + //Setup for first AMBE Frame + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //First AMBE Frame, Full 36 + for(i = 0; i < 36; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+12] = dibit; + redundancyA[i] = dibit; + ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //check for repetitive data if caught in a 'no carrier' loop? Just picking random values. + //this will test for no carrier (input signal) and return us to no sync state if necessary + if (redundancyA[16] == redundancyB[16] && redundancyA[27] == redundancyB[27] && + redundancyA[01] == redundancyB[01] && redundancyA[32] == redundancyB[32] && + redundancyA[03] == redundancyB[03] && redundancyA[33] == redundancyB[33] && + redundancyA[13] == redundancyB[13] && redundancyA[07] == redundancyB[07] ) + { + //goto END; + } + for(i = 0; i < 36; i++) + { + redundancyB[i] = redundancyA[i]; + } + + //Setup for Second AMBE Frame + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //Second AMBE Frame, First Half 18 dibits just before Sync or EmbeddedSignalling + for(i = 0; i < 18; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+48] = dibit; + ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr2[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + // signaling data or sync + for(i = 0; i < 24; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+66] = dibit; + syncdata[(2*i)] = (1 & (dibit >> 1)); // bit 1 + syncdata[(2*i)+1] = (1 & dibit); // bit 0 + sync[i] = (dibit | 1) + 48; + + if (i < 4 || i > 19) // + { + EmbeddedSignalling[2*i] = (1 & (dibit >> 1)); // bit 1 + EmbeddedSignalling[2*i+1] = (1 & dibit); // bit 0 + } + + // load the superframe to do the voiceburstsync processing + if(internalslot == 0 && vc1 > 1 && vc1 < 6) //grab on vc1 values 2-5 B C D and E + { + /* Time slot 1 superframe buffer filling => SYNC data */ + state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2] = (1 & (dibit >> 1)); // bit 1 + state->TS1SuperFrame.TimeSlotRawVoiceFrame[vc1-1].Sync[i*2+1] = (1 & dibit); // bit 0 + } + if(internalslot == 1 && vc2 > 1 && vc2 < 6) //grab on vc2 values 2-5 B C D and E + { + /* Time slot 2 superframe buffer filling => SYNC data */ + state->TS2SuperFrame.TimeSlotRawVoiceFrame[vc2-1].Sync[i*2] = (1 & (dibit >> 1)); // bit 1 + state->TS2SuperFrame.TimeSlotRawVoiceFrame[vc2-1].Sync[i*2+1] = (1 & dibit); // bit 0 + } + + } + + sync[24] = 0; + EmbeddedSignallingOk = -1; + if(QR_16_7_6_decode(EmbeddedSignalling)) + { + EmbeddedSignallingOk = 1; + } + + internalcolorcode = 69; //set so we know if this value is being set properly + if(EmbeddedSignallingOk == 1) + { + state->color_code = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); + internalcolorcode = (unsigned int)((EmbeddedSignalling[0] << 3) + (EmbeddedSignalling[1] << 2) + (EmbeddedSignalling[2] << 1) + EmbeddedSignalling[3]); + state->color_code_ok = EmbeddedSignallingOk; + //Power Indicator, not the other PI (header) + state->PI = (unsigned int)EmbeddedSignalling[4]; + state->PI_ok = EmbeddedSignallingOk; + //Link Control Start Stop Indicator + state->LCSS = (unsigned int)((EmbeddedSignalling[5] << 1) + EmbeddedSignalling[6]); + state->LCSS_ok = EmbeddedSignallingOk; + + } + //else skipcount++; + + //Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling + for(i = 0; i < 18; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+90] = dibit; + ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr2[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + //WIP for RC inbound sync data, part 2, second 24 bits (12 dibits) + if (i <= 12) + { + rcsyncdata[i+12] = (dibit | 1) + 48; //test and double check positions for this sync data + } + + } + + //Setup for Third AMBE Frame + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //Third AMBE Frame, Full 36 + for(i = 0; i < 36; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+108] = dibit; + ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr3[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + //end early to allow next sync without skipping a voice superframe + //only use if only doing 6 VC and nothing else, otherwise, will lose sync + if (vc1 == 6 && i == 30) + { + //i = 36; + } + + } + + if ( (strcmp (sync, DMR_MS_VOICE_SYNC) == 0) ) // + { + if (internalslot == 0) + { + vc1 = 1; + fprintf (stderr, "MS Slot 1 Voice Sync \n"); + //activeslot = 0; + + } + if (internalslot == 1) + { + vc2 = 1; + //fprintf (stderr, "MS Slot 2 Voice Sync \n"); + //activeslot = 1; + } + state->dmr_ms_mode = 1; //set to 1 here?? + } + + state->dmr_ms_mode = 1; //set to 1 here? + //testing to see if we need to do something to get MS mode working properly, + //get proper sync, skip frames, etc. + if (state->dmr_ms_mode == 1 ) //&& vc1 < 7 + { + //do something + fprintf (stderr, "MS MODE "); + } + + //don't know if we will catch an RC sync in here or not, should be on VC6 if it occurs + if ( (strcmp (rcsync, DMR_RC_DATA_SYNC) == 0) || (strcmp (sync, DMR_RC_DATA_SYNC) == 0) ) //should be in same position as sync + { + fprintf (stderr,"%s ", getTime()); + if (internalslot == 0) + { + sprintf(state->slot1light, "[slot1]"); + sprintf(state->slot2light, " slot2 "); + fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | RC ", state->color_code); + //test with vc1 reset disabled, if all is well, leave disabled + //vc1 = 1; + } + if (internalslot == 1) + { + sprintf(state->slot2light, "[slot2]"); + sprintf(state->slot1light, " slot1 "); + fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | RC ", state->color_code); + //test with vc1 reset disabled, if all is well, leave disabled + //vc2 = 1; + } + fprintf (stderr, "\n "); //21 spaces to line up the sync + //processDMRdata (opts, state); + state->dmr_ms_rc = 1; //don't know what to do with this, if anything... + goto SKIP; + } + + //check for sync pattern here after collected the rest of the payload, decide what to do with it + if ( (strcmp (sync, DMR_MS_DATA_SYNC) == 0) ) + { + fprintf (stderr,"%s ", getTime()); + if (internalslot == 0) + { + sprintf(state->slot1light, "[slot1]"); + sprintf(state->slot2light, " slot2 "); + //fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | MS Data ", state->color_code); + fprintf (stderr,"Sync: +DMR "); + //test with vc1 reset disabled, if all is well, leave disabled + //vc1 = 1; + } + if (internalslot == 1) + { + sprintf(state->slot2light, "[slot2]"); + sprintf(state->slot1light, " slot1 "); + //fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | Data ", state->color_code); + fprintf (stderr,"Sync: +DMR "); + //test with vc1 reset disabled, if all is well, leave disabled + //vc2 = 1; + } + //fprintf (stderr, "\n "); //21 spaces to line up the sync + //fprintf (stderr, " "); //21 spaces to line up the sync + state->dmr_ms_mode = 1; //set to 1 here?? + processDMRdata (opts, state); + skipcount++; + //goto SKIP; + goto END; + } + + if( (strcmp (sync, DMR_MS_DATA_SYNC) != 0) && internalslot == activeslot && vc1 < 7) //only play voice no MS Data Sync and vc1 below 6 (no voice resync) + { + + skipcount = 0; //reset skip count if processing voice frames + fprintf (stderr,"%s ", getTime()); + if (internalslot == 0) + { + fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc1); + } + + if (internalslot == 1) + { + fprintf (stderr,"Sync: +DMR slot1 [slot2] | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc2); + } + if (internalslot == 0 && vc1 == 6) //presumably when full (and no sync issues) + { + //process voice burst + ProcessVoiceBurstSync(opts, state); + fprintf (stderr, "\n"); + } + if (internalslot == 1 && vc2 == 6) //presumably when full (and no sync issues) + { + //process voice burst + //ProcessVoiceBurstSync(opts, state); + //fprintf (stderr, "\n"); + } + + processMbeFrame (opts, state, NULL, ambe_fr, NULL); + processMbeFrame (opts, state, NULL, ambe_fr2, NULL); + processMbeFrame (opts, state, NULL, ambe_fr3, NULL); + if (internalslot == 0) + { + //vc1++; + } + if (internalslot == 1) + { + vc2++; + } + } + vc1++; + //6 seems optimal for MS, allows to quickly exit and resync if wonky or something + if ( (vc1 > 6) || skipcount > 2) //escape to find new sync if deadspins without a renewed voice frame sync inside of loop + { + goto END; + } + + SKIP: + skipDibit (opts, state, 144); //skip to next slot? + state->dmr_ms_rc = 0; + + //since we are in a repetitive loop, run ncursesPrinter here + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } + + } // end while loop + //reset these variables when exiting MS mode. + END: + //get first half payload dibits and store them in the payload for the next repitition + skipDibit (opts, state, 144); + //CACH + First Half Payload = 12 + 54 + for (i = 0; i < 66; i++) //66 + { + dibit = getDibit(opts, state); + if (opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i] = dibit; + //fprintf(stderr, "%X", state->dmr_stereo_payload[i]); + } + + state->dmr_stereo = 0; + state->dmr_ms_mode = 0; + state->dmr_ms_rc = 0; + +} + +//Only process 2nd half voice payload (3rd frame) and then jump to full MS Voice decoding. +void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) +{ + int i, j, k, l, dibit; + int *dibit_p; + char ambe_fr[4][24] = {0}; + char ambe_fr2[4][24] = {0}; + char ambe_fr3[4][24] = {0}; + const int *w, *x, *y, *z; + char sync[25]; + char syncdata[48]; + char cachdata[13] = {0}; + int mutecurrentslot; + int msMode; + char cc[4]; + unsigned char EmbeddedSignalling[16]; + unsigned int EmbeddedSignallingOk; + + //add time to mirror sync + time_t now; + char * getTime(void) //get pretty hh:mm:ss timestamp + { + time_t t = time(NULL); + + char * curr; + char * stamp = asctime(localtime( & t)); + + curr = strtok(stamp, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + + return curr; + } + + dibit_p = state->dmr_payload_p - 90; + //payload buffer tests + //CACH + First Half Payload + Sync = 12 + 54 + 24 + //fprintf(stderr, "\n Full DMR Stereo Dump Dibits 90 From Buffer\n"); + for (i = 0; i < 90; i++) //90 + { + state->dmr_stereo_payload[i] = *dibit_p; + dibit_p++; + //fprintf(stderr, "%X", state->dmr_stereo_payload[i]); + } + //end payload buffer test + + for(i = 0; i < 12; i++) + { + dibit = state->dmr_stereo_payload[i]; + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + cachdata[i] = dibit; + } + + //Setup for first AMBE Frame + + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //First AMBE Frame, Full 36 + for(i = 0; i < 36; i++) + { + dibit = state->dmr_stereo_payload[i+12]; + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + //state->dmr_stereo_payload[i+12] = dibit; + ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //Setup for Second AMBE Frame + + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //Second AMBE Frame, First Half 18 dibits just before Sync or EmbeddedSignalling + for(i = 0; i < 18; i++) + { + dibit = state->dmr_stereo_payload[i+48]; + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr2[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling + for(i = 0; i < 18; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr2[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + //Setup for Third AMBE Frame + + //Interleave Schedule + w = rW; + x = rX; + y = rY; + z = rZ; + + //Third AMBE Frame, Full 36 + for(i = 0; i < 36; i++) + { + dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr3[*y][*z] = (1 & dibit); // bit 0 + + w++; + x++; + y++; + z++; + + } + + fprintf (stderr, "MS MODE "); + fprintf (stderr,"%s ", getTime()); + fprintf (stderr,"Sync: +DMR | Color Code=XX | DMRSTEREO | VC1 FS \n"); + processMbeFrame (opts, state, NULL, ambe_fr, NULL); + processMbeFrame (opts, state, NULL, ambe_fr2, NULL); + processMbeFrame (opts, state, NULL, ambe_fr3, NULL); + skipDibit (opts, state, 144); //skip to next TDMA slot + dmrMS (opts, state); //bootstrap into full TDMA frame + +} + +void dmrMSData (dsd_opts * opts, dsd_state * state) +{ + int i; + int dibit; + int *dibit_p; + unsigned int burst; + + //add time to mirror sync + time_t now; + char * getTime(void) //get pretty hh:mm:ss timestamp + { + time_t t = time(NULL); + + char * curr; + char * stamp = asctime(localtime( & t)); + + curr = strtok(stamp, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + + return curr; + } + + //CACH + First Half Payload + Sync = 12 + 54 + 24 + //fprintf(stderr, "\n Full DMR Stereo Dump Dibits 90 From Buffer\n"); + for (i = 0; i < 90; i++) //90 + { + //fprintf(stderr, "%X", state->dmr_stereo_payload[i]); + } + + for (i = 0; i < 54; i++) + { + dibit = getDibit(opts, state); + if (opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i+90] = dibit; + + } + //fprintf(stderr, "\n"); + //print nice pretty lines + fprintf (stderr, "MS MODE "); + fprintf (stderr, "%s ", getTime()); + //fprintf (stderr, "Sync: +MS DATA | Color Code=XX | DMRSTEREO | Data "); + fprintf (stderr, "Sync: +DMR "); + //fprintf (stderr, "\n "); + + //sprintf for slot 1, doesn't matter, just makes print out of data look uniform setting ahead of time + sprintf(state->slot1light, "[slot1]"); + sprintf(state->slot2light, " slot2 "); + + //process data + state->dmr_stereo = 1; + state->dmr_ms_mode = 1; + processDMRdata (opts, state); + state->dmr_stereo = 0; + state->dmr_ms_mode = 0; + + //get potential first half payload dibits and store them in the payload for the next repitition, MS voice or data. + skipDibit (opts, state, 144); + //CACH + First Half Payload = 12 + 54 + for (i = 0; i < 66; i++) //66 + { + dibit = getDibit(opts, state); + if (opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } + state->dmr_stereo_payload[i] = dibit; + //fprintf(stderr, "%X", state->dmr_stereo_payload[i]); + } + +} diff --git a/src/dmr_process_voice.c b/src/dmr_process_voice.c index da3519f..9c3e2af 100644 --- a/src/dmr_process_voice.c +++ b/src/dmr_process_voice.c @@ -19,6 +19,26 @@ #include "dmr_const.h" #include "p25p1_check_hdu.h" // + +// +void ProcessDMR (dsd_opts * opts, dsd_state * state) +{ + uint32_t i, j; + uint32_t Frame; + TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameL = NULL; + TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameR = NULL; + TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameRC = NULL; //Reverse Test for MS Backwards + + int *errs; + int *errs2; + unsigned long long int k; + int x; + k = 0; + + TSVoiceSupFrameL = &state->TS1SuperFrame; + TSVoiceSupFrameR = &state->TS2SuperFrame; + +// int BP[256] = { 0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903, 0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306, @@ -54,71 +74,53 @@ int BP[256] = { 0x41F5, 0x5EF5, 0xA2F5, 0xBDF5, 0x64F6, 0x7BF6, 0x87F6, 0x98F6 //255 }; // -void ProcessDMR (dsd_opts * opts, dsd_state * state) -{ - uint32_t i, j; - uint32_t Frame; - TimeSlotVoiceSuperFrame_t * TSVoiceSupFrame = NULL; - TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameL = NULL; - TimeSlotVoiceSuperFrame_t * TSVoiceSupFrameR = NULL; - - int *errs; - int *errs2; - int *errsR; - int *errs2R; - unsigned long long int k; - int x; - k = 0; - - if(state->currentslot == 0) - { - TSVoiceSupFrame = &state->TS1SuperFrame; - } - else - { - TSVoiceSupFrame = &state->TS2SuperFrame; - } - //TSVoiceSupFrameL = &state->TS1SuperFrame; - //TSVoiceSupFrameR = &state->TS2SuperFrame; - -// -if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0) +if (state->currentslot == 0 && state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0) { + fprintf (stderr, "%s", KYEL); fprintf(stderr, " BPK %lld", state->K); + fprintf (stderr, "%s", KNRM); + k = BP[state->K]; + k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k ); for(Frame = 0; Frame < 6; Frame++) { for(i = 0; i < 3; i++) { for(j = 0; j < 49; j++) - { - k = BP[state->K]; - k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k ); + { x = ( ((k << j) & 0x800000000000) >> 47 ); - TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x; - } + TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x; + } + } + } +} + +if (state->currentslot == 1 && state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0) +{ + fprintf (stderr, "%s", KYEL); + fprintf(stderr, " BPK %lld", state->K); + fprintf (stderr, "%s", KNRM); + k = BP[state->K]; + k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k ); + for(Frame = 0; Frame < 6; Frame++) + { + for(i = 0; i < 3; i++) + { + for(j = 0; j < 49; j++) + { + x = ( ((k << j) & 0x800000000000) >> 47 ); + TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i][j] ^= x; + } } } } // - for(Frame = 0; Frame < 6; Frame++) +if (state->currentslot == 0) +{ + for(Frame = 0; Frame < 6; Frame++) //6 { /* 1 DMR frame contains 3 AMBE voice samples */ - //fprintf (stderr, "\n 1AMBE "); for(i = 0; i < 3; i++) { - - errs = (int*)&(TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs1[i]); - errs2 = (int*)&(TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs2[i]); - state->errs = TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement - state->errs2 = TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement - - mbe_processAmbe2450Dataf (state->audio_out_temp_buf, errs, errs2, state->err_str, - TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i], - state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); - - /* - if (state->currentslot == 0) - { errs = (int*)&(TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs1[i]); errs2 = (int*)&(TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs2[i]); state->errs = TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement @@ -128,45 +130,16 @@ if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0) TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i], state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); - state->debug_audio_errors += *errs2; - //state->debug_audio_errors += *errs2R; - - processAudio(opts, state); - playSynthesizedVoice (opts, state); - } - if (state->currentslot == 1) - { - errsR = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]); - errs2R = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]); - state->errs = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement - state->errs2 = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement - //state->audio_out_temp_bufR = state->audio_out_temp_buf; - - mbe_processAmbe2450Dataf (state->audio_out_temp_buf, errsR, errs2R, state->err_strR, - TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i], - state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); - - state->debug_audio_errors += *errs2R; - processAudio(opts, state); - playSynthesizedVoice (opts, state); - } - - mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, errsR, errs2R, state->err_strR, - TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i], - state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); - */ - if (opts->mbe_out_f != NULL) { - saveAmbe2450Data (opts, state, TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]); + saveAmbe2450Data (opts, state, TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]); } if (opts->errorbars == 1) { - fprintf(stderr, "%s", state->err_str); + //fprintf(stderr, "%s", state->err_str); } state->debug_audio_errors += *errs2; - //state->debug_audio_errors += *errs2R; processAudio(opts, state); //playSynthesizedVoice (opts, state); @@ -176,14 +149,59 @@ if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0) writeSynthesizedVoice (opts, state); } - if (opts->audio_out == 1 && opts->p25enc != 1) //play only if not equal to enc value, going to set p25enc to 1 if enc detected?? + //play only if not equal to enc value, going to set p25enc to 1 if enc detected?? + if (opts->audio_out == 1 && opts->p25enc != 1) { playSynthesizedVoice (opts, state); } } /* End for(i = 0; i < 3; i++) */ } /* End for(Frame = 0; Frame < 6; Frame++) */ -} /* End ProcessDMREncryption() */ - + } //End if Current Slot == 0 + + if (state->currentslot == 1) + { + for(Frame = 0; Frame < 6; Frame++) + { + /* 1 DMR frame contains 3 AMBE voice samples */ + for(i = 0; i < 3; i++) + { + errs = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]); + errs2 = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]); + state->errs = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement + state->errs2 = TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement + + mbe_processAmbe2450Dataf (state->audio_out_temp_buf, errs, errs2, state->err_str, + TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i], + state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); + + if (opts->mbe_out_f != NULL) + { + saveAmbe2450Data (opts, state, TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i]); + } + if (opts->errorbars == 1) + { + //fprintf(stderr, "%s", state->err_str); + } + + state->debug_audio_errors += *errs2; + + processAudio(opts, state); + //playSynthesizedVoice (opts, state); + + if (opts->wav_out_f != NULL) + { + writeSynthesizedVoice (opts, state); + } + + //play only if not equal to enc value, going to set p25enc to 1 if enc detected?? + if (opts->audio_out == 1 && opts->p25enc != 1) + { + playSynthesizedVoice (opts, state); + } + } /* End for(i = 0; i < 3; i++) */ + } /* End for(Frame = 0; Frame < 6; Frame++) */ + } //End if Current Slot == 1 +} /* End ProcessDMR */ /* End of file */ diff --git a/src/dmr_sync.c b/src/dmr_sync.c index ade6d1d..17f3e3a 100644 --- a/src/dmr_sync.c +++ b/src/dmr_sync.c @@ -22,6 +22,8 @@ //#define PRINT_TERMINAISON_LC_BYTES //#define PRINT_VOICE_BURST_BYTES +//Need to work in a way to seperate data bursts on seperate slots, having data pouring into both slots simultaneously +//Need to make seperate superframe arrays for each void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98], uint8_t syncdata[48], uint8_t SlotType[20]) { //NEED TRELLIS DECODER HERE @@ -36,8 +38,9 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] TimeSlotVoiceSuperFrame_t * TSVoiceSupFrame = NULL; uint8_t R[3]; uint8_t BPTCReservedBits = 0; + short int slot = 0; - + slot = (short int)state->currentslot; /* Check the current time slot */ if(state->currentslot == 0) { @@ -63,35 +66,46 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] unsigned char tdibits_to_bits[196]; if (1 == 2) { - fprintf (stderr, "\n Raw Trellis Dibits to Bits\n "); + //fprintf (stderr, "\n Raw Trellis Dibits to Bits\n "); for (i = 0; i < 98; i++) { tdibits_to_bits[i * 2] = (tdibits[i] >> 0) & 1; tdibits_to_bits[(i * 2) + 1] = (tdibits[1] >> 1) & 1; - fprintf (stderr, "%d%d", tdibits_to_bits[i * 2], tdibits_to_bits[(i * 2) + 1]); - } - } - if (opts->payload == 1) - { - //fprintf (stderr, "\n Raw Trellis Dibits\n "); - for (i = 0; i < 98; i++) - { - //fprintf (stderr, "#%d [%X] ", i, tdibits[i]); - //tdibits_reverse[97-i] = tdibits[i]; - //tdibits_reverse[97-i] = ((tdibits[i] & 1)<<1) | ((tdibits[i] & 2)>>1); - //tdibits_inverted[i] = tdibits[i] ^ 2; + //fprintf (stderr, "%d%d", tdibits_to_bits[i * 2], tdibits_to_bits[(i * 2) + 1]); } } + //fprintf (stderr, "\n Raw Trellis Dibits\n "); + for (i = 0; i < 98; i++) + { + //fprintf (stderr, "#%d [%X] ", i, tdibits[i]); + tdibits_reverse[97-i] = tdibits[i]; + //tdibits_reverse[97-i] = ((tdibits[i] & 1)<<1) | ((tdibits[i] & 2)>>1); + //tdibits_inverted[i] = tdibits[i] ^ 2; + } + + unsigned char TrellisReturn[18]; - CDMRTrellisDecode(tdibits, TrellisReturn); //figure out how this works!! + //CDMRTrellisDecode(tdibits, TrellisReturn); //figure out how this works!! + CDMRTrellisDecode(tdibits_reverse, TrellisReturn); //NEEDS REVERSE DIBITS! if (opts->payload == 1) { + fprintf (stderr,"%s", KCYN); fprintf (stderr, "\nFull 3/4 Rate Trellis Payload\n "); for (i = 0; i < 18; i++) { fprintf (stderr, "[%02X]", TrellisReturn[i]); } + fprintf (stderr, "\n Hex to Ascii - "); + for (i = 0; i < 18; i++) + { + if (TrellisReturn[i] <= 0x7E && TrellisReturn[i] >=0x20) + { + fprintf (stderr, "%c", TrellisReturn[i]); + } + else fprintf (stderr, "."); + } + fprintf (stderr,"%s", KNRM); //change back to normal } /* Extract the BPTC 196,96 DMR data */ //IrrecoverableErrors = BPTC_196x96_Extract_Data(DeInteleavedData, DmrDataBit, R); @@ -100,7 +114,7 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] // /* Fill the reserved bit (R(0)-R(2) of the BPTC(196,96) block) */ //BPTCReservedBits = (R[0] & 0x01) | ((R[1] << 1) & 0x02) | ((R[2] << 2) & 0x08); - /* + for(i = 0, j = 0; i < 18; i++, j+=8) { DmrDataBit[j + 0] = (TrellisReturn[i] >> 7) & 0x01; @@ -112,8 +126,9 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] DmrDataBit[j + 6] = (TrellisReturn[i] >> 1) & 0x01; DmrDataBit[j + 7] = (TrellisReturn[i] >> 0) & 0x01; } - */ + //the reverse card + /* for(i = 0, j = 0; i < 18; i++, j+=8) { DmrDataBit[j + 0] = (TrellisReturn[17-i] >> 0) & 0x01; @@ -125,12 +140,14 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] DmrDataBit[j + 6] = (TrellisReturn[17-i] >> 6) & 0x01; DmrDataBit[j + 7] = (TrellisReturn[17-i] >> 7) & 0x01; } + */ /* Convert the 96 bit of voice LC Header data into 12 bytes */ k = 0; - for(i = 0; i < 18; i++) + for(i = 0; i < 16; i++) //16, or 18? seems to have two extra bytes in front currently { - state->dmr_34_rate_sf[i] = state->dmr_34_rate_sf[i+18]; //shift middle to left 12 to load up new round - state->dmr_34_rate_sf[i+18] = state->dmr_34_rate_sf[i+36]; //shift far right to middle 12, going three frames deep; + state->dmr_34_rate_sf[slot][i] = state->dmr_34_rate_sf[slot][i+16]; //shift middle to left 12 to load up new round + state->dmr_34_rate_sf[slot][i+16] = state->dmr_34_rate_sf[slot][i+32]; //shift far right middle to left middle 12, going four frames deep; + state->dmr_34_rate_sf[slot][i+32] = state->dmr_34_rate_sf[slot][i+48]; DmrDataByte[i] = 0; for(j = 0; j < 8; j++) { @@ -139,10 +156,25 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] DmrDataByte[i] = DmrDataByte[i] | (DmrDataBit[k] & 0x01); k++; } - //state->dmr_34_rate_sf[i+36] = DmrDataByte[i]; //copy byte to right hand side of shift frame - state->dmr_34_rate_sf[i+36] = TrellisReturn[i]; + //state->dmr_34_rate_sf[i+36] = ~DmrDataByte[i]; //copy byte to right hand side of shift frame + //state->dmr_34_rate_sf[i+36] = ~TrellisReturn[i]& 0xFF; + state->dmr_34_rate_sf[slot][i+48] = TrellisReturn[i+2]; //plus two to skip the first two bytes } - + if (opts->payload == 2) + { + fprintf (stderr, "%s",KGRN); + fprintf (stderr, "\n Rate 3/4 Superframe - Slot [%d]\n ",slot+1); + for (i = 0; i < (16*4); i++) + { + fprintf (stderr, "[%02X]", state->dmr_34_rate_sf[slot][i]); + if (i == 15 || i == 31 || i == 47) + { + fprintf (stderr, "\n "); //line break and two spaces after each 16 bytes + } + } + fprintf (stderr, "%s ", KNRM); + } + //fprintf (stderr, "%s ", KNRM); /* Fill the CRC extracted (before Reed-Solomon (12,9) FEC correction) */ CRCExtracted = 0; //for(i = 0; i < 24; i++) @@ -167,8 +199,9 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] /* Convert corrected 12 bytes into 96 bits */ - //Headers and Addresses + + /* if ( (state->dmr_34_rate_sf[0] & 0x3F) == 0x05) //0x3F?? or == 0x05 { fprintf (stderr, "\n IP4 Header"); @@ -185,27 +218,41 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] fprintf (stderr, " [%08d]", (state->dmr_34_rate_sf[5] <<16 ) + (state->dmr_34_rate_sf[6] << 8) + state->dmr_34_rate_sf[7] ); fprintf (stderr, " - Port %05d", (state->dmr_34_rate_sf[10] << 8) + state->dmr_34_rate_sf[11]); } + */ //LRRP - if (state->dmr_34_rate_sf[0] == 0x0 && state->dmr_34_rate_sf[4] == 0x0D) //Start LRRP now + if ( (state->dmr_34_rate_sf[slot][0] & 0x7F) == 0x45) //Start LRRP now { - fprintf (stderr, "\n Data Blocks [%d]", state->dmr_34_rate_sf[5]); - for (short i = 6; i <= 36; i++) + fprintf (stderr, "%s ", KMAG); + //fprintf (stderr, "\n IP4 Header"); //Not sure this is accurate info IP4 Header? + //fprintf (stderr, "\n Data Blocks [%d]", state->dmr_34_rate_sf[5]); + for (short i = 1; i < 64; i++) //find way to get padding so we only go as deep as we need to! { - if ( state->dmr_34_rate_sf[i] == 0x34 ) //timestamp + if ( state->dmr_34_rate_sf[slot][i] == 0x0C) //Source and Destination info + { + fprintf (stderr, "\n Source:"); + fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_34_rate_sf[slot][i+0] & 0x3F), state->dmr_34_rate_sf[slot][i+1], state->dmr_34_rate_sf[slot][i+2], state->dmr_34_rate_sf[slot][i+3]); //strip first two bits off 1st byte + fprintf (stderr, " [%08d]", (state->dmr_34_rate_sf[slot][i+1] <<16 ) + (state->dmr_34_rate_sf[slot][i+2] << 8) + state->dmr_34_rate_sf[slot][i+3] ); + fprintf (stderr, " - Port %05d", (state->dmr_34_rate_sf[slot][i+8] << 8) + state->dmr_34_rate_sf[slot][i+9]); + fprintf (stderr, "\n Destination:"); + fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_34_rate_sf[slot][i+4] & 0x3F), state->dmr_34_rate_sf[slot][i+5], state->dmr_34_rate_sf[slot][6], state->dmr_34_rate_sf[slot][i+7]); //strip first two bits off 4th byte?? + fprintf (stderr, " [%08d]", (state->dmr_34_rate_sf[slot][i+5] <<16 ) + (state->dmr_34_rate_sf[slot][i+6] << 8) + state->dmr_34_rate_sf[slot][i+7] ); + fprintf (stderr, " - Port %05d", (state->dmr_34_rate_sf[slot][i+10] << 8) + state->dmr_34_rate_sf[slot][i+11]); + } + if ( state->dmr_34_rate_sf[slot][i] == 0x34 ) //timestamp { fprintf (stderr, "\n LRRP - Timestamp: "); - fprintf (stderr, "%4d.", (state->dmr_34_rate_sf[i+1] << 6) + (state->dmr_34_rate_sf[i+2] >> 2) ); //4 digit year - fprintf (stderr, "%02d.", ( ((state->dmr_34_rate_sf[i+2] & 0x3) << 2) + ((state->dmr_34_rate_sf[i+3] & 0xC0) >> 6)) ); //2 digit month - fprintf (stderr, "%02d", ( (state->dmr_34_rate_sf[i+3] & 0x30) >> 1) + ((state->dmr_34_rate_sf[i+3] & 0x0E) >> 1) ); //2 digit day - fprintf (stderr, " %02d:",( (state->dmr_34_rate_sf[i+3] & 0x01) << 4) + ((state->dmr_34_rate_sf[i+4] & 0xF0) >> 4) ); //2 digit hour - fprintf (stderr, "%02d:",( (state->dmr_34_rate_sf[i+4] & 0x0F) << 2) + ((state->dmr_34_rate_sf[i+5] & 0xC0) >> 6) ); //2 digit minute - fprintf (stderr, "%02d", ( (state->dmr_34_rate_sf[i+5] & 0x3F) << 0) ); //2 digit second + fprintf (stderr, "%4d.", (state->dmr_34_rate_sf[slot][i+1] << 6) + (state->dmr_34_rate_sf[slot][i+2] >> 2) ); //4 digit year + fprintf (stderr, "%02d.", ( ((state->dmr_34_rate_sf[slot][i+2] & 0x3) << 2) + ((state->dmr_34_rate_sf[slot][i+3] & 0xC0) >> 6)) ); //2 digit month + fprintf (stderr, "%02d", ( (state->dmr_34_rate_sf[slot][i+3] & 0x30) >> 1) + ((state->dmr_34_rate_sf[slot][i+3] & 0x0E) >> 1) ); //2 digit day + fprintf (stderr, " %02d:",( (state->dmr_34_rate_sf[slot][i+3] & 0x01) << 4) + ((state->dmr_34_rate_sf[slot][i+4] & 0xF0) >> 4) ); //2 digit hour + fprintf (stderr, "%02d:",( (state->dmr_34_rate_sf[slot][i+4] & 0x0F) << 2) + ((state->dmr_34_rate_sf[slot][i+5] & 0xC0) >> 6) ); //2 digit minute + fprintf (stderr, "%02d", ( (state->dmr_34_rate_sf[slot][i+5] & 0x3F) << 0) ); //2 digit second } - if ( state->dmr_34_rate_sf[i] == 0x51 ) //lattitude and longitude + if ( state->dmr_34_rate_sf[slot][i] == 0x51 ) //lattitude and longitude { fprintf (stderr, "\n LRRP -"); fprintf (stderr, " Lat: "); - if (state->dmr_34_rate_sf[i+1] & 0x80) //first bit indicates a sign, or hemisphere? + if (state->dmr_34_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? { fprintf (stderr, "-"); } @@ -213,47 +260,79 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] long int lrrplon; double lat_unit = (double)180/(double)4294967295; double lon_unit = (double)360/(double)4294967295; - lrrplat = ( ( ((state->dmr_34_rate_sf[i+1] & 0x7F ) << 24 ) + (state->dmr_34_rate_sf[i+2] << 16) + (state->dmr_34_rate_sf[i+3] << 8) + state->dmr_34_rate_sf[i+4]) * 1 ); - lrrplon = ( ( (state->dmr_34_rate_sf[i+5] << 24 ) + (state->dmr_34_rate_sf[i+6] << 16) + (state->dmr_34_rate_sf[i+7] << 8) + state->dmr_34_rate_sf[i+8]) * 1 ); + lrrplat = ( ( ((state->dmr_34_rate_sf[slot][i+1] & 0x7F ) << 24 ) + (state->dmr_34_rate_sf[slot][i+2] << 16) + (state->dmr_34_rate_sf[slot][i+3] << 8) + state->dmr_34_rate_sf[slot][i+4]) * 1 ); + lrrplon = ( ( (state->dmr_34_rate_sf[slot][i+5] << 24 ) + (state->dmr_34_rate_sf[slot][i+6] << 16) + (state->dmr_34_rate_sf[slot][i+7] << 8) + state->dmr_34_rate_sf[slot][i+8]) * 1 ); fprintf (stderr, "%.5lf ", ((double)lrrplat) * lat_unit); fprintf (stderr, " Lon: "); - if (state->dmr_34_rate_sf[i+5] & 0x80) //first bit indicates a sign, or hemisphere? + if (state->dmr_34_rate_sf[slot][i+5] & 0x80) //first bit indicates a sign, or hemisphere? + { + //fprintf (stderr, "-"); + } + fprintf (stderr, "%.5lf", (lrrplon * lon_unit) ); + sprintf ( state->dmr_lrrp[3], "Lat: %.5lf Lon: %.5lf", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); + //print for easy copy/paste into browser? + fprintf (stderr, " ("); + if (state->dmr_34_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? { fprintf (stderr, "-"); } - fprintf (stderr, "%.5lf", (lrrplon * lon_unit) ); + fprintf (stderr, "%.5lf, %.5lf)", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); } - if ( state->dmr_34_rate_sf[i] == 0x6C ) + if ( state->dmr_34_rate_sf[slot][i] == 0x6C ) { //either Plus is wrong, or I'm wrong on higher velocities exceeding 0xFF. //fprintf (stderr, "\n LRRP - Vi %02X Vf %02X Velocity Units (hex)", state->dmr_34_rate_sf[i+1], state->dmr_34_rate_sf[i+2]); - double velocity = ( ((double)( (state->dmr_34_rate_sf[i+1] ) + state->dmr_34_rate_sf[i+2] )) / ( (double)128)); + double velocity = ( ((double)( (state->dmr_34_rate_sf[slot][i+1] ) + state->dmr_34_rate_sf[slot][i+2] )) / ( (double)128)); //fprintf (stderr, "\n LRRP - %.4lf Meters Per Second", velocity); fprintf (stderr, "\n LRRP - %.4lf m/s %.4lf km/h %.4lf mph", velocity, (3.6 * velocity), (2.2369 * velocity) ); + sprintf ( state->dmr_lrrp[1], "Vel: %.4lf kph", (3.6 * velocity)); } - if ( state->dmr_34_rate_sf[i] == 0x56 ) + if ( state->dmr_34_rate_sf[slot][i] == 0x56 ) { //check for appropriate terminology here - Heading, bearing, course, or track? - fprintf (stderr, "\n LRRP - Direction %d Degrees", state->dmr_34_rate_sf[i+1] * 2); + fprintf (stderr, "\n LRRP - Direction %d Degrees", state->dmr_34_rate_sf[slot][i+1] * 2); + sprintf ( state->dmr_lrrp[2], "Dir: %d Deg", state->dmr_34_rate_sf[slot][i+1] * 2); } } } + fprintf (stderr, "%s ", KNRM); //Full if (opts->payload == 2) { - fprintf (stderr, "\nFull 3/4 Rate Payload DmrDataByte (reverse bits)\n "); + fprintf (stderr, "\nFull 3/4 Rate Payload DmrDataByte (reverse)\n "); for (i = 0; i < 18; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + + fprintf (stderr, "\nFull 3/4 Rate Payload DmrDataByte (reverse inverted)\n "); + for (i = 0; i < 18; i++) + { + fprintf (stderr, "[%02X]", ~DmrDataByte[i] & 0xFF); + } } } +//This is Data Header, why did I name it Data Data void ProcessDataData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]) { + short int slot = 0; + slot = (short int)state->currentslot; + + //clear out the 3/4 rate data superframe so we don't repeat old info + for (short int i = 0; i < (16*4); i++) + { + state->dmr_34_rate_sf[slot][i] = 0; + } + //clear out the 1/2 rate data superframe so we don't repeat old info + for (short int i = 0; i < (12*3); i++) + { + state->dmr_12_rate_sf[slot][i] = 0; + } + //Placeholder uint32_t i, j, k; uint32_t CRCExtracted = 0; @@ -317,18 +396,18 @@ void ProcessDataData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint for(i = 0; i < 16; i++) { CRCExtracted = CRCExtracted << 1; - CRCExtracted = CRCExtracted | (uint32_t)(DmrDataBit[i + 72] & 1); - //CRCExtracted = CRCExtracted | (uint32_t)(DmrDataBit[i + 80] & 1); //80-96 for PI header + //CRCExtracted = CRCExtracted | (uint32_t)(DmrDataBit[i + 72] & 1); + CRCExtracted = CRCExtracted | (uint32_t)(DmrDataBit[i + 80] & 1); //80-96 for PI header } //Look into whether or not we need to run these CRC checks for this header information //and see if its applied the same or differently /* Apply the CRC mask (see DMR standard B.3.12 Data Type CRC Mask) */ - CRCExtracted = CRCExtracted ^ 0x969696; //does this mask get applied here though for PI? - //CRCExtracted = CRCExtracted ^ 0x6969; + //CRCExtracted = CRCExtracted ^ 0x969696; //does this mask get applied here though for PI? + CRCExtracted = CRCExtracted ^ 0xCCCC; /* Check/correct the full link control data and compute the Reed-Solomon (12,9) CRC */ - CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0x969696); + CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0xCCCC); //CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0x6969); /* Convert corrected 12 bytes into 96 bits */ @@ -347,15 +426,16 @@ void ProcessDataData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint //test if((IrrecoverableErrors == 0) && CRCCorrect) { - fprintf (stderr, "\n(Data CRC Okay)"); + //fprintf (stderr, "\n(Data CRC Okay)"); } else if((IrrecoverableErrors == 0)) { - fprintf (stderr, "\n(Data FEC Okay)"); + //fprintf (stderr, "\n(Data FEC Okay)"); } - else fprintf (stderr, ("\n(Data CRC Fail, FEC Fail)")); + else {}//fprintf (stderr, ("\n(Data CRC Fail, FEC Fail)")); // + fprintf (stderr, "%s ", KMAG); if (DmrDataByte[0] == 0x43) { fprintf (stderr, "\n IP4 Source IP:"); @@ -374,14 +454,17 @@ void ProcessDataData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint fprintf (stderr, " Destination:"); fprintf (stderr, " %d", (DmrDataByte[5] <<16 ) + (DmrDataByte[6] <<8 ) + DmrDataByte[7] ); } + fprintf (stderr, "%s ", KNRM); //Full if (opts->payload == 1) { - fprintf (stderr, "\nFull Data Rate Payload "); + fprintf (stderr, "%s", KCYN); + fprintf (stderr, "\nFull Data Header Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "%s", KNRM); } } @@ -497,11 +580,13 @@ void Process1Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t //Full if (opts->payload == 1) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "\nFull Rate 1 Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "%s", KNRM); } } @@ -579,11 +664,11 @@ void ProcessMBChData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint //and see if its applied the same or differently /* Apply the CRC mask (see DMR standard B.3.12 Data Type CRC Mask) */ //CRCExtracted = CRCExtracted ^ 0x969696; //does this mask get applied here though for PI? - //CRCExtracted = CRCExtracted ^ 0x6969; + CRCExtracted = CRCExtracted ^ 0xAAAA; /* Check/correct the full link control data and compute the Reed-Solomon (12,9) CRC */ //CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0x969696); - //CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0x6969); + CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0xAAAA); /* Convert corrected 12 bytes into 96 bits */ for(i = 0, j = 0; i < 12; i++, j+=8) @@ -617,11 +702,13 @@ void ProcessMBChData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint //Full if (opts->payload == 1) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "\nFull MBC Header Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "%s", KNRM); } } @@ -737,11 +824,13 @@ void ProcessMBCData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8 //Full if (opts->payload == 1) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "\nFull MBC Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "%s", KNRM); } } @@ -857,11 +946,13 @@ void ProcessWTFData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8 //Full if (opts->payload == 1) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "\nFull WTF Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "%s", KNRM); } } @@ -881,6 +972,8 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ TimeSlotVoiceSuperFrame_t * TSVoiceSupFrame = NULL; uint8_t R[3]; uint8_t BPTCReservedBits = 0; + short int slot = 0; + slot = (short int)state->currentslot; /* Check the current time slot */ if(state->currentslot == 0) @@ -909,8 +1002,10 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ k = 0; for(i = 0; i < 12; i++) { - state->dmr_12_rate_sf[i] = state->dmr_12_rate_sf[i+12]; //shift middle 12 to leftmost 12 to load up new round - state->dmr_12_rate_sf[i+12] = state->dmr_12_rate_sf[i+24]; //shift far right 12 to middle 12, going three frames deep; + state->dmr_12_rate_sf[slot][i] = state->dmr_12_rate_sf[slot][i+12]; //shift middle 12 to leftmost 12 to load up new round + state->dmr_12_rate_sf[slot][i+12] = state->dmr_12_rate_sf[slot][i+24]; //shift middle right 12 to middle left 12, going four frames deep; + state->dmr_12_rate_sf[slot][i+24] = state->dmr_12_rate_sf[slot][i+36]; //shift far right 12 to middle right 12, going four frames deep; + state->dmr_12_rate_sf[slot][i+36] = state->dmr_12_rate_sf[slot][i+48]; DmrDataByte[i] = 0; for(j = 0; j < 8; j++) { @@ -918,7 +1013,22 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ DmrDataByte[i] = DmrDataByte[i] | (DmrDataBit[k] & 0x01); k++; } - state->dmr_12_rate_sf[i+24] = DmrDataByte[i]; //copy byte to right hand side of shift frame + state->dmr_12_rate_sf[slot][i+48] = DmrDataByte[i]; //copy byte to right hand side of shift frame + } + + if (opts->payload == 2) + { + fprintf (stderr, "%s",KGRN); + fprintf (stderr, "\n Rate 1/2 Superframe - Slot [%d]\n ",slot+1); + for (i = 0; i < (12*5); i++) + { + fprintf (stderr, "[%02X]", state->dmr_12_rate_sf[slot][i]); + if (i == 11 || i == 23 || i == 35 || i == 47) //line break and two spaces after each 16 bytes + { + fprintf (stderr, "\n "); + } + } + fprintf (stderr, "%s ", KNRM); } /* Fill the CRC extracted (before Reed-Solomon (12,9) FEC correction) */ @@ -944,13 +1054,18 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ //test if((IrrecoverableErrors == 0) && CRCCorrect) { - fprintf (stderr, "\n(1/2 Rate CRC Okay)"); + //fprintf (stderr, "\n(1/2 Rate CRC Okay)"); } else if((IrrecoverableErrors == 0)) { - fprintf (stderr, "\n(1/2 Rate FEC Okay)"); + //fprintf (stderr, "\n(1/2 Rate FEC Okay)"); + } + else + { + fprintf (stderr, "%s", KRED); + fprintf (stderr, ("\n(1/2 Rate CRC Fail, FEC Fail)")); + fprintf (stderr, "%s", KNRM); } - else fprintf (stderr, ("\n(1/2 Rate CRC Fail, FEC Fail)")); /* Convert corrected 12 bytes into 96 bits */ for(i = 0, j = 0; i < 12; i++, j+=8) @@ -964,45 +1079,64 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ DmrDataBit[j + 6] = (DmrDataByte[i] >> 1) & 0x01; DmrDataBit[j + 7] = (DmrDataByte[i] >> 0) & 0x01; } - - //Headers and Addresses - if ( (state->dmr_12_rate_sf[0] & 0x3F) == 0x05) //0x05, or 0x45? + //Headers Source Destination + if ( (state->dmr_12_rate_sf[slot][36] & 0x7F) == 0x45) //Start Source Destination early in case not enough 1/2 data frames { - fprintf (stderr, "\n IP4 Header"); - } - //ARS? - if ( (state->dmr_12_rate_sf[0] & 0x3F) == 0x0C) - { - fprintf (stderr, "\n Source:"); - fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_12_rate_sf[0] & 0x3F), state->dmr_12_rate_sf[1], state->dmr_12_rate_sf[2], state->dmr_12_rate_sf[3]); //strip first two bits off 1st byte - fprintf (stderr, " [%08d]", (state->dmr_12_rate_sf[1] <<16 ) + (state->dmr_12_rate_sf[2] << 8) + state->dmr_12_rate_sf[3] ); - fprintf (stderr, " - Port %05d", (state->dmr_12_rate_sf[8] << 8) + state->dmr_12_rate_sf[9]); - fprintf (stderr, "\n Destination:"); - fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_12_rate_sf[4] & 0x3F), state->dmr_12_rate_sf[5], state->dmr_12_rate_sf[6], state->dmr_12_rate_sf[7]); //strip first two bits off 4th byte?? - fprintf (stderr, " [%08d]", (state->dmr_12_rate_sf[5] <<16 ) + (state->dmr_12_rate_sf[6] << 8) + state->dmr_12_rate_sf[7] ); - fprintf (stderr, " - Port %05d", (state->dmr_12_rate_sf[10] << 8) + state->dmr_12_rate_sf[11]); + fprintf (stderr, "%s ", KMAG); + //fprintf (stderr, "\n IP4 Header"); //Not sure this is accurate info IP4 Header? + //fprintf (stderr, "\n Data Blocks [%d]", state->dmr_34_rate_sf[5]); + for (short i = 36; i < 60; i++) //find way to get padding so we only go as deep as we need to! + { + if ( state->dmr_12_rate_sf[slot][i] == 0x0C) //Source and Destination info + { + fprintf (stderr, "\n Source:"); + fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_12_rate_sf[slot][i+0] & 0x3F), state->dmr_12_rate_sf[slot][i+1], state->dmr_12_rate_sf[slot][i+2], state->dmr_12_rate_sf[slot][i+3]); //strip first two bits off 1st byte + fprintf (stderr, " [%08d]", (state->dmr_12_rate_sf[slot][i+1] <<16 ) + (state->dmr_12_rate_sf[slot][i+2] << 8) + state->dmr_12_rate_sf[slot][i+3] ); + fprintf (stderr, " - Port %05d", (state->dmr_12_rate_sf[slot][i+8] << 8) + state->dmr_12_rate_sf[slot][i+9]); + fprintf (stderr, "\n Destination:"); + fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_12_rate_sf[slot][i+4] & 0x3F), state->dmr_12_rate_sf[slot][i+5], state->dmr_12_rate_sf[slot][6], state->dmr_12_rate_sf[slot][i+7]); //strip first two bits off 4th byte?? + fprintf (stderr, " [%08d]", (state->dmr_12_rate_sf[slot][i+5] <<16 ) + (state->dmr_12_rate_sf[slot][i+6] << 8) + state->dmr_12_rate_sf[slot][i+7] ); + fprintf (stderr, " - Port %05d", (state->dmr_12_rate_sf[slot][i+10] << 8) + state->dmr_12_rate_sf[slot][i+11]); + } + } + fprintf (stderr, "%s ", KNRM); } //LRRP - if (state->dmr_12_rate_sf[0] == 0x0 && state->dmr_12_rate_sf[4] == 0x0D) //Start LRRP now + if ( (state->dmr_12_rate_sf[slot][0] & 0x7F) == 0x45) //Start LRRP now { - //fprintf (stderr, "\n Data Blocks [%d]", state->dmr_12_rate_sf[5]); - for (short i = 6; i <= 36; i++) + fprintf (stderr, "%s ", KMAG); + //fprintf (stderr, "\n IP4 Header"); //Not sure this is accurate info IP4 Header? + //fprintf (stderr, "\n Data Blocks [%d]", state->dmr_34_rate_sf[5]); + for (short i = 1; i < 60; i++) //find way to get padding so we only go as deep as we need to! { - if ( state->dmr_12_rate_sf[i] == 0x34 ) //timestamp + /* + if ( state->dmr_12_rate_sf[slot][i] == 0x0C) //Source and Destination info + { + fprintf (stderr, "\n Source:"); + fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_12_rate_sf[slot][i+0] & 0x3F), state->dmr_12_rate_sf[slot][i+1], state->dmr_12_rate_sf[slot][i+2], state->dmr_12_rate_sf[slot][i+3]); //strip first two bits off 1st byte + fprintf (stderr, " [%08d]", (state->dmr_12_rate_sf[slot][i+1] <<16 ) + (state->dmr_12_rate_sf[slot][i+2] << 8) + state->dmr_12_rate_sf[slot][i+3] ); + fprintf (stderr, " - Port %05d", (state->dmr_12_rate_sf[slot][i+8] << 8) + state->dmr_12_rate_sf[slot][i+9]); + fprintf (stderr, "\n Destination:"); + fprintf (stderr, " %03d.%03d.%03d.%03d", (state->dmr_12_rate_sf[slot][i+4] & 0x3F), state->dmr_12_rate_sf[slot][i+5], state->dmr_12_rate_sf[slot][6], state->dmr_12_rate_sf[slot][i+7]); //strip first two bits off 4th byte?? + fprintf (stderr, " [%08d]", (state->dmr_12_rate_sf[slot][i+5] <<16 ) + (state->dmr_12_rate_sf[slot][i+6] << 8) + state->dmr_12_rate_sf[slot][i+7] ); + fprintf (stderr, " - Port %05d", (state->dmr_12_rate_sf[slot][i+10] << 8) + state->dmr_12_rate_sf[slot][i+11]); + } + */ + if ( state->dmr_12_rate_sf[slot][i] == 0x34 ) //timestamp { fprintf (stderr, "\n LRRP - Timestamp: "); - fprintf (stderr, "%4d.", (state->dmr_12_rate_sf[i+1] << 6) + (state->dmr_12_rate_sf[i+2] >> 2) ); //4 digit year - fprintf (stderr, "%02d.", ( ((state->dmr_12_rate_sf[i+2] & 0x3) << 2) + ((state->dmr_12_rate_sf[i+3] & 0xC0) >> 6)) ); //2 digit month - fprintf (stderr, "%02d", ( (state->dmr_12_rate_sf[i+3] & 0x30) >> 1) + ((state->dmr_12_rate_sf[i+3] & 0x0E) >> 1) ); //2 digit day - fprintf (stderr, " %02d:",( (state->dmr_12_rate_sf[i+3] & 0x01) << 4) + ((state->dmr_12_rate_sf[i+4] & 0xF0) >> 4) ); //2 digit hour - fprintf (stderr, "%02d:",( (state->dmr_12_rate_sf[i+4] & 0x0F) << 2) + ((state->dmr_12_rate_sf[i+5] & 0xC0) >> 6) ); //2 digit minute - fprintf (stderr, "%02d", ( (state->dmr_12_rate_sf[i+5] & 0x3F) << 0) ); //2 digit second + fprintf (stderr, "%4d.", (state->dmr_12_rate_sf[slot][i+1] << 6) + (state->dmr_12_rate_sf[slot][i+2] >> 2) ); //4 digit year + fprintf (stderr, "%02d.", ( ((state->dmr_12_rate_sf[slot][i+2] & 0x3) << 2) + ((state->dmr_12_rate_sf[slot][i+3] & 0xC0) >> 6)) ); //2 digit month + fprintf (stderr, "%02d", ( (state->dmr_12_rate_sf[slot][i+3] & 0x30) >> 1) + ((state->dmr_12_rate_sf[slot][i+3] & 0x0E) >> 1) ); //2 digit day + fprintf (stderr, " %02d:",( (state->dmr_12_rate_sf[slot][i+3] & 0x01) << 4) + ((state->dmr_12_rate_sf[slot][i+4] & 0xF0) >> 4) ); //2 digit hour + fprintf (stderr, "%02d:",( (state->dmr_12_rate_sf[slot][i+4] & 0x0F) << 2) + ((state->dmr_12_rate_sf[slot][i+5] & 0xC0) >> 6) ); //2 digit minute + fprintf (stderr, "%02d", ( (state->dmr_12_rate_sf[slot][i+5] & 0x3F) << 0) ); //2 digit second } - if ( state->dmr_12_rate_sf[i] == 0x51 ) //lattitude and longitude + if ( state->dmr_12_rate_sf[slot][i] == 0x51 ) //lattitude and longitude { fprintf (stderr, "\n LRRP -"); fprintf (stderr, " Lat: "); - if (state->dmr_12_rate_sf[i+1] & 0x80) //first bit indicates a sign, or hemisphere? + if (state->dmr_12_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? { fprintf (stderr, "-"); } @@ -1010,46 +1144,64 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ long int lrrplon; double lat_unit = (double)180/(double)4294967295; double lon_unit = (double)360/(double)4294967295; - lrrplat = ( ( ((state->dmr_12_rate_sf[i+1] & 0x7F ) << 24 ) + (state->dmr_12_rate_sf[i+2] << 16) + (state->dmr_12_rate_sf[i+3] << 8) + state->dmr_12_rate_sf[i+4]) * 1 ); - lrrplon = ( ( (state->dmr_12_rate_sf[i+5] << 24 ) + (state->dmr_12_rate_sf[i+6] << 16) + (state->dmr_12_rate_sf[i+7] << 8) + state->dmr_12_rate_sf[i+8]) * 1 ); + lrrplat = ( ( ((state->dmr_12_rate_sf[slot][i+1] & 0x7F ) << 24 ) + (state->dmr_12_rate_sf[slot][i+2] << 16) + (state->dmr_12_rate_sf[slot][i+3] << 8) + state->dmr_12_rate_sf[slot][i+4]) * 1 ); + lrrplon = ( ( (state->dmr_12_rate_sf[slot][i+5] << 24 ) + (state->dmr_12_rate_sf[slot][i+6] << 16) + (state->dmr_12_rate_sf[slot][i+7] << 8) + state->dmr_12_rate_sf[slot][i+8]) * 1 ); fprintf (stderr, "%.5lf ", ((double)lrrplat) * lat_unit); fprintf (stderr, " Lon: "); - if (state->dmr_12_rate_sf[i+5] & 0x80) //first bit indicates a sign, or hemisphere? + if (state->dmr_12_rate_sf[slot][i+5] & 0x80) //first bit indicates a sign, or hemisphere? { //fprintf (stderr, "-"); } fprintf (stderr, "%.5lf", (lrrplon * lon_unit) ); - //sprintf ( state->dmr_lrrp[3], "Lat: %.5lf Lon: %.5lf", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); + sprintf ( state->dmr_lrrp[3], "Lat: %.5lf Lon: %.5lf", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); + //print for easy copy/paste into browser? + fprintf (stderr, " ("); + if (state->dmr_12_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? + { + fprintf (stderr, "-"); + } + fprintf (stderr, "%.5lf, %.5lf)", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); } - if ( state->dmr_12_rate_sf[i] == 0x6C ) + if ( state->dmr_12_rate_sf[slot][i] == 0x6C ) { //either Plus is wrong, or I'm wrong on higher velocities exceeding 0xFF. - //fprintf (stderr, "\n LRRP - Vi %02X Vf %02X Velocity Units (hex)", state->dmr_12_rate_sf[i+1], state->dmr_12_rate_sf[i+2]); - double velocity = ( ((double)( (state->dmr_12_rate_sf[i+1] ) + state->dmr_12_rate_sf[i+2] )) / ( (double)128)); + //fprintf (stderr, "\n LRRP - Vi %02X Vf %02X Velocity Units (hex)", state->dmr_34_rate_sf[i+1], state->dmr_34_rate_sf[i+2]); + double velocity = ( ((double)( (state->dmr_12_rate_sf[slot][i+1] ) + state->dmr_12_rate_sf[slot][i+2] )) / ( (double)128)); //fprintf (stderr, "\n LRRP - %.4lf Meters Per Second", velocity); fprintf (stderr, "\n LRRP - %.4lf m/s %.4lf km/h %.4lf mph", velocity, (3.6 * velocity), (2.2369 * velocity) ); - //sprintf ( state->dmr_lrrp[1], "Vel: %.4lf kph", (3.6 * velocity)); + sprintf ( state->dmr_lrrp[1], "Vel: %.4lf kph", (3.6 * velocity)); } - if ( state->dmr_12_rate_sf[i] == 0x56 ) + if ( state->dmr_12_rate_sf[slot][i] == 0x56 ) { //check for appropriate terminology here - Heading, bearing, course, or track? - fprintf (stderr, "\n LRRP - Direction %d Degrees", state->dmr_12_rate_sf[i+1] * 2); - //sprintf ( state->dmr_lrrp[2], "Dir: %d Deg", state->dmr_12_rate_sf[i+1] * 2); + fprintf (stderr, "\n LRRP - Direction %d Degrees", state->dmr_12_rate_sf[slot][i+1] * 2); + sprintf ( state->dmr_lrrp[2], "Dir: %d Deg", state->dmr_12_rate_sf[slot][i+1] * 2); } } } - + fprintf (stderr, "%s ", KNRM); //Full if (opts->payload == 1) { - fprintf (stderr, "\nFull 1/2 Rate Payload "); + fprintf (stderr,"%s", KCYN); + fprintf (stderr, "\n Full 1/2 Rate Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "\n Hex to Ascii - "); + for (i = 0; i < 12; i++) + { + if (DmrDataByte[i] <= 0x7E && DmrDataByte[i] >=0x20) + { + fprintf (stderr, "%c", DmrDataByte[i]); + } + else fprintf (stderr, "."); + } + fprintf (stderr,"%s", KNRM); } } @@ -1127,22 +1279,27 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t //and see if its applied the same or differently /* Apply the CRC mask (see DMR standard B.3.12 Data Type CRC Mask) */ //CRCExtracted = CRCExtracted ^ 0x969696; //does this mask get applied here though for PI? - CRCExtracted = CRCExtracted ^ 0x6969; + CRCExtracted = CRCExtracted ^ 0xA5A5; /* Check/correct the full link control data and compute the Reed-Solomon (12,9) CRC */ //CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0x969696); - CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0x6969); + CRCCorrect = ComputeAndCorrectFullLinkControlCrc(DmrDataByte, &CRCComputed, 0xA5A5); //test if((IrrecoverableErrors == 0) && CRCCorrect) { - fprintf (stderr, "\n(CSBK CRC Okay)"); + //fprintf (stderr, "\n(CSBK CRC Okay)"); } else if((IrrecoverableErrors == 0)) { - fprintf (stderr, "\n(CSBK FEC Okay)"); + //fprintf (stderr, "\n(CSBK FEC Okay)"); + } + else + { + //fprintf (stderr, "%s", KRED); + //fprintf (stderr, ("\n(CSBK CRC Fail, FEC Fail)")); + //fprintf (stderr, "%s", KNRM); } - else fprintf (stderr, ("\n(CSBK CRC Fail, FEC Fail)")); /* Convert corrected 12 bytes into 96 bits */ for(i = 0, j = 0; i < 12; i++, j+=8) @@ -1170,8 +1327,10 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t uint8_t nb3 = DmrDataByte[4] & 0x3F; //extract(csbk, 34, 40); uint8_t nb4 = DmrDataByte[5] & 0x3F; //extract(csbk, 42, 48); uint8_t nb5 = DmrDataByte[6] & 0x3F; //extract(csbk, 50, 56); + fprintf (stderr, "%s", KMAG); fprintf (stderr, "\nMotoTRBO Connect Plus Neighbors\n"); fprintf(stderr, " NB1(%02x), NB2(%02x), NB3(%02x), NB4(%02x), NB5(%02x)", nb1, nb2, nb3, nb4, nb5); + fprintf (stderr, "%s", KNRM); sprintf(state->dmr_branding, " MotoTRBO Connect Plus "); } //ConnectPLUS Section // @@ -1181,8 +1340,10 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t uint32_t grpAddr = ( (DmrDataByte[5] << 16) + (DmrDataByte[6] << 8) + DmrDataByte[7] ); //extract(csbk, 40, 64); uint8_t lcn = ( (DmrDataByte[8] & 0xF0 ) >> 4 ) ; //extract(csbk, 64, 68); 0xF0 LCN not report same as 'plus'? uint8_t tslot = ( (DmrDataByte[8] & 0x08 ) >> 3 ); //csbk[68]; TS seems fine + fprintf (stderr, "%s", KGRN); fprintf (stderr, "\nMotoTRBO Connect Plus Channel Grant\n"); fprintf(stderr, " srcAddr(%8d), grpAddr(%8d), LCN(%d), TS(%d)",srcAddr, grpAddr, lcn, tslot); + fprintf (stderr, "%s", KNRM); sprintf(state->dmr_branding, " MotoTRBO Connect Plus "); } @@ -1192,8 +1353,10 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t uint32_t grpAddr = ( (DmrDataByte[5] << 16) + (DmrDataByte[6] << 8) + DmrDataByte[7] ); //extract(csbk, 40, 64); uint8_t lcn = ( (DmrDataByte[8] & 0xF0 ) >> 4 ) ; //extract(csbk, 64, 68); 0xF0 LCN not report same as 'plus'? uint8_t tslot = ( (DmrDataByte[8] & 0x08 ) >> 3 ); //csbk[68]; TS seems fine + fprintf (stderr, "%s", KRED); fprintf (stderr, "\nMotoTRBO Connect Plus Terminate Channel Grant\n"); //Data only shows a srcAddr?? fprintf(stderr, " srcAddr(%8d), grpAddr(%8d), LCN(%d), TS(%d)",srcAddr, grpAddr, lcn, tslot); + fprintf (stderr, "%s", KNRM); sprintf(state->dmr_branding, " MotoTRBO Connect Plus "); } @@ -1203,8 +1366,10 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t uint32_t grpAddr = ( (DmrDataByte[5] << 16) + (DmrDataByte[6] << 8) + DmrDataByte[7] ); //extract(csbk, 40, 64); uint8_t lcn = ( (DmrDataByte[8] & 0xF0 ) >> 4 ) ; //extract(csbk, 64, 68); 0xF0 LCN not report same as 'plus'? uint8_t tslot = ( (DmrDataByte[8] & 0x08 ) >> 3 ); //csbk[68]; TS seems fine + fprintf (stderr, "%s", KCYN); fprintf (stderr, "\nMotoTRBO Connect Plus Data Channel Grant\n"); //Data I have doesn't show any values for lcn or tslot fprintf(stderr, " srcAddr(%8d), grpAddr(%8d), LCN(%d), TS(%d)",srcAddr, grpAddr, lcn, tslot); + fprintf (stderr, "%s", KNRM); sprintf(state->dmr_branding, " MotoTRBO Connect Plus "); } @@ -1292,7 +1457,7 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t //possible Site identifier, CSBK Aloha? if (csbk_o == 0x19) //DmrDataByte[0] == 0x99? { - fprintf (stderr, "\n CSBK Aloha?"); + //fprintf (stderr, "\n CSBK Aloha?"); //fprintf (stderr, "\n Site ID %d-%d.%d", (DmrDataByte[2] & 0xF0 >> 4), DmrDataByte[2] & 0xF, DmrDataByte[3]); //fprintf (stderr, " DCC %d", DmrDataByte[1]); //sprintf ( state->dmr_callsign[0], "Site ID %d-%d.%d", (DmrDataByte[2] & 0xF0 >> 4), DmrDataByte[2] & 0xF, DmrDataByte[3]); @@ -1330,11 +1495,13 @@ void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t //Full if (opts->payload == 1) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "\nFull CSBK Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "%s", KNRM); } } @@ -1434,19 +1601,37 @@ void ProcessDmrPIHeader(dsd_opts * opts, dsd_state * state, uint8_t info[196], u state->payload_mi = ( ((DmrDataByte[3]) << 24) + ((DmrDataByte[4]) << 16) + ((DmrDataByte[5]) << 8) + (DmrDataByte[6]) ); if (1 == 1) //have it always print? { + fprintf (stderr, "%s ", KYEL); fprintf (stderr, "\n DMR PI Header ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algid, state->payload_keyid, state->payload_mi); + fprintf (stderr, "%s ", KNRM); } //test if((IrrecoverableErrors == 0) && CRCCorrect) { - fprintf (stderr, " (PI CRC Okay)"); + //fprintf (stderr, " (PI CRC Okay)"); } else if((IrrecoverableErrors == 0)) { - fprintf (stderr, " (PI FEC Okay)"); + //fprintf (stderr, " (PI FEC Okay)"); + } + else { + fprintf (stderr, "%s ", KRED); + fprintf (stderr, (" (PI CRC Fail, FEC Fail)")); + fprintf (stderr, "%s ", KNRM); + } + + //Full + if (opts->payload == 1) + { + fprintf (stderr, "%s", KCYN); + fprintf (stderr, "\nFull PI Header Payload "); + for (i = 0; i < 12; i++) + { + fprintf (stderr, "[%02X]", DmrDataByte[i]); + } + fprintf (stderr, "%s", KNRM); } - else fprintf (stderr, (" (PI CRC Fail, FEC Fail)")); } @@ -1575,6 +1760,7 @@ void ProcessDmrVoiceLcHeader(dsd_opts * opts, dsd_state * state, uint8_t info[19 } } /* Print the destination ID (TG) and the source ID */ + fprintf (stderr, "%s ", KGRN); fprintf(stderr, "\n TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; @@ -1591,13 +1777,16 @@ void ProcessDmrVoiceLcHeader(dsd_opts * opts, dsd_state * state, uint8_t info[19 * a PI Header will be sent with the encryption mode and DSD will upgrade automatically * the new encryption mode */ opts->EncryptionMode = MODE_BASIC_PRIVACY; - + fprintf (stderr, "%s ", KRED); fprintf(stderr, "Encrypted "); + //fprintf (stderr, "%s ", KNRM); } else { opts->EncryptionMode = MODE_UNENCRYPTED; + fprintf (stderr, "%s ", KGRN); fprintf(stderr, "Clear/Unencrypted "); + //fprintf (stderr, "%s ", KNRM); } /* Check the "Reserved" bits */ @@ -1618,10 +1807,11 @@ void ProcessDmrVoiceLcHeader(dsd_opts * opts, dsd_state * state, uint8_t info[19 else fprintf(stderr, "No Priority "); /* We should never go here */ } fprintf(stderr, "Call "); + fprintf (stderr, "%s ", KNRM); - if(TSVoiceSupFrame->FullLC.DataValidity) fprintf(stderr, "(CRC OK ) "); - else if(IrrecoverableErrors == 0) fprintf(stderr, "RAS (FEC OK/CRC ERR)"); - else fprintf(stderr, "(FEC FAIL/CRC ERR)"); + if(TSVoiceSupFrame->FullLC.DataValidity) {}//fprintf(stderr, "(CRC OK ) "); + else if(IrrecoverableErrors == 0) {}//fprintf(stderr, "RAS (FEC OK/CRC ERR)"); + else {}//fprintf(stderr, "(FEC FAIL/CRC ERR)"); #ifdef PRINT_VOICE_LC_HEADER_BYTES fprintf(stderr, "\n"); @@ -1657,12 +1847,15 @@ void ProcessDmrVoiceLcHeader(dsd_opts * opts, dsd_state * state, uint8_t info[19 //Full if (opts->payload == 1) { - fprintf (stderr, "\nFull Voice Header Payload "); + fprintf (stderr, "%s", KCYN); + fprintf (stderr, "\nFull Voice LC Header Payload "); for (i = 0; i < 12; i++) { fprintf (stderr, "[%02X]", DmrDataByte[i]); } + fprintf (stderr, "%s", KNRM); } + } /* End ProcessDmrVoiceLcHeader() */ @@ -1797,9 +1990,12 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 //tlc if((IrrecoverableErrors == 0) && CRCCorrect) //amateur DMR seems to only set radio ID up here I think, figure out best way to set without messing up other DMR types { - fprintf(stderr, "\n TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); + fprintf (stderr, "%s \n", KRED); + fprintf (stderr, " SLOT %d", state->currentslot+1); + fprintf(stderr, " TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); - fprintf(stderr, "(CRC OK ) "); + fprintf (stderr, "%s ", KNRM); + //fprintf(stderr, "(CRC OK ) "); if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode == 0) //other opcodes may convey callsigns, names, etc. /* if ( TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0xAF || @@ -1811,7 +2007,7 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 { state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - state->dmr_color_code = state->color_code; + //state->dmr_color_code = state->color_code; state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; } @@ -1824,9 +2020,12 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 } else if(IrrecoverableErrors == 0) { - fprintf(stderr, "\n TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); + fprintf (stderr, "%s \n", KRED); + fprintf (stderr, " SLOT %d", state->currentslot+1); + fprintf(stderr, " TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); fprintf(stderr, "RAS (FEC OK/CRC ERR)"); //tlc + fprintf (stderr, "%s ", KNRM); if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode == 0) //other opcodes may convey callsigns, names, etc. /* if ( TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0xAF || @@ -1838,7 +2037,7 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 { state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - state->dmr_color_code = state->color_code; + //state->dmr_color_code = state->color_code; state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; } @@ -1849,7 +2048,7 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 //state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; //state->dmr_color_code = state->color_code; } - else fprintf(stderr, "\n(FEC FAIL/CRC ERR)"); + else {} //fprintf(stderr, "\n(FEC FAIL/CRC ERR)"); #ifdef PRINT_TERMINAISON_LC_BYTES fprintf(stderr, "\n"); @@ -1881,6 +2080,17 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 fprintf(stderr, "Hamming Irrecoverable Errors = %u\n", IrrecoverableErrors); #endif /* PRINT_TERMINAISON_LC_BYTES */ + + if (opts->payload == 1) + { + fprintf (stderr, "%s", KCYN); + fprintf (stderr, "\nFull TLC Payload "); + for (i = 0; i < 12; i++) + { + fprintf (stderr, "[%02X]", DmrDataByte[i]); + } + fprintf (stderr, "%s", KNRM); + } } /* End ProcessDmrTerminaisonLC() */ @@ -1993,7 +2203,7 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) /* Check the CRC values */ if((IrrecoverableErrors == 0))// && CRCCorrect) { - /* Data ara correct */ + /* Data is correct */ //fprintf(stderr, "\nLink Control (LC) Data CRCs are correct !!! Number of error = %u\n", NbOfError); /* CRC is correct so consider the Full LC data as correct/valid */ @@ -2005,87 +2215,83 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) TSVoiceSupFrame->FullLC.DataValidity = 0; } - //GPS, not sure if in right place or not though - if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode == 0x08) - { - long int lrrplat; - long int lrrplon; - double lat_unit = (double)180/(double)4294967295; //damned floats screweing me over lol - double lon_unit = (double)360/(double)4294967295; - //lrrplat = ( ( ((DmrDataByte[0] & 0x3F) << 24 ) + (DmrDataByte[1] << 16) + (DmrDataByte[2] << 8) + DmrDataByte[3]) * 1 ); //(0x0B4/0xFFFFFFFF) - //lrrplon = ( ( (DmrDataByte[4] << 24 ) + (DmrDataByte[5] << 16) + (DmrDataByte[6] << 8) + DmrDataByte[7]) * 1 ); //(0x168/0xFFFFFFFF) //0x3F, or whole thing?; - - //fprintf (stderr, " Standard GPS Coordinates?? Check Payload.\n"); - //fprintf (stderr, "Figure out what to put here"); - - } - //ASCII HEX cheat sheet // 20 - space; 09 - Horizontal Tab; 0A Line Feed; 0D - Carriage Feed; 00 - Null; // 30 - 39 are 0-9 numerals // 41 - 5A are upper case A-Z letters // 61-7A are lower case a-z letters - // + // 7B-7F misc characters (colon, semicolon, etc) // let's assume that something has to indicate end of valid characters? + + //Embedded Alias if ( TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x03 && TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x08 && opts->payload == 1) { - //fprintf (stderr, "Call Sign %X [ ", TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3); sprintf (state->dmr_callsign[TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3], ""); //blank here so it doesn't grow out of control? for (i = 0; i < 10; i++) { - if ( - //(LC_DataBytes[i] > 0x29 && LC_DataBytes[i] < 0x3A) || //numerals - //(LC_DataBytes[i] > 0x40 && LC_DataBytes[i] < 0x5B) || //uppers - //(LC_DataBytes[i] > 0x60 && LC_DataBytes[i] < 0x7B) || //lowers - //(LC_DataBytes[i] == 0x20) ) //space - (LC_DataBytes[i] > 0x19 && LC_DataBytes[i] < 0x7F) ) //full range of 'normal' characters? + //full range of alphanumerical characters? + if ( (LC_DataBytes[i] > 0x19 && LC_DataBytes[i] < 0x7F) ) { - //fprintf (stderr, "%c", LC_DataBytes[i]); sprintf ( state->dmr_callsign[TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3] + strlen(state->dmr_callsign[TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3]) , "%c", LC_DataBytes[i]); } } - //fprintf (stderr, "]\n"); if (opts->use_ncurses_terminal == 1) { - fprintf (stderr, "\n Alias Header and Blocks: [%s%s%s%s%s]", state->dmr_callsign[0], state->dmr_callsign[1], state->dmr_callsign[2], state->dmr_callsign[3], state->dmr_callsign[4] ); + fprintf (stderr, "%s", KCYN); + if (state->dmr_stereo == 0) + { + fprintf(stderr, "\n"); + } + fprintf (stderr, " SLOT %d", state->currentslot+1); + fprintf (stderr, " Embedded Alias Header and Blocks: [%s%s%s%s%s]", state->dmr_callsign[0], state->dmr_callsign[1], state->dmr_callsign[2], state->dmr_callsign[3], state->dmr_callsign[4] ); + fprintf (stderr, "%s ", KNRM); + } + } + + if ( TSVoiceSupFrame->FullLC.FullLinkControlOpcode == 0x08 && opts->payload == 1) //Embedded GPS + { + sprintf (state->dmr_callsign[TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3], ""); //blank here so it doesn't grow out of control? + for (i = 0; i < 10; i++) + { + //full range of alphanumerical characters? + if ( (LC_DataBytes[i] > 0x19 && LC_DataBytes[i] < 0x7F) ) + { + sprintf ( state->dmr_callsign[TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3] + + strlen(state->dmr_callsign[TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3]) , "%c", LC_DataBytes[i]); + } + } + if (opts->use_ncurses_terminal == 1) + { + fprintf (stderr, "%s", KCYN); + if (state->dmr_stereo == 0) + { + fprintf(stderr, "\n"); + } + fprintf (stderr, " SLOT %d", state->currentslot+1); + fprintf (stderr, " Embedded GPS: [%s]", state->dmr_callsign[5] ); + fprintf (stderr, "%s ", KNRM); } } /* Print the destination ID (TG) and the source ID */ - if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x04 || TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x09) //voice burst, was > 0x07 + if((IrrecoverableErrors == 0) && CRCCorrect) { - //fprintf(stderr, " TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); - //fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); - //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; - //state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - } - - //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; - //state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - //state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; - - if((IrrecoverableErrors == 0) && CRCCorrect) //voice burst - { - //fprintf(stderr, " TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); - //fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); - //fprintf(stderr, "(CRC OK ) "); - //only set on good CRC? if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x04 || TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x09) //other opcodes may convey callsigns, names, etc. was > 0x07 - /* - if ( TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0xAF || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x04 || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x05 || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x06 || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x07 ) //work out why amateur sets sourceid on other codes, but pro only does on whatever - */ { - fprintf(stderr, "\n TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); + fprintf (stderr, "%s", KGRN); + if (state->dmr_stereo == 0) + { + fprintf(stderr, "\n"); + } + fprintf (stderr, " SLOT %d", state->currentslot+1); + fprintf(stderr, " TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); - fprintf(stderr, "(CRC OK ) "); + fprintf (stderr, "%s ", KNRM); + //fprintf(stderr, "(CRC OK ) "); state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - state->dmr_color_code = state->color_code; + //state->dmr_color_code = state->color_code; //state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; //state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; } @@ -2101,21 +2307,22 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) //fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); //fprintf(stderr, "RAS (FEC OK/CRC ERR)"); //voice burst //or set if was corrected - if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x04 || TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x07) //other opcodes may convey callsigns, names, etc. - /* - if ( TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0xAF || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x04 || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x05 || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x06 || - TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x07 ) //other opcodes may convey callsigns, names, etc. - */ + if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x04 || TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x07) { - fprintf(stderr, "\n TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); + fprintf (stderr, "%s", KGRN); + if (state->dmr_stereo == 0) + { + fprintf(stderr, "\n"); + } + fprintf (stderr, " SLOT %d", state->currentslot+1); + fprintf(stderr, " TG=%u Src=%u ", TSVoiceSupFrame->FullLC.GroupAddress, TSVoiceSupFrame->FullLC.SourceAddress); fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); + fprintf (stderr, "%s ", KRED); fprintf(stderr, "RAS (FEC OK/CRC ERR) "); + fprintf (stderr, "%s ", KNRM); state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - state->dmr_color_code = state->color_code; + //state->dmr_color_code = state->color_code; //state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; //state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; } @@ -2125,7 +2332,7 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; //state->dmr_color_code = state->color_code; } - else fprintf(stderr, "\n(FEC FAIL/CRC ERR)"); + else {} //fprintf(stderr, "\n(FEC FAIL/CRC ERR)"); #ifdef PRINT_VOICE_BURST_BYTES //fprintf(stderr, "\n"); @@ -2159,13 +2366,16 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) //Full if (opts->payload == 1) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "\nFull Voice Burst Payload "); //for (i = 0; i < 8; i++) for (i = 0; i < 10; i++) { fprintf (stderr, "[%02X]", LC_DataBytes[i]); //amateur DMR hams seem to use this area to send callsigns and names using 04,05,06,07 opcodes } - //fprintf (stderr, "\n"); + fprintf (stderr, "%s", KNRM); + + } } /* End ProcessVoiceBurstSync() */ diff --git a/src/dmr_voice.c b/src/dmr_voice.c index a25e9ff..85f38b5 100644 --- a/src/dmr_voice.c +++ b/src/dmr_voice.c @@ -115,6 +115,16 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state) state->slot1light[0] = ' '; state->slot1light[6] = ' '; } + //method to only listen to a chosen slot when voices occupy both slots simultaneously + //method supersceeded by DMRSTEREO + //state->hardslot = 9; //0 to only listen to slot 0 voice, 1 for slot 1, 9 for both + //if(state->hardslot != 9 && state->hardslot != state->currentslot) + //if(1==1) + //{ + //fprintf (stderr, " Current Slot = %d", state->currentslot + 1); + //fprintf (stderr, "\n"); //line break after breaking out of jail + //goto JUMP; + //} } } cachdata[12] = 0; @@ -370,10 +380,23 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state) sprintf(state->slot2light, "[sLoT2]"); } - if((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0)) + //Comment out Below Lines, or switch if/else if if these cause issues. + /* + else if((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0)) { msMode = 1; + if strcmp (sync, DMR_MS_VOICE_SYNC) == 0) + { + //quickDMRVoice (opts, state); //or make handler for msvoice seperate + //goto JUMP; //quit early when returned here + } } + else if((strcmp (sync, DMR_BS_VOICE_SYNC) == 0) + { + //quickDMRVoice (opts, state); //or make handler for msvoice seperate + //goto JUMP; //quit early when returned here + } + */ // TODO : To be removed // if((j == 0) && (opts->errorbars == 1)) @@ -574,8 +597,9 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state) fprintf(stderr, "%s ", syncbits); #endif - if(j == 5) + if(j == 5) //j == 5 { + // 2nd half next slot skipDibit (opts, state, 54); @@ -617,6 +641,7 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state) } } + } /* End for(j = 0; j < 6; j++) */ if(opts->errorbars == 1) @@ -624,14 +649,25 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state) fprintf(stderr, "%s %s ", state->slot1light, state->slot2light); /* Print the color code */ + fprintf (stderr, "%s", KCYN); fprintf(stderr, "| Color Code=%02d ", (int)state->color_code); + fprintf (stderr, "%s", KNRM); //if(state->color_code_ok) fprintf(stderr, "(OK) |"); - if(state->color_code_ok) fprintf(stderr, "(CRC OK ) |"); //add line break - else fprintf(stderr, "(CRC ERR) |"); //add line break + if(state->color_code_ok) + { + fprintf(stderr, "| (CRC OK ) |"); //add line break + state->dmr_color_code = state->color_code; //set here when voice? otherwise is set off of idle. + } + else + { + fprintf (stderr, "%s", KRED); + fprintf(stderr, "| (CRC ERR) |"); //add line break + fprintf (stderr, "%s", KNRM); + } //fprintf(stderr, " VOICE e: \n"); - fprintf(stderr, " VOICE "); + fprintf(stderr, " VOICE "); } /* Perform the SYNC DMR data embedded decoding */ @@ -642,9 +678,10 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state) /* Print DMR frame (if needed) */ //DMRVoiceFrameProcess(opts, state); //HERE HERE, was enabled, disabled so I could build - + //JUMP: if(opts->errorbars == 1) { fprintf(stderr, "\n"); } + } /* End processDMRvoice() */ diff --git a/src/dpmr_voice.c b/src/dpmr_voice.c index 406e05d..7a04856 100644 --- a/src/dpmr_voice.c +++ b/src/dpmr_voice.c @@ -163,10 +163,10 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state) { dibit = getDibit (opts, state); - if (opts->inverted_dpmr == 1) - { - dibit = (dibit ^ 2); - } + if (opts->inverted_dpmr == 1) + { + dibit = (dibit ^ 2); + } ambe_fr[j + 4][*w][*x] = (1 & (dibit >> 1)); // bit 1 ambe_fr[j + 4][*y][*z] = (1 & dibit); // bit 0 @@ -467,13 +467,17 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state) //fprintf(stderr, "| TG=%s", CalledID); if(state->dPMRVoiceFS2Frame.CalledIDOk) { + fprintf (stderr, "%s", KGRN); fprintf(stderr, "\n| TG=%s", CalledID); + fprintf (stderr, "%s", KNRM); //strcpy (state->dpmr_target_id, CalledID); //HERE HERE state->dpmr_target_id = CalledID; //fprintf(stderr, " (CRC OK) "); if(state->dPMRVoiceFS2Frame.ColorCode[0] != (unsigned int)(-1)) { + fprintf (stderr, "%s", KGRN); fprintf(stderr, " | Color Code=%02d ", (int)state->dPMRVoiceFS2Frame.ColorCode[0]); + fprintf (stderr, "%s", KNRM); state->dpmr_color_code = (int)state->dPMRVoiceFS2Frame.ColorCode[0]; } @@ -488,15 +492,19 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state) //fprintf(stderr, "| Src=%s", CallingID); if(state->dPMRVoiceFS2Frame.CallingIDOk) { + fprintf (stderr, "%s", KGRN); fprintf(stderr, "| Src=%s", CallingID); + fprintf (stderr, "%s", KNRM); //strcpy (state->dpmr_caller_id, CallingID); state->dpmr_caller_id = CallingID; - fprintf(stderr, " (CRC OK) \n"); + //fprintf(stderr, " (CRC OK) \n"); } else { + fprintf (stderr, "%s", KRED); fprintf(stderr, " (CRC ERR) \n"); + fprintf (stderr, "%s", KNRM); } #endif /* (NB_OF_DPMR_VOICE_FRAME_TO_DECODE == 2) */ @@ -583,7 +591,7 @@ void ScrambledPMRBit(uint32_t * LfsrValue, uint8_t * BufferIn, uint8_t * BufferO LFSRValue >>= 1; } - /* There are 72 bit to encrypt for voice and 288 bit for data */ + /* There are 72 bit to descramble for voice and 288 bit for data */ for(i = 0; i < NbOfBitToScramble; i++) { BufferOut[i] = (BufferIn[i] ^ S[0]) & 0x01; @@ -613,8 +621,8 @@ void ScrambledPMRBit(uint32_t * LfsrValue, uint8_t * BufferIn, uint8_t * BufferO } /* End ScrambleDPmrBit() */ -/* Scrambler used for dPMR encryption / decryption, - * see ETSI TS 102 658 chapter 7.3 for the +/* Scrambler used for dPMR scrambling / descrambling, + * see ETSI TS 102 658 chapter 7.4 for the * polynomial description. * It is a X^9 + X^5 + 1 polynomial. */ void DeInterleave6x12DPmrBit(uint8_t * BufferIn, uint8_t * BufferOut) diff --git a/src/dsd_audio.c b/src/dsd_audio.c index b70e310..136280a 100644 --- a/src/dsd_audio.c +++ b/src/dsd_audio.c @@ -21,8 +21,6 @@ pa_sample_spec ss; pa_sample_spec tt; pa_sample_spec zz; pa_sample_spec cc; -//pa_channel_map channel_map; - void openPulseOutput(dsd_opts * opts) { @@ -34,68 +32,39 @@ void openPulseOutput(dsd_opts * opts) tt.format = PA_SAMPLE_S16NE; tt.channels = opts->pulse_digi_out_channels; //doing tests with 2 channels at 22050 for 44100 audio default in pulse tt.rate = opts->pulse_digi_rate_out; //48000, switches to 8000 when using RTL dongle - //fprintf (stderr,"digi rate out = %d\n", opts->pulse_digi_rate_out); - //pa_channel_map_init_stereo(&channel_map); - //ss + if (opts->monitor_input_audio == 1) - //if (opts->frame_dmr == 1 && opts->audio_in_type != 3) { - opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "Raw Audio", &ss, NULL, NULL, NULL); - //opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD FME", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO Right", &ss, NULL, NULL, NULL); + opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "Raw Audio Out", &ss, NULL, NULL, NULL); } //tt pa_channel_map* left = 0; //NULL and 0 are same in this context pa_channel_map* right = 0; //NULL and 0 are same in this context - //pa_channel_map* right; - //pa_channel_map_init(right); - opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, opts->output_name, &tt, left, NULL, NULL); - //opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD FME", PA_STREAM_PLAYBACK, NULL, "Digi Audio Out LEFT", &tt, left, NULL, NULL); - //opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "Digi Audio Out RIGHT", &tt, right, NULL, NULL); + + if (opts->dmr_stereo == 0) + { + opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, opts->output_name, &tt, left, NULL, NULL); + + } + if (opts->dmr_stereo == 1) + { + opts->pulse_digi_dev_out = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO LEFT", &tt, left, NULL, NULL); + opts->pulse_digi_dev_outR = pa_simple_new(NULL, "DSD-FME", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO RIGHT", &tt, right, NULL, NULL); + } + } void openPulseInput(dsd_opts * opts) { - zz.format = PA_SAMPLE_S16NE; - zz.channels = opts->pulse_raw_in_channels; - zz.rate = opts->pulse_raw_rate_in; //48000 - cc.format = PA_SAMPLE_S16NE; cc.channels = opts->pulse_digi_in_channels; cc.rate = opts->pulse_digi_rate_in; //48000 - //zz - if (opts->monitor_input_audio == 1) - { - //opts->pulse_raw_dev_in = pa_simple_new(NULL, "DSD-FME", PA_STREAM_RECORD, NULL, "Raw Audio In", &zz, NULL, NULL, NULL); - } - //cc opts->pulse_digi_dev_in = pa_simple_new(NULL, "DSD-FME", PA_STREAM_RECORD, NULL, opts->output_name, &cc, NULL, NULL, NULL); } -//playRawAudio may be obsoleted now that I can run these correctly right inside of dsd_symbol -void playRawAudio(dsd_opts * opts, dsd_state * state) -{ - short obuf, outl, i, sample2, something; - something = state->samplesPerSymbol / 1; //1 for buffer steal loops, 5 for rtl loop - //something = 1; - if (opts->audio_in_type == 0 && opts->audio_out_type == 0){ //hack, but might as well for this particular type since its nearly perfect - for (i=0; i < something; i++){ - //read (opts->audio_in_fd, &sample2, 2); //reading here seems to get same speed as gfsk modulation - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); - //pa_simple_read(opts->pulse_raw_dev_in, &state->pulse_raw_out_buffer, 2, NULL ); - //obuf = state->pulse_raw_out_buffer / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping - //obuf = state->input_sample_buffer; - //obuf = state->pulse_raw_out_buffer; - //write (opts->audio_out_fd, (void*)&obuf, 2); - //pa_simple_write(opts->pulse_raw_dev_out, (void*)&obuf, 2, NULL); - //pa_simple_write(opts->pulse_digi_dev_out, (void*)&obuf, 2, NULL); - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); - } - } -} //end playRawAudio - void processAudio (dsd_opts * opts, dsd_state * state) @@ -109,7 +78,6 @@ processAudio (dsd_opts * opts, dsd_state * state) // detect max level max = 0; state->audio_out_temp_buf_p = state->audio_out_temp_buf; - //state->audio_out_temp_buf_pR = state->audio_out_temp_bufR; for (n = 0; n < 160; n++) { aout_abs = fabsf (*state->audio_out_temp_buf_p); @@ -118,24 +86,18 @@ processAudio (dsd_opts * opts, dsd_state * state) max = aout_abs; } state->audio_out_temp_buf_p++; - //state->audio_out_temp_buf_pR++; } *state->aout_max_buf_p = max; - //*state->aout_max_buf_pR = max; + state->aout_max_buf_p++; - //state->aout_max_buf_pR++; + state->aout_max_buf_idx++; - //state->aout_max_buf_idxR++; + if (state->aout_max_buf_idx > 24) { state->aout_max_buf_idx = 0; state->aout_max_buf_p = state->aout_max_buf; } - //if (state->aout_max_buf_idxR > 24) - // { - // state->aout_max_buf_idxR = 0; - // state->aout_max_buf_pR = state->aout_max_bufR; - // } // lookup max history for (i = 0; i < 25; i++) @@ -241,6 +203,145 @@ processAudio (dsd_opts * opts, dsd_state * state) state->audio_out_idx2++; } } + +} + +void +processAudioR (dsd_opts * opts, dsd_state * state) +{ + + int i, n; + float aout_abs, max, gainfactor, gaindelta, maxbuf; + if (opts->audio_gainR == (float) 0) + { + // detect max level + max = 0; + state->audio_out_temp_buf_pR = state->audio_out_temp_bufR; + for (n = 0; n < 160; n++) + { + aout_abs = fabsf (*state->audio_out_temp_buf_pR); + if (aout_abs > max) + { + max = aout_abs; + } + state->audio_out_temp_buf_pR++; + } + *state->aout_max_buf_pR = max; + + state->aout_max_buf_pR++; + + state->aout_max_buf_idxR++; + + if (state->aout_max_buf_idxR > 24) + { + state->aout_max_buf_idxR = 0; + state->aout_max_buf_pR = state->aout_max_bufR; + } + + // lookup max history + for (i = 0; i < 25; i++) + { + maxbuf = state->aout_max_bufR[i]; + if (maxbuf > max) + { + max = maxbuf; + } + } + + // determine optimal gain level + if (max > (float) 0) + { + gainfactor = ((float) 30000 / max); + } + else + { + gainfactor = (float) 50; + } + if (gainfactor < state->aout_gainR) + { + state->aout_gainR = gainfactor; + gaindelta = (float) 0; + } + else + { + if (gainfactor > (float) 50) + { + gainfactor = (float) 50; + } + gaindelta = gainfactor - state->aout_gainR; + if (gaindelta > ((float) 0.05 * state->aout_gainR)) + { + gaindelta = ((float) 0.05 * state->aout_gainR); + } + } + gaindelta /= (float) 160; + } + else + { + gaindelta = (float) 0; + } + + if(opts->audio_gainR >= 0) + { + // adjust output gain + state->audio_out_temp_buf_pR = state->audio_out_temp_bufR; + for (n = 0; n < 160; n++) + { + *state->audio_out_temp_buf_pR = (state->aout_gainR + ((float) n * gaindelta)) * (*state->audio_out_temp_buf_pR); + state->audio_out_temp_buf_pR++; + } + state->aout_gainR += ((float) 160 * gaindelta); + } + + // copy audio data to output buffer and upsample if necessary + state->audio_out_temp_buf_pR = state->audio_out_temp_bufR; + if (opts->split == 0) //shouldn't need splitR + { + for (n = 0; n < 160; n++) + { + upsample (state, *state->audio_out_temp_buf_pR); + state->audio_out_temp_buf_pR++; + state->audio_out_float_buf_pR += 6; + state->audio_out_idxR += 6; + state->audio_out_idx2R += 6; + } + state->audio_out_float_buf_pR -= (960 + opts->playoffsetR); + // copy to output (short) buffer + for (n = 0; n < 960; n++) + { + if (*state->audio_out_float_buf_pR > 32767.0F) + { + *state->audio_out_float_buf_pR = 32767.0F; + } + else if (*state->audio_out_float_buf_pR < -32768.0F) + { + *state->audio_out_float_buf_pR = -32768.0F; + } + *state->audio_out_buf_pR = (short) *state->audio_out_float_buf_pR; + state->audio_out_buf_pR++; + state->audio_out_float_buf_pR++; + } + state->audio_out_float_buf_pR += opts->playoffsetR; + } + else + { + for (n = 0; n < 160; n++) + { + if (*state->audio_out_temp_buf_pR > 32767.0F) + { + *state->audio_out_temp_buf_pR = 32767.0F; + } + else if (*state->audio_out_temp_buf_pR < -32768.0F) + { + *state->audio_out_temp_buf_pR = -32768.0F; + } + *state->audio_out_buf_pR = (short) *state->audio_out_temp_buf_pR; + state->audio_out_buf_pR++; + state->audio_out_temp_buf_pR++; + state->audio_out_idxR++; + state->audio_out_idx2R++; + } + } } void @@ -310,183 +411,77 @@ playSynthesizedVoice (dsd_opts * opts, dsd_state * state) ssize_t result; if (state->audio_out_idx > opts->delay) - { - // output synthesized speech to sound card + { + // output synthesized speech to sound card if(opts->audio_out_type == 2) { -#ifdef USE_PORTAUDIO - PaError err = paNoError; - do - { - long available = Pa_GetStreamWriteAvailable( opts->audio_out_pa_stream ); - if(available < 0) - err = available; - //fprintf (stderr,"Frames available: %d\n", available); - if( err != paNoError ) - break; - if(available > SAMPLE_RATE_OUT * PA_LATENCY_OUT) - { - //It looks like this might not be needed for very small latencies. However, it's definitely needed for a bit larger ones. - //When PA_LATENCY_OUT == 0.500 I get output buffer underruns if I don't use this. With PA_LATENCY_OUT <= 0.100 I don't see those happen. - //But with PA_LATENCY_OUT < 0.100 I run the risk of choppy audio and stream errors. - fprintf (stderr,"\nSyncing voice output stream\n"); - err = Pa_StopStream( opts->audio_out_pa_stream ); - if( err != paNoError ) - break; - } - - err = Pa_IsStreamActive( opts->audio_out_pa_stream ); - if(err == 0) - { - fprintf (stderr,"Start voice output stream\n"); - err = Pa_StartStream( opts->audio_out_pa_stream ); - } - else if(err == 1) - { - err = paNoError; - } - if( err != paNoError ) - break; - - err = Pa_WriteStream( opts->audio_out_pa_stream, (state->audio_out_buf_p - state->audio_out_idx), state->audio_out_idx ); - if( err != paNoError ) - break; - } while(0); - - if( err != paNoError ) - { - fprintf (stderr, "An error occured while using the portaudio output stream\n" ); - fprintf (stderr, "Error number: %d\n", err ); - fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); - } - -#endif + //go F yourself PA } else - if (opts->monitor_input_audio == 1){ - //pa_simple_flush(opts->pulse_raw_dev_in, NULL); - //pa_simple_flush(opts->pulse_raw_dev_out, NULL); - //state->pulse_raw_out_buffer = 0; - //pa_simple_write(opts->pulse_raw_dev_out, (void*)&state->pulse_raw_out_buffer, 2, NULL); - - } //two slot audio testing, still need to seperate channels first internally, but this will play them out of different streams - /* - if(state->currentslot == 0 && opts->audio_in_type != 3) + + if(state->currentslot == 0 && opts->audio_in_type != 3 && opts->dmr_stereo == 1) { pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works. - } - if(state->currentslot == 1 && opts->audio_in_type != 3) - { - pa_simple_write(opts->pulse_raw_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works. - //pa_simple_write(opts->pulse_raw_dev_out, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL); //Yay! It works. + state->audio_out_idx = 0; } - if (opts->audio_in_type == 3) + //if input type is rtl dongle or no dmr stereo...do I need it this way still? + if (opts->audio_in_type == 3 || opts->dmr_stereo == 0) { pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works. + state->audio_out_idx = 0; } - */ - pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works. - state->audio_out_idx = 0; } if (state->audio_out_idx2 >= 800000) - { - state->audio_out_float_buf_p = state->audio_out_float_buf + 100; - state->audio_out_buf_p = state->audio_out_buf + 100; - memset (state->audio_out_float_buf, 0, 100 * sizeof (float)); - memset (state->audio_out_buf, 0, 100 * sizeof (short)); - state->audio_out_idx2 = 0; - } + { + state->audio_out_float_buf_p = state->audio_out_float_buf + 100; + state->audio_out_buf_p = state->audio_out_buf + 100; + memset (state->audio_out_float_buf, 0, 100 * sizeof (float)); + memset (state->audio_out_buf, 0, 100 * sizeof (short)); + state->audio_out_idx2 = 0; + } + } -#ifdef USE_PORTAUDIO -int getPADevice(char* dev, int input, PaStream** stream) +void +playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state) { - int devnum = atoi(dev + 3); - fprintf (stderr,"Using portaudio device %d.\n", devnum); + ssize_t result; - PaError err; + if (state->audio_out_idxR > opts->delay) + { + // output synthesized speech to sound card + if(opts->audio_out_type == 2) + { + //go F yourself PA + } + else - int numDevices = Pa_GetDeviceCount(); - if( numDevices < 0 ) - { - fprintf (stderr, "ERROR: Pa_GetDeviceCount returned 0x%x\n", numDevices ); - err = numDevices; - goto error; - } - if( devnum >= numDevices) - { - fprintf (stderr, "ERROR: Requested device %d is larger than number of devices.\n", devnum ); - return(1); - } + //two slot audio testing, still need to seperate channels first internally, but this will play them out of different streams + if(opts->dmr_stereo == 1) //state->currentslot == 1 && opts->audio_in_type != 3 && opts->dmr_stereo == 1 + { + pa_simple_write(opts->pulse_digi_dev_outR, (state->audio_out_buf_pR - state->audio_out_idxR), (state->audio_out_idxR * 2), NULL); //Yay! It works. + state->audio_out_idxR = 0; + } + } - const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo( devnum ); - - /* print device name */ -#ifdef WIN32 - { /* Use wide char on windows, so we can show UTF-8 encoded device names */ - wchar_t wideName[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, deviceInfo->name, -1, wideName, MAX_PATH-1); - wprintf ( L"Name = %s\n", wideName ); - } -#else - fprintf (stderr, "Name = %s\n", deviceInfo->name ); -#endif - if((input == 1) && (deviceInfo->maxInputChannels == 0)) - { - fprintf (stderr, "ERROR: Requested device %d is not an input device.\n", devnum ); - return(1); - } - if((input == 0) && (deviceInfo->maxOutputChannels == 0)) - { - fprintf (stderr, "ERROR: Requested device %d is not an output device.\n", devnum ); - return(1); - } - - //Create stream parameters - PaStreamParameters parameters; - parameters.device = devnum; - parameters.channelCount = 1; /* mono */ - parameters.sampleFormat = paInt16; //Shorts - parameters.suggestedLatency = (input == 1) ? PA_LATENCY_IN : PA_LATENCY_OUT; - parameters.hostApiSpecificStreamInfo = NULL; - - //Open stream - err = Pa_OpenStream( - stream, - (input == 1) ? ¶meters : NULL, - (input == 0) ? ¶meters : NULL, - (input == 1) ? SAMPLE_RATE_IN : SAMPLE_RATE_OUT, - PA_FRAMES_PER_BUFFER, - paClipOff, - NULL /*callback*/, - NULL ); - if( err != paNoError ) goto error; - - return 0; - -error: - fprintf (stderr, "An error occured while initializing a portaudio stream\n" ); - fprintf (stderr, "Error number: %d\n", err ); - fprintf (stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); - return err; + if (state->audio_out_idx2R >= 800000) + { + state->audio_out_float_buf_pR = state->audio_out_float_bufR + 100; + state->audio_out_buf_pR = state->audio_out_bufR + 100; + memset (state->audio_out_float_bufR, 0, 100 * sizeof (float)); + memset (state->audio_out_bufR, 0, 100 * sizeof (short)); + state->audio_out_idx2R = 0; + } } -#endif void openAudioOutDevice (dsd_opts * opts, int speed) { - // get info of device/file - /* - if(strncmp(opts->audio_out_dev, "pulse", 5) == 0) - { - opts->audio_out_type == 0; - } - */ if(strncmp(opts->audio_out_dev, "pa:", 3) == 0) { opts->audio_out_type = 2; @@ -518,70 +513,6 @@ openAudioOutDevice (dsd_opts * opts, int speed) fprintf (stderr,"Error, %s is not a device. use -w filename for wav output.\n", opts->audio_out_dev); exit(1); } -/* -#ifdef SOLARIS - sample_info_t aset, aget; - - opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY); - if (opts->audio_out_fd == -1) - { - fprintf (stderr,"Error, couldn't open %s\n", opts->audio_out_dev); - //exit (1); - } - - // get current - ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset); - aset.record.sample_rate = speed; - aset.play.sample_rate = speed; - aset.record.channels = 1; - aset.play.channels = 1; - aset.record.precision = 16; - aset.play.precision = 16; - aset.record.encoding = AUDIO_ENCODING_LINEAR; - aset.play.encoding = AUDIO_ENCODING_LINEAR; - - if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1) - { - fprintf (stderr,"Error setting sample device parameters\n"); - exit (1); - } -#endif - -#if defined(BSD) && !defined(__APPLE__) - - int fmt; - - opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY); - if (opts->audio_out_fd == -1) - { - fprintf (stderr,"Error, couldn't open %s\n", opts->audio_out_dev); - opts->audio_out = 0; - //exit(1); - } - - fmt = 0; - if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0) - { - fprintf (stderr,"ioctl reset error \n"); - } - fmt = speed; - if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0) - { - fprintf (stderr,"ioctl speed error \n"); - } - fmt = 0; - if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0) - { - fprintf (stderr,"ioctl stereo error \n"); - } - fmt = AFMT_S16_LE; - if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0) - { - fprintf (stderr,"ioctl setfmt error \n"); - } - -#endif -*/ } fprintf (stderr,"Audio Out Device: %s\n", opts->audio_out_dev); } @@ -661,90 +592,8 @@ openAudioInDevice (dsd_opts * opts) { // this is a device, use old handling, pulse audio now opts->audio_in_type = 0; -/* -#ifdef SOLARIS - sample_info_t aset, aget; - int rgain; - rgain = 64; - - if (opts->split == 1) - { - opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY); - } - else - { - opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR); - } - if (opts->audio_in_fd == -1) - { - fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev); - //exit(1); - } - - // get current - ioctl (opts->audio_in_fd, AUDIO_GETINFO, &aset); - - aset.record.sample_rate = SAMPLE_RATE_IN; - aset.play.sample_rate = SAMPLE_RATE_IN; - aset.record.channels = 1; - aset.play.channels = 1; - aset.record.precision = 16; - aset.play.precision = 16; - aset.record.encoding = AUDIO_ENCODING_LINEAR; - aset.play.encoding = AUDIO_ENCODING_LINEAR; - aset.record.port = AUDIO_LINE_IN; - aset.record.gain = rgain; - - if (ioctl (opts->audio_in_fd, AUDIO_SETINFO, &aset) == -1) - { - fprintf (stderr,"Error setting sample device parameters\n"); - exit (1); - } -#endif -*/ -/* -#if defined(BSD) && !defined(__APPLE__) - int fmt; - - if (opts->split == 1) - { - opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY); - } - else - { - opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR); - } - - if (opts->audio_in_fd == -1) - { - fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev); - opts->audio_out = 0; - } - - fmt = 0; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_RESET) < 0) - { - fprintf (stderr,"ioctl reset error \n"); - } - fmt = SAMPLE_RATE_IN; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0) - { - fprintf (stderr,"ioctl speed error \n"); - } - fmt = 0; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0) - { - fprintf (stderr,"ioctl stereo error \n"); - } - fmt = AFMT_S16_LE; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0) - { - fprintf (stderr,"ioctl setfmt error \n"); - } -#endif -*/ - } + } } if (opts->split == 1) diff --git a/src/dsd_dibit.c b/src/dsd_dibit.c index 76672c3..1ef3820 100644 --- a/src/dsd_dibit.c +++ b/src/dsd_dibit.c @@ -185,9 +185,16 @@ use_symbol (dsd_opts* opts, dsd_state* state, int symbol) } if (state->dibit_buf_p > state->dibit_buf + 900000) - { - state->dibit_buf_p = state->dibit_buf + 200; - } + { + state->dibit_buf_p = state->dibit_buf + 200; + } + + //dmr buffer + if (state->dmr_payload_p > state->dmr_payload_buf + 900000) + { + state->dmr_payload_p = state->dmr_payload_buf + 200; + } + //dmr buffer end } static int @@ -211,6 +218,7 @@ invert_dibit(int dibit) } static int digitize (dsd_opts* opts, dsd_state* state, int symbol) +//int digitize (dsd_opts* opts, dsd_state* state, int symbol) { // determine dibit state if ((state->synctype == 6) || (state->synctype == 14)|| (state->synctype == 18)) @@ -252,8 +260,10 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol) return (0); // +1 } } + else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) || - (state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) || (state->synctype == 17)) + (state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13) || + (state->synctype == 17) ) { // 1 -P25p1 @@ -263,7 +273,6 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol) // 11 -DMR (inverted signal voice frame) // 13 -DMR (inverted signal data frame) // 17 -NXDN (inverted data frame) - // int valid; int dibit; @@ -361,64 +370,12 @@ 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++; + //dmr buffer + *state->dmr_payload_p = dibit; + state->dmr_payload_p++; + //dmr buffer end return dibit; } } @@ -447,9 +404,7 @@ get_dibit_and_analog_signal (dsd_opts* opts, dsd_state* state, int* out_analog_s // state->sbuf[state->sidx] = symbol; - // - //state->pulse_raw_out_buffer = symbol; - // + if (out_analog_signal != NULL) { *out_analog_signal = symbol; diff --git a/src/dsd_file.c b/src/dsd_file.c index 64b96ff..de168b0 100644 --- a/src/dsd_file.c +++ b/src/dsd_file.c @@ -76,7 +76,6 @@ saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d) for (i = 0; i < 7; i++) //using 7 seems to break older amb files where it was 6, need to test 7 on 7 some more { b = 0; - for (j = 0; j < 8; j++) { b = b << 1; diff --git a/src/dsd_frame.c b/src/dsd_frame.c index ea83287..0992492 100644 --- a/src/dsd_frame.c +++ b/src/dsd_frame.c @@ -35,14 +35,20 @@ printFrameInfo (dsd_opts * opts, dsd_state * state) } if (state->nac != 0) { + fprintf (stderr, "%s", KCYN); fprintf (stderr,"nac: [%4X] ", state->nac); + fprintf (stderr, "%s", KNRM); } if (opts->verbose > 1) { + fprintf (stderr, "%s", KGRN); fprintf (stderr,"src: [%8i] ", state->lastsrc); + fprintf (stderr, "%s", KNRM); } + fprintf (stderr, "%s", KGRN); fprintf (stderr,"tg: [%5i] ", state->lasttg); + fprintf (stderr, "%s", KNRM); } void @@ -168,8 +174,8 @@ processFrame (dsd_opts * opts, dsd_state * state) processDSTAR_HD (opts, state); return; } - - else if ((state->synctype >= 10) && (state->synctype <= 13)) + //Start DMR Types + else if ((state->synctype >= 10) && (state->synctype <= 13) || (state->synctype == 32) || (state->synctype == 33) || (state->synctype == 34) ) //32-34 DMR MS and RC { state->nac = 0; state->lastsrc = 0; @@ -182,21 +188,63 @@ processFrame (dsd_opts * opts, dsd_state * state) //fprintf (stderr,"inlvl: %2i%% ", level); } } - if ((state->synctype == 11) || (state->synctype == 12)) + if ( (state->synctype == 11) || (state->synctype == 12) || (state->synctype == 32) ) //DMR Voice Modes { - if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL) && opts->dmr_stereo == 0) { openMbeOutFile (opts, state); } sprintf (state->fsubtype, " VOICE "); - processDMRvoice (opts, state); + if (opts->dmr_stereo == 0 && state->synctype < 32) // -T option for DMR (TDMA) stereo + { + processDMRvoice (opts, state); + } + if (opts->dmr_stereo == 0 && state->synctype == 32) + { + fprintf (stderr, "%s", KRED); + fprintf (stderr, "Please use the -T option to handle MS Mode with DMR Stereo TDMA Handling\n"); + fprintf (stderr, "%s", KNRM); + } + if (opts->dmr_stereo == 1) + { + state->dmr_stereo = 1; //set the state to 1 when handling pure voice frames + if (state->synctype > 31 ) + { + dmrMSBootstrap (opts, state); //bootstrap into MS Bootstrap (voice only) + } + else dmrBSBootstrap (opts, state); //bootstrap into BS Bootstrap + } } + else if ( (state->synctype == 33) || (state->synctype == 34) ) //MS Data and RC data + { + if (opts->dmr_stereo == 0) + { + closeMbeOutFile (opts, state); + state->err_str[0] = 0; + fprintf (stderr, "%s", KRED); + fprintf (stderr, "Please use the -T option to handle MS Mode with DMR Stereo TDMA Handling\n"); + fprintf (stderr, "%s", KNRM); + } + if (opts->dmr_stereo == 1) + { + dmrMSData (opts, state); + } + } else + { + if (opts->dmr_stereo == 0) { closeMbeOutFile (opts, state); state->err_str[0] = 0; processDMRdata (opts, state); } + //switch dmr_stereo to 0 when handling BS data frame syncs with processDMRdata + if (opts->dmr_stereo == 1) + { + state->dmr_stereo = 0; //set the state to zero for handling pure data frames + processDMRdata (opts, state); + } + } return; } else if ((state->synctype >= 2) && (state->synctype <= 5)) @@ -244,7 +292,20 @@ processFrame (dsd_opts * opts, dsd_state * state) processProVoice (opts, state); return; } - //LEH dPMR + //ysf + else if ((state->synctype == 30) || (state->synctype == 31)) + { + //Do stuff + //fprintf(stderr, "YSF Sync! \n"); + if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) + { + //openMbeOutFile (opts, state); + } + //sprintf(state->fsubtype, " VOICE "); + processYSF(opts, state); + return; + } + //dPMR else if ((state->synctype == 20) || (state->synctype == 24)) { /* dPMR Frame Sync 1 */ @@ -255,7 +316,6 @@ processFrame (dsd_opts * opts, dsd_state * state) /* dPMR Frame Sync 2 */ fprintf(stderr, "dPMR Frame Sync 2 "); - //state->rf_mod = GFSK_MODE; state->nac = 0; state->lastsrc = 0; state->lasttg = 0; @@ -264,7 +324,6 @@ processFrame (dsd_opts * opts, dsd_state * state) if (opts->verbose > 0) { level = (int) state->max / 164; - //fprintf(stderr, "inlvl: %2i%% ", level); } } state->nac = 0; @@ -290,7 +349,7 @@ processFrame (dsd_opts * opts, dsd_state * state) fprintf(stderr, "dPMR Frame Sync 4 "); } //dPMR - else + else //P25 { // Read the NAC, 12 bits j = 0; diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index 85e1a80..be29dc5 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -17,9 +17,8 @@ #include "dsd.h" #include -//#include -//borrowed from LEH for 'improved NXDN sync detection' +//borrowed from DSDcc for 'improved NXDN sync detection' int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr) { int Compare = -1; @@ -50,7 +49,6 @@ int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr) return Compare; } /* End strncmperr() */ -//end LEH time_t now; char * getTime(void) //get pretty hh:mm:ss timestamp @@ -140,15 +138,21 @@ getFrameSync (dsd_opts * opts, dsd_state * state) * 26 = -dPMR Frame Sync 3 * 27 = -dPMR Frame Sync 4 * 28 = +NXDN (sync only) - * 29 = -NXDN (sync only + * 29 = -NXDN (sync only) + * 30 = +YSF + * 31 = -YSF + * 32 = DMR MS Voice + * 33 = DMR MS Data + * 34 = DMR RC Data */ int i, j, t, o, dibit, sync, symbol, synctest_pos, lastt; char synctest[25]; - char synctest12[13]; //LEH DPMR + char synctest12[13]; //dPMR char synctest18[19]; char synctest32[33]; + char synctest20[21]; //YSF char modulation[8]; char *synctest_p; char synctest_buf[10240]; @@ -169,6 +173,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) synctest12[12] = 0; synctest18[18] = 0; synctest32[32] = 0; + synctest20[20] = 0; synctest_pos = 0; synctest_p = synctest_buf + 10; sync = 0; @@ -246,9 +251,9 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } if (state->dibit_buf_p > state->dibit_buf + 900000) - { - state->dibit_buf_p = state->dibit_buf + 200; - } + { + state->dibit_buf_p = state->dibit_buf + 200; + } //determine dibit state if (symbol > 0) @@ -264,6 +269,49 @@ getFrameSync (dsd_opts * opts, dsd_state * state) dibit = 51; // '3' } + //digitize test for storing dibits in buffer correctly for dmr recovery + + if (state->dmr_payload_p > state->dmr_payload_buf + 900000) + { + state->dmr_payload_p = state->dmr_payload_buf + 200; + } + + int valid; + //running estimate_symbol causes an issue with P25 syncing properly + if (opts->frame_p25p1 != 1) + { + valid = estimate_symbol(state->rf_mod, &(state->p25_heuristics), state->last_dibit, symbol, &dibit); + } + + if (opts->frame_dmr == 1 && valid == 0) //opts->dmr_stereo + { + if (symbol > state->center) + { + if (symbol > state->umid) + { + *state->dmr_payload_p = 1; // +3 + } + else + { + *state->dmr_payload_p = 0; // +1 + } + } + else + { + if (symbol < state->lmid) + { + *state->dmr_payload_p = 3; // -3 + } + else + { + *state->dmr_payload_p = 2; // -1 + } + } + state->dmr_payload_p++; + + } + // end digitize and dmr buffer testing + *synctest_p = dibit; if (t >= 18) { @@ -502,7 +550,53 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } } + //YSF sync + strncpy(synctest20, (synctest_p - 19), 20); //double check make sure this is right + if(opts->frame_ysf == 1) //(opts->frame_ysf == 1 + { + if (0 == 0) //opts->inverted_ysf == 0 + { + if (strcmp(synctest20, FUSION_SYNC) == 0) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + fprintf (stderr, "\nYSF FUSION SYNC \n"); + opts->inverted_ysf = 0; //should we set this here? + state->lastsynctype = 30; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (30); + } + } + } + if(opts->frame_ysf == 1) //(opts->frame_ysf == 1 + { + if (0 == 0) //opts->inverted_ysf == 1 + { + if (strcmp(synctest20, INV_FUSION_SYNC) == 0) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + fprintf (stderr, "\nINVERTED YSF FUSION SYNC \n"); + opts->inverted_ysf = 1; //should we set this here? + state->lastsynctype = 31; + if ( opts->monitor_input_audio == 1) + { + + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (31); + } + } + } + //end YSF sync //dPMR sync strncpy(synctest, (synctest_p - 23), 24); strncpy(synctest12, (synctest_p - 11), 12); @@ -512,7 +606,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) { if(strcmp(synctest, DPMR_FRAME_SYNC_1) == 0) { - fprintf (stderr, "+dPMR FS1\n"); + //fprintf (stderr, "+dPMR FS1\n"); } if(strcmp(synctest12, DPMR_FRAME_SYNC_2) == 0) { @@ -528,22 +622,26 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, "+dPMR ", synctest_pos + 1, modulation); } state->lastsynctype = 21; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } return (21); } if(strcmp(synctest12, DPMR_FRAME_SYNC_3) == 0) { - fprintf (stderr, "+dPMR FS3 \n"); + //fprintf (stderr, "+dPMR FS3 \n"); } if(strcmp(synctest, DPMR_FRAME_SYNC_4) == 0) { - fprintf (stderr, "+dPMR FS4 \n"); + //fprintf (stderr, "+dPMR FS4 \n"); } } if (opts->inverted_dpmr == 1) { if(strcmp(synctest, INV_DPMR_FRAME_SYNC_1) == 0) { - fprintf (stderr, "-dPMR FS1 \n"); + //fprintf (stderr, "-dPMR FS1 \n"); } if(strcmp(synctest12, INV_DPMR_FRAME_SYNC_2) == 0) { @@ -560,15 +658,19 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } state->lastsynctype = 25; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } return (25); } if(strcmp(synctest12, INV_DPMR_FRAME_SYNC_3) == 0) { - fprintf (stderr, "-dPMR FS3 \n"); + //fprintf (stderr, "-dPMR FS3 \n"); } if(strcmp(synctest, INV_DPMR_FRAME_SYNC_4) == 0) { - fprintf (stderr, "-dPMR FS4 \n"); + //fprintf (stderr, "-dPMR FS4 \n"); } } } @@ -576,7 +678,97 @@ getFrameSync (dsd_opts * opts, dsd_state * state) //New DMR Sync 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) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + //state->directmode = 0; + //fprintf (stderr, "DMR MS Data"); + if (0 == 0) //opts->inverted_dmr + { + // data frame + sprintf(state->ftype, "DMR MS"); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, "+DMR MS Data", synctest_pos + 1, modulation); + } + if (state->lastsynctype != 33) //33 + { + //state->firstframe = 1; + } + state->lastsynctype = 33; //33 + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (33); //33 + } + } + //not sure if this should be here, RC data should only be present in vc6? + if(strcmp (synctest, DMR_RC_DATA_SYNC) == 0) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + //state->directmode = 0; + //fprintf (stderr, "DMR RC DATA\n"); + state->dmr_ms_rc == 1; //set flag for RC data, then process accordingly and reset back to 0 afterwards + if (0 == 0) //opts->inverted_dmr + { + // voice frame + sprintf(state->ftype, "DMR RC"); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, "+DMR RC Data", synctest_pos + 1, modulation); + } + if (state->lastsynctype != 34) + { + //state->firstframe = 1; + } + state->lastsynctype = 34; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (34); + } + } + + if(strcmp (synctest, DMR_MS_VOICE_SYNC) == 0) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + //state->directmode = 0; + //fprintf (stderr, "DMR MS VOICE\n"); + if (0 == 0) //opts->inverted_dmr + { + // voice frame + sprintf(state->ftype, "DMR MS"); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, "+DMR MS Voice", synctest_pos + 1, modulation); + } + if (state->lastsynctype != 32) + { + //state->firstframe = 1; + } + state->lastsynctype = 32; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (32); + } + } + + //if ((strcmp (synctest, DMR_MS_DATA_SYNC) == 0) || (strcmp (synctest, DMR_BS_DATA_SYNC) == 0)) + if (strcmp (synctest, DMR_BS_DATA_SYNC) == 0) { state->carrier = 1; state->offset = synctest_pos; @@ -594,7 +786,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 10; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (10); @@ -614,7 +805,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 11; if ( opts->monitor_input_audio == 1) { - pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (11); } @@ -638,7 +829,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 10; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (10); @@ -649,7 +839,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) sprintf(state->ftype, "DMR "); if (opts->errorbars == 1) { - printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation); } if (state->lastsynctype != 11) { @@ -658,7 +848,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 11; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (11); @@ -678,12 +867,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state) sprintf(state->ftype, "DMR "); if (opts->errorbars == 1) { - printFrameSync (opts, state, "+DMR ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, "+DMR ", synctest_pos + 1, modulation); } state->lastsynctype = 10; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (10); @@ -694,7 +882,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) sprintf(state->ftype, "DMR "); if (opts->errorbars == 1) { - printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation); } if (state->lastsynctype != 11) { @@ -703,13 +891,14 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 11; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (11); } } /* End if(strcmp (synctest, DMR_DIRECT_MODE_TS2_DATA_SYNC) == 0) */ - 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)) + if(strcmp (synctest, DMR_BS_VOICE_SYNC) == 0) { state->carrier = 1; state->offset = synctest_pos; @@ -729,8 +918,13 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->firstframe = 1; } state->lastsynctype = 12; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } return (12); } + else { // inverted data frame @@ -742,7 +936,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 13; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (13); @@ -771,7 +964,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 12; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (12); @@ -811,7 +1003,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 12; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (12); @@ -827,7 +1018,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 13; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (13); @@ -835,7 +1026,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } //End if(strcmp (synctest, DMR_DIRECT_MODE_TS2_VOICE_SYNC) == 0) } //End if (opts->frame_dmr == 1) - //end LEH DMR Sync + //end DMR Sync if (opts->frame_provoice == 1) { strncpy (synctest32, (synctest_p - 31), 32); @@ -855,7 +1046,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 14; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (14); @@ -875,7 +1066,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 15; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (15); @@ -885,8 +1076,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) if ((opts->frame_nxdn96 == 1) || (opts->frame_nxdn48 == 1)) { strncpy (synctest18, (synctest_p - 17), 18); - //if ((strcmp (synctest18, NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_VOICE_SYNC) == 0)) //or is this the double up test? - //borrowing from LEH here WOW! This works so much better, its not even a joke if ((strncmperr (synctest18, NXDN_BS_VOICE_SYNC, 18, 1) == 0) || (strncmperr (synctest18, NXDN_MS_VOICE_SYNC, 18, 1) == 0)) { now = time(NULL); @@ -903,7 +1092,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) sprintf (state->ftype, "NXDN48 "); //get rid of spaces if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } if (opts->errorbars == 1) @@ -917,7 +1106,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) sprintf (state->ftype, "NXDN96"); if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } if (opts->errorbars == 1) @@ -967,7 +1156,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 9; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (9); @@ -1009,7 +1198,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 16; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (16); @@ -1052,7 +1241,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 17; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (17); @@ -1082,7 +1271,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 6; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (6); @@ -1102,7 +1291,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 7; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (7); @@ -1122,7 +1311,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 18; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (18); @@ -1142,7 +1331,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->lastsynctype = 19; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); + pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (19); @@ -1212,7 +1401,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state) return (4); } - else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) || (strcmp (synctest, DMR_MS_VOICE_SYNC) != 0))) + + //dmr desync handling, causes issues with TDMA stereo (MS especially), consider removing + //may have been because we had BS Voice twice on here, seems okay, continue testing + /* + else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) )) { state->carrier = 1; state->offset = synctest_pos; @@ -1221,17 +1414,18 @@ getFrameSync (dsd_opts * opts, dsd_state * state) sprintf (state->ftype, "(DMR) "); if (opts->errorbars == 1) { - printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } return (11); } - else if ((state->lastsynctype == 12) && ((strcmp (synctest, DMR_BS_DATA_SYNC) != 0) || (strcmp (synctest, DMR_MS_DATA_SYNC) != 0))) + */ + + else if ( (state->lastsynctype == 32) && (strcmp (synctest, DMR_MS_VOICE_SYNC) != 0) ) { state->carrier = 1; state->offset = synctest_pos; @@ -1240,18 +1434,76 @@ getFrameSync (dsd_opts * opts, dsd_state * state) sprintf (state->ftype, "(DMR) "); if (opts->errorbars == 1) { - printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation); + //printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; if ( opts->monitor_input_audio == 1) { - //pa_simple_drain(opts->pulse_raw_dev_out, NULL); pa_simple_flush(opts->pulse_raw_dev_out, NULL); } - return (12); + return (32); //32 } - } - } + + else if ( (state->lastsynctype == 33) && (strcmp (synctest, DMR_MS_DATA_SYNC) != 0) ) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + sprintf (state->ftype, "(DMR) "); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation); + } + state->lastsynctype = -1; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (33); //33 + } + else if ( (state->lastsynctype == 34) && (strcmp (synctest, DMR_RC_DATA_SYNC) != 0) ) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + sprintf (state->ftype, "(DMR) "); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation); + } + state->lastsynctype = -1; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (34); //34 + } + + else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) )) + { + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + sprintf (state->ftype, "(DMR) "); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation); + } + state->lastsynctype = -1; + if ( opts->monitor_input_audio == 1) + { + pa_simple_flush(opts->pulse_raw_dev_out, NULL); + } + return (11); //11 + } + + //DMR desync + + } //if t == 24 + } // t >= 18 if (exitflag == 1) { @@ -1294,12 +1546,9 @@ getFrameSync (dsd_opts * opts, dsd_state * state) return (-1); } } - if ( opts->monitor_input_audio == 1 && (time(NULL) - now) > 1 ) //okay, still something going on, latency issues - //if ( opts->monitor_input_audio == 1) - { - //playRawAudio(opts, state); //this is on line 21 in dsd_audio.c - } + } return (-1); } +//1111 diff --git a/src/dsd_main.c b/src/dsd_main.c index 9fa5f92..361ba6d 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -26,17 +26,6 @@ #include "provoice_const.h" #include "git_ver.h" -//pretty pretty colors - -#define KNRM "\x1B[0m" -#define KRED "\x1B[31m" -#define KGRN "\x1B[32m" -#define KYEL "\x1B[33m" -#define KBLU "\x1B[34m" -#define KMAG "\x1B[35m" -#define KCYN "\x1B[36m" -#define KWHT "\x1B[37m" - int pretty_colors() { fprintf (stderr,"%sred\n", KRED); @@ -84,6 +73,10 @@ noCarrier (dsd_opts * opts, dsd_state * state) { state->dibit_buf_p = state->dibit_buf + 200; memset (state->dibit_buf, 0, sizeof (int) * 200); + //dmr buffer + state->dmr_payload_p = state->dibit_buf + 200; + memset (state->dmr_payload_buf, 0, sizeof (int) * 200); + //dmr buffer end if (opts->mbe_out_f != NULL) { closeMbeOutFile (opts, state); @@ -93,7 +86,7 @@ noCarrier (dsd_opts * opts, dsd_state * state) state->carrier = 0; state->max = 15000; state->min = -15000; - state->center = 0; + state->center = 0; //quick disable for dmr testing with buffer state->err_str[0] = 0; state->err_strR[0] = 0; sprintf (state->fsubtype, " "); @@ -110,15 +103,26 @@ noCarrier (dsd_opts * opts, dsd_state * state) sprintf (state->slot1light, " slot1 "); state->firstframe = 0; if (opts->audio_gain == (float) 0) - { - state->aout_gain = 25; - } + { + state->aout_gain = 25; + } + + if (opts->audio_gainR == (float) 0) + { + state->aout_gainR = 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; + + memset (state->aout_max_bufR, 0, sizeof (float) * 200); + state->aout_max_buf_pR = state->aout_max_bufR; + state->aout_max_buf_idxR = 0; + sprintf (state->algid, "________"); sprintf (state->keyid, "________________"); mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); + mbe_initMbeParms (state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2); } void @@ -151,11 +155,13 @@ initOpts (dsd_opts * opts) #endif opts->split = 0; opts->playoffset = 0; + opts->playoffsetR = 0; opts->mbe_out_dir[0] = 0; opts->mbe_out_file[0] = 0; opts->mbe_out_path[0] = 0; opts->mbe_out_f = NULL; opts->audio_gain = 0; + opts->audio_gainR = 0; opts->audio_out = 1; opts->wav_out_file[0] = 0; opts->wav_out_f = NULL; @@ -163,7 +169,7 @@ initOpts (dsd_opts * opts) opts->serial_baud = 115200; sprintf (opts->serial_dev, "/dev/ttyUSB0"); opts->resume = 0; - opts->frame_dstar = 1; + opts->frame_dstar = 1; opts->frame_x2tdma = 1; opts->frame_p25p1 = 1; opts->frame_nxdn48 = 0; @@ -200,13 +206,14 @@ initOpts (dsd_opts * opts) opts->pulse_digi_in_channels = 1; //2 opts->pulse_digi_out_channels = 1; //2 - sprintf (opts->output_name, "Default Channel"); + sprintf (opts->output_name, "Auto Detect"); opts->pulse_flush = 1; //set 0 to flush, 1 for flushed opts->use_ncurses_terminal = 0; opts->payload = 0; opts->EncryptionMode = MODE_UNENCRYPTED; opts->inverted_dpmr = 0; + opts->dmr_stereo = 0; //change currently only in dsd_frame.c } void @@ -218,13 +225,18 @@ initState (dsd_state * state) state->dibit_buf = malloc (sizeof (int) * 1000000); state->dibit_buf_p = state->dibit_buf + 200; memset (state->dibit_buf, 0, sizeof (int) * 200); + //dmr buffer -- double check this set up + state->dmr_payload_buf = malloc (sizeof (int) * 1000000); + state->dmr_payload_p = state->dmr_payload_buf + 200; + memset (state->dmr_payload_buf, 0, sizeof (int) * 200); + //dmr buffer end state->repeat = 0; state->audio_out_buf = malloc (sizeof (short) * 1000000); state->audio_out_bufR = malloc (sizeof (short) * 1000000); memset (state->audio_out_buf, 0, 100 * sizeof (short)); memset (state->audio_out_bufR, 0, 100 * sizeof (short)); state->audio_out_buf_p = state->audio_out_buf + 100; - state->audio_out_buf_pR = state->audio_out_buf + 100; + state->audio_out_buf_pR = state->audio_out_bufR + 100; state->audio_out_float_buf = malloc (sizeof (float) * 1000000); state->audio_out_float_bufR = malloc (sizeof (float) * 1000000); memset (state->audio_out_float_buf, 0, 100 * sizeof (float)); @@ -296,6 +308,11 @@ initState (dsd_state * state) memset (state->aout_max_buf, 0, sizeof (float) * 200); state->aout_max_buf_p = state->aout_max_buf; state->aout_max_buf_idx = 0; + + memset (state->aout_max_bufR, 0, sizeof (float) * 200); + state->aout_max_buf_pR = state->aout_max_bufR; + state->aout_max_buf_idxR = 0; + state->samplesPerSymbol = 10; state->symbolCenter = 4; sprintf (state->algid, "________"); @@ -304,10 +321,17 @@ initState (dsd_state * state) state->cur_mp = malloc (sizeof (mbe_parms)); state->prev_mp = malloc (sizeof (mbe_parms)); state->prev_mp_enhanced = malloc (sizeof (mbe_parms)); + + state->cur_mp2 = malloc (sizeof (mbe_parms)); + state->prev_mp2 = malloc (sizeof (mbe_parms)); + state->prev_mp_enhanced2 = malloc (sizeof (mbe_parms)); + mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); + mbe_initMbeParms (state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2); state->p25kid = 0; state->debug_audio_errors = 0; + state->debug_audio_errorsR = 0; state->debug_header_errors = 0; state->debug_header_critical_errors = 0; @@ -340,6 +364,7 @@ initState (dsd_state * state) sprintf (state->dmr_lrrp[5], ""); state->K = 0; + state->dmr_stereo = 0; #ifdef TRACE_DSD state->debug_sample_index = 0; @@ -380,7 +405,7 @@ usage () fprintf (stderr," -g Audio output gain (default = 0 = auto, disable = -1)\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"); + fprintf (stderr," -W Monitor Source Audio When No Sync Detected (WIP!)\n"); fprintf (stderr,"\n"); fprintf (stderr,"RTL-SDR options:\n"); fprintf (stderr," -c RTL-SDR Frequency\n"); @@ -429,6 +454,9 @@ usage () fprintf (stderr," -n Reset P25 Heuristics and initState variables on mixed signal decoding\n"); fprintf (stderr," Helps when decoding mixed signal types at same time\n"); fprintf (stderr," (WiP! May Cause Slow Memory Leak - Experimental)\n"); + fprintf (stderr," -T Enable DMR TDMA Stereo Voice (Two Slot Dual Voices)\n"); + fprintf (stderr," This feature will open two streams for slot 1 voice and slot 2 voice\n"); + fprintf (stderr," (WiP! May Cause DMR sync break resync issues)\n"); fprintf (stderr," -Z Log MBE Payload to console\n"); fprintf (stderr,"\n"); fprintf (stderr,"Report bugs to: https://github.com/lwvmobile/dsd-fme/issues \n"); @@ -674,7 +702,7 @@ main (int argc, char **argv) exitflag = 0; signal (SIGINT, sigfun); - while ((c = getopt (argc, argv, "haep:P:qstv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:K:NWrlZ")) != -1) + while ((c = getopt (argc, argv, "haep:P:qstv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:K:NWrlZT")) != -1) { opterr = 0; switch (c) @@ -771,8 +799,10 @@ main (int argc, char **argv) case 'W': //monitor_input_audio if no sync opts.monitor_input_audio = 1; + fprintf (stderr, "%s", KRED); fprintf (stderr,"Monitoring Source Audio when carrier present and No Sync Detected.\n"); fprintf (stderr," - May cause Pulse Audio Server to crash on some systems.\n"); + fprintf (stderr, "%s", KNRM); break; case 'N': @@ -786,6 +816,17 @@ main (int argc, char **argv) fprintf (stderr,"Logging MBE Payload to console\n"); break; + case 'T': + opts.dmr_stereo = 1; //just the end user option + state.dmr_stereo = 1; //this values toggles on and off depending on voice or data handling + opts.pulse_digi_rate_out = 24000; + opts.pulse_digi_out_channels = 2; + fprintf (stderr, "%s", KRED); + fprintf (stderr,"Experimental DMR Stereo Sync and Functionality. WIP!\n"); + fprintf (stderr,"DMR Stereo will disable WAV and MBE file saving!\n"); + fprintf (stderr, "%s", KNRM); + break; + case 'z': sscanf (optarg, "%d", &opts.scoperate); opts.errorbars = 0; @@ -830,13 +871,16 @@ main (int argc, char **argv) { fprintf (stderr,"Setting audio out gain to %f\n", opts.audio_gain); state.aout_gain = opts.audio_gain; + state.aout_gainR = opts.audio_gain; } break; case 'n': opts.reset_state = 1; + fprintf (stderr, "%s", KRED); 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"); + fprintf (stderr, "%s", KNRM); break; case 'w': strncpy(opts.wav_out_file, optarg, 1023); @@ -866,7 +910,7 @@ main (int argc, char **argv) opts.frame_dmr = 1; opts.frame_dpmr = 0; opts.frame_provoice = 0; - sprintf (opts.output_name, "Default Channel"); + sprintf (opts.output_name, "Auto Detect"); } else if (optarg[0] == 'd') { @@ -889,7 +933,7 @@ main (int argc, char **argv) opts.frame_nxdn48 = 0; opts.frame_nxdn96 = 0; opts.frame_dmr = 0; - opts.frame_dpmr = 0; //borrow from LEH + opts.frame_dpmr = 0; opts.frame_provoice = 0; sprintf (opts.output_name, "X2-TDMA"); fprintf (stderr,"Decoding only X2-TDMA frames.\n"); @@ -902,7 +946,7 @@ main (int argc, char **argv) opts.frame_nxdn48 = 0; opts.frame_nxdn96 = 0; opts.frame_dmr = 0; - opts.frame_dpmr = 0; //borrow from LEH + opts.frame_dpmr = 0; opts.frame_provoice = 1; state.samplesPerSymbol = 5; state.symbolCenter = 2; @@ -911,8 +955,7 @@ main (int argc, char **argv) opts.mod_gfsk = 1; state.rf_mod = 2; sprintf (opts.output_name, "ProVoice"); - //fprintf (stderr,"Setting symbol rate to 9600 / second\n"); - //fprintf (stderr,"Enabling only GFSK modulation optimizations.\n"); + fprintf (stderr,"Setting symbol rate to 9600 / second\n"); fprintf (stderr,"Decoding only ProVoice frames.\n"); } else if (optarg[0] == '1') @@ -942,6 +985,7 @@ main (int argc, char **argv) opts.frame_dmr = 0; opts.frame_dpmr = 0; opts.frame_provoice = 0; + opts.frame_ysf = 0; state.samplesPerSymbol = 20; state.symbolCenter = 10; opts.mod_c4fm = 1; @@ -951,9 +995,30 @@ main (int argc, char **argv) sprintf (opts.output_name, "NXDN48"); //opts.symboltiming = 2400; //NXDN48 uses 2400 symbol rate fprintf (stderr,"Setting symbol rate to 2400 / second\n"); - //fprintf (stderr,"Enabling only C4FM modulation optimizations.\n"); fprintf (stderr,"Decoding only NXDN 4800 baud frames.\n"); } + else if (optarg[0] == 'y') + { + opts.frame_dstar = 0; + opts.frame_x2tdma = 0; + opts.frame_p25p1 = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 0; + opts.frame_dmr = 0; + opts.frame_dpmr = 0; + opts.frame_provoice = 0; + opts.frame_ysf = 1; + state.samplesPerSymbol = 10; + //state.symbolCenter = 10; + opts.mod_c4fm = 1; + opts.mod_qpsk = 0; + opts.mod_gfsk = 0; + state.rf_mod = 0; + sprintf (opts.output_name, "YSF"); + //opts.symboltiming = 2400; //NXDN48 uses 2400 symbol rate + fprintf (stderr,"Setting symbol rate to 2400 / second\n"); + fprintf (stderr,"Decoding only YSF frames.\nNot working yet!\n"); + } else if (optarg[0] == 'n') { opts.frame_dstar = 0; @@ -969,7 +1034,6 @@ main (int argc, char **argv) opts.mod_gfsk = 0; state.rf_mod = 0; sprintf (opts.output_name, "NXDN96"); - //fprintf (stderr,"Enabling only C4FM modulation optimizations.\n"); fprintf (stderr,"Decoding only NXDN 9600 baud frames.\n"); } else if (optarg[0] == 'r') @@ -986,13 +1050,8 @@ main (int argc, char **argv) opts.mod_qpsk = 0; opts.mod_gfsk = 0; // state.rf_mod = 0; // - //opts.pulse_raw_rate_out = 24000; //doing tests with 2 channels at 24000 for 48000 audio default in pulse - //opts.pulse_digi_rate_out = 24000; //need to copy this to rtl type in and change rate out to 8000 - //opts.pulse_raw_out_channels = 2; - //opts.pulse_digi_out_channels = 2; //2 sprintf (opts.output_name, "DMR/MOTOTRBO"); - //sprintf (opts.output_name, "DMR/MOTOTRBO Left"); - fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n"); + //fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n"); fprintf (stderr,"Decoding only DMR/MOTOTRBO frames.\n"); } else if (optarg[0] == 'm') @@ -1005,6 +1064,7 @@ main (int argc, char **argv) opts.frame_dmr = 0; opts.frame_provoice = 0; opts.frame_dpmr = 1; + opts.frame_ysf = 0; //testing with NXDN48 parameters state.samplesPerSymbol = 20; //same as NXDN48 - 20 state.symbolCenter = 10; //same as NXDN48 - 10 opts.mod_c4fm = 1; @@ -1013,11 +1073,10 @@ main (int argc, char **argv) state.rf_mod = 0; sprintf (opts.output_name, "dPMR"); fprintf(stderr, "Notice: dPMR cannot autodetect polarity. \n Use -xd option if Inverted Signal expected.\n"); - //fprintf(stderr, "Enabling only C4FM modulation optimizations.\n"); fprintf(stderr, "Decoding only dPMR frames.\n"); } break; - //don't mess with the modulations, doesn't really do anything anyways + //don't mess with the modulations, doesn't really do anything meaningful anyways case 'm': if (optarg[0] == 'a') { @@ -1127,7 +1186,6 @@ main (int argc, char **argv) if (opts.use_ncurses_terminal == 1) { ncursesOpen(); - //ncursesPrinter(&opts, &state); } if (opts.resume > 0) @@ -1165,6 +1223,7 @@ main (int argc, char **argv) { opts.split = 1; opts.playoffset = 0; + opts.playoffsetR = 0; opts.delay = 0; if (strlen(opts.wav_out_file) > 0) { @@ -1179,6 +1238,7 @@ main (int argc, char **argv) { opts.split = 1; opts.playoffset = 0; + opts.playoffsetR = 0; opts.delay = 0; if (strlen(opts.wav_out_file) > 0) { @@ -1197,7 +1257,8 @@ main (int argc, char **argv) else { opts.split = 0; - opts.playoffset = 25; // 38 + opts.playoffset = 25; // 38 + opts.playoffsetR = 25; // 38 opts.delay = 0; openAudioInDevice (&opts); //disabled all four instances of openAudio devices, in and out for now opts.audio_out_fd = opts.audio_in_fd; @@ -1214,8 +1275,8 @@ main (int argc, char **argv) else { liveScanner (&opts, &state); - } + if (opts.use_ncurses_terminal == 1){ //ncursesClose (); } diff --git a/src/dsd_mbe.c b/src/dsd_mbe.c index bfc5883..0c64119 100644 --- a/src/dsd_mbe.c +++ b/src/dsd_mbe.c @@ -126,44 +126,78 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a } 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); -#ifdef AMBE_PACKET_OUT - - for(i=0; i<49; i++) { - ambe_d_str[i] = ambe_d[i] + '0'; + //stereo slots and slot 0 (left slot) + if (state->currentslot == 0 && opts->dmr_stereo == 1) + { + 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); } - 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) + //stereo slots and slot 1 (right slot) + if (state->currentslot == 1 && opts->dmr_stereo == 1) + { + mbe_processAmbe3600x2450Framef (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR, ambe_fr, ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality); + //just put this in here for troubleshooting for now + if (opts->mbe_out_f != NULL) { saveAmbe2450Data (opts, state, ambe_d); } + } + if (opts->dmr_stereo == 0) + { + 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); + + if (opts->mbe_out_f != NULL) + { + saveAmbe2450Data (opts, state, ambe_d); + } + } + + } if (opts->errorbars == 1) { //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_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; - - processAudio (opts, state); - if (opts->wav_out_f != NULL) - { - writeSynthesizedVoice (opts, state); - } - - if (opts->audio_out == 1) + state->debug_audio_errorsR += state->errs2R; + if (opts->dmr_stereo == 1 && state->currentslot == 0) + { + processAudio (opts, state); + if (opts->audio_out == 1) { playSynthesizedVoice (opts, state); } + } + if (opts->dmr_stereo == 1 && state->currentslot == 1) + { + processAudioR (opts, state); + if (opts->audio_out == 1) + { + playSynthesizedVoiceR (opts, state); + } + } + if (opts->dmr_stereo == 0) + { + processAudio (opts, state); + if (opts->audio_out == 1) + { + playSynthesizedVoice (opts, state); + } + } + if (opts->wav_out_f != NULL && opts->dmr_stereo == 0) + { + writeSynthesizedVoice (opts, state); + } + /* + if (opts->audio_out == 1) + { + playSynthesizedVoice (opts, state); + } + */ } /* This function decipher data */ diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 0325817..8de1877 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -42,6 +42,7 @@ int i = 0; char * s0last = " "; char * s1last = " "; char versionstr[25]; +char lrrp[6][9999]; //local lrrp storage 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", @@ -54,14 +55,15 @@ char * FM_bannerN[9] = { "https://github.com/lwvmobile/dsd-fme/tree/pulseaudio " }; -char * SyncTypes[30] = { +//need to double check these sync types, not quite matching up with frame_sync +char * SyncTypes[36] = { "+P25P1", "-P25P1", "+X2TDMA DATA", "-X2TDMA DATA", "+X2TDMA VOICE", "-X2TDMA VOICE", - "+DSTARC", + "+DSTAR", "-DSTAR", "+NXDN VOICE", //8 "-NXDN VOICE", //9 @@ -82,7 +84,14 @@ char * SyncTypes[30] = { "-dPMR", "-dPMR", "-dPMR", - "-dPMR" + "-dPMR", + "+NXDN (sync only)", + "-NXDN (sync only)", + "+YSF", + "-YSF", + "DMR MS VOICE", + "DMR MS DATA", + "DMR RC DATA" }; @@ -202,7 +211,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //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 == 10 || lls == 11 || lls == 12 || lls == 13) ) //DMR - if ( (call_matrix[9][4] != dcc || call_matrix[9][2] != rd) && (lls == 12 || lls == 13) ) //DMR, needs work + if ( (call_matrix[9][4] != dcc || call_matrix[9][2] != rd) && (lls == 12 || lls == 13 || lls == 32) ) //DMR, needs work { //reset amateur signs on radio id change for (short i = 0; i < 5; i++) @@ -228,6 +237,35 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) call_matrix[9][5] = time(NULL); //i++; } + /* + //needs work, look at saving just values to part of the state->dmr_lrrp array, or rework for int values + if ( (strcmp(state->dmr_lrrp[3], lrrp[3]) != 0) && (lls == 10 || lls == 11) ) //DMR Data LRRP + { + sprintf (lrrp[1], state->dmr_lrrp[1]); + sprintf (lrrp[2], state->dmr_lrrp[2]); + sprintf (lrrp[3], state->dmr_lrrp[3]); + //lrrp[1] = state->dmr_lrrp[1]; + //lrrp[2] = state->dmr_lrrp[2]; + //lrrp[3] = state->dmr_lrrp[3]; + 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] = (unsigned long long int)&lrrp[3]; + call_matrix[9][2] = (unsigned long long int)&lrrp[1]; + call_matrix[9][3] = (unsigned long long int)&lrrp[2]; + 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 @@ -304,9 +342,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("--Audio Decode----------------------------------------------------------------\n"); + printw ("| Decoding: %s \n", opts->output_name); 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 ("| Voice Error: [%i][%i] \n| Error Bars: [%s] \n", state->errs, state->errs2, state->err_str); // + printw ("| Voice Error: [%i][%i] \n", state->errs, state->errs2); printw ("------------------------------------------------------------------------------\n"); @@ -320,11 +359,16 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) // case 3: Ptr = "AES"; break; // default: Ptr = "Unknown Cipher Type"; break; //} - + /* if (state->lastsynctype != -1) //not sure if this will be okay { lls = state->lastsynctype; } + */ + if (state->synctype > 0 && state->synctype < 34) //not sure if this will be okay + { + lls = state->synctype; + } if (state->nxdn_last_rid > 0 && state->nxdn_last_rid != src); { src = state->nxdn_last_rid; @@ -340,20 +384,20 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //if (state->dmr_color_code > 0 && (lls == 10 || lls == 11 || lls == 12 || lls == 13) ) //DMR, DCC only carried on Data? //if (state->color_code > -1 && (lls == 10 || lls == 11 || lls == 12 || lls == 13) ) //DMR, DCC only carried on Data? - if (state->color_code_ok && (lls == 12 || lls == 13) ) //DMR, needs work + if (state->color_code_ok && (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32 || lls == 33) ) //DMR, needs work { dcc = state->dmr_color_code; //dcc = state->color_code; } - if (state->lastsrc > 0 && (lls == 12 || lls == 13 || lls == 0 || lls == 1)) //DMR Voice and P25P1 + if (state->lastsrc > 0 && (lls == 12 || lls == 13 || lls == 0 || lls == 1 || lls == 32)) //DMR Voice and P25P1 { rd = state->lastsrc; opts->p25enc = 0; } - if (state->lasttg > 0 && (lls == 12 || lls == 13 || lls == 0 || lls == 1)) //DMR Voice and P25P1 + if (state->lasttg > 0 && (lls == 12 || lls == 13 || lls == 0 || lls == 1 || lls == 32)) //DMR Voice and P25P1 { tg = state->lasttg; opts->p25enc = 0; @@ -440,7 +484,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //printw("| System Type: %s \n", ALGIDS[state->payload_keyid] ); } //if (state->lastsynctype == 12 || state->lastsynctype == 13) //DMR Voice Types - if (lls == 12 || lls == 13) //DMR Voice Types + if (lls == 12 || lls == 13 || lls == 32) //DMR Voice Types { //printw ("| DCC: [%i] FID: [%02X]\n", dcc, state->dmr_fid); //attron(COLOR_PAIR(3)); @@ -538,7 +582,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //if (state->lastsynctype == 10 || state->lastsynctype == 11) //DMR Data Types - if (lls == 10 || lls == 11 ) //DMR Data Types + if (lls == 10 || lls == 11 || lls == 33) //DMR Data Types { //printw ("| DCC: [%i]\n", dcc); printw ("| DCC: [%2i] FID: [%02X] SOP: [%02X] \n", dcc, state->dmr_fid, state->dmr_so); @@ -654,7 +698,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("TG [%4d] ", call_matrix[9-j][4]); printw ("RID [%4d] ", call_matrix[9-j][2]); } - if (lls == 0 || lls == 1 || lls == 12 || lls == 13 || lls == 10 || lls == 11 ) //P25 P1 and DMR + if (lls == 0 || lls == 1 || lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32 || lls == 33) //P25 P1 and DMR { printw ("TID [%8d] ", call_matrix[9-j][1]); printw ("RID [%8d] ", call_matrix[9-j][2]); diff --git a/src/dsd_symbol.c b/src/dsd_symbol.c index 96dccb1..ceb5cdf 100644 --- a/src/dsd_symbol.c +++ b/src/dsd_symbol.c @@ -300,8 +300,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) state->lastsample = sample; - //steal sample here for rtl input or stdin input - state->input_sample_buffer = sample; //sample or sum, honestly this seemt to be best place to grab this sadly, sounds terrible most everywhere else + } symbol = (sum / count); diff --git a/src/dsd_upsample.c b/src/dsd_upsample.c index 42623f4..a700acd 100644 --- a/src/dsd_upsample.c +++ b/src/dsd_upsample.c @@ -23,8 +23,19 @@ upsample (dsd_state * state, float invalue) int i, j, sum; float *outbuf1, c, d; - - outbuf1 = state->audio_out_float_buf_p; + if (state->currentslot == 0 && state->dmr_stereo == 1) + { + outbuf1 = state->audio_out_float_buf_p; + } + if (state->currentslot == 1 && state->dmr_stereo == 1) + { + outbuf1 = state->audio_out_float_buf_pR; + } + if (state->dmr_stereo == 0) + { + outbuf1 = state->audio_out_float_buf_p; + } + //outbuf1 = state->audio_out_float_buf_p; outbuf1--; c = *outbuf1; d = invalue; @@ -43,6 +54,33 @@ upsample (dsd_state * state, float invalue) *outbuf1 = d; outbuf1++; + if (state->currentslot == 1 && state->dmr_stereo == 1) + { + if (state->audio_out_idx2R > 24) + { + // smoothing + outbuf1 -= 16; + for (j = 0; j < 4; j++) + { + for (i = 0; i < 6; i++) + { + sum = 0; + outbuf1 -= 2; + sum += (int)*outbuf1; + outbuf1 += 2; + sum += (int)*outbuf1; + outbuf1 += 2; + sum += (int)*outbuf1; + outbuf1 -= 2; + *outbuf1 = (sum / (float) 3); + outbuf1++; + } + outbuf1 -= 8; + } + } + } + if (state->currentslot == 0 && state->dmr_stereo == 1) + { if (state->audio_out_idx2 > 24) { // smoothing @@ -65,4 +103,30 @@ upsample (dsd_state * state, float invalue) outbuf1 -= 8; } } + } + if (state->dmr_stereo == 0) + { + if (state->audio_out_idx2 > 24) + { + // smoothing + outbuf1 -= 16; + for (j = 0; j < 4; j++) + { + for (i = 0; i < 6; i++) + { + sum = 0; + outbuf1 -= 2; + sum += (int)*outbuf1; + outbuf1 += 2; + sum += (int)*outbuf1; + outbuf1 += 2; + sum += (int)*outbuf1; + outbuf1 -= 2; + *outbuf1 = (sum / (float) 3); + outbuf1++; + } + outbuf1 -= 8; + } + } + } } diff --git a/src/dstar.c b/src/dstar.c index 9ca83e3..a5a945c 100644 --- a/src/dstar.c +++ b/src/dstar.c @@ -128,14 +128,15 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) { slowdata[0] ^= 0x70; slowdata[1] ^= 0x4f; slowdata[2] ^= 0x93; - //fprintf (stderr, "unscrambled- %s",slowdata); + //fprintf (stderr, "unscrambled- %c%c%c \n", slowdata[0], slowdata[1], slowdata[2] ); } else if (framecount == 0) { - //fprintf (stderr, "never scrambled-%s\n",slowdata); + //fprintf (stderr, "never scrambled-%c\n",slowdata); + //fprintf (stderr, "never scrambled- %c%c%c \n", slowdata[0], slowdata[1], slowdata[2] ); } framecount++; - } + } //end while loop end: if (opts->errorbars == 1) { fprintf (stderr, "\n"); diff --git a/src/nxdn_data.c b/src/nxdn_data.c index 82b0684..3dc93e2 100644 --- a/src/nxdn_data.c +++ b/src/nxdn_data.c @@ -66,12 +66,19 @@ void processNXDNData (dsd_opts * opts, dsd_state * state) //fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); if(CrcIsGood) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); - fprintf (stderr, "(CRC OK) "); + fprintf (stderr, "%s", KNRM); + //fprintf (stderr, "(CRC OK) "); state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead } - else fprintf (stderr, "(CRC ERR) "); + else + { + fprintf (stderr, "%s", KRED); + fprintf (stderr, "(CRC ERR) "); + fprintf (stderr, "%s", KNRM); + } /* Decode the SACCH only when all 4 voice frame diff --git a/src/nxdn_lib.c b/src/nxdn_lib.c index 786e781..22c8c75 100644 --- a/src/nxdn_lib.c +++ b/src/nxdn_lib.c @@ -732,6 +732,7 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) } /* Print the "Call Type" */ + fprintf (stderr, "%s", KGRN); fprintf(stderr, "\n %s - ", NXDN_Call_Type_To_Str(CallType)); //line break and 1 space //sprintf (state->nxdn_call_type, NXDN_Call_Type_To_Str(CallType)); //fix warning below //warning: format not a string literal and no format arguments [-Wformat-security] @@ -753,12 +754,16 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) /* Print the Key ID */ if(CipherType != 0) { + fprintf (stderr, "%s", KYEL); fprintf(stderr, "Key ID %u - ", KeyID & 0xFF); + fprintf (stderr, "%s", KNRM); //state->nxdn_key = (KeyID & 0xFF); } /* Print Source ID and Destination ID (Talk Group or Unit ID) */ + fprintf(stderr, "Src=%u - Dst/TG=%u ", SourceUnitID & 0xFFFF, DestinationID & 0xFFFF); + fprintf (stderr, "%s", KNRM); if(state->NxdnElementsContent.VCallCrcIsGood) @@ -770,18 +775,15 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) state->nxdn_key = (KeyID & 0xFF); state->nxdn_cipher_type = CipherType; } - fprintf(stderr, "(CRC OK) "); + //fprintf(stderr, "(CRC 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"); + else + { + fprintf (stderr, "%s", KRED); + fprintf(stderr, "(CRC ERR) "); + fprintf (stderr, "%s", KNRM); + } } /* End NXDN_decode_VCALL() */ diff --git a/src/nxdn_voice.c b/src/nxdn_voice.c index 3d3a270..04b12ab 100644 --- a/src/nxdn_voice.c +++ b/src/nxdn_voice.c @@ -80,11 +80,18 @@ void processNXDNVoice (dsd_opts * opts, dsd_state * state) //if(CrcIsGood) fprintf(stderr, " (OK) - "); if(CrcIsGood) { + fprintf (stderr, "%s", KCYN); fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1); - fprintf (stderr, "(CRC OK) "); + fprintf (stderr, "%s", KNRM); + //fprintf (stderr, "(CRC OK) "); state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead } - else fprintf(stderr, "(CRC ERR) "); + else + { + fprintf (stderr, "%s", KRED); + fprintf(stderr, "(CRC ERR) "); + fprintf (stderr, "%s", KNRM); + } /* Determine the current part of superframe diff --git a/src/p25p1_hdu.c b/src/p25p1_hdu.c index 5aa1d2f..2c6a9ad 100644 --- a/src/p25p1_hdu.c +++ b/src/p25p1_hdu.c @@ -469,19 +469,17 @@ processHDU(dsd_opts* opts, dsd_state* state) mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8); } - //if (state->errs == 0 && algidhex != 0x80) - if (1 == 1) //always print hdu alg info - //if (opts->payload == 1 && state->errs == 0) + if (opts->payload == 1) //print on payload == 1 { - //fprintf (stderr, " HDU ALG ID: 0x%X KEY ID: 0x%X MI: %s \n", algidhex, kidhex, mi); + fprintf (stderr, "%s", KYEL); fprintf (stderr, " HDU ALG ID: 0x%X KEY ID: 0x%X MI: 0x%08llX%08llX%02llX MFID: 0x%02X \n", algidhex, kidhex, mihex1, mihex2, mihex3, state->payload_mfid); + fprintf (stderr, "%s", KNRM); } if (opts->p25enc == 1 && opts->payload == 0) { algidhex = strtol (algid, NULL, 2); kidhex = strtol (kid, NULL, 2); - //fprintf (stderr, "mi: %s algid: $%x kid: $%x\n", mi, algidhex, kidhex); } if (opts->p25lc == 1) { diff --git a/src/p25p1_ldu1.c b/src/p25p1_ldu1.c index fc0519a..2c6fe5f 100644 --- a/src/p25p1_ldu1.c +++ b/src/p25p1_ldu1.c @@ -51,7 +51,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state) if (opts->errorbars == 1) { - fprintf (stderr, "e:"); + //fprintf (stderr, "e:"); } // IMBE 1 diff --git a/src/p25p1_ldu2.c b/src/p25p1_ldu2.c index 0432f6a..90ebe4d 100644 --- a/src/p25p1_ldu2.c +++ b/src/p25p1_ldu2.c @@ -51,7 +51,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state) if (opts->errorbars == 1) { - fprintf (stderr, "e:"); + //fprintf (stderr, "e:"); } // IMBE 1 @@ -375,18 +375,16 @@ processLDU2 (dsd_opts * opts, dsd_state * state) mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8); } - //if (state->errs == 0 && algidhex != 0x80) - if (1 == 1) //always print the LDU2 alg info - //if (opts->payload == 1 && state->errs == 0) + if (opts->payload == 1) //print on payload == 1 { - //fprintf (stderr, " LDU2 ALG ID: 0x%X KEY ID: 0x%X MI: %s \n", algidhex, kidhex, mi); + fprintf (stderr, "%s", KYEL); fprintf (stderr, " LDU2 ALG ID: 0x%X KEY ID: 0x%X MI: 0x%08llX%08llX%02llX\n", algidhex, kidhex, mihex1, mihex2, mihex3); + fprintf (stderr, "%s", KNRM); } - //if (opts->p25enc == 1 && opts->payload == 0) + if (opts->payload == 0) { algidhex = strtol (algid, NULL, 2); kidhex = strtol (kid, NULL, 2); - //fprintf (stderr, "mi: %s algid: $%x kid: $%x\n", mi, algidhex, kidhex); } } diff --git a/src/p25p1_tdu.c b/src/p25p1_tdu.c index 4f4e501..432983a 100644 --- a/src/p25p1_tdu.c +++ b/src/p25p1_tdu.c @@ -22,7 +22,9 @@ processTDU (dsd_opts* opts, dsd_state* state) // Next we should find an status dibit if (status_count != 35) { + fprintf (stderr, "%s", KRED); fprintf (stderr, "*** SYNC ERROR\n"); + fprintf (stderr, "%s", KNRM); } // trailing status symbol diff --git a/src/p25p1_tdulc.c b/src/p25p1_tdulc.c index 1f5152a..2e56bf2 100644 --- a/src/p25p1_tdulc.c +++ b/src/p25p1_tdulc.c @@ -114,7 +114,9 @@ read_and_correct_dodeca_word (dsd_opts* opts, dsd_state* state, char* dodeca, in } else { + fprintf (stderr, "%s", KRED); fprintf (stderr, " IRRECOVERABLE"); + fprintf (stderr, "%s", KNRM); } fprintf (stderr, "\n"); #endif @@ -293,7 +295,9 @@ processTDULC (dsd_opts* opts, dsd_state* state) // Next we should find an status dibit if (status_count != 35) { + fprintf (stderr, "%s", KRED); fprintf (stderr, "*** SYNC ERROR\n"); + fprintf (stderr, "%s", KNRM); } // trailing status symbol diff --git a/src/trellis.cpp b/src/trellis.cpp index e667bbd..73b4315 100644 --- a/src/trellis.cpp +++ b/src/trellis.cpp @@ -1,8 +1,7 @@ /* * Copyright (C) 2016 by Jonathan Naylor, G4KLX * - * Modifications of original code to work with OP25 - * Copyright (C) 2019 by Graham J. Norbury + * Heavy Modificatins of Original Code to work for DSD-FME * * 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 @@ -14,7 +13,6 @@ * GNU General Public License for more details. */ #include "dsd.h" -//#include "trellis.h" #include #include @@ -52,6 +50,23 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U #define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) unsigned char state = 0U; +//rework quickHamming to accept unsigned intergers instead and go bit by bit +int quickHamming(unsigned int butt, unsigned int farts) +{ + unsigned int i = 0, count = 0, shit = 0, shart = 0; + //fprintf (stderr, "Distance Compare %X - %X \n", butt, farts ); + for (i; i < 3; i++) //shift three places tops; + { + shit = (butt >> i) & 0b1; + shart = (farts >> i) & 0b1; + if (shit != shart) + { + count++; + } + } + + return count; +} bool CDMRTrellisFixCode(unsigned char* points, unsigned int failPos, unsigned char* payload) { @@ -101,44 +116,107 @@ void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* paylo // convert bits to bytes + //fprintf (stderr, "\n Tribit Binary Sequence\n "); + for (short i = 0; i < 144; i++) + { + //fprintf (stderr, "%b", bits[i]); + } + for(short int i = 0; i < 18; i++) + { + payload[i] = (bits[i * 8 + 0] << 7) | (bits[i * 8 + 1] << 6) | (bits[i * 8 + 2] << 5) | (bits[i * 8 + 3] << 4) | + (bits[i * 8 + 4] << 3) | (bits[i * 8 + 5] << 2) | (bits[i * 8 + 6] << 1) | (bits[i * 8 + 7] << 0); + } - for (int i = 0; i < 144; i++) - payload[i/8] = (payload[i/8] << 1) | bits[i]; + //for (int i = 0; i < 144; i++) + //payload[i/8] = (payload[i/8] << 1) | bits[i]; + //DmrDataBit[j + 0] = (TrellisReturn[17-i] >> 0) & 0x01; //example } unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tribits) { + //unsigned char state = 0U; //move outside of function to preserve state for every iteration //let's try reversing the points to pass through the decode table instead of flipping them here, //it may mess up the fixcode and failpos POS state = 0U; - for (unsigned int i = 0U; i < 49U; i++) { + for (unsigned int i = 0U; i < 49U;) //total number of points to process + { tribits[i] = 9U; - - for (unsigned int j = 0U; j < 8U; j++) { - //if (points[i] == ENCODE_TABLE[state * 8U + j]) { - if (points[i] == DECODE_TABLE[state * 8U + j]) { - //if (points[48-i] == DECODE_TABLE[state * 8U + j]) { + for (unsigned int j = 0U; j < 8U; j++) + { + //if (points[i] == DECODE_TABLE[state * 8U + j]) + //if (points[48-i] == DECODE_TABLE[state * 8U + j]) + if (points[i] == ENCODE_TABLE[state * 8U + j]) + { tribits[i] = j; + state = tribits[i]; //carry over if found right away + i++; //increment i by one value break; } } - + //try to find shortest distance for surviving paths and decide on one + //seems to be that two paths will have distance value 1, and two will have distance value 2 + //need to keep totaling up a few rounds before we can eliminate a path and resume? if (tribits[i] == 9U) - return i; + { + int distance = 0; + int maxdistance = 99; //random metric for two position distance + int pathdistance = 0; + unsigned int match = 0; + unsigned int nextmatch = 0; + unsigned int q = 0; + //only 4 possible states for each point, but in 8 (0-7) FSM states + char path[99][99] = {0}; //[i][pathcount] = distance + int pathcount = 0; + for (unsigned int o = 0; o < 64; o++) //check entire state transition table for matches + { + if (points[i] == ENCODE_TABLE[o]) //ENCODE TABLE + { + match = o / (unsigned int)8; //get dividend no remainder/decimal I hope, get fsm state 0-7 + //fprintf (stderr, "\n Point #%d [%d] Match State %d Position %d Tribit Value %d \n", i, points[i], match, o, o % (unsigned int)8); + distance = quickHamming(match, state); + //fprintf (stderr, "Raw Distance Current %d\n", distance); + path[i][pathcount] = distance ; //save which table values (paths) match as possible values and distance + for (q; q < 64; q++) //check entire state transition table for next point match + { + if (points[i+1] == ENCODE_TABLE[q]) //ENCODE TABLE + { + nextmatch = q / (unsigned int)8; + path[i+1][pathcount] = quickHamming(nextmatch, q % (unsigned int)8); + //fprintf (stderr, "Raw Distance Next %d\n", path[i+1][pathcount]); + pathcount++; + //fprintf (stderr, "State 0 Match %d Distance %d \n", o, distance); + } + } + for (short int z = 0; z <= pathcount; z++) //add metrics on paths to find shortest distance + { + pathdistance = path[i][0] + path[i+1][z]; + //fprintf (stderr, "Total Path Distance %d\n", pathdistance); + if (pathdistance <= maxdistance) //equal too in case of tie? + { + maxdistance = pathdistance; + tribits[i] = o % (unsigned int)8; //remainder value will be tribit value on table + if (i < 49) //just in case we are on 49 already, don't want to crash or something. + { + tribits[i+1] = q % (unsigned int)8; //remainder value will be tribit value on table + } - state = tribits[i]; + //fprintf (stderr, "Point #%d [%d] - Tribit Candidate %d\n", i, points[i], tribits[i] ); + //fprintf (stderr, "Point #%d [%d]- Tribit Candidate %d\n", i+1, points[i+1], tribits[i+1] ); + } + } + } + //fprintf (stderr, "Selected Point #%d [%d] - Tribit Selection %d\n", i, points[i], tribits[i] ); + //fprintf (stderr, "Selected Point #%d [%d]- Tribit Selection %d\n", i+1, points[i+1], tribits[i+1] ); + } + state = tribits[i+1]; //not quite sure if this will be needed or not, if so, set state to last found value + i += 2; //increment i by two since we already got the next tribit value as well; + //state = tribits[i]; //not quite sure if this will be needed or not, if so, set state to last found value + //i++; //increment i by two since we already got the next tribit value as well; + } } - - //if (tribits[48U] != 0U) - if (tribits[48U] != 0U) // - { - return 48U; - } - - return 999U; } @@ -146,7 +224,8 @@ void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits) { int n; signed char dibit; - + //can only assume this is giving the correct dibits out, and not inverse or something. + /* for (int i = 0; i < 98; i++) { n = i * 2; if (n >= 98) n += 68; @@ -157,19 +236,44 @@ void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits) bool b2 = data[n] != 0x0; if (!b1 && b2) - dibit = +3; + dibit = +3; // 1 - 01 else if (!b1 && !b2) - dibit = +1; + dibit = +1; // 0 - 00 else if (b1 && !b2) - dibit = -1; + dibit = -1; // 2 - 10 else - dibit = -3; + dibit = -3; // 3 - 11 - n = INTERLEAVE_TABLE[i]; //should this go in reverse? - dibits[n] = dibit; + */ + //Keep it simple! + for (int i = 0; i < 98; i++) + { + n = INTERLEAVE_TABLE[97-i]; + //n = i; + if (data[i] == 0) + { + dibits[n] = 1; //1 + } + if (data[i] == 1) + { + dibits[n] = 3; //3 + } + if (data[i] == 2) + { + dibits[n] = -1; //-1 + } + if (data[i] == 3) + { + dibits[n] = -3; //-3 + } + } + + //n = INTERLEAVE_TABLE[i]; //should this go in reverse? + //n = INTERLEAVE_TABLE[97-i]; //should this go in reverse? + //dibits[n] = dibit; //should this go in reverse too? not sure on this one, but definitely the INTERLEAVE_TABLE //n = INTERLEAVE_TABLE[97-i]; //should this go in reverse? //dibits[97-n] = dibit; - } + //} } void CDMRTrellisDibitsToPoints(const signed char* dibits, unsigned char* points) @@ -324,7 +428,7 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload) } signed char dibits[98U]; CDMRTrellisDeinterleave(data, dibits); - if (1 == 1) + if (1 == 2) { fprintf (stderr, "\n Trellis Deinterleaved Dibits inside Decoder (converted to signed)\n "); for (short i = 0; i < 98; i++) @@ -333,8 +437,19 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload) } } unsigned char points[49U]; + unsigned char reverse_points[49U]; CDMRTrellisDibitsToPoints(dibits, points); - if (1 == 1) + //maybe keep point 49 at 49, since its the flush? + //fprintf (stderr, "\n Trellis Reverse Points inside Decoder\n "); + for (short i = 0; i < 49; i++) + { + reverse_points[i] = points[48-i]; + //fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]); + } + //reverse_points[48] = points[48]; + //fprintf (stderr, "#%d [%02u] ", 48, reverse_points[48]); + + if (1 == 2) { fprintf (stderr, "\n Trellis Points inside Decoder\n "); for (short i = 0; i < 49; i++) @@ -343,19 +458,11 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload) } } // Check the original code - unsigned char reverse_points[49U]; - fprintf (stderr, "\n Trellis Reversed Points inside Decoder\n "); - for (short i = 0; i < 49; i++) - { - reverse_points[i] = points[48-i]; - fprintf (stderr, "#%d [%02u] ", i, reverse_points[i]); - } - //unsigned int failPos = CDMRTrellisCheckCode(points, tribits); - unsigned int failPos = CDMRTrellisCheckCode(reverse_points, tribits); + unsigned int failPos = CDMRTrellisCheckCode(points, tribits); + //unsigned int failPos = CDMRTrellisCheckCode(reverse_points, tribits); //stack smashing detected terminated - - if (1 == 1) + if (1 == 2) { fprintf (stderr, "\n Check Code Trellis Tribits inside Decoder\n "); for (short i = 0; i < 49; i++) @@ -367,27 +474,36 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload) if (failPos == 999U) { CDMRTrellisTribitsToBits(tribits, payload); - if (1 == 1) + if (1 == 2) { - fprintf (stderr, "\nTrellis Payload Tribits to Bits failPos == 999U\n "); - for (short i = 0; i < 18; i++) + fprintf (stderr, "\nTrellis Payload Tribits\n %s ", KCYN); + for (short i = 0; i < 49; i++) { fprintf (stderr, "#%d [%0u] ", i, tribits[i]); //shouldn't have any values greater that 0x7? } } + if (1 == 2) + { + fprintf (stderr, "\nTrellis Payload Tribits to Bytes inside Decoder\n %s ", KCYN); + for (short i = 0; i < 18; i++) + { + fprintf (stderr, "[%02X]", payload[i]); + } + fprintf (stderr,"%s", KNRM); //change back to normal + } return true; } unsigned char savePoints[49U]; for (unsigned int i = 0U; i < 49U; i++) - //savePoints[i] = points[i]; - savePoints[i] = reverse_points[i]; + savePoints[i] = points[i]; + //savePoints[i] = reverse_points[i]; - //bool ret = CDMRTrellisFixCode(points, failPos, payload); - bool ret = CDMRTrellisFixCode(reverse_points, failPos, payload); + bool ret = CDMRTrellisFixCode(points, failPos, payload); + //bool ret = CDMRTrellisFixCode(reverse_points, failPos, payload); if (ret){ - if (1 == 1) + if (1 == 2) { fprintf (stderr, "\n if return Trellis Tribits inside Decoder\n "); for (short i = 0; i < 49; i++) @@ -396,7 +512,7 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload) } } - if (1 == 1) + if (1 == 2) { fprintf (stderr, "\nTrellis Payload Tribits to Bits fix return true\n "); //this one seems to be happening for (short i = 0; i < 18; i++) @@ -408,9 +524,9 @@ bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload) if (failPos == 0U) { - if (1 == 1) + if (1 == 2) { - fprintf (stderr, "\nTrellis Payload Tribits to Bits failPos == 0U\n "); + fprintf (stderr, "\nTrellis Payload Tribits to Bytes failPos == 0U\n "); for (short i = 0; i < 18; i++) { fprintf (stderr, "[%02X]", payload[i]); diff --git a/src/ysf.c b/src/ysf.c new file mode 100644 index 0000000..8882036 --- /dev/null +++ b/src/ysf.c @@ -0,0 +1,287 @@ +/*------------------------------------------------------------------------------- + * ysf.c + * Yaesu Fusion Decoder for DSD + * + * LWVMOBILE + * 2022-04 DSD-FME Florida Man Edition + *-----------------------------------------------------------------------------*/ + /* + * 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" + +const int fichInterleave[100] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, + 1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96, + 2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97, + 3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73, 78, 83, 88, 93, 98, + 4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64, 69, 74, 79, 84, 89, 94, 99, +}; + +const int vd2Interleave[104] = { + 0, 26, 52, 78, + 1, 27, 53, 79, + 2, 28, 54, 80, + 3, 29, 55, 81, + 4, 30, 56, 82, + 5, 31, 57, 83, + 6, 32, 58, 84, + 7, 33, 59, 85, + 8, 34, 60, 86, + 9, 35, 61, 87, + 10, 36, 62, 88, + 11, 37, 63, 89, + 12, 38, 64, 90, + 13, 39, 65, 91, + 14, 40, 66, 92, + 15, 41, 67, 93, + 16, 42, 68, 94, + 17, 43, 69, 95, + 18, 44, 70, 96, + 19, 45, 71, 97, + 20, 46, 72, 98, + 21, 47, 73, 99, + 22, 48, 74, 100, + 23, 49, 75, 101, + 24, 50, 76, 102, + 25, 51, 77, 103 +}; + +const int vfrInterleave[144] = { //IMBE 7200x4400 full rate interleave schedule + 0, 24, 48, 72, 96, 120, 25, 1, 73, 49, 121, 97, + 2, 26, 50, 74, 98, 122, 27, 3, 75, 51, 123, 99, + 4, 28, 52, 76, 100, 124, 29, 5, 77, 53, 125, 101, + 6, 30, 54, 78, 102, 126, 31, 7, 79, 55, 127, 103, + 8, 32, 56, 80, 104, 128, 33, 9, 81, 57, 129, 105, + 10, 34, 58, 82, 106, 130, 35, 11, 83, 59, 131, 107, + 12, 36, 60, 84, 108, 132, 37, 13, 85, 61, 133, 109, + 14, 38, 62, 86, 110, 134, 39, 15, 87, 63, 135, 111, + 16, 40, 64, 88, 112, 136, 41, 17, 89, 65, 137, 113, + 18, 42, 66, 90, 114, 138, 43, 19, 91, 67, 139, 115, + 20, 44, 68, 92, 116, 140, 45, 21, 93, 69, 141, 117, + 22, 46, 70, 94, 118, 142, 47, 23, 95, 71, 143, 119 +}; + +//half-rate ambe3600x2450 interleave schedule +const int YSFrW[36] = { + 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 2, + 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2 +}; + +// bit index +const int YSFrX[36] = { + 23, 10, 22, 9, 21, 8, + 20, 7, 19, 6, 18, 5, + 17, 4, 16, 3, 15, 2, + 14, 1, 13, 0, 12, 10, + 11, 9, 10, 8, 9, 7, + 8, 6, 7, 5, 6, 4 +}; + +// bit 0 +// frame index +const int YSFrY[36] = { + 0, 2, 0, 2, 0, 2, + 0, 2, 0, 3, 0, 3, + 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3 +}; + +// bit index +const int YSFrZ[36] = { + 5, 3, 4, 2, 3, 1, + 2, 0, 1, 13, 0, 12, + 22, 11, 21, 10, 20, 9, + 19, 8, 18, 7, 17, 6, + 16, 5, 15, 4, 14, 3, + 13, 2, 12, 1, 11, 0 +}; + +void processYSF(dsd_opts * opts, dsd_state * state) //YSF +{ + //480 dibits - 20 dibit sync leaves 460 dibits (920 bits) each 'superframe' + fprintf (stderr, "processYSF Function \n"); + uint32_t i, j, k; + unsigned char dibit; + const int *w, *x, *y, *z; + char ambe_fr[8][4][24]; + unsigned char storage[8][4][24]; //may expand later + unsigned char discard[460]; //just set up for now to hold random dibit grabs with nothing to do but skip them + unsigned char vch[4][36]; //correct size array for 4*32 dibit VD2 VCH? + unsigned char fich[200]; //store as bits after deinterleaving + unsigned char fichraw[100]; + unsigned char fichdibits[100]; //deinterleaved fich dibits + unsigned char fichbytes[26]; + unsigned int fi = 0; + unsigned int cs = 0; + unsigned int cm = 0; + unsigned int bn = 0; + unsigned int bt = 0; + unsigned int fn = 0; + unsigned int ft = 0; + unsigned int mr = 0; + unsigned int ip = 0; + unsigned int dt = 0; //DT, 2 bytes (according to manual, but has to be two bits) + unsigned int sq = 0; + unsigned int sc = 0; + int vd1 = 1; + int vd2 = 0; + unsigned int msbI = 0; + unsigned int lsbI = 0; + unsigned char vd2BitsRaw[104]; + opts->inverted_ysf = 0; //here for testing purposes, move to main later + for (i = 0; i < 100; i++) //100 dibits for fich + { + dibit = getDibit (opts, state); + + if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1 + { + dibit = (dibit ^ 2); + } + fichraw[i] = dibit; //raw storage for debug + fichdibits[fichInterleave[i]] = dibit; //sort into proper order + //fich[i*2] = (1 & (dibit >> 1)); // bit 1 + //fich[i*2+1] = (1 & dibit); // bit 0 + fich[i*2] = (fichdibits[fichInterleave[i]] >> 1) & 1; + //fprintf (stderr, "%b", fich[i*2]); + fich[i*2+1] = fichdibits[fichInterleave[i]] & 1; + //fprintf (stderr, "%b", fich[i*2+1]); + if (i == 4) + { + //datatype = dibit; + } + } + //fprintf (stderr, "\nFICH BYTES = "); + for (i = 0; i < 25; i++) //bits to bytes + { + fichbytes[i] = 0; //initialize to see what isn't beign set + fichbytes[i] = ( (fich[i*8] << 7) | (fich[i*8+1] << 6) | (fich[i*8+2] << 5) | (fich[i*8+3] << 4) | + (fich[i*8+4] << 3) | (fich[i*8+5] << 2) | (fich[i*8+6] << 1) | (fich[i*8+7] << 0) ); + //fprintf (stderr, "[%02X]", fichbytes[i]); + } + //fprintf (stderr, "\n"); + //datatype = (fich[8] << 1) + fich[9]; + dt = fichbytes[2] & 0x03; + for (i = 0; i < 2; i++) + { + //datatype << 1; + //datatype = datatype | fichraw[i+8]; + //fprintf (stderr, "%02b", fichdibits[i+4]); + //fprintf (stderr, "%02b", fichdibits[i+11]); + } + //fprintf (stderr, "Datatype = %02b\n", dt); + //quick dirty VD1 method? + if (0 == 0) //dt == 0 for VD1 + { + fprintf (stderr, "processYSF VD1 \n"); + for (j = 0; j < 5; j++) //5 DCH and VCH + { + w = YSFrW; + x = YSFrX; + y = YSFrY; + z = YSFrZ; + k = 0; + for (i = 0; i < 36; i++) + { + dibit = getDibit (opts, state); + + if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1 + { + dibit = (dibit ^ 2); + } + + storage[j][*w][*x] = (1 & (dibit >> 1)); // bit 1 + storage[j][*y][*z] = (1 & dibit); // bit 0 + + } + + + + //AMBE VCH + for (i = 0; i < 36; i++) + { + dibit = getDibit (opts, state); + + if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1 + { + dibit = (dibit ^ 2); + } + + ambe_fr[j][*w][*x] = (1 & (dibit >> 1)); // bit 1 + ambe_fr[j][*y][*z] = (1 & dibit); // bit 0 + w++; + x++; + y++; + z++; + } + //processMbeFrame (opts, state, NULL, ambe_fr[j], NULL); + } //end j < 4 loop + } //end VD1 + //move processMbeFrame to outside of dibit loop to prevent slip + for (j = 0; j < 5; j++) + { + //processMbeFrame (opts, state, NULL, ambe_fr[j], NULL); + } + //VD2 method + if (0 == 3) //dt == 3 + { + fprintf (stderr, "processYSF VD2 \n"); + for (j = 0; j < 4; j++) + { + //VCH[j] and VeCH[j] + for (i = 0; i < 20; i++) //32? + { + dibit = getDibit (opts, state); + + if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1 + { + dibit = (dibit ^ 2); + } + //collect dibits into array for processing + vch[j][i] = dibit; + w = YSFrW; + x = YSFrX; + y = YSFrY; + z = YSFrZ; + msbI = vd2Interleave[(j+1)*i]; //don't this this is remotely correct, really could use the manual right about now + lsbI = vd2Interleave[(j+1)*i+1]; + vd2BitsRaw[msbI] = ((vch[j][i] >> 1) & 1); + vd2BitsRaw[lsbI] = (vch[j][i] & 1); + } // VCH[j] + //DCH[j] + for (i = 0; i < 20; i++) //32? + { + dibit = getDibit (opts, state); + + if (opts->inverted_ysf == 1) //opts->inverted_ysf == 1 + { + dibit = (dibit ^ 2); + } + discard[i] = dibit; + } //end DCH[j] + } //end for j loop + + } //end VD2 + +} //end processYSF