diff --git a/include/dsd.h b/include/dsd.h index cb17246..bc4123f 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -348,6 +348,10 @@ typedef struct //Trunking - Tune Data Calls uint8_t trunk_tune_data_calls; + //'DSP' Format Output + uint8_t use_dsp_output; + char dsp_out_file[1024]; + } dsd_opts; typedef struct diff --git a/src/dmr_bs.c b/src/dmr_bs.c index 7fa0ec3..c488a80 100644 --- a/src/dmr_bs.c +++ b/src/dmr_bs.c @@ -371,6 +371,20 @@ void dmrBS (dsd_opts * opts, dsd_state * state) state->last_cc_sync_time = time(NULL); } + //'DSP' output to file + if (opts->use_dsp_output == 1) + { + FILE * pFile; //file pointer + pFile = fopen (opts->dsp_out_file, "a"); + fprintf (pFile, "\n%d 10 ", internalslot+1); //0x10 for voice burst + for (i = 6; i < 72; i++) //33 bytes, no CACH + { + int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1]; + fprintf (pFile, "%X", dsp_byte); + } + fclose (pFile); + } + //reset err checks cach_err = 1; tact_okay = 0; @@ -458,6 +472,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) uint8_t cach_err = 0; uint8_t sync_okay = 1; + uint8_t internalslot; char cachdata[25]; int cachInterleave[24] = @@ -490,10 +505,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) { dibit = *dibit_p; dibit_p++; - if(opts->inverted_dmr == 1) - { - dibit = (dibit ^ 2); - } + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i] = dibit; } @@ -521,7 +533,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) } } - state->currentslot = tact_bits[1]; + internalslot = state->currentslot = tact_bits[1]; //Setup for first AMBE Frame @@ -588,6 +600,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) for(i = 0; i < 18; i++) { dibit = getDibit(opts, state); + state->dmr_stereo_payload[i+90] = dibit; ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 ambe_fr2[*y][*z] = (1 & dibit); // bit 0 @@ -610,6 +623,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) for(i = 0; i < 36; i++) { dibit = getDibit(opts, state); + state->dmr_stereo_payload[i+108] = dibit; ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1 ambe_fr3[*y][*z] = (1 & dibit); // bit 0 @@ -620,6 +634,20 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) } + //'DSP' output to file + if (opts->use_dsp_output == 1) + { + FILE * pFile; //file pointer + pFile = fopen (opts->dsp_out_file, "a"); + fprintf (pFile, "\n%d 10 ", internalslot+1); //0x10 for "voice burst" + for (i = 6; i < 72; i++) //33 bytes, no CACH + { + int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1]; + fprintf (pFile, "%X", dsp_byte); + } + fclose (pFile); + } + fprintf (stderr,"%s ", getTime()); char polarity[3]; char light[18]; diff --git a/src/dmr_data.c b/src/dmr_data.c index 0b46d6a..0c35c7e 100644 --- a/src/dmr_data.c +++ b/src/dmr_data.c @@ -56,6 +56,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[i]; } + else state->dmr_stereo_payload[i] = dibit; cachdata[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1 cachdata[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0 @@ -103,6 +104,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[i+12]; } + else state->dmr_stereo_payload[i+12] = dibit; info[2*i] = (1 & (dibit >> 1)); // bit 1 info[(2*i)+1] = (1 & dibit); // bit 0 } @@ -118,6 +120,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[61]; } + else state->dmr_stereo_payload[61] = dibit; SlotType[0] = (1 & (dibit >> 1)); // bit 1 SlotType[1] = (1 & dibit); // bit 0 @@ -132,6 +135,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[62]; } + else state->dmr_stereo_payload[62] = dibit; SlotType[2] = (1 & (dibit >> 1)); // bit 1 SlotType[3] = (1 & dibit); // bit 0 @@ -146,6 +150,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[63]; } + else state->dmr_stereo_payload[63] = dibit; SlotType[4] = (1 & (dibit >> 1)); // bit 1 SlotType[5] = (1 & dibit); // bit 0 @@ -160,6 +165,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[64]; } + else state->dmr_stereo_payload[64] = dibit; SlotType[6] = (1 & (dibit >> 1)); // bit 1 SlotType[7] = (1 & dibit); // bit 0 @@ -175,6 +181,8 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[65]; } + else state->dmr_stereo_payload[65] = dibit; + SlotType[8] = (1 & (dibit >> 1)); // bit 1 SlotType[9] = (1 & dibit); // bit 0 @@ -191,6 +199,8 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[i+66]; } + else 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; @@ -236,6 +246,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) if (state->dmr_stereo == 0) { dibit = getDibit(opts, state); + state->dmr_stereo_payload[i+90] = dibit; } if (state->dmr_stereo == 1) { @@ -277,6 +288,7 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) if (state->dmr_stereo == 0) { dibit = getDibit(opts, state); + state->dmr_stereo_payload[i+95] = dibit; } if (state->dmr_stereo == 1) diff --git a/src/dmr_dburst.c b/src/dmr_dburst.c index 0fa0eb9..c6bdcdb 100644 --- a/src/dmr_dburst.c +++ b/src/dmr_dburst.c @@ -168,6 +168,21 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196 { if (state->dmr_ms_mode == 0) fprintf(stderr, "| Color Code=%02d ", state->dmr_color_code); fprintf(stderr, "|%s", state->fsubtype); + + //'DSP' output to file + if (opts->use_dsp_output == 1) + { + FILE * pFile; //file pointer + pFile = fopen (opts->dsp_out_file, "a"); + fprintf (pFile, "\n%d %02X ", slot+1, databurst); //use hex value of current data burst type + for (i = 6; i < 72; i++) //33 bytes, no CACH + { + int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1]; + fprintf (pFile, "%X", dsp_byte); + } + fclose (pFile); + } + } //Most Data Sync Burst types will use the bptc 196x96 diff --git a/src/dmr_ms.c b/src/dmr_ms.c index 5b64dca..cf4749c 100644 --- a/src/dmr_ms.c +++ b/src/dmr_ms.c @@ -87,7 +87,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) for(i = 0; i < 12; i++) { dibit = getDibit(opts, state); - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; cachdata[i] = dibit; state->dmr_stereo_payload[i] = dibit; @@ -119,7 +119,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) for(i = 0; i < 36; i++) { dibit = getDibit(opts, state); - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i+12] = dibit; @@ -144,7 +144,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) for(i = 0; i < 18; i++) { dibit = getDibit(opts, state); - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i+48] = dibit; ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 @@ -161,7 +161,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) for(i = 0; i < 24; i++) { dibit = getDibit(opts, state); - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i+66] = dibit; @@ -190,7 +190,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) for(i = 0; i < 18; i++) { dibit = getDibit(opts, state); - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i+90] = dibit; ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 @@ -214,7 +214,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) for(i = 0; i < 36; i++) { dibit = getDibit(opts, state); - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i+108] = dibit; ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1 @@ -227,6 +227,20 @@ void dmrMS (dsd_opts * opts, dsd_state * state) } + //'DSP' output to file + if (opts->use_dsp_output == 1) + { + FILE * pFile; //file pointer + pFile = fopen (opts->dsp_out_file, "a"); + fprintf (pFile, "\n%d 10 ", state->currentslot+1); //0x10 for "voice burst", forced to slot 1 + for (i = 6; i < 72; i++) //33 bytes, no CACH + { + int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1]; + fprintf (pFile, "%X", dsp_byte); + } + fclose (pFile); + } + state->dmr_ms_mode = 1; memcpy (ambe_fr4, ambe_fr2, sizeof(ambe_fr2)); @@ -292,7 +306,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) dibit = getDibit(opts, state); if (opts->inverted_dmr == 1) { - dibit = (dibit ^ 2); + dibit = (dibit ^ 2) & 3; } state->dmr_stereo_payload[i] = dibit; @@ -379,7 +393,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) dibit = state->dmr_stereo_payload[i]; if(opts->inverted_dmr == 1) { - dibit = (dibit ^ 2); + dibit = (dibit ^ 2) & 3; } cachdata[i] = dibit; } @@ -398,7 +412,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) dibit = state->dmr_stereo_payload[i+12]; if(opts->inverted_dmr == 1) { - dibit = (dibit ^ 2); + dibit = (dibit ^ 2) & 3; } state->dmr_stereo_payload[i+12] = dibit; ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1 @@ -425,7 +439,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) dibit = state->dmr_stereo_payload[i+48]; if(opts->inverted_dmr == 1) { - dibit = (dibit ^ 2); + dibit = (dibit ^ 2) & 3; } ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 ambe_fr2[*y][*z] = (1 & dibit); // bit 0 @@ -443,8 +457,9 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) dibit = getDibit(opts, state); if(opts->inverted_dmr == 1) { - dibit = (dibit ^ 2); + dibit = (dibit ^ 2) & 3; } + state->dmr_stereo_payload[i+90] = dibit; ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1 ambe_fr2[*y][*z] = (1 & dibit); // bit 0 @@ -469,8 +484,9 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) dibit = getDibit(opts, state); if(opts->inverted_dmr == 1) { - dibit = (dibit ^ 2); + dibit = (dibit ^ 2) & 3; } + state->dmr_stereo_payload[i+108] = dibit; ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1 ambe_fr3[*y][*z] = (1 & dibit); // bit 0 @@ -481,6 +497,20 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) } + //'DSP' output to file + if (opts->use_dsp_output == 1) + { + FILE * pFile; //file pointer + pFile = fopen (opts->dsp_out_file, "a"); + fprintf (pFile, "\n%d 10 ", state->currentslot+1); //0x10 for "voice burst", force to slot 1 + for (i = 6; i < 72; i++) //33 bytes, no CACH + { + int dsp_byte = (state->dmr_stereo_payload[i*2] << 2) | state->dmr_stereo_payload[i*2 + 1]; + fprintf (pFile, "%X", dsp_byte); + } + fclose (pFile); + } + fprintf (stderr, "%s ", getTime()); if (opts->inverted_dmr == 0) { @@ -558,7 +588,7 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) { dibit = *dibit_p; dibit_p++; - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i] = dibit; } @@ -566,7 +596,7 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) for (i = 0; i < 54; i++) { dibit = getDibit(opts, state); - if(opts->inverted_dmr == 1) dibit = (dibit ^ 2); + if(opts->inverted_dmr == 1) dibit = (dibit ^ 2) & 3; state->dmr_stereo_payload[i+90] = dibit; } diff --git a/src/dsd_main.c b/src/dsd_main.c index 87200fc..56da813 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -69,6 +69,7 @@ comp (const void *a, const void *b) //struct for checking existence of directory to write to struct stat st = {0}; char wav_file_directory[1024] = {0}; +char dsp_filename[1024] = {0}; unsigned long long int p2vars = 0; char * pEnd; //bugfix @@ -516,6 +517,10 @@ initOpts (dsd_opts * opts) opts->dPMR_next_part_of_superframe = 0; + //dsp structured file + opts->dsp_out_file[0] = 0; + opts->use_dsp_output = 0; + } //initopts void @@ -885,6 +890,7 @@ usage () printf (" -a Enable Call Alert Beep (NCurses Terminal Only)\n"); printf (" (Warning! Might be annoying.)\n"); printf (" -L Specify Filename for LRRP Data Output.\n"); + printf (" -Q Specify Filename for DSP Structured File Output. (placed in DSP folder)\n"); printf (" -c Output symbol capture to .bin file\n"); printf (" -q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice\n"); printf (" -V Enable Audio Smoothing on Upsampled 48k/1 or 24k/2 Audio (Capital V)\n"); @@ -1189,7 +1195,7 @@ main (int argc, char **argv) exitflag = 0; // signal (SIGINT, sigfun); - while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:Y:K:H:X:NQWrlZTF01:2:345:6:7:89:E")) != -1) + while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:Y:K:H:X:NQ:WrlZTF01:2:345:6:7:89:E")) != -1) { opterr = 0; switch (c) @@ -1207,6 +1213,23 @@ main (int argc, char **argv) //Disabled the Serial Port Dev and Baud Rate, etc, If somebody uses that function, sorry... + case 'Q': //'DSP' Structured Output file for OKDMRlib + sprintf (wav_file_directory, "./DSP"); + wav_file_directory[1023] = '\0'; + if (stat(wav_file_directory, &st) == -1) + { + fprintf (stderr, "-Q %s DSP file directory does not exist\n", wav_file_directory); + fprintf (stderr, "Creating directory %s to save DSP Structured files\n", wav_file_directory); + mkdir(wav_file_directory, 0700); //user read write execute, needs execute for some reason or segfault + } + //read in filename + //sprintf (opts.wav_out_file, "./WAV/DSD-FME-X1.wav"); + strncpy(dsp_filename, optarg, 1023); + sprintf(opts.dsp_out_file, "%s/%s", wav_file_directory, dsp_filename); + fprintf (stderr, "Saving DSP Structured files to %s\n", opts.dsp_out_file); + opts.use_dsp_output = 1; + break; + //Enable Audio Smoothing for Upsampled Audio case '0': case 'V': @@ -1460,7 +1483,7 @@ main (int argc, char **argv) wav_file_directory[1023] = '\0'; if (stat(wav_file_directory, &st) == -1) { - fprintf (stderr, "-T %s WAV file directory does not exist\n", wav_file_directory); + fprintf (stderr, "-P %s WAV file directory does not exist\n", wav_file_directory); fprintf (stderr, "Creating directory %s to save decoded wav files\n", wav_file_directory); mkdir(wav_file_directory, 0700); //user read write execute, needs execute for some reason or segfault }