mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 09:17:20 -05:00
167 lines
5.2 KiB
C
167 lines
5.2 KiB
C
#include "dsd.h"
|
|
#include "nxdn_const.h"
|
|
|
|
//don't know why this doesn't work right in LEH, need to figure that out for him
|
|
//works just fien when ripped from his and into mine
|
|
//must be some random thing, I'll look at his when I have a chance
|
|
void processNXDNVoice (dsd_opts * opts, dsd_state * state)
|
|
{
|
|
int i, j, dibit;
|
|
char ambe_fr[4][24];
|
|
unsigned char sacch_raw[72] = {0};
|
|
unsigned char sacch_decoded[32] = {0}; /* 26 bit + 6 bit CRC */
|
|
const int *w, *x, *y, *z;
|
|
unsigned char *pr;
|
|
uint8_t CrcIsGood = 0;
|
|
uint8_t StructureField = 0;
|
|
uint8_t RAN = 0;
|
|
uint8_t PartOfFrame = 0;
|
|
char ambe7bytesArray[7] = {0};
|
|
int PartOfEncryptedSuperFrame = 0;
|
|
|
|
if (opts->errorbars == 1)
|
|
{
|
|
fprintf(stderr, "VOICE - ");
|
|
}
|
|
|
|
/* Start pseudo-random NXDN sequence after
|
|
* LICH = 16 bit = 8 dibit
|
|
* ==> Index 8 */
|
|
pr = (unsigned char *)(&nxdnpr2[8]);
|
|
for (i = 0; i < 30; i++)
|
|
{
|
|
dibit = getDibit (opts, state);
|
|
|
|
/* Store and de-interleave directly SACCH bits */
|
|
sacch_raw[(2*i)] = ((*pr) & 1) ^ (1 & (dibit >> 1)); // bit 1
|
|
sacch_raw[(2*i)+1] = (1 & dibit); // bit 0
|
|
|
|
// TODO : Deinterleave is done in the "NXDN_SACCH_decode" function
|
|
// /* Store and de-interleave directly SACCH bits */
|
|
// sacch_raw[nsW[2*i]] = *pr ^ (1 & (dibit >> 1)); // bit 1
|
|
// sacch_raw[nsW[2*i+1]] = (1 & dibit); // bit 0
|
|
pr++;
|
|
#ifdef NXDN_DUMP
|
|
fprintf(stderr, "%c", dibit + 48);
|
|
#endif
|
|
}
|
|
#ifdef NXDN_DUMP
|
|
fprintf(stderr, " ");
|
|
#endif
|
|
|
|
// TODO : Unpuncture is done in the "NXDN_SACCH_decode" function
|
|
// /* For the sake of simplicity, handle the re-insertion of punctured bits here.
|
|
// * This makes the actual Viterbi decoder code a LOT simpler. */
|
|
// for (i = 30; i < 36; i++)
|
|
// {
|
|
// sacch_raw[nsW[2*i]] = 0;
|
|
// sacch_raw[nsW[2*i+1]] = 0;
|
|
// }
|
|
|
|
/* Decode the SACCH fields */
|
|
CrcIsGood = NXDN_SACCH_raw_part_decode(sacch_raw, sacch_decoded);
|
|
StructureField = (sacch_decoded[0]<<1 | sacch_decoded[1]<<0) & 0x03; /* Compute the Structure Field (remove 2 first bits of the SR Information in the SACCH) */
|
|
RAN = (sacch_decoded[2]<<5 | sacch_decoded[3]<<4 | sacch_decoded[4]<<3 | sacch_decoded[5]<<2 | sacch_decoded[6]<<1 | sacch_decoded[7]<<0) & 0x3F; /* Compute the RAN (6 last bits of the SR Information in the SACCH) */
|
|
|
|
/* Compute the Part of Frame according to the structure field */
|
|
if (StructureField == 3) PartOfFrame = 0;
|
|
else if(StructureField == 2) PartOfFrame = 1;
|
|
else if(StructureField == 1) PartOfFrame = 2;
|
|
else if(StructureField == 0) PartOfFrame = 3;
|
|
else PartOfFrame = 0; /* Normally we should never go here */
|
|
|
|
/* Fill the SACCH structure */
|
|
state->NxdnSacchRawPart[PartOfFrame].CrcIsGood = CrcIsGood;
|
|
state->NxdnSacchRawPart[PartOfFrame].StructureField = StructureField;
|
|
state->NxdnSacchRawPart[PartOfFrame].RAN = RAN;
|
|
memcpy(state->NxdnSacchRawPart[PartOfFrame].Data, &sacch_decoded[8], 18); /* Copy the 18 bits of SACCH content */
|
|
|
|
//fprintf(stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1);
|
|
//if(CrcIsGood) fprintf(stderr, " (OK) - ");
|
|
if(CrcIsGood)
|
|
{
|
|
fprintf (stderr, "%s", KCYN);
|
|
fprintf (stderr, "RAN=%02d - Part %d/4 ", RAN, PartOfFrame + 1);
|
|
fprintf (stderr, "%s", KNRM);
|
|
//fprintf (stderr, "(CRC OK) ");
|
|
state->nxdn_last_ran = RAN; //disable, try to grab this in voice instead
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "%s", KRED);
|
|
fprintf(stderr, "(CRC ERR) ");
|
|
fprintf (stderr, "%s", KNRM);
|
|
}
|
|
|
|
|
|
/* Determine the current part of superframe
|
|
* (in an AES or DES encrypted frame, two superframes
|
|
* are used with the same IV, so to decipher the sound
|
|
* correctly we must know the current superframe part) */
|
|
if(state->NxdnElementsContent.PartOfNextEncryptedFrame == 1) PartOfEncryptedSuperFrame = 0;
|
|
else if(state->NxdnElementsContent.PartOfNextEncryptedFrame == 2) PartOfEncryptedSuperFrame = 1;
|
|
else PartOfEncryptedSuperFrame = 0;
|
|
|
|
/* Decode the SACCH only when all 4 voice frame
|
|
* SACCH spare parts have been received */
|
|
if(PartOfFrame == 3)
|
|
{
|
|
/* Decode the entire SACCH content */
|
|
NXDN_SACCH_Full_decode(opts, state);
|
|
}
|
|
|
|
|
|
if (opts->errorbars == 1)
|
|
{
|
|
//fprintf(stderr, "e:");
|
|
}
|
|
|
|
/* Start pseudo-random NXDN sequence after
|
|
* LICH = 16 bit = 8 dibit +
|
|
* SACCH = 60 bit = 30 dibit
|
|
* = 76 bit = 38 dibit
|
|
* ==> Index 38 */
|
|
pr = (unsigned char *)(&nxdnpr2[38]);
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
w = nW;
|
|
x = nX;
|
|
y = nY;
|
|
z = nZ;
|
|
for (i = 0; i < 36; i++)
|
|
{
|
|
dibit = getDibit (opts, state);
|
|
#ifdef NXDN_DUMP
|
|
fprintf(stderr, "%c", dibit + 48);
|
|
#endif
|
|
ambe_fr[*w][*x] = *pr ^ (1 & (dibit >> 1)); // bit 1
|
|
pr++;
|
|
ambe_fr[*y][*z] = (1 & dibit); // bit 0
|
|
|
|
w++;
|
|
x++;
|
|
y++;
|
|
z++;
|
|
}
|
|
if (opts->payload == 1 && opts->dmr_stereo == 1)
|
|
{
|
|
fprintf(stderr, "\n");
|
|
}
|
|
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
|
|
|
} /* End for (j = 0; j < 4; j++) */
|
|
|
|
if (opts->errorbars == 1)
|
|
{
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
/* Reset the SACCH CRCs when all 4 voice frame
|
|
* SACCH spare parts have been received */
|
|
if(PartOfFrame == 3)
|
|
{
|
|
/* Reset all CRCs of the SACCH */
|
|
for(i = 0; i < 4; i++) state->NxdnSacchRawPart[i].CrcIsGood = 0;
|
|
}
|
|
} /* End processNXDNVoice() */
|