mirror of https://github.com/lwvmobile/dsd-fme.git
331 lines
10 KiB
Diff
331 lines
10 KiB
Diff
diff --git a/include/dsd.h b/include/dsd.h
|
|
index 4a75702..3cf085e 100644
|
|
--- a/include/dsd.h
|
|
+++ b/include/dsd.h
|
|
@@ -317,6 +317,7 @@ typedef struct
|
|
long int rtl_rms;
|
|
int monitor_input_audio;
|
|
int analog_only;
|
|
+ int ghosts_only;
|
|
int pulse_raw_rate_in;
|
|
int pulse_raw_rate_out;
|
|
int pulse_digi_rate_in;
|
|
@@ -1342,6 +1343,8 @@ void rtl_udp_tune(dsd_opts * opts, dsd_state * state, long int frequency);
|
|
long int GetCurrentFreq(int sockfd);
|
|
bool SetFreq(int sockfd, long int freq);
|
|
bool SetModulation(int sockfd, int bandwidth);
|
|
+bool SetModulationWFM(int sockfd, int bandwidth);
|
|
+void death (dsd_opts * opts, dsd_state * state);
|
|
//commands below unique to GQRX only, not usable on SDR++
|
|
bool GetSignalLevel(int sockfd, double *dBFS);
|
|
bool GetSquelchLevel(int sockfd, double *dBFS);
|
|
diff --git a/src/3.c b/src/3.c
|
|
index e104993..b9033bd 100644
|
|
--- a/src/3.c
|
|
+++ b/src/3.c
|
|
@@ -591,4 +591,176 @@ long int raw_rms(int16_t *samples, int len, int step) //use samplespersymbol as
|
|
rms = (long int)sqrt((p-err) / len);
|
|
if (rms < 0) rms = 150;
|
|
return rms;
|
|
-}
|
|
\ No newline at end of file
|
|
+}
|
|
+
|
|
+
|
|
+//Ghosts
|
|
+void death (dsd_opts * opts, dsd_state * state)
|
|
+{
|
|
+ int i, x, result = 0;
|
|
+ short ghosts[960];
|
|
+ short spooks[960];
|
|
+ short demons[960];
|
|
+ short sample = 0;
|
|
+
|
|
+ memset (ghosts, 0, 960*sizeof(short));
|
|
+ memset (spooks, 0, 960*sizeof(short));
|
|
+ memset (demons, 0, 960*sizeof(short));
|
|
+
|
|
+ while (!exitflag) //while the software is running
|
|
+ {
|
|
+ //death on speaks at 48k/1 short output
|
|
+ if (opts->audio_in_type == 0)
|
|
+ {
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL );
|
|
+ ghosts[i] = sample;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL );
|
|
+ spooks[i] = sample;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL );
|
|
+ demons[i] = sample;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (opts->audio_in_type == 8)
|
|
+ {
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ result = sf_read_short(opts->tcp_file_in, &sample, 1);
|
|
+ if (result == 0)
|
|
+ {
|
|
+ sf_close(opts->tcp_file_in);
|
|
+ fprintf (stderr, "Connection to the Underworld Severed.\n");
|
|
+ fprintf (stderr, "Closing Death Speech Decoder.\n");
|
|
+ cleanupAndExit(opts, state);
|
|
+ }
|
|
+ ghosts[i] = sample;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ result = sf_read_short(opts->tcp_file_in, &sample, 1);
|
|
+ if (result == 0)
|
|
+ {
|
|
+ sf_close(opts->tcp_file_in);
|
|
+ fprintf (stderr, "Connection to the Underworld Severed.\n");
|
|
+ fprintf (stderr, "Closing Death Speech Decoder.\n");
|
|
+ cleanupAndExit(opts, state);
|
|
+ }
|
|
+ spooks[i] = sample;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ result = sf_read_short(opts->tcp_file_in, &sample, 1);
|
|
+ if (result == 0)
|
|
+ {
|
|
+ sf_close(opts->tcp_file_in);
|
|
+ fprintf (stderr, "Connection to the Underworld Severed.\n");
|
|
+ fprintf (stderr, "Closing Death Speech Decoder.\n");
|
|
+ cleanupAndExit(opts, state);
|
|
+ }
|
|
+ demons[i] = sample;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ //RTL Input
|
|
+ #ifdef USE_RTLSDR
|
|
+ if (opts->audio_in_type == 3)
|
|
+ {
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ get_rtlsdr_sample(&sample, opts, state);
|
|
+ ghosts[i] = sample;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ get_rtlsdr_sample(&sample, opts, state);
|
|
+ spooks[i] = sample;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 960; i++)
|
|
+ {
|
|
+ get_rtlsdr_sample(&sample, opts, state);
|
|
+ demons[i] = sample;
|
|
+ }
|
|
+ }
|
|
+ #endif
|
|
+
|
|
+ //The Dead Don't Like OSS input yet
|
|
+
|
|
+ //Listen to the Howls of the Deceased
|
|
+ if (opts->audio_out_type == 0 && opts->slot1_on == 1)
|
|
+ {
|
|
+ pa_simple_write(opts->pulse_raw_dev_out, ghosts, 960*2, NULL);
|
|
+ pa_simple_write(opts->pulse_raw_dev_out, spooks, 960*2, NULL);
|
|
+ pa_simple_write(opts->pulse_raw_dev_out, demons, 960*2, NULL);
|
|
+ }
|
|
+
|
|
+ if (opts->audio_out_type == 8) //UDP Audio
|
|
+ {
|
|
+ udp_socket_blasterA (opts, state, 960*2, ghosts);
|
|
+ udp_socket_blasterA (opts, state, 960*2, spooks);
|
|
+ udp_socket_blasterA (opts, state, 960*2, demons);
|
|
+ }
|
|
+
|
|
+ //added a condition check so that if OSS output and 8K, switches to 48K when opening OSS
|
|
+ if (opts->audio_out_type == 5 && opts->floating_point == 0 && opts->slot1_on == 1)
|
|
+ {
|
|
+ write (opts->audio_out_fd, ghosts, 960*2);
|
|
+ write (opts->audio_out_fd, spooks, 960*2);
|
|
+ write (opts->audio_out_fd, demons, 960*2);
|
|
+ }
|
|
+
|
|
+ //STDOUT -- I don't see the harm of adding this here, will be fine for analog only or digital only (non-mixed analog and digital)
|
|
+ if (opts->audio_out_type == 1 && opts->floating_point == 0 && opts->slot1_on == 1)
|
|
+ {
|
|
+ write (opts->audio_out_fd, ghosts, 960*2);
|
|
+ write (opts->audio_out_fd, spooks, 960*2);
|
|
+ write (opts->audio_out_fd, demons, 960*2);
|
|
+ }
|
|
+
|
|
+ //Undulate the Crystal Ball
|
|
+ if (x >= opts->trunk_hangtime)
|
|
+ {
|
|
+ long int spook_channel = state->trunk_lcn_freq[0];
|
|
+
|
|
+ //rigctl
|
|
+ if (opts->use_rigctl == 1)
|
|
+ {
|
|
+ if (opts->setmod_bw != 0 ) SetModulationWFM(opts->rigctl_sockfd, opts->setmod_bw);
|
|
+ SetFreq(opts->rigctl_sockfd, spook_channel);
|
|
+ }
|
|
+
|
|
+ //rtl
|
|
+ if (opts->audio_in_type == 3)
|
|
+ {
|
|
+ #ifdef USE_RTLSDR
|
|
+ rtl_dev_tune(opts, spook_channel);
|
|
+ #endif
|
|
+ }
|
|
+
|
|
+ //
|
|
+ state->trunk_lcn_freq[0] += 200000;
|
|
+
|
|
+ if (state->trunk_lcn_freq[0] > 106100000)
|
|
+ state->trunk_lcn_freq[0] = 87900000;
|
|
+
|
|
+ x = 0;
|
|
+
|
|
+ }
|
|
+
|
|
+ x++;
|
|
+
|
|
+ } //end while loop
|
|
+} //end ghosts
|
|
\ No newline at end of file
|
|
diff --git a/src/dsd_main.c b/src/dsd_main.c
|
|
index ca878e9..f14995d 100644
|
|
--- a/src/dsd_main.c
|
|
+++ b/src/dsd_main.c
|
|
@@ -696,6 +696,7 @@ initOpts (dsd_opts * opts)
|
|
|
|
opts->monitor_input_audio = 0; //enable with -8
|
|
opts->analog_only = 0; //only turned on with -fA
|
|
+ opts->ghosts_only = 0; //ghostbox mode with -fG
|
|
|
|
opts->inverted_p2 = 0;
|
|
opts->p2counter = 0;
|
|
@@ -1358,6 +1359,7 @@ usage ()
|
|
printf ("Decoder options:\n");
|
|
printf (" -fa Auto Detection\n");
|
|
printf (" -fA Passive Analog Audio Monitor\n");
|
|
+ printf (" -fG Ghosts, Demons, Specters, Ghouls, and Skeletons (Ghost Box)\n");
|
|
printf (" -ft TDMA Trunking P25p1 Control and Voice, P25p2 Trunked Channels, and DMR\n");
|
|
printf (" -fs DMR TDMA BS and MS Simplex\n");
|
|
printf (" -f1 Decode only P25 Phase 1\n");
|
|
@@ -2172,6 +2174,35 @@ main (int argc, char **argv)
|
|
sprintf (opts.output_name, "Analog Monitor");
|
|
fprintf (stderr,"Only Monitoring Passive Analog Signal\n");
|
|
}
|
|
+ else if (optarg[0] == 'G') //listen to spooky scary skeletons
|
|
+ {
|
|
+ opts.frame_dstar = 0;
|
|
+ opts.frame_x2tdma = 0;
|
|
+ opts.frame_p25p1 = 0;
|
|
+ opts.frame_p25p2 = 0;
|
|
+ opts.frame_nxdn48 = 0;
|
|
+ opts.frame_nxdn96 = 0;
|
|
+ opts.frame_dmr = 0;
|
|
+ opts.frame_dpmr = 0;
|
|
+ opts.frame_provoice = 0;
|
|
+ opts.frame_ysf = 0;
|
|
+ opts.frame_m17 = 0;
|
|
+ opts.pulse_digi_rate_out = 8000;
|
|
+ opts.pulse_digi_out_channels = 1;
|
|
+ opts.dmr_stereo = 0;
|
|
+ state.dmr_stereo = 0;
|
|
+ opts.dmr_mono = 0;
|
|
+ state.rf_mod = 0;
|
|
+ opts.monitor_input_audio = 1;
|
|
+ opts.ghosts_only = 1;
|
|
+ state.trunk_lcn_freq[0] = 87900000; //everybody knows ghosts live on the Broadcast FM band
|
|
+ opts.setmod_bw = 150000; //Ghosts annunciate clearly with about 150,000 PB
|
|
+ opts.trunk_hangtime = 0;
|
|
+ opts.rtlsdr_center_freq = 850000000;
|
|
+ opts.rtl_bandwidth = 48;
|
|
+ sprintf (opts.output_name, "Ghost Box");
|
|
+ fprintf (stderr,"Sounds of the Dead.\n");
|
|
+ }
|
|
else if (optarg[0] == 'd')
|
|
{
|
|
opts.frame_dstar = 1;
|
|
@@ -3462,6 +3493,22 @@ main (int argc, char **argv)
|
|
processM17IPF(&opts, &state);
|
|
}
|
|
|
|
+ else if (opts.ghosts_only == 1)
|
|
+ {
|
|
+ #ifdef USE_RTLSDR
|
|
+ if(opts.audio_in_type == 3)
|
|
+ open_rtlsdr_stream(&opts);
|
|
+ #endif
|
|
+
|
|
+ if (opts.audio_in_type == 0)
|
|
+ openPulseInput(&opts);
|
|
+
|
|
+ if (opts.audio_out_type == 0)
|
|
+ openPulseOutput(&opts);
|
|
+
|
|
+ death(&opts, &state);
|
|
+ }
|
|
+
|
|
else
|
|
{
|
|
|
|
diff --git a/src/dsd_rigctl.c b/src/dsd_rigctl.c
|
|
index 820ac7e..f12bacc 100644
|
|
--- a/src/dsd_rigctl.c
|
|
+++ b/src/dsd_rigctl.c
|
|
@@ -163,6 +163,28 @@ bool SetModulation(int sockfd, int bandwidth)
|
|
return true;
|
|
}
|
|
|
|
+bool SetModulationWFM(int sockfd, int bandwidth)
|
|
+{
|
|
+ char buf[BUFSIZE];
|
|
+ //the bandwidth is now a user/system based configurable variable
|
|
+ sprintf (buf, "M WFM %d\n", bandwidth); //SDR++ has changed the token from FM to NFM, even if Ryzerth fixes it later, users may still have an older version
|
|
+ Send(sockfd, buf);
|
|
+ Recv(sockfd, buf);
|
|
+
|
|
+ //if it fails the first time, send the other token instead
|
|
+ if (strcmp(buf, "RPRT 1\n") == 0 ) //sdr++ has a linebreak here, is that in all versions of the protocol?
|
|
+ {
|
|
+ sprintf (buf, "M WFM %d\n", bandwidth); //anything not SDR++
|
|
+ Send(sockfd, buf);
|
|
+ Recv(sockfd, buf);
|
|
+ }
|
|
+
|
|
+ if (strcmp(buf, "RPRT 1\n") == 0 )
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
bool GetSignalLevel(int sockfd, double *dBFS)
|
|
{
|
|
char buf[BUFSIZE];
|
|
diff --git a/src/rtl_sdr_fm.cpp b/src/rtl_sdr_fm.cpp
|
|
index ad04667..dd6566c 100644
|
|
--- a/src/rtl_sdr_fm.cpp
|
|
+++ b/src/rtl_sdr_fm.cpp
|
|
@@ -1034,7 +1034,7 @@ void open_rtlsdr_stream(dsd_opts *opts)
|
|
//init with low pass if decoding P25 or EDACS/Provoice
|
|
if (opts->frame_p25p1 == 1 || opts->frame_p25p2 == 1 || opts->frame_provoice == 1)
|
|
demod_init_ro2(&demod);
|
|
- else if (opts->analog_only == 1 || opts->m17encoder == 1)
|
|
+ else if (opts->analog_only == 1 || opts->m17encoder == 1 || opts->ghosts_only == 1)
|
|
demod_init_analog(&demod);
|
|
else demod_init(&demod);
|
|
output_init(&output);
|