1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-27 02:09:14 -05:00

DSD demod plugin: integration of DSD engine

This commit is contained in:
f4exb 2016-04-09 02:27:32 +02:00
parent 3f92de1d53
commit 97b60ccb87
11 changed files with 436 additions and 341 deletions

View File

@ -15,22 +15,21 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <pthread.h>
#include "dsd_cleanupexit.h" #include "dsd_cleanupexit.h"
#include "dsd_nocarrier.h" #include "dsd_nocarrier.h"
#include "dsd.h" #include "dsd.h"
void void cleanupAndExit(dsd_opts * opts, dsd_state * state)
cleanupAndExit (dsd_opts * opts, dsd_state * state)
{ {
noCarrier (opts, state); noCarrier(opts, state);
#ifdef USE_LIBSNDFILE #ifdef USE_LIBSNDFILE
if (opts->wav_out_f != NULL) if (opts->wav_out_f != NULL)
{ {
closeWavOutFile (opts, state); closeWavOutFile (opts, state);
} }
#endif #endif
printf ("Exiting.\n"); printf("dsd::cleanupAndExit: Exiting.\n");
//exit (0); // You just can't do that within SDRangel int rc = 0;
pthread_exit(&rc);
} }

View File

@ -20,8 +20,7 @@
#define NULL 0 #define NULL 0
#endif #endif
void void printFrameInfo(dsd_opts * opts, dsd_state * state)
printFrameInfo (dsd_opts * opts, dsd_state * state)
{ {
int level; int level;
@ -29,22 +28,21 @@ printFrameInfo (dsd_opts * opts, dsd_state * state)
level = (int) state->max / 164; level = (int) state->max / 164;
if (opts->verbose > 0) if (opts->verbose > 0)
{ {
printf ("inlvl: %2i%% ", level); printf("inlvl: %2i%% ", level);
} }
if (state->nac != 0) if (state->nac != 0)
{ {
printf ("nac: %4X ", state->nac); printf("nac: %4X ", state->nac);
} }
if (opts->verbose > 1) if (opts->verbose > 1)
{ {
printf ("src: %8i ", state->lastsrc); printf("src: %8i ", state->lastsrc);
} }
printf ("tg: %5i ", state->lasttg); printf("tg: %5i ", state->lasttg);
} }
void void processFrame(dsd_opts * opts, dsd_state * state)
processFrame (dsd_opts * opts, dsd_state * state)
{ {
int i, j, dibit; int i, j, dibit;
@ -77,16 +75,16 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0) if (opts->verbose > 0)
{ {
level = (int) state->max / 164; level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level); printf("inlvl: %2i%% ", level);
} }
} }
state->nac = 0; state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
sprintf (state->fsubtype, " VOICE "); sprintf(state->fsubtype, " VOICE ");
processNXDNVoice (opts, state); processNXDNVoice(opts, state);
return; return;
} }
else if ((state->synctype == 16) || (state->synctype == 17)) else if ((state->synctype == 16) || (state->synctype == 17))
@ -100,16 +98,16 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0) if (opts->verbose > 0)
{ {
level = (int) state->max / 164; level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level); printf("inlvl: %2i%% ", level);
} }
} }
state->nac = 0; state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
sprintf (state->fsubtype, " DATA "); sprintf(state->fsubtype, " DATA ");
processNXDNData (opts, state); processNXDNData(opts, state);
return; return;
} }
else if ((state->synctype == 6) || (state->synctype == 7)) else if ((state->synctype == 6) || (state->synctype == 7))
@ -122,16 +120,16 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0) if (opts->verbose > 0)
{ {
level = (int) state->max / 164; level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level); printf("inlvl: %2i%% ", level);
} }
} }
state->nac = 0; state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
sprintf (state->fsubtype, " VOICE "); sprintf(state->fsubtype, " VOICE ");
processDSTAR (opts, state); processDSTAR(opts, state);
return; return;
} }
else if ((state->synctype == 18) || (state->synctype == 19)) else if ((state->synctype == 18) || (state->synctype == 19))
@ -144,16 +142,16 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0) if (opts->verbose > 0)
{ {
level = (int) state->max / 164; level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level); printf("inlvl: %2i%% ", level);
} }
} }
state->nac = 0; state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
sprintf (state->fsubtype, " DATA "); sprintf(state->fsubtype, " DATA ");
processDSTAR_HD (opts, state); processDSTAR_HD(opts, state);
return; return;
} }
@ -167,23 +165,25 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0) if (opts->verbose > 0)
{ {
level = (int) state->max / 164; level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level); printf("inlvl: %2i%% ", level);
} }
} }
if ((state->synctype == 11) || (state->synctype == 12)) if ((state->synctype == 11) || (state->synctype == 12))
{ {
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
sprintf (state->fsubtype, " VOICE "); sprintf(state->fsubtype, " VOICE ");
processDMRvoice (opts, state); processDMRvoice(opts, state);
} }
else else
{ {
closeMbeOutFile (opts, state); if (opts->mbe_out_f != NULL) {
closeMbeOutFile(opts, state);
}
state->err_str[0] = 0; state->err_str[0] = 0;
processDMRdata (opts, state); processDMRdata(opts, state);
} }
return; return;
} }
@ -192,22 +192,24 @@ processFrame (dsd_opts * opts, dsd_state * state)
state->nac = 0; state->nac = 0;
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
} }
if ((state->synctype == 3) || (state->synctype == 4)) if ((state->synctype == 3) || (state->synctype == 4))
{ {
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
sprintf (state->fsubtype, " VOICE "); sprintf(state->fsubtype, " VOICE ");
processX2TDMAvoice (opts, state); processX2TDMAvoice(opts, state);
} }
else else
{ {
closeMbeOutFile (opts, state); if (opts->mbe_out_f != NULL) {
closeMbeOutFile(opts, state);
}
state->err_str[0] = 0; state->err_str[0] = 0;
processX2TDMAdata (opts, state); processX2TDMAdata(opts, state);
} }
return; return;
} }
@ -221,15 +223,15 @@ processFrame (dsd_opts * opts, dsd_state * state)
if (opts->verbose > 0) if (opts->verbose > 0)
{ {
level = (int) state->max / 164; level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level); printf("inlvl: %2i%% ", level);
} }
} }
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL)) if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
sprintf (state->fsubtype, " VOICE "); sprintf(state->fsubtype, " VOICE ");
processProVoice (opts, state); processProVoice(opts, state);
return; return;
} }
else else
@ -237,238 +239,245 @@ processFrame (dsd_opts * opts, dsd_state * state)
j = 0; j = 0;
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
{ {
dibit = getDibit (opts, state); dibit = getDibit(opts, state);
nac[j] = (1 & (dibit >> 1)) + 48; // bit 1 nac[j] = (1 & (dibit >> 1)) + 48; // bit 1
j++; j++;
nac[j] = (1 & dibit) + 48; // bit 0 nac[j] = (1 & dibit) + 48; // bit 0
j++; j++;
} }
nac[12] = 0; nac[12] = 0;
state->nac = strtol (nac, NULL, 2); state->nac = strtol(nac, NULL, 2);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
duid[i] = getDibit (opts, state) + 48; duid[i] = getDibit(opts, state) + 48;
} }
} }
if (strcmp (duid, "00") == 0) if (strcmp(duid, "00") == 0)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" HDU\n"); printf(" HDU\n");
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_dir[0] != 0)
{ {
closeMbeOutFile (opts, state); if (opts->mbe_out_f != NULL) {
openMbeOutFile (opts, state); closeMbeOutFile(opts, state);
} }
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); openMbeOutFile(opts, state);
}
mbe_initMbeParms(state->cur_mp, state->prev_mp,
state->prev_mp_enhanced);
state->lastp25type = 2; state->lastp25type = 2;
sprintf (state->fsubtype, " HDU "); sprintf(state->fsubtype, " HDU ");
processHDU (opts, state); processHDU(opts, state);
} }
else if (strcmp (duid, "11") == 0) else if (strcmp(duid, "11") == 0)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" LDU1 "); printf(" LDU1 ");
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_dir[0] != 0)
{ {
if (opts->mbe_out_f == NULL) if (opts->mbe_out_f == NULL)
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
} }
state->lastp25type = 1; state->lastp25type = 1;
sprintf (state->fsubtype, " LDU1 "); sprintf(state->fsubtype, " LDU1 ");
state->numtdulc = 0; state->numtdulc = 0;
processLDU1 (opts, state); processLDU1(opts, state);
} }
else if (strcmp (duid, "22") == 0) else if (strcmp(duid, "22") == 0)
{ {
if (state->lastp25type != 1) if (state->lastp25type != 1)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" Ignoring LDU2 not preceeded by LDU1\n"); printf(" Ignoring LDU2 not preceeded by LDU1\n");
} }
state->lastp25type = 0; state->lastp25type = 0;
sprintf (state->fsubtype, " "); sprintf(state->fsubtype, " ");
} }
else else
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" LDU2 "); printf(" LDU2 ");
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_dir[0] != 0)
{ {
if (opts->mbe_out_f == NULL) if (opts->mbe_out_f == NULL)
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
} }
state->lastp25type = 2; state->lastp25type = 2;
sprintf (state->fsubtype, " LDU2 "); sprintf(state->fsubtype, " LDU2 ");
state->numtdulc = 0; state->numtdulc = 0;
processLDU2 (opts, state); processLDU2(opts, state);
} }
} }
else if (strcmp (duid, "33") == 0) else if (strcmp(duid, "33") == 0)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" TDULC\n"); printf(" TDULC\n");
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_dir[0] != 0)
{ {
closeMbeOutFile (opts, state); if (opts->mbe_out_f != NULL) {
closeMbeOutFile(opts, state);
} }
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); }
mbe_initMbeParms(state->cur_mp, state->prev_mp,
state->prev_mp_enhanced);
state->lasttg = 0; state->lasttg = 0;
state->lastsrc = 0; state->lastsrc = 0;
state->lastp25type = 0; state->lastp25type = 0;
state->err_str[0] = 0; state->err_str[0] = 0;
sprintf (state->fsubtype, " TDULC "); sprintf(state->fsubtype, " TDULC ");
state->numtdulc++; state->numtdulc++;
if ((opts->resume > 0) && (state->numtdulc > opts->resume)) if ((opts->resume > 0) && (state->numtdulc > opts->resume))
{ {
resumeScan (opts, state); resumeScan(opts, state);
} }
processTDULC (opts, state); processTDULC(opts, state);
state->err_str[0] = 0; state->err_str[0] = 0;
} }
else if (strcmp (duid, "03") == 0) else if (strcmp(duid, "03") == 0)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" TDU\n"); printf(" TDU\n");
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_f != NULL)
{ {
closeMbeOutFile (opts, state); closeMbeOutFile(opts, state);
} }
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); mbe_initMbeParms(state->cur_mp, state->prev_mp,
state->prev_mp_enhanced);
state->lasttg = 0; state->lasttg = 0;
state->lastsrc = 0; state->lastsrc = 0;
state->lastp25type = 0; state->lastp25type = 0;
state->err_str[0] = 0; state->err_str[0] = 0;
sprintf (state->fsubtype, " TDU "); sprintf(state->fsubtype, " TDU ");
skipDibit (opts, state, 40); skipDibit(opts, state, 40);
} }
else if (strcmp (duid, "13") == 0) else if (strcmp(duid, "13") == 0)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" TSDU\n"); printf(" TSDU\n");
} }
if (opts->resume > 0) if (opts->resume > 0)
{ {
resumeScan (opts, state); resumeScan(opts, state);
} }
state->lasttg = 0; state->lasttg = 0;
state->lastsrc = 0; state->lastsrc = 0;
state->lastp25type = 3; state->lastp25type = 3;
sprintf (state->fsubtype, " TSDU "); sprintf(state->fsubtype, " TSDU ");
skipDibit (opts, state, 328); skipDibit(opts, state, 328);
} }
else if (strcmp (duid, "30") == 0) else if (strcmp(duid, "30") == 0)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" PDU\n"); printf(" PDU\n");
} }
if (opts->resume > 0) if (opts->resume > 0)
{ {
resumeScan (opts, state); resumeScan(opts, state);
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_dir[0] != 0)
{ {
if (opts->mbe_out_f == NULL) if (opts->mbe_out_f == NULL)
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
} }
state->lastp25type = 4; state->lastp25type = 4;
sprintf (state->fsubtype, " PDU "); sprintf(state->fsubtype, " PDU ");
} }
// try to guess based on previous frame if unknown type // try to guess based on previous frame if unknown type
else if (state->lastp25type == 1) else if (state->lastp25type == 1)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf ("(LDU2) "); printf("(LDU2) ");
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_dir[0] != 0)
{ {
if (opts->mbe_out_f == NULL) if (opts->mbe_out_f == NULL)
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
} }
state->lastp25type = 0; state->lastp25type = 0;
sprintf (state->fsubtype, "(LDU2) "); sprintf(state->fsubtype, "(LDU2) ");
state->numtdulc = 0; state->numtdulc = 0;
processLDU2 (opts, state); processLDU2(opts, state);
} }
else if (state->lastp25type == 2) else if (state->lastp25type == 2)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf ("(LDU1) "); printf("(LDU1) ");
} }
if (opts->mbe_out_dir[0] != 0) if (opts->mbe_out_dir[0] != 0)
{ {
if (opts->mbe_out_f == NULL) if (opts->mbe_out_f == NULL)
{ {
openMbeOutFile (opts, state); openMbeOutFile(opts, state);
} }
} }
state->lastp25type = 0; state->lastp25type = 0;
sprintf (state->fsubtype, "(LDU1) "); sprintf(state->fsubtype, "(LDU1) ");
state->numtdulc = 0; state->numtdulc = 0;
processLDU1 (opts, state); processLDU1(opts, state);
} }
else if (state->lastp25type == 3) else if (state->lastp25type == 3)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" (TSDU)\n"); printf(" (TSDU)\n");
} }
state->lastp25type = 0; state->lastp25type = 0;
sprintf (state->fsubtype, "(TSDU) "); sprintf(state->fsubtype, "(TSDU) ");
skipDibit (opts, state, 328); skipDibit(opts, state, 328);
} }
else if (state->lastp25type == 4) else if (state->lastp25type == 4)
{ {
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" (PDU)\n"); printf(" (PDU)\n");
} }
state->lastp25type = 0; state->lastp25type = 0;
} }
else else
{ {
state->lastp25type = 0; state->lastp25type = 0;
sprintf (state->fsubtype, " "); sprintf(state->fsubtype, " ");
if (opts->errorbars == 1) if (opts->errorbars == 1)
{ {
printFrameInfo (opts, state); printFrameInfo(opts, state);
printf (" duid:%s *Unknown DUID*\n", duid); printf(" duid:%s *Unknown DUID*\n", duid);
} }
} }
} }

View File

@ -46,6 +46,7 @@ int
getFrameSync (dsd_opts * opts, dsd_state * state) getFrameSync (dsd_opts * opts, dsd_state * state)
{ {
/* detects frame sync and returns frame type /* detects frame sync and returns frame type
* -1 -> thread has to terminate
* 0 = +P25p1 * 0 = +P25p1
* 1 = -P25p1 * 1 = -P25p1
* 2 = +X2-TDMA (non inverted signal data frame) * 2 = +X2-TDMA (non inverted signal data frame)
@ -107,6 +108,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{ {
t++; t++;
symbol = getSymbol (opts, state, 0); symbol = getSymbol (opts, state, 0);
if (!state->dsd_running) {
return -1;
}
lbuf[lidx] = symbol; lbuf[lidx] = symbol;
state->sbuf[state->sidx] = symbol; state->sbuf[state->sidx] = symbol;
if (lidx == 23) if (lidx == 23)

View File

@ -21,8 +21,13 @@
void liveScanner(dsd_opts * opts, dsd_state * state) void liveScanner(dsd_opts * opts, dsd_state * state)
{ {
while (1) // FIXME: loop while input available while (state->dsd_running) // FIXME: loop while input available
{ {
// if (pthread_cond_wait(&state->input_ready, &state->input_mutex)) {
// fprintf(stderr, "dsd::liveScanner: Error waiting for input ready condition\n");
// }
//
// fprintf (stderr, "dsd::liveScanner: input is ready\n");
noCarrier(opts, state); noCarrier(opts, state);
state->synctype = getFrameSync(opts, state); state->synctype = getFrameSync(opts, state);
@ -31,7 +36,7 @@ void liveScanner(dsd_opts * opts, dsd_state * state)
state->umid = (((state->max) - state->center) * 5 / 8) + state->center; state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center; state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
while (state->synctype != -1) // TODO: make sure it ends while (state->synctype != -1) // -1 -> exit thread
{ {
processFrame(opts, state); processFrame(opts, state);
state->synctype = getFrameSync(opts, state); state->synctype = getFrameSync(opts, state);
@ -42,4 +47,6 @@ void liveScanner(dsd_opts * opts, dsd_state * state)
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center; state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
} }
} }
fprintf (stderr, "dsd::liveScanner: end loop\n");
} }

View File

@ -21,6 +21,14 @@
#include "dsd_opts.h" #include "dsd_opts.h"
#include "dsd_state.h" #include "dsd_state.h"
#ifdef __cplusplus
extern "C" {
#endif
void liveScanner (dsd_opts * opts, dsd_state * state); void liveScanner (dsd_opts * opts, dsd_state * state);
#ifdef __cplusplus
}
#endif
#endif /* INCLUDE_DSD_LIVESCANNER_H_ */ #endif /* INCLUDE_DSD_LIVESCANNER_H_ */

View File

@ -121,5 +121,16 @@ void initState(dsd_state * state)
#endif #endif
initialize_p25_heuristics(&state->p25_heuristics); initialize_p25_heuristics(&state->p25_heuristics);
// Initialize the mutexes
if (pthread_mutex_init(&state->input_mutex, NULL)) {
fprintf(stderr, "dsd::initState: Unable to initialize input mutex\n");
}
// Initialize the conditions
if (pthread_cond_init(&state->input_ready, NULL)) {
fprintf(stderr, "dsd::initState: Unable to initialize input condition\n");
}
state->dsd_running = 0;
} }

View File

@ -18,6 +18,7 @@
#ifndef INCLUDE_DSD_STATE_H_ #ifndef INCLUDE_DSD_STATE_H_
#define INCLUDE_DSD_STATE_H_ #define INCLUDE_DSD_STATE_H_
#include <pthread.h>
#include <mbelib.h> #include <mbelib.h>
#include "p25p1_heuristics.h" #include "p25p1_heuristics.h"
@ -113,6 +114,11 @@ typedef struct
int output_num_samples; //!< Number of L+R samples available in the above buffer int output_num_samples; //!< Number of L+R samples available in the above buffer
int output_length; //!< L+R buffer size (fixed) int output_length; //!< L+R buffer size (fixed)
int output_finished; //!< 0: not ready, 1: ready int output_finished; //!< 0: not ready, 1: ready
pthread_mutex_t input_mutex;
pthread_cond_t input_ready;
pthread_t dsd_thread;
int dsd_running;
} dsd_state; } dsd_state;
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -86,40 +86,25 @@ int getSymbol(dsd_opts * opts, dsd_state * state, int have_sync)
{ {
if (opts->audio_in_fd == -1) if (opts->audio_in_fd == -1)
{ {
// Get the next sample from the buffer if (state->input_length == 0) // no input available
sample = state->input_samples[state->input_offset++]; // FIXME: get sample only if available {
// wait for input
if (pthread_cond_wait(&state->input_ready, &state->input_mutex)) {
fprintf(stderr, "dsd::getSymbol: Error waiting for input ready condition\n");
}
}
if (state->input_offset == state->input_length) // all available samples have been read if (!state->dsd_running) {
return 0;
}
if (state->input_offset == state->input_length) // finished
{ {
int i; int i;
state->input_length = 0; // states all samples have been consumed
// We've reached the end of the buffer. Wait for more next time.
state->input_length = 0;
state->output_num_samples = state->output_offset; state->output_num_samples = state->output_offset;
// GNUradio drivel //fprintf(stderr, "dsd::getSymbol: input processing has finished\n");
// if (state->output_num_samples > state->output_length)
// {
// state->output_num_samples = state->output_length;
// }
//
// for (i = 0; i < state->output_length - state->output_num_samples; i++)
// {
// state->output_samples[i] = 0;
// }
//
// for (; i < state->output_length; i++)
// {
// state->output_samples[i] = state->output_buffer[i - (state->output_length - state->output_num_samples)] / 32768.0;
// }
//
// state->output_offset -= state->output_num_samples;
//
// for (i = 0; i < state->output_offset; i++)
// {
// state->output_buffer[i] = state->output_buffer[i + state->output_num_samples];
// }
if (state->output_num_samples > state->output_length) if (state->output_num_samples > state->output_length)
{ {
@ -135,6 +120,10 @@ int getSymbol(dsd_opts * opts, dsd_state * state, int have_sync)
state->output_finished = 1; state->output_finished = 1;
} }
else
{
sample = state->input_samples[state->input_offset++]; // get sample and move pointer to next
}
} }
else else
{ {

View File

@ -83,6 +83,59 @@ void DSDDecoder::setInBuffer(const short *inBuffer)
void DSDDecoder::pushSamples(int nbSamples) void DSDDecoder::pushSamples(int nbSamples)
{ {
m_dsdParams.state.input_length = nbSamples;
m_dsdParams.state.input_offset = 0; m_dsdParams.state.input_offset = 0;
m_dsdParams.state.input_length = nbSamples;
if (pthread_cond_signal(&m_dsdParams.state.input_ready)) {
printf("DSDDecoder::pushSamples: Unable to signal input ready");
}
} }
void DSDDecoder::start()
{
qDebug("DSDDecoder::start: starting");
m_dsdParams.state.dsd_running = 1;
if (pthread_create(&m_dsdParams.state.dsd_thread, NULL, &run_dsd, &m_dsdParams))
{
qCritical("DSDDecoder::start: Unable to spawn thread");
m_dsdParams.state.dsd_running = 0;
}
qDebug("DSDDecoder::start: started");
}
void DSDDecoder::stop()
{
if (m_dsdParams.state.dsd_running)
{
qDebug("DSDDecoder::stop: stopping");
m_dsdParams.state.dsd_running = 0;
char *b;
if (pthread_cond_signal(&m_dsdParams.state.input_ready)) {
printf("DSDDecoder::pushSamples: Unable to signal input ready");
}
// if (pthread_join(m_dsdParams.state.dsd_thread, (void**) &b)) {
// qCritical("DSDDecoder::stop: cannot join dsd thread");
// }
qDebug("DSDDecoder::stop: stopped");
}
else
{
qDebug("DSDDecoder::stop: not running");
}
}
void* DSDDecoder::run_dsd(void *arg)
{
dsd_params *params = (dsd_params *) arg;
liveScanner (&params->opts, &params->state);
return NULL;
}

View File

@ -29,6 +29,9 @@ public:
void setInBuffer(const short *inBuffer); void setInBuffer(const short *inBuffer);
void pushSamples(int nbSamples); // Push this amount of samples to the DSD decoder thread void pushSamples(int nbSamples); // Push this amount of samples to the DSD decoder thread
void start();
void stop();
private: private:
typedef struct typedef struct
{ {
@ -36,6 +39,8 @@ private:
dsd_state state; dsd_state state;
} dsd_params; } dsd_params;
static void* run_dsd(void *arg);
dsd_params m_dsdParams; dsd_params m_dsdParams;
}; };

View File

@ -209,10 +209,12 @@ void DSDDemod::start()
{ {
m_audioFifo.clear(); m_audioFifo.clear();
m_phaseDiscri.reset(); m_phaseDiscri.reset();
m_dsdDecoder.start();
} }
void DSDDemod::stop() void DSDDemod::stop()
{ {
m_dsdDecoder.stop();
} }
bool DSDDemod::handleMessage(const Message& cmd) bool DSDDemod::handleMessage(const Message& cmd)