diff --git a/include/dsd.h b/include/dsd.h index 5fd5ad5..4660580 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -374,6 +374,7 @@ typedef struct // int frame_ysf; int inverted_ysf; //not sure if ysf comes in inverted or not, but signal could if IQ flipped + short int aggressive_framesync; //set to 1 for more aggressive framesync, 0 for less aggressive } dsd_opts; @@ -432,7 +433,9 @@ typedef struct char tg[25][16]; int tgcount; int lasttg; + int lasttgR; int lastsrc; + int lastsrcR; int nac; int errs; int errs2; @@ -466,9 +469,13 @@ typedef struct mbe_parms *prev_mp_enhanced2; int p25kid; int payload_algid; + int payload_algidR; int payload_keyid; + int payload_keyidR; int payload_mfid; + int payload_mfidR; int payload_mi; + int payload_miR; unsigned long long int K; unsigned int debug_audio_errors; @@ -488,17 +495,6 @@ typedef struct //input sample buffer for monitoring Input short input_sample_buffer; //HERE HERE short pulse_raw_out_buffer; //HERE HERE - //float *input_sample_buffer; //HERE HERE - short dibit_to_hex_buf; - // state->sr_0 shift registers - short hexbuf; - unsigned long long sr_0; //64-bit shift registers for pushing decoded binary or dibit data - unsigned long long sr_1; //384 - unsigned long long sr_2; // - unsigned long long sr_3; // - unsigned long long sr_4; // - unsigned long long sr_5; // - unsigned long long sr_6; // unsigned int dmr_color_code; unsigned int nxdn_last_ran; @@ -507,8 +503,8 @@ typedef struct unsigned int nxdn_cipher_type; unsigned int nxdn_key; char nxdn_call_type[1024]; - char dmr_callsign[6][99]; //plenty of room in case of overflow; - char dmr_lrrp[6][9999]; + char dmr_callsign[2][6][99]; //plenty of room in case of overflow; + char dmr_lrrp[2][6][9999]; NxdnSacchRawPart_t NxdnSacchRawPart[4]; NxdnFacch1RawPart_t NxdnFacch1RawPart[2]; @@ -531,6 +527,9 @@ typedef struct unsigned int dmr_fid; unsigned int dmr_so; + unsigned int dmr_fidR; + unsigned int dmr_soR; + char slot1light[8]; char slot2light[8]; int directmode; @@ -540,8 +539,6 @@ typedef struct char dmr_branding[25]; 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 @@ -572,6 +569,11 @@ typedef struct short int dmr_stereo; //need state variable for upsample function short int dmr_ms_rc; short int dmr_ms_mode; + unsigned int dmrburstL; + unsigned int dmrburstR; + + //dstar header for ncurses + unsigned char dstarradioheader[41]; #ifdef TRACE_DSD char debug_prefix; @@ -857,6 +859,7 @@ bool QR_16_7_6_decode(unsigned char *rxBits); void InitAllFecFunction(void); void resetState (dsd_state * state); +void dstar_header_decode(dsd_state * state, int radioheaderbuffer[660]); #ifdef __cplusplus extern "C" { diff --git a/include/dstar_header.h b/include/dstar_header.h index 9723fbf..0b8e86d 100644 --- a/include/dstar_header.h +++ b/include/dstar_header.h @@ -2,5 +2,5 @@ #ifndef _DSTAR_HEADER_H #define _DSTAR_HEADER_H -void dstar_header_decode(int radioheaderbuffer[660]); -#endif /* _DSTAR_HEADER_H */ \ No newline at end of file +//void dstar_header_decode(int radioheaderbuffer[660]); +#endif /* _DSTAR_HEADER_H */ diff --git a/src/dmr_bs.c b/src/dmr_bs.c index 7d3c70d..33dc1d1 100644 --- a/src/dmr_bs.c +++ b/src/dmr_bs.c @@ -293,7 +293,7 @@ void dmrBS (dsd_opts * opts, dsd_state * 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) @@ -304,11 +304,13 @@ void dmrBS (dsd_opts * opts, dsd_state * state) fprintf (stderr,"%s ", getTime()); if (internalslot == 0) { + state->dmrburstL = 16; //use 16 for Voice? fprintf (stderr,"Sync: +DMR [slot1] slot2 | Color Code=%02d | DMRSTEREO | VC%d \n", state->color_code, vc1); } if (internalslot == 1) { + state->dmrburstR = 16; //use 16 for Voice? 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) @@ -354,8 +356,8 @@ void dmrBS (dsd_opts * opts, dsd_state * state) } //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 + //set for more aggressive or less aggressive resync during accumulated playback errs + if (opts->aggressive_framesync == 1) { //errors caused due to playing MBE files out of sync, break loop if (state->errs > 2 || state->errsR > 2) diff --git a/src/dmr_data.c b/src/dmr_data.c index d747695..ccb31f2 100644 --- a/src/dmr_data.c +++ b/src/dmr_data.c @@ -51,7 +51,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) 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) + if (opts->frame_p25p1 == 0) //opts->frame_p25p1 == 0 { dibit_p = state->dmr_payload_p - 90; } @@ -312,7 +312,17 @@ processDMRdata (dsd_opts * opts, dsd_state * state) //fprintf(stderr, "| Color Code=%02d ", (int)state->color_code); /* Reconstitute the burst type */ + //consider assigning thsi only when slottypeok or similar check passes, eliminate bad burst types from decoding randomly burst = (unsigned int)((SlotType[4] << 3) + (SlotType[5] << 2) + (SlotType[6] << 1) + SlotType[7]); + if (state->currentslot == 0) + { + state->dmrburstL = burst; + } + if (state->currentslot == 1) + { + state->dmrburstR = burst; + } + /* Reconstitute the burst type */ bursttype[0] = SlotType[4] + '0'; diff --git a/src/dmr_ms.c b/src/dmr_ms.c index e8dc69d..5e5aafc 100644 --- a/src/dmr_ms.c +++ b/src/dmr_ms.c @@ -66,7 +66,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) //Run Loop while the getting is good while (loop == 1) { - + state->dmrburstL = 16; //Use 16 for Voice? // No CACH in MS Mode? for(i = 0; i < 12; i++) { @@ -464,7 +464,7 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) return curr; } - + state->dmrburstL = 16; //Use 16 for Voice? dibit_p = state->dmr_payload_p - 90; //payload buffer tests //CACH + First Half Payload + Sync = 12 + 54 + 24 diff --git a/src/dmr_process_voice.c b/src/dmr_process_voice.c index 9c3e2af..36bc56d 100644 --- a/src/dmr_process_voice.c +++ b/src/dmr_process_voice.c @@ -94,7 +94,7 @@ if (state->currentslot == 0 && state->K > 0 && state->dmr_so & 0x40 && state->pa } } -if (state->currentslot == 1 && state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0) +if (state->currentslot == 1 && state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0) { fprintf (stderr, "%s", KYEL); fprintf(stderr, " BPK %lld", state->K); diff --git a/src/dmr_sync.c b/src/dmr_sync.c index 17f3e3a..dd9cbda 100644 --- a/src/dmr_sync.c +++ b/src/dmr_sync.c @@ -219,13 +219,17 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] fprintf (stderr, " - Port %05d", (state->dmr_34_rate_sf[10] << 8) + state->dmr_34_rate_sf[11]); } */ + //temp hide behind payload until working better + if (opts->payload == 1) + { //LRRP if ( (state->dmr_34_rate_sf[slot][0] & 0x7F) == 0x45) //Start LRRP now { + sprintf ( state->dmr_lrrp[state->currentslot][0], "LRRP - "); 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! + for (short i = 1; i < 60; i++) //find way to get padding so we only go as deep as we need to! changed from 64 to 60 to skip the CRC Bytes for confirmed data { if ( state->dmr_34_rate_sf[slot][i] == 0x0C) //Source and Destination info { @@ -269,9 +273,13 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] //fprintf (stderr, "-"); } fprintf (stderr, "%.5lf", (lrrplon * lon_unit) ); - sprintf ( state->dmr_lrrp[3], "Lat: %.5lf Lon: %.5lf", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); + if (state->dmr_34_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? + { + sprintf ( state->dmr_lrrp[state->currentslot][3], "Lat: -%.5lf Lon: %.5lf ", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); + } + else sprintf ( state->dmr_lrrp[state->currentslot][3], "Lat: %.5lf Lon: %.5lf ", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); //print for easy copy/paste into browser? - fprintf (stderr, " ("); + //fprintf (stderr, " ("); if (state->dmr_34_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? { fprintf (stderr, "-"); @@ -287,16 +295,17 @@ void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98] 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)); + sprintf ( state->dmr_lrrp[state->currentslot][4], "Vel: %.4lf kph ", (3.6 * velocity)); } 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[slot][i+1] * 2); - sprintf ( state->dmr_lrrp[2], "Dir: %d Deg", state->dmr_34_rate_sf[slot][i+1] * 2); + sprintf ( state->dmr_lrrp[state->currentslot][5], "Dir: %d Deg ", state->dmr_34_rate_sf[slot][i+1] * 2); } } } + }//end payload fprintf (stderr, "%s ", KNRM); //Full if (opts->payload == 2) @@ -1080,7 +1089,8 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ DmrDataBit[j + 7] = (DmrDataByte[i] >> 0) & 0x01; } //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 + //Start Source Destination early in case not enough 1/2 data frames + if ( (state->dmr_12_rate_sf[slot][36] & 0x7F) == 0x45 ) { fprintf (stderr, "%s ", KMAG); //fprintf (stderr, "\n IP4 Header"); //Not sure this is accurate info IP4 Header? @@ -1101,13 +1111,73 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ } fprintf (stderr, "%s ", KNRM); } + /* + //Jurek lrrp, 0x41 is probably a different header type or something, or I need to look at the data header packet PDU first. + if ( (state->dmr_12_rate_sf[slot][36] & 0x7F) == 0x41) //Start LRRP now + { + sprintf ( state->dmr_lrrp[state->currentslot][0], "LRRP - "); + fprintf (stderr, "%s ", KMAG); + 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] == 0x51 ) //lattitude and longitude + { + fprintf (stderr, "\n LRRP -"); + fprintf (stderr, " Lat: "); + if (state->dmr_12_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? + { + fprintf (stderr, "-"); + } + long int lrrplat; + long int lrrplon; + double lat_unit = (double)180/(double)4294967295; + double lon_unit = (double)360/(double)4294967295; + 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[slot][i+5] & 0x80) //first bit indicates a sign, or hemisphere? + { + //fprintf (stderr, "-"); + } + fprintf (stderr, "%.5lf", (lrrplon * lon_unit) ); + sprintf ( state->dmr_lrrp[state->currentslot][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[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_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[state->currentslot][4], "Vel: %.4lf kph ", (3.6 * velocity)); + } + 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[slot][i+1] * 2); + sprintf ( state->dmr_lrrp[state->currentslot][5], "Dir: %d Deg ", state->dmr_12_rate_sf[slot][i+1] * 2); + } + } + } + //end Jurek lrrp + */ //LRRP if ( (state->dmr_12_rate_sf[slot][0] & 0x7F) == 0x45) //Start LRRP now { + sprintf ( state->dmr_lrrp[state->currentslot][0], "LRRP - "); 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! + for (short i = 1; i < 56; i++) //find way to get padding so we only go as deep as we need to! changed from 60 to 56 to skip the CRC bytes { /* if ( state->dmr_12_rate_sf[slot][i] == 0x0C) //Source and Destination info @@ -1153,9 +1223,12 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ //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_12_rate_sf[slot][i+1] & 0x80) //first bit indicates a sign, or hemisphere? + { + sprintf ( state->dmr_lrrp[state->currentslot][3], "Lat: -%.5lf Lon: %.5lf ", ((double)lrrplat) * lat_unit , (lrrplon * lon_unit) ); + } + else sprintf ( state->dmr_lrrp[state->currentslot][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, "-"); @@ -1171,13 +1244,13 @@ void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_ 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[state->currentslot][4], "Vel: %.4lf kph ", (3.6 * velocity)); } 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[slot][i+1] * 2); - sprintf ( state->dmr_lrrp[2], "Dir: %d Deg", state->dmr_12_rate_sf[slot][i+1] * 2); + sprintf ( state->dmr_lrrp[state->currentslot][5], "Dir: %d Deg ", state->dmr_12_rate_sf[slot][i+1] * 2); } } } @@ -1595,17 +1668,35 @@ void ProcessDmrPIHeader(dsd_opts * opts, dsd_state * state, uint8_t info[196], u DmrDataBit[j + 7] = (DmrDataByte[i] >> 0) & 0x01; } - - state->payload_algid = DmrDataByte[0]; - state->payload_keyid = DmrDataByte[2]; - state->payload_mi = ( ((DmrDataByte[3]) << 24) + ((DmrDataByte[4]) << 16) + ((DmrDataByte[5]) << 8) + (DmrDataByte[6]) ); - if (1 == 1) //have it always print? + if (state->currentslot == 0) { - 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); + state->payload_algid = DmrDataByte[0]; + state->payload_keyid = DmrDataByte[2]; + 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 Slot 1"); + fprintf (stderr, " 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); + } } + if (state->currentslot == 1) + { + state->payload_algidR = DmrDataByte[0]; + state->payload_keyidR = DmrDataByte[2]; + state->payload_miR = ( ((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 Slot 2"); + fprintf (stderr, " DMR PI Header ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08X", state->payload_algidR, state->payload_keyidR, state->payload_miR); + fprintf (stderr, "%s ", KNRM); + } + } + + //test if((IrrecoverableErrors == 0) && CRCCorrect) { @@ -2005,11 +2096,24 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x07 ) //work out why amateur sets sourceid on other codes, but pro only does on whatever */ { - state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; - state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - //state->dmr_color_code = state->color_code; - state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; - state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + if (state->currentslot == 0) + { + //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; + //state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + } + if (state->currentslot == 1) + { + //state->lasttgR = TSVoiceSupFrame->FullLC.GroupAddress; + //state->lastsrcR = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fidR = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_soR = TSVoiceSupFrame->FullLC.ServiceOptions; + } + + } //only set on good CRC value or corrected values //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; @@ -2035,11 +2139,22 @@ void ProcessDmrTerminaisonLC(dsd_opts * opts, dsd_state * state, uint8_t info[19 TSVoiceSupFrame->FullLC.FullLinkControlOpcode != 0x07 ) //work out why amateur sets sourceid on other codes, but pro only does on whatever */ { - state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; - state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - //state->dmr_color_code = state->color_code; - state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; - state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + if (state->currentslot == 0) + { + //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; + //state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + } + if (state->currentslot == 1) + { + //state->lasttgR = TSVoiceSupFrame->FullLC.GroupAddress; + //state->lastsrcR = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fidR = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_soR = TSVoiceSupFrame->FullLC.ServiceOptions; + } } //only set on good CRC value or corrected values //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; @@ -2224,41 +2339,43 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) // 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) + if ( TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x03 && TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x08) { - sprintf (state->dmr_callsign[TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3], ""); //blank here so it doesn't grow out of control? + sprintf (state->dmr_callsign[state->currentslot][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]); + sprintf ( state->dmr_callsign[state->currentslot][TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3] + + strlen(state->dmr_callsign[state->currentslot][TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3]) , "%c", LC_DataBytes[i]); } } if (opts->use_ncurses_terminal == 1) { - fprintf (stderr, "%s", KCYN); + fprintf (stderr, "%s", KMAG); 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, " Embedded Alias Header and Blocks: [%s%s%s%s%s]", state->dmr_callsign[state->currentslot][0], + state->dmr_callsign[state->currentslot][1], state->dmr_callsign[state->currentslot][2], + state->dmr_callsign[state->currentslot][3], state->dmr_callsign[state->currentslot][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? + sprintf (state->dmr_callsign[state->currentslot][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]); + sprintf ( state->dmr_callsign[state->currentslot][TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3] + + strlen(state->dmr_callsign[state->currentslot][TSVoiceSupFrame->FullLC.FullLinkControlOpcode - 3]) , "%c", LC_DataBytes[i]); } } if (opts->use_ncurses_terminal == 1) @@ -2269,7 +2386,7 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) fprintf(stderr, "\n"); } fprintf (stderr, " SLOT %d", state->currentslot+1); - fprintf (stderr, " Embedded GPS: [%s]", state->dmr_callsign[5] ); + fprintf (stderr, " Embedded GPS: [%s]", state->dmr_callsign[state->currentslot][5] ); fprintf (stderr, "%s ", KNRM); } } @@ -2277,7 +2394,7 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) /* Print the destination ID (TG) and the source ID */ if((IrrecoverableErrors == 0) && CRCCorrect) { - if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x04 || TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x09) //other opcodes may convey callsigns, names, etc. was > 0x07 + if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x04 || TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x08) //other opcodes may convey callsigns, names, etc. was > 0x07 { fprintf (stderr, "%s", KGRN); if (state->dmr_stereo == 0) @@ -2289,16 +2406,30 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) fprintf(stderr, "FID=0x%02X ", TSVoiceSupFrame->FullLC.FeatureSetID); fprintf (stderr, "%s ", KNRM); //fprintf(stderr, "(CRC OK ) "); - state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; - state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; + if (state->currentslot == 0) + { + state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; + state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + } + if (state->currentslot == 1) + { + state->lasttgR = TSVoiceSupFrame->FullLC.GroupAddress; + state->lastsrcR = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fidR = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_soR = TSVoiceSupFrame->FullLC.ServiceOptions; + } //state->dmr_color_code = state->color_code; //state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; //state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; } //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; //state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; - state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + //state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; + //state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; //state->dmr_color_code = state->color_code; } else if(IrrecoverableErrors == 0) @@ -2307,7 +2438,7 @@ 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) + if (TSVoiceSupFrame->FullLC.FullLinkControlOpcode < 0x04 || TSVoiceSupFrame->FullLC.FullLinkControlOpcode > 0x08) //7, or 8? { fprintf (stderr, "%s", KGRN); if (state->dmr_stereo == 0) @@ -2320,16 +2451,30 @@ void ProcessVoiceBurstSync(dsd_opts * opts, dsd_state * state) 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; + if (state->currentslot == 0) + { + state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; + state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + } + if (state->currentslot == 1) + { + state->lasttgR = TSVoiceSupFrame->FullLC.GroupAddress; + state->lastsrcR = TSVoiceSupFrame->FullLC.SourceAddress; + //state->dmr_color_code = state->color_code; + state->dmr_fidR = TSVoiceSupFrame->FullLC.FeatureSetID; + state->dmr_soR = TSVoiceSupFrame->FullLC.ServiceOptions; + } //state->dmr_color_code = state->color_code; //state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; //state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; } //state->lasttg = TSVoiceSupFrame->FullLC.GroupAddress; //state->lastsrc = TSVoiceSupFrame->FullLC.SourceAddress; - state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; - state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; + //state->dmr_fid = TSVoiceSupFrame->FullLC.FeatureSetID; + //state->dmr_so = TSVoiceSupFrame->FullLC.ServiceOptions; //state->dmr_color_code = state->color_code; } else {} //fprintf(stderr, "\n(FEC FAIL/CRC ERR)"); diff --git a/src/dmr_voice.c b/src/dmr_voice.c index 85f38b5..e7322c3 100644 --- a/src/dmr_voice.c +++ b/src/dmr_voice.c @@ -129,6 +129,15 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state) } cachdata[12] = 0; + //set state-dmrburstL and R here to a value for ncurses + if (state->currentslot == 0) + { + state->dmrburstL = 16; //use 16 for Voice? + } + if (state->currentslot == 1) + { + state->dmrburstR = 16; //Use 16 for Voice? + } #ifdef DMR_DUMP k = 0; diff --git a/src/dsd_frame.c b/src/dsd_frame.c index 0992492..38dc782 100644 --- a/src/dsd_frame.c +++ b/src/dsd_frame.c @@ -177,9 +177,12 @@ processFrame (dsd_opts * opts, dsd_state * state) //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 { + //disable so radio id doesn't blink in and out during ncurses and aggressive_framesync state->nac = 0; - state->lastsrc = 0; - state->lasttg = 0; + //state->lastsrc = 0; + //state->lasttg = 0; + //state->lastsrcR = 0; + //state->lasttgR = 0; if (opts->errorbars == 1) { if (opts->verbose > 0) diff --git a/src/dsd_main.c b/src/dsd_main.c index 361ba6d..1e2142b 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -93,8 +93,11 @@ noCarrier (dsd_opts * opts, dsd_state * state) sprintf (state->ftype, " "); state->errs = 0; state->errs2 = 0; + //should I disable this or not? state->lasttg = 0; state->lastsrc = 0; + state->lasttgR = 0; + state->lastsrcR = 0; state->lastp25type = 0; state->repeat = 0; state->nac = 0; @@ -213,7 +216,8 @@ initOpts (dsd_opts * opts) opts->EncryptionMode = MODE_UNENCRYPTED; opts->inverted_dpmr = 0; - opts->dmr_stereo = 0; //change currently only in dsd_frame.c + opts->dmr_stereo = 0; + opts->aggressive_framesync = 1; //more aggressive to combat wonk wonk voice decoding } void @@ -346,25 +350,51 @@ initState (dsd_state * state) state->dpmr_caller_id = 0; state->dpmr_target_id = 0; - state->payload_mi = 0; + state->payload_mi = 0; + state->payload_miR = 0; state->payload_mfid = 0; + state->payload_mfidR = 0; state->payload_algid = 0; + state->payload_algidR = 0; state->payload_keyid = 0; + state->payload_keyidR = 0; sprintf (state->dmr_branding, " "); - sprintf (state->dmr_callsign[0], ""); - sprintf (state->dmr_callsign[1], ""); - sprintf (state->dmr_callsign[2], ""); - sprintf (state->dmr_callsign[3], ""); - sprintf (state->dmr_lrrp[0], ""); - sprintf (state->dmr_lrrp[1], ""); - sprintf (state->dmr_lrrp[2], ""); - sprintf (state->dmr_lrrp[3], ""); - sprintf (state->dmr_lrrp[4], ""); - sprintf (state->dmr_lrrp[5], ""); + sprintf (state->dmr_callsign[0][0], ""); + sprintf (state->dmr_callsign[0][1], ""); + sprintf (state->dmr_callsign[0][2], ""); + sprintf (state->dmr_callsign[0][3], ""); + sprintf (state->dmr_callsign[0][4], ""); + sprintf (state->dmr_callsign[0][5], ""); + sprintf (state->dmr_callsign[1][0], ""); + sprintf (state->dmr_callsign[1][1], ""); + sprintf (state->dmr_callsign[1][2], ""); + sprintf (state->dmr_callsign[1][3], ""); + sprintf (state->dmr_callsign[1][4], ""); + sprintf (state->dmr_callsign[1][5], ""); + sprintf (state->dmr_lrrp[0][0], ""); + sprintf (state->dmr_lrrp[0][1], ""); + sprintf (state->dmr_lrrp[0][2], ""); + sprintf (state->dmr_lrrp[0][3], ""); + sprintf (state->dmr_lrrp[0][4], ""); + sprintf (state->dmr_lrrp[0][5], ""); + sprintf (state->dmr_lrrp[1][0], ""); + sprintf (state->dmr_lrrp[1][1], ""); + sprintf (state->dmr_lrrp[1][2], ""); + sprintf (state->dmr_lrrp[1][3], ""); + sprintf (state->dmr_lrrp[1][4], ""); + sprintf (state->dmr_lrrp[1][5], ""); state->K = 0; state->dmr_stereo = 0; + state->dmrburstL = 17; //initialize at higher value than possible + state->dmrburstR = 17; //17 in char array is set for ERR + state->dmr_so = 0; + state->dmr_soR = 0; + state->dmr_fid = 0; + state->dmr_fidR = 0; + + memset(state->dstarradioheader, 0, 41); #ifdef TRACE_DSD state->debug_sample_index = 0; @@ -452,11 +482,14 @@ usage () fprintf (stderr," -M Min/Max buffer size for QPSK decision point tracking\n"); fprintf (stderr," (default=15)\n"); fprintf (stderr," -n Reset P25 Heuristics and initState variables on mixed 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," Helps when decoding mixed signal types (P25P1) at same time\n"); + fprintf (stderr," (WiP! May Cause Slow Memory Leak or System Hang - 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," May Cause Skipping or sync issues if bad signal/errors\n"); + fprintf (stderr," -F Enable DMR TDMA Stereo Passive Frame Sync\n"); + fprintf (stderr," This feature will attempt to resync less often due to excessive voice errors\n"); + fprintf (stderr," Use if skipping occurs, but may cuase wonky audio due to loss of good sync\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"); @@ -697,12 +730,12 @@ main (int argc, char **argv) initOpts (&opts); initState (&state); - InitAllFecFunction(); //HERE + InitAllFecFunction(); 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:NWrlZT")) != -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:NWrlZTF")) != -1) { opterr = 0; switch (c) @@ -824,6 +857,14 @@ main (int argc, char **argv) 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,"Also consider using -F if playback is too choppy!\n"); + fprintf (stderr, "%s", KNRM); + break; + + case 'F': + opts.aggressive_framesync = 0; + fprintf (stderr, "%s", KRED); + fprintf (stderr,"DMR Stereo Aggressive Resync Disabled!\n"); fprintf (stderr, "%s", KNRM); break; @@ -878,8 +919,9 @@ main (int argc, char **argv) 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," -Helps with multiple signal type decoding\n"); + //fprintf (stderr," -(WiP! May cause slow memory leak)\n"); + fprintf (stderr," -(Disabled until memory leak issues can be resolved!)\n"); fprintf (stderr, "%s", KNRM); break; case 'w': @@ -968,9 +1010,9 @@ main (int argc, char **argv) opts.frame_dmr = 0; opts.frame_dpmr = 0; opts.frame_provoice = 0; - opts.mod_gfsk = 0; opts.mod_c4fm = 1; opts.mod_qpsk = 0; + opts.mod_gfsk = 0; state.rf_mod = 0; // sprintf (opts.output_name, "P25P1"); fprintf (stderr,"Decoding only P25 Phase 1 frames.\n"); @@ -997,27 +1039,27 @@ main (int argc, char **argv) fprintf (stderr,"Setting symbol rate to 2400 / second\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] == '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') { diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 8de1877..00541d8 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -30,20 +30,20 @@ int reset = 0; char c; //getch key -int tg; //last tg +int tg; +int tgR; int tgn; -int rd; //last rid -int rn; //last ran -int nc; //nac -int src; //last rid? double? -int lls = -1; //last last sync type -int dcc = -1; //initialize with 0 to prevent core dump +int rd; +int rdR; +int rn; +int nc; +int src; +int lls = -1; +int dcc = -1; 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) ; +unsigned long long int call_matrix[33][6]; + char * FM_bannerN[9] = { " CTRL + C twice to exit", " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗", @@ -55,7 +55,6 @@ char * FM_bannerN[9] = { "https://github.com/lwvmobile/dsd-fme/tree/pulseaudio " }; -//need to double check these sync types, not quite matching up with frame_sync char * SyncTypes[36] = { "+P25P1", "-P25P1", @@ -65,16 +64,16 @@ char * SyncTypes[36] = { "-X2TDMA VOICE", "+DSTAR", "-DSTAR", - "+NXDN VOICE", //8 - "-NXDN VOICE", //9 - "+DMR DATA", //10 - "-DMR DATA", //11 - "+DMR VOICE", //12 - "-DMR VOICE", //13 - "+PROVOICE", //14 - "-PROVOICE", //15 - "+NXDN DATA", //16 - "-NXDN DATA", //17 + "+NXDN VOICE", + "-NXDN VOICE", + "+DMR DATA", + "-DMR DATA", + "+DMR VOICE", + "-DMR VOICE", + "+PROVOICE", + "-PROVOICE", + "+NXDN DATA", + "-NXDN DATA", "+DSTAR HD", "-DSTAR HD", "+dPMR", @@ -92,6 +91,27 @@ char * SyncTypes[36] = { "DMR MS VOICE", "DMR MS DATA", "DMR RC DATA" +}; + +char * DMRBusrtTypes[18] = { + "PI Header ", + "VOICE LC HDR ", + "TLC ", + "CSBK ", + "MBC Header ", + "MBC Cont ", + "DATA Header ", + "RATE 1/2 DATA ", + "RATE 3/4 DATA ", + "Slot Idle ", + "Rate 1 DATA ", + "ERR ", //These values for ERR may be Reserved for use in future? + "ERR ", + "ERR ", + "ERR ", + "ERR ", + "Voice ", //Using 16 for Voice since its higher than possible value? + "INITIAL " //17 is assigned on start up }; @@ -125,48 +145,139 @@ void ncursesOpen () noecho(); cbreak(); - //fprintf (stderr, "Opening NCurses Terminal. \n"); - } void ncursesPrinter (dsd_opts * opts, dsd_state * state) { int level; - - //level = (int) state->max / 164; level = 0; //start each cycle with 0 - erase(); - //disabling until wide support can be built for LM, etc. $(ncursesw5-config --cflags --libs) - printw ("%s \n", FM_bannerN[0]); //top line in white - attron(COLOR_PAIR(4)); - for (short int i = 1; i < 7; i++) //following lines in cyan - { - printw("%s \n", FM_bannerN[i]); - } - attroff(COLOR_PAIR(4)); - printw ("--Build Info------------------------------------------------------------------\n"); - printw ("| %s \n", FM_bannerN[7]); //http link - printw ("| Digital Speech Decoder: Florida Man Edition\n"); - printw ("| Github Build Version: %s \n", GIT_TAG); - printw ("| mbelib version %s\n", versionstr); - //printw ("| Press CTRL+C twice to exit\n"); - printw ("------------------------------------------------------------------------------\n"); + //Variable reset/set section + + //carrier reset if (state->carrier == 0) //reset these to 0 when no carrier { - state->payload_algid = 0; - state->payload_keyid = 0; + state->payload_algid = 0; + state->payload_keyid = 0; + state->payload_keyidR = 0; + state->payload_algidR = 0; //state->payload_mfid = 0; - state->payload_mi = 0; + state->payload_mi = 0; + state->payload_miR = 0; state->nxdn_key = 0; state->nxdn_cipher_type = 0; - + //memset(state->dstarradioheader, 0, 41); sprintf(state->dmr_branding, " "); } - if ( (lls == 14 || lls == 15) && (time(NULL) - call_matrix[9][5] > 5) && state->carrier == 1) //honestly have no idea how to do this for pV, just going time based? only update on carrier == 1. + //set lls sync types + if (state->synctype >= 0 && state->synctype < 35) //not sure if this will be okay + { + lls = state->synctype; + } + + //reset DMR alias block and embedded gps if burst type is not 16 or carrier drop + if (state->dmrburstL != 16 || state->carrier == 0) + { + for (short i = 0; i < 6; i++) + { + sprintf (state->dmr_callsign[0][i], ""); + } + } + if (state->dmrburstR != 16 || state->carrier == 0) + { + for (short i = 0; i < 6; i++) + { + sprintf (state->dmr_callsign[1][i], ""); + } + } + + //reset DMR LRRP when call is active on current slot if burst type is not data or carrier drop + if (state->dmrburstL == 16 || state->carrier == 0) + { + for (short i = 0; i < 6; i++) + { + //sprintf (state->dmr_lrrp[0][i], ""); + } + } + if (state->dmrburstR == 16 || state->carrier == 0) + { + for (short i = 0; i < 6; i++) + { + //sprintf (state->dmr_lrrp[1][i], ""); + } + } + + //NXDN + if (state->nxdn_last_rid > 0 && state->nxdn_last_rid != src); + { + src = state->nxdn_last_rid; + } + if (state->nxdn_last_ran > -1 && state->nxdn_last_ran != rn); + { + rn = state->nxdn_last_ran; + } + if (state->nxdn_last_tg > 0 && state->nxdn_last_tg != tgn); + { + tgn = state->nxdn_last_tg; + } + + //DMR CC + if (state->color_code_ok && state->dmr_color_code != -1 && (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32 || lls == 33) ) + { + dcc = state->dmr_color_code; + } + + //DMR SRC + if ( (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32) ) + { + if (state->dmrburstL == 16 && state->lastsrc > 0) //state->currentslot == 0 && + { + rd = state->lastsrc; + } + + if (state->dmrburstR == 16 && state->lastsrcR > 0) //state->currentslot == 1 && + { + rdR = state->lastsrcR; + } + //move to seperate P25 version plz + opts->p25enc = 0; + } + + //DMR TG + if ( (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32) ) + { + if (state->dmrburstL == 16 && state->lasttg > 0) //state->currentslot == 0 && + { + tg = state->lasttg; + } + + if (state->dmrburstR == 16 && state->lastsrcR > 0) //state->currentslot == 1 && + { + tgR = state->lasttgR; + } + opts->p25enc = 0; + } + + //P25 + if (state->nac > 0) + { + nc = state->nac; + } + if ( state->lasttg > 0 && (lls == 0 || lls == 1) ) + { + tg = state->lasttg; + } + if ( state->lastsrc > 0 && (lls == 0 || lls == 1) ) + { + rd = state->lastsrc; + } + + //Call History Matrix Shuffling + //ProVoice + if ( (lls == 14 || lls == 15) && (time(NULL) - call_matrix[9][5] > 5) && state->carrier == 1) { for (short int k = 0; k < 9; k++) { @@ -184,12 +295,33 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) call_matrix[9][3] = 1; call_matrix[9][4] = 1; call_matrix[9][5] = time(NULL); - //nowN = time(NULL); + } - //if ( (state->nxdn_last_rid != src && src > 0) || (state->nxdn_last_ran != rn && rn > 0) ) //find condition to make this work well, probably if last != local last variables - //if ( (call_matrix[9][2] != src && src > 0) || (call_matrix[9][1] != rn && rn > 0) ) //NXDN working well now with this, updates immediately and only once - if ( call_matrix[9][2] != src && src > 0 && rn > -1 ) //NXDN working well now with this, updates immediately and only once + //D-STAR, work on adding the headers later + if ( (lls == 6 || lls == 7 || lls == 18 || lls == 19) && (time(NULL) - call_matrix[9][5] > 5) && state->carrier == 1) + { + 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] = 1; + call_matrix[9][2] = 1; + call_matrix[9][3] = 1; + call_matrix[9][4] = 1; + call_matrix[9][5] = time(NULL); + + } + + //NXDN + if ( call_matrix[9][2] != src && src > 0 && rn > -1 ) { for (short int k = 0; k < 9; k++) { @@ -209,17 +341,11 @@ 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 || lls == 32) ) //DMR, needs work + //DMR MS + if ( call_matrix[9][2] != rd && (lls == 32 || lls == 33 || lls == 34) ) { - //reset amateur signs on radio id change - for (short i = 0; i < 5; i++) - { - sprintf (state->dmr_callsign[i], ""); - } - //dcc = state->dmr_color_code; - for (short int k = 0; k < 9; k++) + + for (short int k = 0; k < 10; k++) { call_matrix[k][0] = call_matrix[k+1][0]; call_matrix[k][1] = call_matrix[k+1][1]; @@ -232,22 +358,40 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) call_matrix[9][0] = lls; call_matrix[9][1] = tg; call_matrix[9][2] = rd; - call_matrix[9][3] = 0; + call_matrix[9][3] = 1; //hard set slot number call_matrix[9][4] = dcc; 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 + + //DMR BS Slot 1 - matrix 0-4 + if ( call_matrix[4][2] != rd && (lls == 12 || lls == 13 || lls == 10 || lls == 11) ) { - 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++) + + for (short int k = 0; k < 4; 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[4][0] = lls; + call_matrix[4][1] = tg; + call_matrix[4][2] = rd; + call_matrix[4][3] = 1; //hard set slot number + call_matrix[4][4] = dcc; + call_matrix[4][5] = time(NULL); + + } + + //DMR BS Slot 2 - matrix 5-9 + if ( call_matrix[9][2] != rdR && (lls == 12 || lls == 13 || lls == 10 || lls == 11) ) + { + + for (short int k = 5; k < 9; k++) { call_matrix[k][0] = call_matrix[k+1][0]; call_matrix[k][1] = call_matrix[k+1][1]; @@ -258,17 +402,16 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } 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][1] = tgR; + call_matrix[9][2] = rdR; + call_matrix[9][3] = 2; //hard set slot number 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 + } + + //P25 + if ( (lls == 0 || lls == 1) && call_matrix[9][2] != rd && nc > 0 && tg > 0) { for (short int k = 0; k < 9; k++) { @@ -286,15 +429,30 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) call_matrix[9][3] = 0; call_matrix[9][4] = nc; call_matrix[9][5] = time(NULL); - //i++; + } - //printw ("Time: "); - //printw ("%s \n", getTimeN()); + + //Start Printing Section + erase(); + printw ("%s \n", FM_bannerN[0]); //top line in white + attron(COLOR_PAIR(4)); + for (short int i = 1; i < 7; i++) //following lines in cyan + { + printw("%s \n", FM_bannerN[i]); + } + attroff(COLOR_PAIR(4)); + printw ("--Build Info------------------------------------------------------------------\n"); + printw ("| %s \n", FM_bannerN[7]); //http link + printw ("| Digital Speech Decoder: Florida Man Edition\n"); + printw ("| Github Build Version: %s \n", GIT_TAG); + printw ("| mbelib version %s\n", versionstr); + //printw ("| Press CTRL+C twice to exit\n"); + printw ("------------------------------------------------------------------------------\n"); attron(COLOR_PAIR(4)); printw ("--Input Output----------------------------------------------------------------\n"); if (opts->audio_in_type == 0) { - printw ("| Pulse Audio Input [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_in/1000, opts->pulse_digi_in_channels); + printw ("| Pulse Audio Input: [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_in/1000, opts->pulse_digi_in_channels); } if (opts->audio_in_type == 1) { @@ -311,17 +469,17 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } if (opts->audio_out_type == 0) { - printw ("| Pulse Audio Output [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels); + printw ("| Pulse Audio Output: [%i] kHz [%i] Channel\n", opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels); } if (opts->monitor_input_audio == 1) { - printw ("| Monitoring Source Audio when carrier present and No Sync Detected\n"); + printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected\n"); } - if (opts->mbe_out_dir[0] != 0) + if (opts->mbe_out_dir[0] != 0 && opts->dmr_stereo == 0) { printw ("| Writing MBE data files to directory %s\n", opts->mbe_out_dir); } - if (opts->wav_out_file[0] != 0) + if (opts->wav_out_file[0] != 0 && opts->dmr_stereo == 0) { printw ("| Appending Audio WAV to file %s\n", opts->wav_out_file); } @@ -340,83 +498,52 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) reset = 0; } - printw ("--Audio Decode----------------------------------------------------------------\n"); - printw ("| Decoding: %s \n", opts->output_name); + 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 ("| Voice Error: [%i][%i] \n", state->errs, state->errs2); + if (opts->dmr_stereo == 0) + { + printw ("| Voice Error: [%i][%i] \n", state->errs, state->errs2); + } + + if (opts->dmr_stereo == 1) + { + printw ("| Voice ErrS1: [%i][%i] \n", state->errs, state->errs2); + printw ("| Voice ErrS2: [%i][%i] \n", state->errsR, state->errs2R); + } printw ("------------------------------------------------------------------------------\n"); - printw ("--Call Info-------------------------------------------------------------------\n"); - //NXDN Ciper Types - //switch(CipherType) - //{ - // case 0: Ptr = ""; break; /* Non-ciphered mode / clear call */ - // case 1: Ptr = "Scrambler"; break; - // case 2: Ptr = "DES"; break; - // case 3: Ptr = "AES"; break; - // default: Ptr = "Unknown Cipher Type"; break; - //} - /* - if (state->lastsynctype != -1) //not sure if this will be okay + //DSTAR...what a pain... + if (lls == 6 || lls == 7 || lls == 18 || lls == 19) { - 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; - } - if (state->nxdn_last_ran > -1 && state->nxdn_last_ran != rn); - { - rn = state->nxdn_last_ran; - } - if (state->nxdn_last_tg > 0 && state->nxdn_last_tg != tgn); - { - tgn = state->nxdn_last_tg; + if (state->dstarradioheader[3] != 0) // + { + printw ("| RPT 2: [%c%c%c%c%c%c%c%c] ", state->dstarradioheader[3], state->dstarradioheader[4], + state->dstarradioheader[5], state->dstarradioheader[6], state->dstarradioheader[7], state->dstarradioheader[8], + state->dstarradioheader[9], state->dstarradioheader[10]); + printw ("RPT 1: [%c%c%c%c%c%c%c%c] \n| ", state->dstarradioheader[11], state->dstarradioheader[12], + state->dstarradioheader[13], state->dstarradioheader[14], state->dstarradioheader[15], state->dstarradioheader[16], + state->dstarradioheader[17], state->dstarradioheader[18]); + printw ("YOUR: [%c%c%c%c%c%c%c%c] ", state->dstarradioheader[19], state->dstarradioheader[20], + state->dstarradioheader[21], state->dstarradioheader[22], state->dstarradioheader[23], state->dstarradioheader[24], + state->dstarradioheader[25], state->dstarradioheader[26]); + printw ("MY: [%c%c%c%c%c%c%c%c] [%c%c%c%c]\n", state->dstarradioheader[27], + state->dstarradioheader[28], state->dstarradioheader[29], state->dstarradioheader[30], state->dstarradioheader[31], + state->dstarradioheader[32], state->dstarradioheader[33], state->dstarradioheader[34], state->dstarradioheader[35], + state->dstarradioheader[36], state->dstarradioheader[37], state->dstarradioheader[38]); + } } - //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 || 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 || lls == 32)) //DMR Voice and P25P1 - { - rd = state->lastsrc; - opts->p25enc = 0; - } - - if (state->lasttg > 0 && (lls == 12 || lls == 13 || lls == 0 || lls == 1 || lls == 32)) //DMR Voice and P25P1 - { - tg = state->lasttg; - opts->p25enc = 0; - } - - //if (state->lastsynctype == 8 || state->lastsynctype == 9 || state->lastsynctype == 16 || state->lastsynctype == 17) //change this to NXDN syncs later on + //NXDN if (lls == 8 || lls == 9 || lls == 16 || lls == 17) { printw ("| RAN: [%2d] ", rn); printw ("TID: [%4d] ", tgn); - //printw ("| RID: [%d] \n", src); printw ("RID: [%4d] \n| ALG: [0x%02X] KEY [0x%02X] ", src, state->nxdn_cipher_type, state->nxdn_key); if (state->carrier == 1) { printw("%s ", state->nxdn_call_type); - //attron(COLOR_PAIR(4)); - //printw ("No Encryption "); - //attroff(COLOR_PAIR(4)); - //attron(COLOR_PAIR(3)); } if (state->nxdn_cipher_type == 0x1 && state->carrier == 1) { @@ -448,31 +575,16 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } //printw("%s ", state->nxdn_call_type); printw("\n"); - - } - //printw ("Error?: [%i] [%i] \n", state->errs, state->errs2); //what are these? - /* //wasn't we already doing this twice - if (state->lasttg > 0 && state->lastsrc > 0) + //P25 + if (lls == 0 || lls == 1) { - tg = state->lasttg; - rd = state->lastsrc; - } - */ - if (state->nac > 0) - { - nc = state->nac; - } - if ((lls == 0 || lls == 1)) //1 for P25 P1 Audio - { - //printw("| TID:[%i] | RID:[%i] \n", tg, rd); - //printw("| NAC: [0x%X] \n", nc); printw("| TID:[%8i] RID:[%8i] ", tg, rd); printw("NAC: [0x%3X] \n", nc); printw("| ALG:[0x%02X] ", state->payload_algid); printw(" KEY:[0x%04X] ", state->payload_keyid); - printw(" MFID: [0x%02X] ", state->payload_mfid); //no way of knowing if this is accurate info yet + printw(" MFID: [0x%02X] ", state->payload_mfid); //no way of knowing if this is accurate info yet if (state->payload_algid != 0x80 && state->payload_algid != 0x0 && state->carrier == 1) { attron(COLOR_PAIR(2)); @@ -481,182 +593,218 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) attron(COLOR_PAIR(3)); } printw("\n"); - //printw("| System Type: %s \n", ALGIDS[state->payload_keyid] ); - } - //if (state->lastsynctype == 12 || state->lastsynctype == 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)); - printw ("| DCC: [%2i] FID: [%02X] SOP: [%02X] ", dcc, state->dmr_fid, state->dmr_so); - //if(state->payload_mi == 0 && state->dmr_so & 0x40) - if(state->payload_mi == 0 && (state->dmr_so & 0xCF) == 0x40) //4F or CF mask? - { - attron(COLOR_PAIR(5)); - printw ("**BP** "); - //printw ("0x%X", state->payload_algid); - attroff(COLOR_PAIR(5)); - attron(COLOR_PAIR(3)); - } - //if(state->payload_keyid > 0 && state->dmr_so & 0x40) - if(state->payload_keyid > 0 && (state->dmr_so & 0xCF) == 0x40) - { - attron(COLOR_PAIR(5)); - printw (" ALG: [0x%02X] KEY [0x%02X] MI [0x%08X]", state->payload_algid, state->payload_keyid, state->payload_mi); - //printw ("0x%X", state->payload_algid); - attroff(COLOR_PAIR(5)); - attron(COLOR_PAIR(3)); - } - //if(state->K > 0 && state->payload_keyid == 0 && state->dmr_so & 0x40) - if(state->K > 0 && (state->dmr_so & 0xCF) == 0x40) - { - attron(COLOR_PAIR(5)); - printw ("BPK [%3lld]", state->K); - attroff(COLOR_PAIR(5)); - attron(COLOR_PAIR(3)); - } - - printw("\n"); - printw ("| TID: [%8i] RID: [%8i]", tg, rd); - - if (1 == 1) //figure out what to put here later on for amateur call signs - { - printw (" ["); - for (short i = 0; i < 5; i++) - { - printw ("%s", state->dmr_callsign[i]); - } - printw ("]"); - } - //if(state->dmr_so & 0x80) //1000 0000 //prints emergency on some amateru DMR repeaters with 0x8E SOP code, need to investigate - if(state->dmr_so == 0x80) - { - attron(COLOR_PAIR(2)); - printw (" **Emergency** "); - attroff(COLOR_PAIR(2)); - attron(COLOR_PAIR(3)); - } - - //if(state->dmr_so & 0x40) //0100 0000 - if(state->dmr_so == 0x40) //0100 0000 - { - attron(COLOR_PAIR(2)); - printw (" **ENC** "); - //printw ("0x%X", state->payload_algid); - attroff(COLOR_PAIR(2)); - attron(COLOR_PAIR(3)); - if (state->K == 0) - { - //opts->p25enc = 1; //just testing for now - } - - } - - //if(state->dmr_so & 0x30) //0010 0000 - if(state->dmr_so == 0x30) //0010 0000 - { - attron(COLOR_PAIR(2)); - printw (" **Private Call** "); - attroff(COLOR_PAIR(2)); - attron(COLOR_PAIR(3)); - } - printw("\n"); - //printw ("%s ", state->slot0light); - printw ("| SLOT 1 "); - if (state->currentslot == 0) //find out how to tell when slot0 has voice - { - s0last = "Voice"; - //printw("Voice"); - } - printw ("%s ", s0last); - - //printw ("%s ", state->slot1light); - printw ("SLOT 2 "); - if (state->currentslot == 1) //find out how to tell when slot1 has voice - { - s1last = "Voice"; - //printw("Voice"); - } - printw ("%s \n", s1last); } - - //if (state->lastsynctype == 10 || state->lastsynctype == 11) //DMR Data Types - if (lls == 10 || lls == 11 || lls == 33) //DMR Data Types + //DMR BS/MS Voice and Data Types + if ( lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32 || lls == 33 || lls == 34) { - //printw ("| DCC: [%i]\n", dcc); - printw ("| DCC: [%2i] FID: [%02X] SOP: [%02X] \n", dcc, state->dmr_fid, state->dmr_so); - printw ("| TID: [%8i] RID: [%8i]", tg, rd); - - if (1 == 1) //figure out what to put here later on for amateur call signs + printw ("| "); + if (lls < 30) { - printw (" ["); - for (short i = 0; i < 5; i++) - { - printw ("%s", state->dmr_callsign[i]); - } - printw ("]"); + printw ("DMR BS - DCC: [%02i] ", dcc); } - //does this need to be in DATA type? - /* - if(state->dmr_so & 0x80) + else + { + printw ("DMR MS - DCC: [%02i] ", dcc); + } + + printw ("\n"); + //Slot 1 [0] + printw ("| SLOT 1 - "); + if (state->dmrburstL != 16 && state->carrier == 1 && state->lasttg > 0 && state->lastsrc > 0) { attron(COLOR_PAIR(2)); - printw (" **Emergency** "); + } + printw ("TGT: [%8i] SRC: [%8i] ", state->lasttg, state->lastsrc); + if (state->dmrburstL != 16 && state->carrier == 1 && state->lasttg > 0 && state->lastsrc > 0) + { attroff(COLOR_PAIR(2)); attron(COLOR_PAIR(3)); } + printw ("FID: [%02X] SVC: [%02X] ", state->dmr_fid, state->dmr_so); + printw ("%s ", DMRBusrtTypes[state->dmrburstL]); + printw ("\n"); + printw ("| | "); //10 spaces + //Burger King + if(state->dmrburstL == 16 && state->payload_mi == 0 && (state->dmr_so & 0xCF) == 0x40) //4F or CF mask? + { + attron(COLOR_PAIR(5)); + printw (" **BP** "); + attroff(COLOR_PAIR(5)); + attron(COLOR_PAIR(3)); + } + //Point + if(state->dmrburstL == 16 && state->payload_mi == 0 && state->K > 0 && (state->dmr_so & 0xCF) == 0x40) + { + attron(COLOR_PAIR(1)); + printw ("BPK [%3lld] ", state->K); + attroff(COLOR_PAIR(1)); + attron(COLOR_PAIR(3)); + } + //ALG, KeyID, MI + if(state->dmrburstL == 16 && state->payload_keyid > 0 && (state->dmr_so & 0xCF) == 0x40) + { + attron(COLOR_PAIR(1)); + printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X]", state->payload_algid, state->payload_keyid, state->payload_mi); + attroff(COLOR_PAIR(1)); + attron(COLOR_PAIR(3)); + } - if(state->dmr_so & 0x40) + if(state->dmrburstL == 16 && state->dmr_so == 0x40) //0100 0000 { attron(COLOR_PAIR(2)); printw (" **ENC** "); attroff(COLOR_PAIR(2)); attron(COLOR_PAIR(3)); } - - if(state->dmr_so & 0x30) + if(state->dmrburstL == 16 && state->dmr_so == 0x80) + { + attron(COLOR_PAIR(2)); + printw (" **Emergency** "); + attroff(COLOR_PAIR(2)); + attron(COLOR_PAIR(3)); + } + if(state->dmrburstL == 16 && state->dmr_so == 0x30) //0010 0000 { attron(COLOR_PAIR(2)); printw (" **Private Call** "); attroff(COLOR_PAIR(2)); attron(COLOR_PAIR(3)); } - */ - printw("\n"); + printw ("\n"); + //Alias Blocks and Embedded GPS + printw ("| | "); //10 spaces + if(state->dmrburstL == 16) //only during call + { + attron(COLOR_PAIR(5)); + for (short i = 0; i < 5; i++) + { + printw ("%s", state->dmr_callsign[0][i]); + } + //Embedded GPS (not LRRP) + printw ("%s", state->dmr_callsign[0][5] ); + attroff(COLOR_PAIR(5)); + if (state->carrier == 1) + { + attron(COLOR_PAIR(3)); + } - //printw ("%s ", state->slot0light); - printw ("| SLOT 1 "); - if (state->currentslot == 0) //find out how to tell when slot0 has voice - { - s0last = "Data "; - if (strcmp (state->fsubtype, " Slot idle ") == 0) + //LRRP + if(state->dmrburstL != 16) //only during data { - s0last = "Idle "; + attron(COLOR_PAIR(5)); + for (short i = 0; i < 5; i++) + { + printw ("%s", state->dmr_lrrp[0][i]); + } + attroff(COLOR_PAIR(5)); + if (state->carrier == 1) + { + attron(COLOR_PAIR(3)); + } } } - printw ("%s ", s0last); - //printw ("%s ", state->slot1light); - printw ("SLOT 2 "); - if (state->currentslot == 1) //find out how to tell when slot1 has voice + printw ("\n"); + + //Slot 2 [1] + if (lls < 30){ //Don't print on MS mode + printw ("| SLOT 2 - "); + if (state->dmrburstR != 16 && state->carrier == 1 && state->lasttgR > 0 && state->lastsrcR > 0) { - s1last = "Data "; - if (strcmp (state->fsubtype, " Slot idle ") == 0) + attron(COLOR_PAIR(2)); + } + printw ("TGT: [%8i] SRC: [%8i] ", state->lasttgR, state->lastsrcR); + if (state->dmrburstR != 16 && state->carrier == 1 && state->lasttgR > 0 && state->lastsrcR > 0) + { + attroff(COLOR_PAIR(2)); + attron(COLOR_PAIR(3)); + } + printw ("FID: [%02X] SVC: [%02X] ", state->dmr_fidR, state->dmr_soR); + printw ("%s ", DMRBusrtTypes[state->dmrburstR]); + printw ("\n"); + printw ("| | "); //12 spaces + + //Burger King 2 + if(state->dmrburstR == 16 && state->payload_miR == 0 && (state->dmr_soR & 0xCF) == 0x40) //4F or CF mask? + { + attron(COLOR_PAIR(5)); + printw (" **BP** "); + attroff(COLOR_PAIR(5)); + attron(COLOR_PAIR(3)); + } + //Point 2 + if(state->dmrburstR == 16 && state->payload_miR == 0 && state->K > 0 && (state->dmr_soR & 0xCF) == 0x40) + { + attron(COLOR_PAIR(1)); + printw ("BPK [%3lld] ", state->K); + attroff(COLOR_PAIR(1)); + attron(COLOR_PAIR(3)); + } + //ALG, KeyID, MI 2 + if(state->dmrburstR == 16 && state->payload_keyidR > 0 && (state->dmr_soR & 0xCF) == 0x40) + { + attron(COLOR_PAIR(1)); + printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X]", state->payload_algidR, state->payload_keyidR, state->payload_miR); + attroff(COLOR_PAIR(1)); + attron(COLOR_PAIR(3)); + } + //Call Types, may switch to the more robust version later? + if(state->dmrburstR == 16 && state->dmr_soR == 0x40) //0100 0000 + { + attron(COLOR_PAIR(2)); + printw (" **ENC** "); + attroff(COLOR_PAIR(2)); + attron(COLOR_PAIR(3)); + } + if(state->dmrburstR == 16 && state->dmr_soR == 0x80) + { + attron(COLOR_PAIR(2)); + printw (" **Emergency** "); + attroff(COLOR_PAIR(2)); + attron(COLOR_PAIR(3)); + } + if(state->dmrburstR == 16 && state->dmr_soR == 0x30) //0010 0000 + { + attron(COLOR_PAIR(2)); + printw (" **Private Call** "); + attroff(COLOR_PAIR(2)); + attron(COLOR_PAIR(3)); + } + printw ("\n"); + //Alias Blocks and Embedded GPS + printw ("| | "); //10 spaces + if(state->dmrburstR == 16) //only during call + { + attron(COLOR_PAIR(5)); + for (short i = 0; i < 5; i++) { - s1last = "Idle "; + printw ("%s", state->dmr_callsign[1][i]); + } + //Embedded GPS (not LRRP) + printw ("%s", state->dmr_callsign[1][5] ); + attroff(COLOR_PAIR(5)); + if (state->carrier == 1) + { + attron(COLOR_PAIR(3)); } } - printw ("%s \n", s1last); - /* - if (state->dmr_lrrp[3] != NULL) + //LRRP + if(state->dmrburstR != 16) //only during data { - printw ("| LRRP -"); - printw (" %s", state->dmr_lrrp[3]); - printw (" %s", state->dmr_lrrp[1]); - printw (" %s\n", state->dmr_lrrp[2]); + attron(COLOR_PAIR(5)); + for (short i = 0; i < 5; i++) + { + printw ("%s", state->dmr_lrrp[1][i]); + } + attroff(COLOR_PAIR(5)); + if (state->carrier == 1) + { + attron(COLOR_PAIR(3)); + } } - */ - } + printw ("\n"); + } // end if not MS + } //end DMR BS Types //dPMR if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27) @@ -665,97 +813,73 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("TID: [%s] RID: [%s] \n", state->dpmr_target_id, state->dpmr_caller_id); } - if (lls != -1) //is there a synctype 0? + if (lls == 6 || lls == 7 || lls == 18 || lls == 19 || lls == 14 || lls == 15) { printw ("| %s ", SyncTypes[lls]); //printw ("%s", state->dmr_branding); printw ("\n"); } + //fence bottom printw ("------------------------------------------------------------------------------\n"); //colors off if (state->carrier == 1){ //same as above attroff(COLOR_PAIR(3)); } - //if (state->carrier == 0){ //same as above - //attroff(COLOR_PAIR(1)); - //} attron(COLOR_PAIR(4)); //cyan for history - //add other interesting info to put here - //make Call_Matrix - //0 - sync type; 1 - tg/ran; 2 - rid; 3 - slot; 4 - cc; 5 - time(NULL) ; - printw ("--Call History----------------------------------------------------------------\n"); for (short int j = 0; j < 10; j++) { + //only print if a valid time was assinged to the matrix if ( ((time(NULL) - call_matrix[9-j][5]) < 9999) ) - //if (1 == 1) { - printw ("| #%d %s ", j, SyncTypes[call_matrix[9-j][0]]); - if (lls == 8 || lls == 9 || lls == 16 || lls == 17) - { - printw ("RAN [%2d] ", call_matrix[9-j][1]); - 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 || lls == 32 || lls == 33) //P25 P1 and DMR - { - printw ("TID [%8d] ", call_matrix[9-j][1]); - printw ("RID [%8d] ", call_matrix[9-j][2]); - } - if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27) //dPMR - { - printw ("TID [%8d] ", call_matrix[9-j][1]); - printw ("RID [%8d] ", call_matrix[9-j][2]); - printw ("DCC [%2d] ", call_matrix[9-j][4]); + printw ("| %s ", SyncTypes[call_matrix[9-j][0]]); + if (lls == 8 || lls == 9 || lls == 16 || lls == 17) + { + printw ("RAN [%2lld] ", call_matrix[9-j][1]); + printw ("TG [%4lld] ", call_matrix[9-j][4]); + printw ("RID [%4lld] ", call_matrix[9-j][2]); + } + //dPMR + if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27) + { + printw ("TGT [%8lld] ", call_matrix[9-j][1]); + printw ("SRC [%8lld] ", call_matrix[9-j][2]); + printw ("DCC [%2lld] ", call_matrix[9-j][4]); + } + //P25P1 Voice and Data + if (call_matrix[9-j][0] == 0 || call_matrix[9-j][0] == 1) + { + printw ("TID [%8lld] ", call_matrix[9-j][1]); + printw ("RID [%8lld] ", call_matrix[9-j][2]); + printw ("NAC [0x%03llX] ", call_matrix[9-j][4]); + } + //DMR BS Types + if (call_matrix[9-j][0] == 12 || call_matrix[9-j][0] == 13 || call_matrix[9-j][0] == 10 || call_matrix[9-j][0] == 11 ) + { + printw ("S[%d] ", call_matrix[9-j][3]); + printw ("TGT [%8lld] ", call_matrix[9-j][1]); + printw ("SRC [%8lld] ", call_matrix[9-j][2]); + printw ("DCC [%02lld] ", call_matrix[9-j][4]); + } + //DMR MS Types + if (call_matrix[9-j][0] == 32 || call_matrix[9-j][0] == 33 || call_matrix[9-j][0] == 34 ) + { + //printw ("S[%d] ", call_matrix[9-j][3]); + printw ("TGT [%8lld] ", call_matrix[9-j][1]); + printw ("SRC [%8lld] ", call_matrix[9-j][2]); + printw ("DCC [%02lld] ", call_matrix[9-j][4]); + } + printw ("%lld secs ago\n", time(NULL) - call_matrix[9-j][5]); } + } //end Call History + //fence bottom + printw ("------------------------------------------------------------------------------\n"); + attroff(COLOR_PAIR(4)); //cyan for history - //printw ("RID [%08d] ", call_matrix[9-j][2]); - //printw ("S %d - ", call_matrix[j][3]); - if (call_matrix[9-j][0] == 0 || call_matrix[9-j][0] == 1) //P25P1 Voice - { - printw ("NAC [0x%3X] ", call_matrix[9-j][4]); - } - if (call_matrix[9-j][0] == 12 || call_matrix[9-j][0] == 13 || call_matrix[9-j][0] == 10 || call_matrix[9-j][0] == 11 ) //DMR Voice Types - { - printw ("DCC [%2d] ", call_matrix[9-j][4]); - } - printw ("%d secs ago\n", time(NULL) - call_matrix[9-j][5]); - } - //printw("\n"); - } - printw ("------------------------------------------------------------------------------\n"); - attroff(COLOR_PAIR(4)); //cyan for history - //put sync type at very bottom - //printw ("%s %s\n", state->ftype, state->fsubtype); //some ftype strings have extra spaces in them - //if (state->lastsynctype != -1) //is there a synctype 0? - //while((c = getch()) != '~') { - // printw ("%c\n",c);} - //c = getch(); - /* - if (c = getch() != '~') - { - printf ("%c\n",c); - printf ("closing NCurses"); - ncursesClose(); - } - */ - //debug sr printw - if (1==2) //disable this later on - { - - printw ("sr_0 = %16llX \n", state->sr_0); - printw ("sr_1 = %16llX \n", state->sr_1); - printw ("sr_2 = %16llX \n", state->sr_2); - printw ("sr_3 = %16llX \n", state->sr_3); - printw ("sr_4 = %16llX \n", state->sr_4); - printw ("sr_5 = %16llX \n", state->sr_5); - printw ("sr_6 = %16llX \n", state->sr_6); - - } - refresh(); -} + refresh(); +} //end ncursesPrinter void ncursesClose () { diff --git a/src/dsd_reset.c b/src/dsd_reset.c index e8aa893..ab6165d 100644 --- a/src/dsd_reset.c +++ b/src/dsd_reset.c @@ -96,12 +96,7 @@ resetState (dsd_state * state) state->nxdn_last_ran = 0; -//#ifdef TRACE_DSD -// state->debug_sample_index = 0; -// state->debug_label_file = NULL; -// state->debug_label_dibit_file = NULL; -// state->debug_label_imbe_file = NULL; -//#endif - + //each time you run this, it increses memory use by 4MB, massive memory leak + //need to revisit this sometime and look into only resetting only the necesary items to let P25 switch between signals (C4FM or Wide) without needing a restart initialize_p25_heuristics(&state->p25_heuristics); //see if we want to re-init this or not, currently seems to cause memory leak when running over and over, mitigated with a reset flag } diff --git a/src/dstar.c b/src/dstar.c index a5a945c..12a47d0 100644 --- a/src/dstar.c +++ b/src/dstar.c @@ -39,6 +39,9 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) { unsigned int bitbuffer = 0; const int *w, *x; + //set carrier to 1 so ncurses will light up green + state->carrier = 1; + if (opts->errorbars == 1) { fprintf (stderr, "e:"); } @@ -56,7 +59,7 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) { } else { framecount = 1; //just saw a sync frame; there should be 20 not 21 till the next } - + //why is this running in a loop for? while (sync_missed < 3) { memset(ambe_fr, 0, 96); @@ -86,6 +89,7 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) { ambe_fr[*w][*x] = (1 & dibit); w++; x++; + } @@ -128,14 +132,30 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) { slowdata[0] ^= 0x70; slowdata[1] ^= 0x4f; slowdata[2] ^= 0x93; - //fprintf (stderr, "unscrambled- %c%c%c \n", slowdata[0], slowdata[1], slowdata[2] ); + //fprintf (stderr, "unscrambled- %02X %02X %02X %02X \n", slowdata[0], slowdata[1], slowdata[2], slowdata[3] ); } else if (framecount == 0) { //fprintf (stderr, "never scrambled-%c\n",slowdata); - //fprintf (stderr, "never scrambled- %c%c%c \n", slowdata[0], slowdata[1], slowdata[2] ); - } + //fprintf (stderr, "never scrambled- %02X %02X %02X %02X \n", slowdata[0], slowdata[1], slowdata[2], slowdata[3] ); + } + for (short int i = 0; i < 4; i++) + { + if (slowdata[i] <= 0x7E && slowdata[i] >=0x20) + { + //fprintf (stderr, "%c", slowdata[i]); + } + //else fprintf (stderr, "."); + } + //fprintf (stderr, "\n"); framecount++; + + //since we are in a while loop, run ncursesPrinter here. + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } + } //end while loop end: if (opts->errorbars == 1) { @@ -154,7 +174,7 @@ void processDSTAR_HD(dsd_opts * opts, dsd_state * state) { // Note: These routines contain GPLed code. Remove if you object to that. // Due to this, they are in a separate source file. - dstar_header_decode(radioheaderbuffer); + dstar_header_decode(state, radioheaderbuffer); //We officially have sync now, so just pass on to the above routine: diff --git a/src/dstar_header.c b/src/dstar_header.c index 204ee7b..db7907c 100644 --- a/src/dstar_header.c +++ b/src/dstar_header.c @@ -19,8 +19,9 @@ #include "fcs.h" #include "descramble.h" #include "dstar_header.h" +#include "dsd.h" -void dstar_header_decode(int radioheaderbuffer[660]) { +void dstar_header_decode(dsd_state * state, int radioheaderbuffer[660]) { int radioheaderbuffer2[660]; unsigned char radioheader[41]; int octetcount, bitcount, loop; @@ -33,6 +34,7 @@ void dstar_header_decode(int radioheaderbuffer[660]) { deinterleave(radioheaderbuffer2, radioheaderbuffer); len = FECdecoder(radioheaderbuffer, radioheaderbuffer2); memset(radioheader, 0, 41); + //memset(state->dstarradioheader, 0, 41); // note we receive 330 bits, but we only use 328 of them (41 octets) // bits 329 and 330 are unused octetcount = 0; @@ -48,6 +50,14 @@ void dstar_header_decode(int radioheaderbuffer[660]) { bitcount = 0; } } + //state->dstarradioheader = radioheader; + + for (short i = 0; i < 41; i++) + { + state->dstarradioheader[i] = radioheader[i]; + } + + // print header fprintf (stderr, "\nDSTAR HEADER: "); //fprintf (stderr, "FLAG1: %02X - FLAG2: %02X - FLAG3: %02X\n", radioheader[0], diff --git a/src/p25p1_hdu.c b/src/p25p1_hdu.c index 2c6a9ad..1bdd2c7 100644 --- a/src/p25p1_hdu.c +++ b/src/p25p1_hdu.c @@ -469,10 +469,10 @@ processHDU(dsd_opts* opts, dsd_state* state) mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8); } - if (opts->payload == 1) //print on payload == 1 + if (1 == 1) //print on payload == 1 { 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, " HDU ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX MFID: 0x%02X \n", algidhex, kidhex, mihex1, mihex2, mihex3, state->payload_mfid); fprintf (stderr, "%s", KNRM); } diff --git a/src/p25p1_ldu2.c b/src/p25p1_ldu2.c index 90ebe4d..c518c92 100644 --- a/src/p25p1_ldu2.c +++ b/src/p25p1_ldu2.c @@ -375,10 +375,10 @@ processLDU2 (dsd_opts * opts, dsd_state * state) mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8); } - if (opts->payload == 1) //print on payload == 1 + if (1 == 1) //print on payload == 1 { 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, " LDU2 ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX\n", algidhex, kidhex, mihex1, mihex2, mihex3); fprintf (stderr, "%s", KNRM); }