DMR Stereo TDMA

DMR Stereo TDMA
--play voice in both TDMA slots with the -T option (dsd -fr -T)
--Improved MS voice (mostly working) and data handling (hit or miss)
--pretty pretty colors on the console log output
--rate 3/4 data decoding partially working
This commit is contained in:
lwvmobile
2022-04-30 04:43:03 -04:00
committed by GitHub
parent 8b48328431
commit 3cd1eefad8
29 changed files with 3291 additions and 1003 deletions

462
src/dmr_bs.c Normal file
View File

@@ -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
}

View File

@@ -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() */

672
src/dmr_ms.c Normal file
View File

@@ -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]);
}
}

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

View File

@@ -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() */

View File

@@ -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)

View File

@@ -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) ? &parameters : NULL,
(input == 0) ? &parameters : 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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -17,9 +17,8 @@
#include "dsd.h"
#include <locale.h>
//#include <ncurses.h>
//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

View File

@@ -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 <num> Audio output gain (default = 0 = auto, disable = -1)\n");
fprintf (stderr," -w <file> 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 <hertz> 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 ();
}

View File

@@ -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 */

View File

@@ -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]);

View File

@@ -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);

View File

@@ -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;
}
}
}
}

View File

@@ -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");

View File

@@ -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

View File

@@ -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() */

View File

@@ -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

View File

@@ -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)
{

View File

@@ -51,7 +51,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
if (opts->errorbars == 1)
{
fprintf (stderr, "e:");
//fprintf (stderr, "e:");
}
// IMBE 1

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 <cstdio>
#include <cassert>
@@ -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]);

287
src/ysf.c Normal file
View File

@@ -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