commit
ab29dd8e6a
|
|
@ -478,6 +478,9 @@ typedef struct
|
|||
unsigned int nxdn_cipher_type;
|
||||
unsigned int nxdn_key;
|
||||
char nxdn_call_type[1024];
|
||||
char dmr_callsign[4][99]; //plenty of room in case of overflow;
|
||||
char dmr_lrrp[6][9999];
|
||||
|
||||
//borrow from LEH
|
||||
NxdnSacchRawPart_t NxdnSacchRawPart[4];
|
||||
NxdnFacch1RawPart_t NxdnFacch1RawPart[2];
|
||||
|
|
@ -507,6 +510,10 @@ typedef struct
|
|||
TimeSlotVoiceSuperFrame_t TS1SuperFrame;
|
||||
TimeSlotVoiceSuperFrame_t TS2SuperFrame;
|
||||
|
||||
char dmr_branding[25];
|
||||
uint8_t dmr_12_rate_sf[36]; //going three frames deep
|
||||
uint8_t dmr_34_rate_sf[54]; //going three frames deep
|
||||
|
||||
//LEH dPMR stuff
|
||||
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
|
||||
|
||||
|
|
@ -776,7 +783,17 @@ uint32_t ComputeAndCorrectFullLinkControlCrc(uint8_t * FullLinkControlDataBytes,
|
|||
uint8_t ComputeCrc5Bit(uint8_t * DMRData);
|
||||
uint8_t * DmrAlgIdToStr(uint8_t AlgID);
|
||||
uint8_t * DmrAlgPrivacyModeToStr(uint32_t PrivacyMode);
|
||||
|
||||
void ProcessDmrPIHeader(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessCSBK(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessDataData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void Process1Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void Process12Data(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void Process34Data(dsd_opts * opts, dsd_state * state, unsigned char tdibits[98], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessMBCData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessMBChData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
void ProcessWTFData(dsd_opts * opts, dsd_state * state, uint8_t info[196], uint8_t syncdata[48], uint8_t SlotType[20]);
|
||||
|
||||
|
||||
void Hamming_7_4_init();
|
||||
void Hamming_7_4_encode(unsigned char *origBits, unsigned char *encodedBits);
|
||||
|
|
@ -827,6 +844,18 @@ void open_rtlsdr_stream(dsd_opts *opts);
|
|||
void cleanup_rtlsdr_stream();
|
||||
void get_rtlsdr_sample(int16_t *sample);
|
||||
void rtlsdr_sighandler();
|
||||
|
||||
//TRELLIS
|
||||
void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* payload);
|
||||
unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tribits);
|
||||
//unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* state, unsigned char* tribits);
|
||||
bool CDMRTrellisFixCode(unsigned char* points, unsigned int failPos, unsigned char* payload);
|
||||
void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits);
|
||||
void CDMRTrellisDibitsToPoints(const signed char* dibits, unsigned char* points);
|
||||
void CDMRTrellisPointsToDibits(const unsigned char* points, signed char* dibits);
|
||||
void CDMRTrellisBitsToTribits(const unsigned char* payload, unsigned char* tribits);
|
||||
bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor, G4KLX
|
||||
*
|
||||
* Modifications of original code to work with OP25
|
||||
* Copyright (C) 2019 by Graham J. Norbury
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef DMRTrellis_H
|
||||
#define DMRTrellis_H
|
||||
|
||||
class CDMRTrellis {
|
||||
public:
|
||||
CDMRTrellis();
|
||||
~CDMRTrellis();
|
||||
|
||||
bool decode(const unsigned char* data, unsigned char* payload);
|
||||
|
||||
private:
|
||||
void deinterleave(const unsigned char* in, signed char* dibits) const;
|
||||
void dibitsToPoints(const signed char* dibits, unsigned char* points) const;
|
||||
void pointsToDibits(const unsigned char* points, signed char* dibits) const;
|
||||
void bitsToTribits(const unsigned char* payload, unsigned char* tribits) const;
|
||||
void tribitsToBits(const unsigned char* tribits, unsigned char* payload) const;
|
||||
bool fixCode(unsigned char* points, unsigned int failPos, unsigned char* payload) const;
|
||||
unsigned int checkCode(const unsigned char* points, unsigned char* tribits) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -96,7 +96,8 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
|||
cachbits[24] = 0;
|
||||
fprintf(stderr, "%s ", cachbits);
|
||||
#endif
|
||||
|
||||
//trellis bits
|
||||
unsigned char trellisdibits[98];
|
||||
// Current slot - First half - Data Payload - 1st part
|
||||
for (i = 0; i < 49; i++)
|
||||
{
|
||||
|
|
@ -106,6 +107,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
|||
{
|
||||
dibit = (dibit ^ 2);
|
||||
}
|
||||
trellisdibits[i] = dibit;
|
||||
info[2*i] = (1 & (dibit >> 1)); // bit 1
|
||||
info[(2*i)+1] = (1 & dibit); // bit 0
|
||||
}
|
||||
|
|
@ -311,6 +313,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
|
||||
// Current slot - First half - Data Payload - 1st part
|
||||
//trellis
|
||||
for (i = 0; i < 49; i++)
|
||||
{
|
||||
dibit = getDibit(opts, state);
|
||||
|
|
@ -318,6 +321,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
|||
{
|
||||
dibit = (dibit ^ 2);
|
||||
}
|
||||
trellisdibits[i+49] = dibit;
|
||||
info[(2*i) + 98] = (1 & (dibit >> 1)); // bit 1
|
||||
info[(2*i) + 99] = (1 & dibit); // bit 0
|
||||
}
|
||||
|
|
@ -371,36 +375,42 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
|||
/* Burst = CSBK */
|
||||
case 0b0011:
|
||||
{
|
||||
ProcessCSBK(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = MBC Header */
|
||||
case 0b0100:
|
||||
{
|
||||
//ProcessMBChData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = MBC */
|
||||
case 0b0101:
|
||||
{
|
||||
//ProcessMBCData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = DATA Header */
|
||||
case 0b0110:
|
||||
{
|
||||
ProcessDataData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = RATE 1/2 DATA */
|
||||
case 0b0111:
|
||||
{
|
||||
Process12Data(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = RATE 3/4 DATA */
|
||||
case 0b1000:
|
||||
{
|
||||
//Process34Data(opts, state, trellisdibits, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -413,6 +423,14 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
|||
/* Burst = Rate 1 DATA */
|
||||
case 0b1010:
|
||||
{
|
||||
//Process1Data(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Burst = WTF 1101 Type DATA */
|
||||
case 0b1101:
|
||||
{
|
||||
//ProcessWTFData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -420,6 +438,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state)
|
|||
default:
|
||||
{
|
||||
/* Nothing to do */
|
||||
//ProcessWTFData(opts, state, (uint8_t *)info, (uint8_t *)syncdata, (uint8_t *)SlotType);
|
||||
break;
|
||||
}
|
||||
} /* End switch(burst) */
|
||||
|
|
|
|||
|
|
@ -44,17 +44,20 @@ void ProcessDMREncryption (dsd_opts * opts, dsd_state * state)
|
|||
TSVoiceSupFrame = &state->TS2SuperFrame;
|
||||
}
|
||||
|
||||
TSVoiceSupFrameL = &state->TS1SuperFrame;
|
||||
TSVoiceSupFrameR = &state->TS2SuperFrame;
|
||||
//TSVoiceSupFrameL = &state->TS1SuperFrame;
|
||||
//TSVoiceSupFrameR = &state->TS2SuperFrame;
|
||||
//
|
||||
//
|
||||
//
|
||||
for(Frame = 0; Frame < 6; Frame++)
|
||||
{
|
||||
/* 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]);
|
||||
//fprintf (stderr, "[%02X] ", TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[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
|
||||
|
|
@ -63,23 +66,45 @@ void ProcessDMREncryption (dsd_opts * opts, dsd_state * state)
|
|||
TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i],
|
||||
state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
//errs = (int*)&(TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs1[i]);
|
||||
//errs2 = (int*)&(TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs2[i]);
|
||||
//state->errs = TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs1[i]; //correct placement
|
||||
//state->errs2 = TSVoiceSupFrame->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement
|
||||
/*
|
||||
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
|
||||
state->errs2 = TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].errs2[i]; //correct placement
|
||||
|
||||
//errsR = (int*)&(TSVoiceSupFrameR->TimeSlotAmbeVoiceFrame[Frame].errs1[i]);
|
||||
//errs2R = (int*)&(TSVoiceSupFrameR->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,
|
||||
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, errs, errs2, state->err_str,
|
||||
// TSVoiceSupFrameL->TimeSlotAmbeVoiceFrame[Frame].AmbeBit[i],
|
||||
// state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
//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);
|
||||
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)
|
||||
{
|
||||
|
|
@ -94,6 +119,7 @@ void ProcessDMREncryption (dsd_opts * opts, dsd_state * state)
|
|||
//state->debug_audio_errors += *errs2R;
|
||||
|
||||
processAudio(opts, state);
|
||||
//playSynthesizedVoice (opts, state);
|
||||
|
||||
if (opts->wav_out_f != NULL)
|
||||
{
|
||||
|
|
|
|||
1504
src/dmr_sync.c
1504
src/dmr_sync.c
File diff suppressed because it is too large
Load Diff
|
|
@ -631,7 +631,7 @@ void processDMRvoice (dsd_opts * opts, dsd_state * state)
|
|||
else fprintf(stderr, "(CRC ERR) |"); //add line break
|
||||
|
||||
//fprintf(stderr, " VOICE e: \n");
|
||||
fprintf(stderr, " VOICE \n");
|
||||
fprintf(stderr, " VOICE ");
|
||||
}
|
||||
|
||||
/* Perform the SYNC DMR data embedded decoding */
|
||||
|
|
|
|||
|
|
@ -37,9 +37,11 @@ void openPulseOutput(dsd_opts * opts)
|
|||
//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->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 Out", &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);
|
||||
//opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD FME", PA_STREAM_PLAYBACK, NULL, "DMR/MOTOTRBO Right", &ss, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
//tt
|
||||
|
|
@ -432,15 +434,20 @@ playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
|
|||
|
||||
//two slot audio testing, still need to seperate channels first internally, but this will play them out of different streams
|
||||
/*
|
||||
if(state->currentslot == 0)
|
||||
if(state->currentslot == 0 && opts->audio_in_type != 3)
|
||||
{
|
||||
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)
|
||||
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.
|
||||
}
|
||||
|
||||
if (opts->audio_in_type == 3)
|
||||
{
|
||||
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.
|
||||
}
|
||||
*/
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
|
|||
k = 0;
|
||||
if (opts->payload == 1) //make opt variable later on to toggle this
|
||||
{
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "\n IMBE ");
|
||||
//fprintf(stderr, "ALGID=%X KEYID=%X\n", state->payload_algid, state->payload_keyid);
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
|
|||
k = 0;
|
||||
if (opts->payload == 1) //make opt variable later on to toggle this
|
||||
{
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "\n AMBE ");
|
||||
}
|
||||
//for (i = 0; i < 6; i++)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@ printFrameInfo (dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
if (state->nac != 0)
|
||||
{
|
||||
fprintf (stderr,"nac: %4X ", state->nac);
|
||||
fprintf (stderr,"nac: [%4X] ", state->nac);
|
||||
}
|
||||
|
||||
if (opts->verbose > 1)
|
||||
{
|
||||
fprintf (stderr,"src: %8i ", state->lastsrc);
|
||||
fprintf (stderr,"src: [%8i] ", state->lastsrc);
|
||||
}
|
||||
fprintf (stderr,"tg: %5i ", state->lasttg);
|
||||
fprintf (stderr,"tg: [%5i] ", state->lasttg);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -421,7 +421,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
|
|||
if (opts->errorbars == 1)
|
||||
{
|
||||
printFrameInfo (opts, state);
|
||||
fprintf (stderr," Ignoring LDU2 not preceeded by LDU1\n");
|
||||
fprintf (stderr,"\n Ignoring LDU2 not preceeded by LDU1\n");
|
||||
}
|
||||
state->lastp25type = 0;
|
||||
sprintf (state->fsubtype, " ");
|
||||
|
|
|
|||
|
|
@ -199,9 +199,9 @@ initOpts (dsd_opts * opts)
|
|||
opts->pulse_digi_in_channels = 1; //2
|
||||
opts->pulse_digi_out_channels = 1; //2
|
||||
|
||||
sprintf (opts->output_name, "Auto Detect");
|
||||
sprintf (opts->output_name, "Default Channel");
|
||||
opts->pulse_flush = 1; //set 0 to flush, 1 for flushed
|
||||
opts->use_ncurses_terminal = 0;
|
||||
opts->use_ncurses_terminal = 0;
|
||||
opts->payload = 0;
|
||||
|
||||
opts->EncryptionMode = MODE_UNENCRYPTED;
|
||||
|
|
@ -213,7 +213,7 @@ initState (dsd_state * state)
|
|||
{
|
||||
|
||||
int i, j;
|
||||
|
||||
state->last_dibit = 0;
|
||||
state->dibit_buf = malloc (sizeof (int) * 1000000);
|
||||
state->dibit_buf_p = state->dibit_buf + 200;
|
||||
memset (state->dibit_buf, 0, sizeof (int) * 200);
|
||||
|
|
@ -326,6 +326,18 @@ initState (dsd_state * state)
|
|||
state->payload_algid = 0;
|
||||
state->payload_keyid = 0;
|
||||
|
||||
sprintf (state->dmr_branding, " ");
|
||||
sprintf (state->dmr_callsign[0], "");
|
||||
sprintf (state->dmr_callsign[1], "");
|
||||
sprintf (state->dmr_callsign[2], "");
|
||||
sprintf (state->dmr_callsign[3], "");
|
||||
sprintf (state->dmr_lrrp[0], "");
|
||||
sprintf (state->dmr_lrrp[1], "");
|
||||
sprintf (state->dmr_lrrp[2], "");
|
||||
sprintf (state->dmr_lrrp[3], "");
|
||||
sprintf (state->dmr_lrrp[4], "");
|
||||
sprintf (state->dmr_lrrp[5], "");
|
||||
|
||||
state->K = 0;
|
||||
|
||||
#ifdef TRACE_DSD
|
||||
|
|
@ -360,7 +372,7 @@ usage ()
|
|||
fprintf (stderr," -z <num> Frame rate for datascope\n");
|
||||
fprintf (stderr,"\n");
|
||||
fprintf (stderr,"Input/Output options:\n");
|
||||
fprintf (stderr," -i <device> Audio input device (default is pulse audio, - for piped stdin, rtl for rtl device)\n");
|
||||
fprintf (stderr," -i <device> Audio input device (default is pulse audio, \n - for piped stdin, rtl for rtl device)\n");
|
||||
fprintf (stderr," -o <device> Audio output device (default is pulse audio)\n");
|
||||
fprintf (stderr," -d <dir> Create mbe data files, use this directory\n");
|
||||
fprintf (stderr," -r <files> Read/Play saved mbe data from file(s)\n");
|
||||
|
|
@ -374,8 +386,8 @@ usage ()
|
|||
fprintf (stderr," -P <num> RTL-SDR PPM Error (default = 0)\n");
|
||||
fprintf (stderr," -D <num> RTL-SDR Device Index Number\n");
|
||||
fprintf (stderr," -G <num> RTL-SDR Device Gain (0-49) (default = 0 Auto Gain)\n");
|
||||
fprintf (stderr," -L <num> RTL-SDR Squelch Level (0 - Open, 25 - Little, 50 - Higher)(Just have to guess really...)\n");
|
||||
fprintf (stderr," -V <num> RTL-SDR Sample Gain Multiplier (default = 1)(1-3 recommended, still testing) \n");
|
||||
fprintf (stderr," -L <num> RTL-SDR Squelch Level (0 - Open, 25 - Little, 50 - Higher)\n (Just have to guess really...)\n");
|
||||
fprintf (stderr," -V <num> RTL-SDR Sample Gain Multiplier (default = 1)\n");
|
||||
fprintf (stderr," -Y <num> RTL-SDR VFO Bandwidth kHz (default = 48)(6, 8, 12, 16, 24, 48) \n");
|
||||
fprintf (stderr," -U <num> RTL-SDR UDP Remote Port (default = 6020)\n");
|
||||
fprintf (stderr,"\n");
|
||||
|
|
@ -858,7 +870,12 @@ main (int argc, char **argv)
|
|||
opts.frame_dmr = 1;
|
||||
opts.frame_dpmr = 0; //borrow from LEH
|
||||
opts.frame_provoice = 0; //turn it on, doesn't work due to symbol rate difference
|
||||
sprintf (opts.output_name, "Auto Detect");
|
||||
//adding stereo for DMR so we don't accidentally segfault
|
||||
//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, "Default Channel");
|
||||
}
|
||||
else if (optarg[0] == 'd')
|
||||
{
|
||||
|
|
@ -979,7 +996,12 @@ 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,"Decoding only DMR/MOTOTRBO frames.\n");
|
||||
}
|
||||
else if (optarg[0] == 'm')
|
||||
|
|
|
|||
|
|
@ -90,12 +90,15 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||
imbe_d[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
if ((state->synctype == 0) || (state->synctype == 1))
|
||||
{
|
||||
// 0 +P25p1
|
||||
// 1 -P25p1
|
||||
|
||||
mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
//mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, processed_block, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
if (opts->mbe_out_f != NULL)
|
||||
{
|
||||
saveImbe4400Data (opts, state, imbe_d);
|
||||
|
|
@ -104,6 +107,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
|||
else if ((state->synctype == 14) || (state->synctype == 15))
|
||||
{
|
||||
mbe_processImbe7100x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe7100_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
//mbe_processImbe7100x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe7100_fr, processed_block, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
if (opts->mbe_out_f != NULL)
|
||||
{
|
||||
saveImbe4400Data (opts, state, imbe_d);
|
||||
|
|
|
|||
|
|
@ -146,9 +146,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
|
||||
if (state->carrier == 0) //reset these to 0 when no carrier
|
||||
{
|
||||
//state->payload_algid = 0;
|
||||
//state->payload_keyid = 0;
|
||||
//state->payload_mfid = 0;
|
||||
state->payload_algid = 0;
|
||||
state->payload_keyid = 0;
|
||||
//state->payload_mfid = 0;
|
||||
state->payload_mi = 0;
|
||||
|
||||
state->nxdn_key = 0;
|
||||
state->nxdn_cipher_type = 0;
|
||||
|
||||
sprintf(state->dmr_branding, " ");
|
||||
}
|
||||
|
||||
if ( (lls == 14 || lls == 15) && (time(NULL) - call_matrix[9][5] > 5) && state->carrier == 1) //honestly have no idea how to do this for pV, just going time based? only update on carrier == 1.
|
||||
|
|
@ -198,6 +204,11 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
//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
|
||||
{
|
||||
//reset amateur signs on radio id change
|
||||
for (short i = 0; i < 5; i++)
|
||||
{
|
||||
sprintf (state->dmr_callsign[i], "");
|
||||
}
|
||||
//dcc = state->dmr_color_code;
|
||||
for (short int k = 0; k < 9; k++)
|
||||
{
|
||||
|
|
@ -279,12 +290,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
if (state->carrier == 1){ //figure out method that will tell me when is active and when not active, maybe carrier but this doesn't print anyways unless activity
|
||||
attron(COLOR_PAIR(3));
|
||||
level = (int) state->max / 164; //only update on carrier present
|
||||
//reset = 1;
|
||||
reset = 1;
|
||||
}
|
||||
if (state->carrier == 0 && opts->reset_state == 1 && reset == 1)
|
||||
{
|
||||
//resetState (state);
|
||||
//reset = 0;
|
||||
resetState (state);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -335,13 +346,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
if (state->lastsrc > 0 && (lls == 12 || lls == 13 || lls == 0 || lls == 1)) //DMR Voice and P25P1
|
||||
{
|
||||
rd = state->lastsrc;
|
||||
//opts->p25enc = 0;
|
||||
opts->p25enc = 0;
|
||||
}
|
||||
|
||||
if (state->lasttg > 0 && (lls == 12 || lls == 13 || lls == 0 || lls == 1)) //DMR Voice and P25P1
|
||||
{
|
||||
tg = state->lasttg;
|
||||
//opts->p25enc = 0;
|
||||
opts->p25enc = 0;
|
||||
}
|
||||
|
||||
//if (state->lastsynctype == 8 || state->lastsynctype == 9 || state->lastsynctype == 16 || state->lastsynctype == 17) //change this to NXDN syncs later on
|
||||
|
|
@ -411,10 +422,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
//printw("| NAC: [0x%X] \n", nc);
|
||||
printw("| TID:[%8i] RID:[%8i] ", tg, rd);
|
||||
printw("NAC: [0x%3X] \n", nc);
|
||||
printw("| ALG: [0x%02X] ", state->payload_algid);
|
||||
printw("KEY: [0x%04X] ", state->payload_keyid);
|
||||
//printw("MFG: [0x%X] ", state->payload_mfid); //no way of knowing if this is accurate info yet
|
||||
if (state->payload_algid != 0x80 && state->carrier == 1)
|
||||
printw("| ALG:[0x%02X] ", state->payload_algid);
|
||||
printw(" KEY:[0x%04X] ", state->payload_keyid);
|
||||
printw(" MFID: [0x%02X] ", state->payload_mfid); //no way of knowing if this is accurate info yet
|
||||
if (state->payload_algid != 0x80 && state->payload_algid != 0x0 && state->carrier == 1)
|
||||
{
|
||||
attron(COLOR_PAIR(2));
|
||||
printw("**ENC**");
|
||||
|
|
@ -430,7 +441,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
//printw ("| DCC: [%i] FID: [%02X]\n", dcc, state->dmr_fid);
|
||||
//attron(COLOR_PAIR(3));
|
||||
printw ("| DCC: [%2i] FID: [%02X] SOP: [%02X] ", dcc, state->dmr_fid, state->dmr_so);
|
||||
if(state->payload_mi == 0 && state->dmr_so & 0x40)
|
||||
//if(state->payload_mi == 0 && state->dmr_so & 0x40)
|
||||
if(state->payload_mi == 0 && state->dmr_so == 0x40)
|
||||
{
|
||||
attron(COLOR_PAIR(5));
|
||||
printw ("**BP** ");
|
||||
|
|
@ -438,7 +450,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
attroff(COLOR_PAIR(5));
|
||||
attron(COLOR_PAIR(3));
|
||||
}
|
||||
if(state->payload_keyid > 0 && state->dmr_so & 0x40)
|
||||
//if(state->payload_keyid > 0 && state->dmr_so & 0x40)
|
||||
if(state->payload_keyid > 0 && state->dmr_so == 0x40)
|
||||
{
|
||||
attron(COLOR_PAIR(5));
|
||||
printw (" ALG: [0x%02X] KEY [0x%02X] MI [0x%08X]", state->payload_algid, state->payload_keyid, state->payload_mi);
|
||||
|
|
@ -446,7 +459,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
attroff(COLOR_PAIR(5));
|
||||
attron(COLOR_PAIR(3));
|
||||
}
|
||||
if(state->K > 0 && state->dmr_so & 0x40)
|
||||
//if(state->K > 0 && state->dmr_so & 0x40)
|
||||
if(state->K > 0 && state->dmr_so == 0x40)
|
||||
{
|
||||
attron(COLOR_PAIR(5));
|
||||
//printw ("K 0x[%12llX]", state->K); //seems to get reset in ncurses for some reason? some bigger issue perhaps? other strange issues occur too with provoice
|
||||
|
|
@ -455,8 +469,19 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
|
||||
printw("\n");
|
||||
printw ("| TID: [%8i] RID: [%8i]", tg, rd);
|
||||
if(state->dmr_so & 0x80) //1000 0000 //prints emergency on some amateru DMR repeaters with 0x8E SOP code, need to investigate
|
||||
printw ("| TID: [%8i] RID: [%8i]", tg, rd);
|
||||
|
||||
if (1 == 1) //figure out what to put here later on for amateur call signs
|
||||
{
|
||||
printw (" [");
|
||||
for (short i = 0; i < 5; i++)
|
||||
{
|
||||
printw ("%s", state->dmr_callsign[i]);
|
||||
}
|
||||
printw ("]");
|
||||
}
|
||||
//if(state->dmr_so & 0x80) //1000 0000 //prints emergency on some amateru DMR repeaters with 0x8E SOP code, need to investigate
|
||||
if(state->dmr_so == 0x80)
|
||||
{
|
||||
attron(COLOR_PAIR(2));
|
||||
printw (" **Emergency** ");
|
||||
|
|
@ -464,21 +489,23 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
attron(COLOR_PAIR(3));
|
||||
}
|
||||
|
||||
if(state->dmr_so & 0x40) //0100 0000
|
||||
//if(state->dmr_so & 0x40) //0100 0000
|
||||
if(state->dmr_so == 0x40) //0100 0000
|
||||
{
|
||||
attron(COLOR_PAIR(2));
|
||||
printw (" **ENC** ");
|
||||
//printw ("0x%X", state->payload_algid);
|
||||
attroff(COLOR_PAIR(2));
|
||||
attron(COLOR_PAIR(3));
|
||||
//if (state->K = 0)
|
||||
//{
|
||||
if (state->K == 0)
|
||||
{
|
||||
//opts->p25enc = 1; //just testing for now
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(state->dmr_so & 0x30) //0010 0000
|
||||
//if(state->dmr_so & 0x30) //0010 0000
|
||||
if(state->dmr_so == 0x30) //0010 0000
|
||||
{
|
||||
attron(COLOR_PAIR(2));
|
||||
printw (" **Private Call** ");
|
||||
|
|
@ -511,7 +538,17 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
{
|
||||
//printw ("| DCC: [%i]\n", dcc);
|
||||
printw ("| DCC: [%2i] FID: [%02X] SOP: [%02X] \n", dcc, state->dmr_fid, state->dmr_so);
|
||||
printw ("| TID: [%8i] RID: [%8i]", tg, rd);
|
||||
printw ("| TID: [%8i] RID: [%8i]", tg, rd);
|
||||
|
||||
if (1 == 1) //figure out what to put here later on for amateur call signs
|
||||
{
|
||||
printw (" [");
|
||||
for (short i = 0; i < 5; i++)
|
||||
{
|
||||
printw ("%s", state->dmr_callsign[i]);
|
||||
}
|
||||
printw ("]");
|
||||
}
|
||||
//does this need to be in DATA type?
|
||||
/*
|
||||
if(state->dmr_so & 0x80)
|
||||
|
|
@ -562,6 +599,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
}
|
||||
printw ("%s \n", s1last);
|
||||
/*
|
||||
if (state->dmr_lrrp[3] != NULL)
|
||||
{
|
||||
printw ("| LRRP -");
|
||||
printw (" %s", state->dmr_lrrp[3]);
|
||||
printw (" %s", state->dmr_lrrp[1]);
|
||||
printw (" %s\n", state->dmr_lrrp[2]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//dPMR
|
||||
|
|
@ -573,7 +619,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
|
||||
if (lls != -1) //is there a synctype 0?
|
||||
{
|
||||
printw ("| %s \n", SyncTypes[lls]);
|
||||
printw ("| %s ", SyncTypes[lls]);
|
||||
printw ("%s", state->dmr_branding);
|
||||
printw ("\n");
|
||||
}
|
||||
printw ("------------------------------------------------------------------------------\n");
|
||||
//colors off
|
||||
|
|
|
|||
|
|
@ -453,14 +453,16 @@ processHDU(dsd_opts* opts, dsd_state* state)
|
|||
status = getDibit (opts, state);
|
||||
//TODO: Do something useful with the status bits...
|
||||
|
||||
if (state->carrier == 1 && state->errs == 0) //only update when carrier is present, and no errors??
|
||||
//if (state->carrier == 1)
|
||||
//if (state->carrier == 1 && state->errs == 0) //only update when carrier is present, and no errors??
|
||||
if (state->carrier == 1)
|
||||
{
|
||||
algidhex = strtol (algid, NULL, 2);
|
||||
kidhex = strtol (kid, NULL, 2);
|
||||
|
||||
state->payload_algid = algidhex;
|
||||
state->payload_keyid = kidhex;
|
||||
//state->payload_mfid = ConvertBitIntoBytes(&mfid[0], 7);
|
||||
//state->payload_mfid = strtol (mfid, NULL, 2);
|
||||
|
||||
mihex1 = (unsigned long long int)ConvertBitIntoBytes(&mi[0], 32);
|
||||
mihex2 = (unsigned long long int)ConvertBitIntoBytes(&mi[32], 32);
|
||||
|
|
@ -468,10 +470,11 @@ processHDU(dsd_opts* opts, dsd_state* state)
|
|||
}
|
||||
|
||||
//if (state->errs == 0 && algidhex != 0x80)
|
||||
if (opts->payload == 1)
|
||||
if (1 == 1) //always print hdu alg info
|
||||
//if (opts->payload == 1 && state->errs == 0)
|
||||
{
|
||||
//fprintf (stderr, " HDU ALG ID: 0x%X KEY ID: 0x%X MI: %s \n", algidhex, kidhex, mi);
|
||||
fprintf (stderr, " HDU ALG ID: 0x%X KEY ID: 0x%X MI: 0x%08llX%08llX%02llX\n", algidhex, kidhex, mihex1, mihex2, mihex3);
|
||||
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);
|
||||
}
|
||||
|
||||
if (opts->p25enc == 1 && opts->payload == 0)
|
||||
|
|
|
|||
|
|
@ -330,9 +330,14 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
|
|||
lcinfo[54] = hex_data[ 0][4] + '0';
|
||||
lcinfo[55] = hex_data[ 0][5] + '0';
|
||||
|
||||
unsigned long long int lcinfohex = 0;
|
||||
if (state->carrier == 1 && state->errs == 0) //only update when carrier is present, otherwise, garbage values may be collected
|
||||
{
|
||||
state->payload_mfid = strtol (mfid, NULL, 2);
|
||||
|
||||
//state->payload_mfid = ConvertBitIntoBytes(&mfid[0], 7);
|
||||
lcinfohex = ConvertBitIntoBytes(&lcinfo[0], 55);
|
||||
//fprintf (stderr, " LDU1 LCINFO %16llX \n", lcinfohex);
|
||||
}
|
||||
|
||||
processP25lcw (opts, state, lcformat, mfid, lcinfo);
|
||||
|
|
|
|||
|
|
@ -360,8 +360,8 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
|||
kid[15] = hex_data[ 0][5] + '0';
|
||||
|
||||
|
||||
if (state->carrier == 1 && state->errs == 0) //only update when carrier is present, and no errors??
|
||||
//if (state->carrier == 1)
|
||||
//if (state->carrier == 1 && state->errs == 0) //only update when carrier is present, and no errors??
|
||||
if (state->carrier == 1)
|
||||
{
|
||||
|
||||
algidhex = strtol (algid, NULL, 2);
|
||||
|
|
@ -376,7 +376,8 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
|
||||
//if (state->errs == 0 && algidhex != 0x80)
|
||||
if (opts->payload == 1)
|
||||
if (1 == 1) //always print the LDU2 alg info
|
||||
//if (opts->payload == 1 && state->errs == 0)
|
||||
{
|
||||
//fprintf (stderr, " LDU2 ALG ID: 0x%X KEY ID: 0x%X MI: %s \n", algidhex, kidhex, mi);
|
||||
fprintf (stderr, " LDU2 ALG ID: 0x%X KEY ID: 0x%X MI: 0x%08llX%08llX%02llX\n", algidhex, kidhex, mihex1, mihex2, mihex3);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,454 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor, G4KLX
|
||||
*
|
||||
* Modifications of original code to work with OP25
|
||||
* Copyright (C) 2019 by Graham J. Norbury
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include "dsd.h"
|
||||
//#include "trellis.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
const unsigned int INTERLEAVE_TABLE[] = {
|
||||
0U, 1U, 8U, 9U, 16U, 17U, 24U, 25U, 32U, 33U, 40U, 41U, 48U, 49U, 56U, 57U, 64U, 65U, 72U, 73U, 80U, 81U, 88U, 89U, 96U, 97U,
|
||||
2U, 3U, 10U, 11U, 18U, 19U, 26U, 27U, 34U, 35U, 42U, 43U, 50U, 51U, 58U, 59U, 66U, 67U, 74U, 75U, 82U, 83U, 90U, 91U,
|
||||
4U, 5U, 12U, 13U, 20U, 21U, 28U, 29U, 36U, 37U, 44U, 45U, 52U, 53U, 60U, 61U, 68U, 69U, 76U, 77U, 84U, 85U, 92U, 93U,
|
||||
6U, 7U, 14U, 15U, 22U, 23U, 30U, 31U, 38U, 39U, 46U, 47U, 54U, 55U, 62U, 63U, 70U, 71U, 78U, 79U, 86U, 87U, 94U, 95U};
|
||||
|
||||
const unsigned char ENCODE_TABLE[] = {
|
||||
0U, 8U, 4U, 12U, 2U, 10U, 6U, 14U,
|
||||
4U, 12U, 2U, 10U, 6U, 14U, 0U, 8U,
|
||||
1U, 9U, 5U, 13U, 3U, 11U, 7U, 15U,
|
||||
5U, 13U, 3U, 11U, 7U, 15U, 1U, 9U,
|
||||
3U, 11U, 7U, 15U, 1U, 9U, 5U, 13U,
|
||||
7U, 15U, 1U, 9U, 5U, 13U, 3U, 11U,
|
||||
2U, 10U, 6U, 14U, 0U, 8U, 4U, 12U,
|
||||
6U, 14U, 0U, 8U, 4U, 12U, 2U, 10U};
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
||||
|
||||
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
#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;
|
||||
//unsigned int superposition = 0;
|
||||
//CDMRTrellis::CDMRTrellis()
|
||||
//{
|
||||
//}
|
||||
|
||||
//CDMRTrellis::~CDMRTrellis()
|
||||
//{
|
||||
//}
|
||||
|
||||
//void CDMRTrellis::tribitsToBits(const unsigned char* tribits, unsigned char* payload) const
|
||||
//void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* payload) const
|
||||
//bool CDMRTrellis::fixCode(unsigned char* points, unsigned int failPos, unsigned char* payload) const
|
||||
//bool CDMRTrellisFixCode(unsigned char* points, unsigned int failPos, unsigned char* payload) const
|
||||
bool CDMRTrellisFixCode(unsigned char* points, unsigned int failPos, unsigned char* payload)
|
||||
|
||||
{
|
||||
//unsigned int bestPos = 0U;
|
||||
//unsigned int bestVal = 0U;
|
||||
|
||||
for (unsigned j = 0U; j < 20U; j++) {
|
||||
unsigned int bestPos = 0U;
|
||||
unsigned int bestVal = 0U;
|
||||
fprintf (stderr, " fail%d-", failPos);
|
||||
|
||||
for (unsigned int i = 0U; i < 16U; i++) {
|
||||
points[failPos] = i;
|
||||
|
||||
fprintf (stderr, "i%d", i);
|
||||
|
||||
unsigned char tribits[49U];
|
||||
unsigned int pos = CDMRTrellisCheckCode(points, tribits);
|
||||
if (pos == 999U) {
|
||||
CDMRTrellisTribitsToBits(tribits, payload);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pos > bestPos) {
|
||||
bestPos = pos;
|
||||
bestVal = i;
|
||||
}
|
||||
}
|
||||
|
||||
points[failPos] = bestVal;
|
||||
failPos = bestPos;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDMRTrellisTribitsToBits(const unsigned char* tribits, unsigned char* payload)
|
||||
|
||||
{
|
||||
//g4klx version below
|
||||
/*
|
||||
for (unsigned int i = 0U; i < 48U; i++) {
|
||||
unsigned char tribit = tribits[i];
|
||||
|
||||
bool b1 = (tribit & 0x04U) == 0x04U;
|
||||
bool b2 = (tribit & 0x02U) == 0x02U;
|
||||
bool b3 = (tribit & 0x01U) == 0x01U;
|
||||
|
||||
unsigned int n = 143U - i * 3U;
|
||||
/*
|
||||
WRITE_BIT(payload, n, b1);
|
||||
n--;
|
||||
WRITE_BIT(payload, n, b2);
|
||||
n--;
|
||||
WRITE_BIT(payload, n, b3);
|
||||
}
|
||||
*/
|
||||
|
||||
// boatbod version below...
|
||||
// convert tribits to bits
|
||||
|
||||
unsigned char bits[144];
|
||||
for (int i = 0; i < 48; i++) {
|
||||
bits[(i * 3) + 0] = (tribits[i] >> 2) & 1;
|
||||
bits[(i * 3) + 1] = (tribits[i] >> 1) & 1;
|
||||
bits[(i * 3) + 2] = tribits[i] & 1;
|
||||
}
|
||||
|
||||
|
||||
// convert bits to bytes
|
||||
|
||||
for (int i = 0; i < 144; i++)
|
||||
payload[i/8] = (payload[i/8] << 1) | bits[i];
|
||||
|
||||
}
|
||||
|
||||
//unsigned int CDMRTrellis::checkCode(const unsigned char* points, unsigned char* tribits) const
|
||||
//unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tribits) const
|
||||
/*
|
||||
unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tribits)
|
||||
|
||||
{
|
||||
//replace i with superposition; revert back if totally borked
|
||||
//unsigned char state = 0U;
|
||||
|
||||
//for (unsigned int i = 0U; i < 49U; i++) {
|
||||
//tribits[i] = 9U;
|
||||
for (superposition; superposition < 49U; superposition++) {
|
||||
tribits[superposition] = 9U;
|
||||
for (unsigned int j = 0U; j < 8U; j++) {
|
||||
if (points[superposition] == ENCODE_TABLE[state * 8U + j]) {
|
||||
tribits[superposition] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tribits[superposition] == 9) {
|
||||
return superposition;
|
||||
//experiment placing fixcode right in here instead
|
||||
//or we need to find a way to update state outside of this function
|
||||
}
|
||||
state = tribits[superposition];
|
||||
|
||||
}
|
||||
//if (tribits[48U] != 0U)
|
||||
//return 48U;
|
||||
|
||||
return 999U;
|
||||
}
|
||||
*/
|
||||
unsigned int CDMRTrellisCheckCode(const unsigned char* points, unsigned char* tribits)
|
||||
{
|
||||
unsigned char state = 0U;
|
||||
|
||||
for (unsigned int i = 0U; i < 49U; i++) {
|
||||
tribits[i] = 9U;
|
||||
|
||||
for (unsigned int j = 0U; j < 8U; j++) {
|
||||
if (points[i] == ENCODE_TABLE[state * 8U + j]) {
|
||||
tribits[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tribits[i] == 9U)
|
||||
return i;
|
||||
|
||||
state = tribits[i];
|
||||
}
|
||||
|
||||
if (tribits[48U] != 0U)
|
||||
return 48U;
|
||||
|
||||
return 999U;
|
||||
}
|
||||
|
||||
//void CDMRTrellis::deinterleave(const unsigned char* data, signed char* dibits) const
|
||||
//void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits) const
|
||||
void CDMRTrellisDeinterleave(const unsigned char* data, signed char* dibits)
|
||||
{
|
||||
int n;
|
||||
signed char dibit;
|
||||
|
||||
for (int i = 0; i < 98; i++) {
|
||||
n = i * 2;
|
||||
if (n >= 98) n += 68;
|
||||
bool b1 = data[n] != 0x0;
|
||||
|
||||
n = i * 2 + 1;
|
||||
if (n >= 98) n += 68;
|
||||
bool b2 = data[n] != 0x0;
|
||||
|
||||
if (!b1 && b2)
|
||||
dibit = +3;
|
||||
else if (!b1 && !b2)
|
||||
dibit = +1;
|
||||
else if (b1 && !b2)
|
||||
dibit = -1;
|
||||
else
|
||||
dibit = -3;
|
||||
|
||||
n = INTERLEAVE_TABLE[i];
|
||||
dibits[n] = dibit;
|
||||
}
|
||||
}
|
||||
|
||||
//void CDMRTrellis::dibitsToPoints(const signed char* dibits, unsigned char* points) const
|
||||
//void CDMRTrellisDibitsToPoints(const signed char* dibits, unsigned char* points) const
|
||||
void CDMRTrellisDibitsToPoints(const signed char* dibits, unsigned char* points)
|
||||
{
|
||||
for (unsigned int i = 0U; i < 49U; i++) {
|
||||
if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == -1)
|
||||
points[i] = 0U;
|
||||
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == -1)
|
||||
points[i] = 1U;
|
||||
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == -3)
|
||||
points[i] = 2U;
|
||||
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == -3)
|
||||
points[i] = 3U;
|
||||
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == -1)
|
||||
points[i] = 4U;
|
||||
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == -1)
|
||||
points[i] = 5U;
|
||||
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == -3)
|
||||
points[i] = 6U;
|
||||
else if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == -3)
|
||||
points[i] = 7U;
|
||||
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == +3)
|
||||
points[i] = 8U;
|
||||
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == +3)
|
||||
points[i] = 9U;
|
||||
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == +1)
|
||||
points[i] = 10U;
|
||||
else if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == +1)
|
||||
points[i] = 11U;
|
||||
else if (dibits[i * 2U + 0U] == +1 && dibits[i * 2U + 1U] == +3)
|
||||
points[i] = 12U;
|
||||
else if (dibits[i * 2U + 0U] == -1 && dibits[i * 2U + 1U] == +3)
|
||||
points[i] = 13U;
|
||||
else if (dibits[i * 2U + 0U] == +3 && dibits[i * 2U + 1U] == +1)
|
||||
points[i] = 14U;
|
||||
else if (dibits[i * 2U + 0U] == -3 && dibits[i * 2U + 1U] == +1)
|
||||
points[i] = 15U;
|
||||
}
|
||||
}
|
||||
|
||||
//void CDMRTrellis::pointsToDibits(const unsigned char* points, signed char* dibits) const
|
||||
//void CDMRTrellisPointsToDibits(const unsigned char* points, signed char* dibits) const
|
||||
void CDMRTrellisPointsToDibits(const unsigned char* points, signed char* dibits)
|
||||
{
|
||||
for (unsigned int i = 0U; i < 49U; i++) {
|
||||
switch (points[i]) {
|
||||
case 0U:
|
||||
dibits[i * 2U + 0U] = +1;
|
||||
dibits[i * 2U + 1U] = -1;
|
||||
break;
|
||||
case 1U:
|
||||
dibits[i * 2U + 0U] = -1;
|
||||
dibits[i * 2U + 1U] = -1;
|
||||
break;
|
||||
case 2U:
|
||||
dibits[i * 2U + 0U] = +3;
|
||||
dibits[i * 2U + 1U] = -3;
|
||||
break;
|
||||
case 3U:
|
||||
dibits[i * 2U + 0U] = -3;
|
||||
dibits[i * 2U + 1U] = -3;
|
||||
break;
|
||||
case 4U:
|
||||
dibits[i * 2U + 0U] = -3;
|
||||
dibits[i * 2U + 1U] = -1;
|
||||
break;
|
||||
case 5U:
|
||||
dibits[i * 2U + 0U] = +3;
|
||||
dibits[i * 2U + 1U] = -1;
|
||||
break;
|
||||
case 6U:
|
||||
dibits[i * 2U + 0U] = -1;
|
||||
dibits[i * 2U + 1U] = -3;
|
||||
break;
|
||||
case 7U:
|
||||
dibits[i * 2U + 0U] = +1;
|
||||
dibits[i * 2U + 1U] = -3;
|
||||
break;
|
||||
case 8U:
|
||||
dibits[i * 2U + 0U] = -3;
|
||||
dibits[i * 2U + 1U] = +3;
|
||||
break;
|
||||
case 9U:
|
||||
dibits[i * 2U + 0U] = +3;
|
||||
dibits[i * 2U + 1U] = +3;
|
||||
break;
|
||||
case 10U:
|
||||
dibits[i * 2U + 0U] = -1;
|
||||
dibits[i * 2U + 1U] = +1;
|
||||
break;
|
||||
case 11U:
|
||||
dibits[i * 2U + 0U] = +1;
|
||||
dibits[i * 2U + 1U] = +1;
|
||||
break;
|
||||
case 12U:
|
||||
dibits[i * 2U + 0U] = +1;
|
||||
dibits[i * 2U + 1U] = +3;
|
||||
break;
|
||||
case 13U:
|
||||
dibits[i * 2U + 0U] = -1;
|
||||
dibits[i * 2U + 1U] = +3;
|
||||
break;
|
||||
case 14U:
|
||||
dibits[i * 2U + 0U] = +3;
|
||||
dibits[i * 2U + 1U] = +1;
|
||||
break;
|
||||
default:
|
||||
dibits[i * 2U + 0U] = -3;
|
||||
dibits[i * 2U + 1U] = +1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void CDMRTrellis::bitsToTribits(const unsigned char* payload, unsigned char* tribits) const
|
||||
//void CDMRTrellisBitsToTribits(const unsigned char* payload, unsigned char* tribits) const
|
||||
void CDMRTrellisBitsToTribits(const unsigned char* payload, unsigned char* tribits)
|
||||
{
|
||||
for (unsigned int i = 0U; i < 48U; i++) {
|
||||
unsigned int n = 143U - i * 3U;
|
||||
|
||||
bool b1 = READ_BIT(payload, n) != 0x00U;
|
||||
n--;
|
||||
bool b2 = READ_BIT(payload, n) != 0x00U;
|
||||
n--;
|
||||
bool b3 = READ_BIT(payload, n) != 0x00U;
|
||||
|
||||
unsigned char tribit = 0U;
|
||||
tribit |= b1 ? 4U : 0U;
|
||||
tribit |= b2 ? 2U : 0U;
|
||||
tribit |= b3 ? 1U : 0U;
|
||||
|
||||
//tribits[i] = tribit;
|
||||
}
|
||||
|
||||
tribits[48U] = 0U;
|
||||
}
|
||||
|
||||
//bool CDMRTrellis::decode(const unsigned char* data, unsigned char* payload)
|
||||
bool CDMRTrellisDecode(const unsigned char* data, unsigned char* payload)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(payload != NULL);
|
||||
if (1 == 1)
|
||||
{
|
||||
fprintf (stderr, "\n Raw Trellis Dibits inside Decoder\n ");
|
||||
for (short i = 0; i < 98; i++)
|
||||
{
|
||||
fprintf (stderr, "[%0d]", data[i]);
|
||||
}
|
||||
}
|
||||
signed char dibits[98U];
|
||||
CDMRTrellisDeinterleave(data, dibits);
|
||||
if (1 == 1)
|
||||
{
|
||||
fprintf (stderr, "\n Trellis Deinterleaved Dibits inside Decoder (converted to signed)\n ");
|
||||
for (short i = 0; i < 98; i++)
|
||||
{
|
||||
fprintf (stderr, "[%d]", dibits[i]); //signed char, values should be -3, -1, 1, 3 only
|
||||
}
|
||||
}
|
||||
unsigned char points[49U];
|
||||
CDMRTrellisDibitsToPoints(dibits, points);
|
||||
if (1 == 1)
|
||||
{
|
||||
fprintf (stderr, "\n Trellis Points inside Decoder (no higher than 15U?)\n ");
|
||||
for (short i = 0; i < 49; i++)
|
||||
{
|
||||
fprintf (stderr, "[%02u]", points[i]);
|
||||
}
|
||||
}
|
||||
// Check the original code
|
||||
unsigned char tribits[49U];
|
||||
unsigned int failPos = CDMRTrellisCheckCode(points, tribits);
|
||||
|
||||
|
||||
|
||||
|
||||
if (failPos == 999U) {
|
||||
CDMRTrellisTribitsToBits(tribits, payload);
|
||||
if (1 == 1)
|
||||
{
|
||||
fprintf (stderr, "\nTrellis Payload Tribits to Bits failPos == 999U\n ");
|
||||
for (short i = 0; i < 18; i++)
|
||||
{
|
||||
fprintf (stderr, "[%02u]", payload[i]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char savePoints[49U];
|
||||
for (unsigned int i = 0U; i < 49U; i++)
|
||||
savePoints[i] = points[i];
|
||||
|
||||
bool ret = CDMRTrellisFixCode(points, failPos, payload);
|
||||
if (ret){
|
||||
|
||||
if (1 == 1)
|
||||
{
|
||||
fprintf (stderr, "\n Trellis Tribits inside Decoder\n ");
|
||||
for (short i = 0; i < 49; i++)
|
||||
{
|
||||
fprintf (stderr, "[%0u]", tribits[i]); //shouldn't have any values greater that 0x7?
|
||||
}
|
||||
}
|
||||
|
||||
if (1 == 1)
|
||||
{
|
||||
fprintf (stderr, "\nTrellis Payload Tribits to Bits fix return true\n "); //this one seems to be happening
|
||||
for (short i = 0; i < 18; i++)
|
||||
{
|
||||
fprintf (stderr, "[%02X]", payload[i]);
|
||||
}
|
||||
}
|
||||
return true; }
|
||||
|
||||
if (failPos == 0U)
|
||||
{
|
||||
if (1 == 1)
|
||||
{
|
||||
fprintf (stderr, "\nTrellis Payload Tribits to Bits failPos == 0U\n ");
|
||||
for (short i = 0; i < 18; i++)
|
||||
{
|
||||
fprintf (stderr, "[%02X]", payload[i]);
|
||||
}
|
||||
}
|
||||
return false; }
|
||||
|
||||
// Backtrack one place for a last go
|
||||
return CDMRTrellisFixCode(savePoints, failPos - 1U, payload);
|
||||
}
|
||||
Loading…
Reference in New Issue