848 lines
23 KiB
C
848 lines
23 KiB
C
#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; //0
|
|
internalslot = 0;
|
|
activeslot = 0;
|
|
|
|
//Run Loop while the getting is good
|
|
while (loop == 1) {
|
|
|
|
short int m = 0;
|
|
|
|
state->dmrburstL = 16; //Use 16 for Voice?
|
|
// 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++;
|
|
|
|
|
|
}
|
|
|
|
if ( ((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) && opts->inverted_dmr == 0) ||
|
|
((strcmp (sync, DMR_MS_DATA_SYNC) == 0) && opts->inverted_dmr == 1) )
|
|
|
|
{
|
|
if (internalslot == 0)
|
|
{
|
|
vc1 = 1;
|
|
state->DMRvcL = 0; //reset here if jitter/sync forces reset
|
|
fprintf (stderr, "MS Slot 1 Voice Sync \n");
|
|
}
|
|
|
|
if (internalslot == 1)
|
|
{
|
|
vc2 = 1;
|
|
state->DMRvcR = 0; //reset here if jitter/sync forces reset
|
|
}
|
|
|
|
state->dmr_ms_mode = 1; //set to 1 here??
|
|
}
|
|
|
|
state->dmr_ms_mode = 1; //set to 1 here?
|
|
|
|
//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);
|
|
fprintf (stderr,"Sync: +DMR MS MODE | 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);
|
|
fprintf (stderr,"Sync: +DMR MS MODE | 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) )
|
|
//fixed to compensate for inverted signal
|
|
if ( ((strcmp (sync, DMR_MS_DATA_SYNC) == 0) && opts->inverted_dmr == 0) ||
|
|
((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) && opts->inverted_dmr == 1) )
|
|
{
|
|
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);
|
|
if (opts->inverted_dmr == 0)
|
|
{
|
|
fprintf (stderr,"Sync: +DMR ");
|
|
}
|
|
else 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);
|
|
if (opts->inverted_dmr == 0)
|
|
{
|
|
fprintf (stderr,"Sync: +DMR MS MODE ");
|
|
}
|
|
else fprintf (stderr,"Sync: -DMR MS MODE ");
|
|
//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) && opts->inverted_dmr == 0) ||
|
|
((strcmp (sync, DMR_MS_VOICE_SYNC) != 0) && opts->inverted_dmr == 1) ) )
|
|
&& internalslot == activeslot && vc1 < 7)
|
|
|
|
{
|
|
|
|
skipcount = 0; //reset skip count if processing voice frames
|
|
fprintf (stderr,"%s ", getTime());
|
|
if (internalslot == 0 && opts->inverted_dmr == 0)
|
|
{
|
|
fprintf (stderr,"Sync: +DMR MS MODE | Color Code=%02d | DMRSTEREO | VC%d ", state->color_code, vc1);
|
|
if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10)
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " PrK %lld", state->K);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (state->DMRvcL == 0 && state->K1 > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x68)
|
|
{
|
|
fprintf (stderr, "\n");
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " SPT %016llX", state->K1);
|
|
if (state->K2 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K2);
|
|
}
|
|
if (state->K3 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K3);
|
|
}
|
|
if (state->K4 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K4);
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
fprintf (stderr, "\n");
|
|
}
|
|
|
|
if (internalslot == 0 && opts->inverted_dmr == 1)
|
|
{
|
|
fprintf (stderr,"Sync: -DMR MS MODE | Color Code=%02d | DMRSTEREO | VC%d ", state->color_code, vc1);
|
|
if (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10)
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " PrK %lld", state->K);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if (state->DMRvcL == 0 && state->K1 > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x68)
|
|
{
|
|
fprintf (stderr, "\n");
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " SPT %016llX", state->K1);
|
|
if (state->K2 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K2);
|
|
}
|
|
if (state->K3 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K3);
|
|
}
|
|
if (state->K4 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K4);
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
fprintf (stderr, "\n");
|
|
}
|
|
|
|
|
|
if (internalslot == 0 && vc1 == 6) //presumably when full (and no sync issues)
|
|
{
|
|
//process voice burst
|
|
ProcessVoiceBurstSync(opts, state);
|
|
fprintf (stderr, "\n");
|
|
}
|
|
|
|
state->dmr_ms_mode == 1;
|
|
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
|
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
|
|
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
|
|
|
|
if (vc1 == 6 && state->payload_algid >= 21)
|
|
{
|
|
state->DMRvcL = 0;
|
|
if (state->payload_mi != 0 && state->payload_algid >= 0x21)
|
|
{
|
|
LFSR(state);
|
|
}
|
|
fprintf (stderr, "\n");
|
|
}
|
|
}
|
|
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 tdma channel
|
|
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;
|
|
|
|
}
|
|
|
|
state->dmr_stereo = 0;
|
|
state->dmr_ms_mode = 0;
|
|
state->dmr_ms_rc = 0;
|
|
state->DMRvcL = 0;
|
|
|
|
}
|
|
|
|
//collect buffered 1st half and get 2nd half voice payload 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;
|
|
}
|
|
state->dmrburstL = 16; //Use 16 for Voice?
|
|
dibit_p = state->dmr_payload_p - 90;
|
|
//payload buffer tests
|
|
//CACH + First Half Payload + Sync = 12 + 54 + 24
|
|
for (i = 0; i < 90; i++) //90
|
|
{
|
|
state->dmr_stereo_payload[i] = *dibit_p;
|
|
dibit_p++;
|
|
}
|
|
//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++;
|
|
|
|
}
|
|
//work around to set erroneous PI header values to 0 if K is active
|
|
if (state->K > 0)
|
|
{
|
|
state->payload_keyid = 0; //just for testing
|
|
state->payload_keyidR = 0; //just for testing
|
|
}
|
|
|
|
fprintf (stderr,"%s ", getTime());
|
|
|
|
if (opts->inverted_dmr == 0)
|
|
{
|
|
fprintf (stderr,"Sync: +DMR MS MODE | Frame Sync | DMRSTEREO | VC1 ");
|
|
if ( (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10) ||
|
|
(state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fid == 0x10) )
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " PrK %lld", state->K);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if ( (state->DMRvcL == 0 && state->K1 > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x68) ||
|
|
(state->DMRvcR == 0 && state->K1 > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fid == 0x68) )
|
|
{
|
|
fprintf (stderr, "\n");
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " SPT %016llX", state->K1);
|
|
if (state->K2 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K2);
|
|
}
|
|
if (state->K3 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K3);
|
|
}
|
|
if (state->K4 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K4);
|
|
}
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
fprintf (stderr, "\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr,"Sync: -DMR MS MODE | Frame Sync | DMRSTEREO | VC1 ");
|
|
if ( (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10) ||
|
|
(state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fid == 0x10) )
|
|
{
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " PrK %lld", state->K);
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
if ( (state->DMRvcL == 0 && state->K1 > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x68) ||
|
|
(state->DMRvcR == 0 && state->K1 > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fid == 0x68) )
|
|
{
|
|
fprintf (stderr, "\n");
|
|
fprintf (stderr, "%s", KYEL);
|
|
fprintf(stderr, " SPT %016llX", state->K1);
|
|
if (state->K2 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K2);
|
|
}
|
|
if (state->K3 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K3);
|
|
}
|
|
if (state->K4 != 0)
|
|
{
|
|
fprintf(stderr, " %016llX", state->K4);
|
|
}
|
|
}
|
|
fprintf (stderr, "%s", KNRM);
|
|
fprintf (stderr, "\n");
|
|
}
|
|
|
|
state->dmr_ms_mode = 1;
|
|
state->DMRvcL = 0;
|
|
|
|
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, b, c;
|
|
int dibit;
|
|
int *dibit_p;
|
|
unsigned int burst;
|
|
|
|
unsigned char MSCach[24] = {0}; //12 dibits = 24 bits
|
|
unsigned char MSSync[48] = {0}; //24 dibits = 48 bits
|
|
unsigned char MSSlot[20] = {0}; //10 dibits = 20 bits
|
|
unsigned char MSBurst[5] = {0};
|
|
int cachInterleave[24] = {0, 7, 8, 9, 1, 10, 11, 12, 2, 13, 14, 15, 3, 16, 4, 17, 18, 19, 5, 20, 21, 22, 6, 23};
|
|
//int cachInterleave[24] = {0,}
|
|
//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;
|
|
}
|
|
b = 0;
|
|
c = 0;
|
|
//CACH + First Half Payload + Sync = 12 + 54 + 24
|
|
//dibit_p = state->dibit_buf_p - 90;
|
|
dibit_p = state->dmr_payload_p - 90;
|
|
for (i = 0; i < 90; i++) //90
|
|
{
|
|
dibit = *dibit_p;
|
|
dibit_p++;
|
|
if(opts->inverted_dmr == 1)
|
|
{
|
|
dibit = (dibit ^ 2);
|
|
}
|
|
state->dmr_stereo_payload[i] = dibit;
|
|
//load cach
|
|
if (i < 12)
|
|
{
|
|
MSCach[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1
|
|
MSCach[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0
|
|
}
|
|
//load slot, first half
|
|
if (i > 60 && i < 66)
|
|
{
|
|
MSSlot[(b*2)] = (1 & (dibit >> 1)); // bit 1
|
|
MSSlot[(b*2)+1] = (1 & dibit); // bit
|
|
b++;
|
|
}
|
|
//load sync
|
|
if (i > 66)
|
|
{
|
|
MSSync[(c*2)] = (1 & (dibit >> 1)); // bit 1
|
|
MSSync[(c*2)+1] = (1 & dibit); // bit 0
|
|
c++;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 54; i++)
|
|
{
|
|
dibit = getDibit(opts, state);
|
|
state->dmr_stereo_payload[i+90] = dibit;
|
|
//load slot, second half
|
|
if (i < 6)
|
|
{
|
|
MSSlot[(b*2)] = (1 & (dibit >> 1)); // bit 1
|
|
MSSlot[(b*2)+1] = (1 & dibit); // bit
|
|
b++;
|
|
}
|
|
|
|
}
|
|
|
|
//hide behind payload due to errs in data in MS mode
|
|
if (opts->payload == 1)
|
|
{
|
|
fprintf (stderr, "%s ", getTime());
|
|
if (opts->inverted_dmr == 0)
|
|
{
|
|
fprintf (stderr,"Sync: +DMR MS MODE ");
|
|
}
|
|
else fprintf (stderr,"Sync: -DMR MS MODE ");
|
|
}
|
|
|
|
|
|
sprintf(state->slot1light, "%s", "");
|
|
sprintf(state->slot2light, "%s", "");
|
|
|
|
//process data
|
|
state->dmr_stereo = 1;
|
|
state->dmr_ms_mode = 1;
|
|
|
|
//only run if payload is set to 1 due to errors with MS data
|
|
if (opts->payload == 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);
|
|
state->dmr_stereo_payload[i] = dibit;
|
|
}
|
|
|
|
}
|