From 97ffe47e77fb848e5c2d2cab846c469a6331ab52 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sun, 12 Mar 2017 09:31:18 +0000 Subject: [PATCH 01/17] Add code to allow the setting of the antenna. --- src/convenience/convenience.c | 18 ++++++++++++++++++ src/convenience/convenience.h | 10 ++++++++++ src/rtl_sdr.c | 12 +++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c index 1a0fbfb..b829ce4 100644 --- a/src/convenience/convenience.c +++ b/src/convenience/convenience.c @@ -148,6 +148,24 @@ int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency) return r; } +int verbose_set_antenna(SoapySDRDevice *dev, char * ant) +{ + int r; + if (ant != NULL) { + r = (int)SoapySDRDevice_setAntenna(dev, SOAPY_SDR_RX, 0, ant); + } else { + r = 0; + } + + if (r != 0) { + fprintf(stderr, "WARNING: Failed to set antenna.\n"); + } else { + char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, 0); + fprintf(stderr, "Antenna set to %s\n", antval); + } + return r; +} + int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate) { int r; diff --git a/src/convenience/convenience.h b/src/convenience/convenience.h index 90ead49..3b23449 100644 --- a/src/convenience/convenience.h +++ b/src/convenience/convenience.h @@ -150,6 +150,16 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str); int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error); +/*! + * Set the antenna value for the device and report status on stderr. + * + * \param dev the device handle + * \param ant string name of the antenna to use + * \return 0 on success + */ + +int verbose_set_antenna(SoapySDRDevice *dev, char * ant); + /*! * Reset buffer * diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 266ce93..480902c 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -60,6 +60,7 @@ void usage(void) "\t[-F output format, CU8|CS8|CS16|CF32 (default: CU8)]\n" "\t[-S force sync output (default: async)]\n" "\t[-D direct_sampling_mode, 0 (default/off), 1 (I), 2 (Q), 3 (no-mod)]\n" + "\t[-A Name of antenna to use]\n" "\tfilename (a '-' dumps samples to stdout)\n\n"); exit(1); } @@ -104,7 +105,8 @@ int main(int argc, char **argv) uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; char *output_format = SOAPY_SDR_CU8; - + char * ant = NULL; + while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:")) != -1) { switch (opt) { case 'd': @@ -132,6 +134,9 @@ int main(int argc, char **argv) case 'S': sync_mode = 1; break; + case 'A': + ant = optarg; + break; case 'F': if (strcasecmp(optarg, "CU8") == 0) { output_format = SOAPY_SDR_CU8; @@ -213,6 +218,11 @@ int main(int argc, char **argv) /* Set the frequency */ verbose_set_frequency(dev, frequency); + /* Set the antenna */ + verbose_set_antenna(dev, ant); + + printf("****Number of channels: %d\n", SoapySDRDevice_getNumChannels(dev, SOAPY_SDR_RX)); + if (NULL == gain_str) { /* Enable automatic gain */ verbose_auto_gain(dev); From d3757a14a4963c58b5b3147948e3df770e15af6d Mon Sep 17 00:00:00 2001 From: matt Date: Sun, 12 Mar 2017 11:09:47 +0000 Subject: [PATCH 02/17] Start to mess around with multichannel. --- src/convenience/convenience.c | 52 ++++++++++++++++++++++++--- src/rtl_sdr.c | 68 ++++++++++++++++++++++------------- 2 files changed, 92 insertions(+), 28 deletions(-) diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c index b829ce4..df5118b 100644 --- a/src/convenience/convenience.c +++ b/src/convenience/convenience.c @@ -139,9 +139,16 @@ int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency) int r; SoapySDRKwargs args = {0}; - r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, 0, (double)frequency, &args); + r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, 0, (double)frequency, &args); + if (r != 0) { + fprintf(stderr, "WARNING: Failed to set center freq. (chan 0)\n"); + } else { + fprintf(stderr, "Tuned to %u Hz.\n", frequency); + } + + r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, 1, (double)frequency, &args); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set center freq.\n"); + fprintf(stderr, "WARNING: Failed to set center freq. (chan 1)\n"); } else { fprintf(stderr, "Tuned to %u Hz.\n", frequency); } @@ -161,8 +168,22 @@ int verbose_set_antenna(SoapySDRDevice *dev, char * ant) fprintf(stderr, "WARNING: Failed to set antenna.\n"); } else { char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, 0); - fprintf(stderr, "Antenna set to %s\n", antval); + fprintf(stderr, "****Antenna set to %s\n", antval); } + + if (ant != NULL) { + r = (int)SoapySDRDevice_setAntenna(dev, SOAPY_SDR_RX, 1, ant); + } else { + r = 0; + } + + if (r != 0) { + fprintf(stderr, "WARNING: Failed to set antenna.\n"); + } else { + char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, 1); + fprintf(stderr, "****Antenna set to %s\n", antval); + } + return r; } @@ -175,6 +196,14 @@ int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate) } else { fprintf(stderr, "Sampling at %u S/s.\n", samp_rate); } + + r = (int)SoapySDRDevice_setSampleRate(dev, SOAPY_SDR_RX, 1, (double)samp_rate); + if (r != 0) { + fprintf(stderr, "WARNING: Failed to set sample rate.\n"); + } else { + fprintf(stderr, "Sampling at %u S/s.\n", samp_rate); + } + return r; } @@ -319,8 +348,15 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str) char *name = args.keys[i]; double value = atof(args.vals[i]); + + fprintf(stderr, "Setting gain element %s: %f dB\n", name, value); + r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 0, name, value); + if (r != 0) { + fprintf(stderr, "WARNING: setGainElement(%s, %f) failed: %d\n", name, value, r); + } + fprintf(stderr, "Setting gain element %s: %f dB\n", name, value); - r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 0, name, value); + r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 1, name, value); if (r != 0) { fprintf(stderr, "WARNING: setGainElement(%s, %f) failed: %d\n", name, value, r); } @@ -334,6 +370,14 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str) } else { fprintf(stderr, "Tuner gain set to %0.2f dB.\n", value); } + r = SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, 1, value); + if (r != 0) { + fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); + } else { + fprintf(stderr, "Tuner gain set to %0.2f dB.\n", value); + } + + // TODO: read back and print each individual getGainElement()s } diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 480902c..1ea5936 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -61,7 +61,7 @@ void usage(void) "\t[-S force sync output (default: async)]\n" "\t[-D direct_sampling_mode, 0 (default/off), 1 (I), 2 (Q), 3 (no-mod)]\n" "\t[-A Name of antenna to use]\n" - "\tfilename (a '-' dumps samples to stdout)\n\n"); + "\tfilename0 filename1 (a '-' dumps samples to stdout)\n\n"); exit(1); } @@ -89,15 +89,19 @@ int main(int argc, char **argv) #ifndef _WIN32 struct sigaction sigact; #endif - char *filename = NULL; + char *filename0 = NULL; + char *filename1 = NULL; int n_read; int r, opt; char *gain_str = NULL; int ppm_error = 0; int sync_mode = 0; int direct_sampling = 0; - FILE *file; - int16_t *buffer; + FILE *file_ch0; + FILE *file_ch1; + int16_t *buffer_ch0; + int16_t *buffer_ch1; + uint8_t *buf8 = NULL; float *fbuf = NULL; // assumed 32-bit char *dev_query = NULL; @@ -107,7 +111,7 @@ int main(int argc, char **argv) char *output_format = SOAPY_SDR_CU8; char * ant = NULL; - while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:A:")) != -1) { switch (opt) { case 'd': dev_query = optarg; @@ -161,10 +165,11 @@ int main(int argc, char **argv) } } - if (argc <= optind) { + if (argc <= optind+1) { usage(); } else { - filename = argv[optind]; + filename0 = argv[optind]; + filename1 = argv[optind+1]; } if(out_block_size < MINIMAL_BUF_LENGTH || @@ -178,7 +183,9 @@ int main(int argc, char **argv) out_block_size = DEFAULT_BUF_LENGTH; } - buffer = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); + buffer_ch0 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); + buffer_ch1 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); + if (output_format == SOAPY_SDR_CS8 || output_format == SOAPY_SDR_CU8) { buf8 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS8)); } else if (output_format == SOAPY_SDR_CF32) { @@ -233,17 +240,23 @@ int main(int argc, char **argv) verbose_ppm_set(dev, ppm_error); - if(strcmp(filename, "-") == 0) { /* Write samples to stdout */ - file = stdout; + if(strcmp(filename0, "-") == 0) { /* Write samples to stdout */ + file_ch0 = stdout; #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif } else { - file = fopen(filename, "wb"); - if (!file) { - fprintf(stderr, "Failed to open %s\n", filename); + file_ch0 = fopen(filename0, "wb"); + if (!file_ch0) { + fprintf(stderr, "Failed to open %s\n", filename0); goto out; } + file_ch1 = fopen(filename1, "wb"); + if (!file_ch1) { + fprintf(stderr, "Failed to open %s\n", filename1); + goto out; + } + } /* Reset endpoint before we start reading from it (mandatory) */ @@ -258,7 +271,7 @@ int main(int argc, char **argv) } suppress_stdout_stop(tmp_stdout); while (!do_exit) { - void *buffs[] = {buffer}; + void *buffs[] = {buffer_ch0, buffer_ch1}; int flags = 0; long long timeNs = 0; long timeoutNs = 1000000; @@ -288,31 +301,36 @@ int main(int argc, char **argv) if (output_format == SOAPY_SDR_CS16) { // The "native" format we read in, write out no conversion needed // (Always reading in CS16 to support >8-bit devices) - if (fwrite(buffer, sizeof(int16_t), n_read, file) != (size_t)n_read) { + if (fwrite(buffer_ch0, sizeof(int16_t), n_read, file_ch0) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); break; } + if (fwrite(buffer_ch1, sizeof(int16_t), n_read, file_ch1) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + break; + } + } else if (output_format == SOAPY_SDR_CS8) { for (i = 0; i < n_read; ++i) { - buf8[i] = ( (int16_t)buffer[i] / 32767.0 * 128.0 + 0.4); + buf8[i] = ( (int16_t)buffer_ch0[i] / 32767.0 * 128.0 + 0.4); } - if (fwrite(buf8, sizeof(uint8_t), n_read, file) != (size_t)n_read) { + if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch0) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); break; } } else if (output_format == SOAPY_SDR_CU8) { for (i = 0; i < n_read; ++i) { - buf8[i] = ( (int16_t)buffer[i] / 32767.0 * 128.0 + 127.4); + buf8[i] = ( (int16_t)buffer_ch0[i] / 32767.0 * 128.0 + 127.4); } - if (fwrite(buf8, sizeof(uint8_t), n_read, file) != (size_t)n_read) { + if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch0) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); break; } } else if (output_format == SOAPY_SDR_CF32) { for (i = 0; i < n_read; ++i) { - fbuf[i] = buffer[i] * 1.0f / SHRT_MAX; + fbuf[i] = buffer_ch0[i] * 1.0f / SHRT_MAX; } - if (fwrite(fbuf, sizeof(float), n_read, file) != (size_t)n_read) { + if (fwrite(fbuf, sizeof(float), n_read, file_ch0) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); break; } @@ -337,13 +355,15 @@ int main(int argc, char **argv) else fprintf(stderr, "\nLibrary error %d, exiting...\n", r); - if (file != stdout) - fclose(file); + if (file_ch0 != stdout) + fclose(file_ch0); + fclose(file_ch1); SoapySDRDevice_deactivateStream(dev, stream, 0, 0); SoapySDRDevice_closeStream(dev, stream); SoapySDRDevice_unmake(dev); - free (buffer); + free (buffer_ch0); + free(buffer_ch1); out: return r >= 0 ? r : -r; } From b403682287b5e5866d9d97695f7c10015190ed53 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Mon, 13 Mar 2017 20:26:28 +0000 Subject: [PATCH 03/17] It now compiles. --- src/convenience/convenience.c | 92 ++++++++++++----------------------- src/convenience/convenience.h | 19 ++++---- src/rtl_fm.c | 15 +++--- src/rtl_power.c | 8 +-- src/rtl_sdr.c | 62 ++++++++++++++++------- 5 files changed, 97 insertions(+), 99 deletions(-) diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c index df5118b..6ae2cfa 100644 --- a/src/convenience/convenience.c +++ b/src/convenience/convenience.c @@ -134,32 +134,26 @@ double atofp(char *s) return atof(s); } -int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency) +int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency, size_t chan) { int r; SoapySDRKwargs args = {0}; - r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, 0, (double)frequency, &args); + r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, chan, (double)frequency, &args); if (r != 0) { fprintf(stderr, "WARNING: Failed to set center freq. (chan 0)\n"); } else { fprintf(stderr, "Tuned to %u Hz.\n", frequency); } - r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, 1, (double)frequency, &args); - if (r != 0) { - fprintf(stderr, "WARNING: Failed to set center freq. (chan 1)\n"); - } else { - fprintf(stderr, "Tuned to %u Hz.\n", frequency); - } return r; } -int verbose_set_antenna(SoapySDRDevice *dev, char * ant) +int verbose_set_antenna(SoapySDRDevice *dev, const char * ant, size_t chan) { int r; if (ant != NULL) { - r = (int)SoapySDRDevice_setAntenna(dev, SOAPY_SDR_RX, 0, ant); + r = (int)SoapySDRDevice_setAntenna(dev, SOAPY_SDR_RX, chan, ant); } else { r = 0; } @@ -167,55 +161,35 @@ int verbose_set_antenna(SoapySDRDevice *dev, char * ant) if (r != 0) { fprintf(stderr, "WARNING: Failed to set antenna.\n"); } else { - char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, 0); + char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, chan); fprintf(stderr, "****Antenna set to %s\n", antval); } - if (ant != NULL) { - r = (int)SoapySDRDevice_setAntenna(dev, SOAPY_SDR_RX, 1, ant); - } else { - r = 0; - } - - if (r != 0) { - fprintf(stderr, "WARNING: Failed to set antenna.\n"); - } else { - char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, 1); - fprintf(stderr, "****Antenna set to %s\n", antval); - } - return r; } -int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate) +int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate, size_t chan) { int r; - r = (int)SoapySDRDevice_setSampleRate(dev, SOAPY_SDR_RX, 0, (double)samp_rate); + r = (int)SoapySDRDevice_setSampleRate(dev, SOAPY_SDR_RX, chan, (double)samp_rate); if (r != 0) { fprintf(stderr, "WARNING: Failed to set sample rate.\n"); } else { fprintf(stderr, "Sampling at %u S/s.\n", samp_rate); } - r = (int)SoapySDRDevice_setSampleRate(dev, SOAPY_SDR_RX, 1, (double)samp_rate); - if (r != 0) { - fprintf(stderr, "WARNING: Failed to set sample rate.\n"); - } else { - fprintf(stderr, "Sampling at %u S/s.\n", samp_rate); - } - return r; } -int verbose_set_bandwidth(SoapySDRDevice *dev, uint32_t bandwidth) +int verbose_set_bandwidth(SoapySDRDevice *dev, uint32_t bandwidth, size_t chan) { int r; - r = (int)SoapySDRDevice_setBandwidth(dev, SOAPY_SDR_RX, 0, (double)bandwidth); + r = (int)SoapySDRDevice_setBandwidth(dev, SOAPY_SDR_RX, chan, (double)bandwidth); uint32_t applied_bw = 0; if (r != 0) { fprintf(stderr, "WARNING: Failed to set bandwidth.\n"); } else if (bandwidth > 0) { - applied_bw = (uint32_t)SoapySDRDevice_getBandwidth(dev, SOAPY_SDR_RX, 0); + applied_bw = (uint32_t)SoapySDRDevice_getBandwidth(dev, SOAPY_SDR_RX, chan); if (applied_bw) fprintf(stderr, "Bandwidth parameter %u Hz resulted in %u Hz.\n", bandwidth, applied_bw); else @@ -277,7 +251,7 @@ int verbose_offset_tuning(SoapySDRDevice *dev) return r; } -int verbose_auto_gain(SoapySDRDevice *dev) +int verbose_auto_gain(SoapySDRDevice *dev, size_t chan) { int r; r = 0; @@ -296,7 +270,7 @@ int verbose_auto_gain(SoapySDRDevice *dev) // For now, set 40.0 dB, high // Note: 26.5 dB in https://github.com/librtlsdr/librtlsdr/blob/master/src/tuner_r82xx.c#L1067 - but it's not the same // TODO: remove or change after auto-gain? https://github.com/pothosware/SoapyRTLSDR/issues/21 rtlsdr_set_tuner_gain_mode(dev, 0); - r = (int)SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, 0, 40.); + r = (int)SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, chan, 40.); if (r != 0) { fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); } else { @@ -307,15 +281,15 @@ int verbose_auto_gain(SoapySDRDevice *dev) // even though it logs HACKRF_ERROR_INVALID_PARAM? https://github.com/rxseger/rx_tools/issues/9 // Total gain is distributed amongst all gains, 116 = 37,65,1; the LNA is OK (<40) but VGA is out of range (65 > 62) // TODO: generic means to set all gains, of any SDR? string parsing LNA=#,VGA=#,AMP=#? - r = (int)SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 0, "LNA", 40.); // max 40 + r = (int)SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, chan, "LNA", 40.); // max 40 if (r != 0) { fprintf(stderr, "WARNING: Failed to set LNA tuner gain.\n"); } - r = (int)SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 0, "VGA", 20.); // max 65 + r = (int)SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, chan, "VGA", 20.); // max 65 if (r != 0) { fprintf(stderr, "WARNING: Failed to set VGA tuner gain.\n"); } - r = (int)SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 0, "AMP", 0.); // on or off + r = (int)SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, chan, "AMP", 0.); // on or off if (r != 0) { fprintf(stderr, "WARNING: Failed to set AMP tuner gain.\n"); } @@ -326,7 +300,7 @@ int verbose_auto_gain(SoapySDRDevice *dev) return r; } -int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str) +int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan) { SoapySDRKwargs args = {0}; size_t i; @@ -348,35 +322,22 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str) char *name = args.keys[i]; double value = atof(args.vals[i]); - fprintf(stderr, "Setting gain element %s: %f dB\n", name, value); - r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 0, name, value); + r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, chan, name, value); if (r != 0) { fprintf(stderr, "WARNING: setGainElement(%s, %f) failed: %d\n", name, value, r); } - fprintf(stderr, "Setting gain element %s: %f dB\n", name, value); - r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, 1, name, value); - if (r != 0) { - fprintf(stderr, "WARNING: setGainElement(%s, %f) failed: %d\n", name, value, r); - } } } else { // Set overall gain and let SoapySDR distribute amongst components double value = atof(gain_str); - r = SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, 0, value); + r = SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, chan, value); if (r != 0) { fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); } else { fprintf(stderr, "Tuner gain set to %0.2f dB.\n", value); } - r = SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, 1, value); - if (r != 0) { - fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); - } else { - fprintf(stderr, "Tuner gain set to %0.2f dB.\n", value); - } - // TODO: read back and print each individual getGainElement()s } @@ -384,12 +345,12 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str) return r; } -int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error) +int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error, size_t chan) { int r; if (ppm_error == 0) { return 0;} - r = (int)SoapySDRDevice_setFrequencyComponent(dev, SOAPY_SDR_RX, 0, "CORR", (double)ppm_error, NULL); + r = (int)SoapySDRDevice_setFrequencyComponent(dev, SOAPY_SDR_RX, chan, "CORR", (double)ppm_error, NULL); if (r != 0) { fprintf(stderr, "WARNING: Failed to set ppm error.\n"); } else { @@ -492,7 +453,8 @@ void suppress_stdout_stop(int tmp_stdout) { } -int verbose_device_search(char *s, SoapySDRDevice **devOut, SoapySDRStream **streamOut, const char *format) +int verbose_device_search(char *s, SoapySDRDevice **devOut, SoapySDRStream **streamOut, const char *format, + const size_t * channels, size_t nchannels) { size_t device_count = 0; size_t i = 0; @@ -510,8 +472,14 @@ int verbose_device_search(char *s, SoapySDRDevice **devOut, SoapySDRStream **str } show_device_info(dev); - - if (SoapySDRDevice_setupStream(dev, streamOut, SOAPY_SDR_RX, format, NULL, 0, &stream_args) != 0) { + if (nchannels > SoapySDRDevice_getNumChannels(dev, SOAPY_SDR_RX)) { + fprintf(stderr, "User asked for more channels (%d) than device supports (%d)\n", + nchannels, SoapySDRDevice_getNumChannels(dev, SOAPY_SDR_RX)); + return -5; + } + + if (SoapySDRDevice_setupStream(dev, streamOut, SOAPY_SDR_RX, format, channels, nchannels, + &stream_args) != 0) { fprintf(stderr, "SoapySDRDevice_setupStream failed\n"); return -3; } diff --git a/src/convenience/convenience.h b/src/convenience/convenience.h index 3b23449..511a6ba 100644 --- a/src/convenience/convenience.h +++ b/src/convenience/convenience.h @@ -70,7 +70,7 @@ double atofp(char *s); * \return 0 on success */ -int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency); +int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency, size_t chan); /*! * Set device sample rate and report status on stderr @@ -80,7 +80,7 @@ int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency); * \return 0 on success */ -int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate); +int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate, size_t chan); /*! * Set device bandwidth and report status on stderr @@ -90,7 +90,7 @@ int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate); * \return 0 on success */ -int verbose_set_bandwidth(SoapySDRDevice *dev, uint32_t bandwidth); +int verbose_set_bandwidth(SoapySDRDevice *dev, uint32_t bandwidth, size_t chan); /*! @@ -119,7 +119,7 @@ int verbose_offset_tuning(SoapySDRDevice *dev); * \return 0 on success */ -int verbose_auto_gain(SoapySDRDevice *dev); +int verbose_auto_gain(SoapySDRDevice *dev, size_t chan); /*! * Set tuner gain and report status on stderr @@ -129,7 +129,7 @@ int verbose_auto_gain(SoapySDRDevice *dev); * \return 0 on success */ -int verbose_gain_set(SoapySDRDevice *dev, int gain); +int verbose_gain_set(SoapySDRDevice *dev, int gain, size_t chan); /*! * Set tuner gain elements by a key/value string @@ -138,7 +138,7 @@ int verbose_gain_set(SoapySDRDevice *dev, int gain); * \param gain_str string of gain element pairs (example LNA=40,VGA=20,AMP=0), or string of overall gain, in dB * \return 0 on success */ -int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str); +int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan); /*! * Set the frequency correction value for the device and report status on stderr. @@ -148,7 +148,7 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str); * \return 0 on success */ -int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error); +int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error, size_t chan); /*! * Set the antenna value for the device and report status on stderr. @@ -158,7 +158,7 @@ int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error); * \return 0 on success */ -int verbose_set_antenna(SoapySDRDevice *dev, char * ant); +int verbose_set_antenna(SoapySDRDevice *dev, const char * ant, size_t chan); /*! * Reset buffer @@ -179,7 +179,8 @@ int verbose_reset_buffer(SoapySDRDevice *dev); * \return dev 0 if successful */ -int verbose_device_search(char *s, SoapySDRDevice **devOut, SoapySDRStream **streamOut, const char *format); +int verbose_device_search(char *s, SoapySDRDevice **devOut, SoapySDRStream **streamOut, const char *format, + const size_t * channels, size_t nchannels); /*! * Start redirecting stdout to stderr to avoid unwanted stdout emissions. diff --git a/src/rtl_fm.c b/src/rtl_fm.c index 0a70e87..0b7b69e 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -1016,7 +1016,7 @@ static void *controller_thread_fn(void *arg) if (!dongle.offset_tuning) fprintf(stderr, " frequency is away from parametrized one, to avoid negative impact from dc\n"); } - verbose_set_frequency(dongle.dev, dongle.freq); + verbose_set_frequency(dongle.dev, dongle.freq, 0); fprintf(stderr, "Oversampling input by: %ix.\n", demod.downsample); fprintf(stderr, "Oversampling output by: %ix.\n", demod.post_downsample); fprintf(stderr, "Buffer size: %0.2fms\n", @@ -1025,7 +1025,7 @@ static void *controller_thread_fn(void *arg) /* Set the sample rate */ if (verbosity) fprintf(stderr, "verbose_set_sample_rate(%.0f Hz)\n", (double)dongle.rate); - verbose_set_sample_rate(dongle.dev, dongle.rate); + verbose_set_sample_rate(dongle.dev, dongle.rate, 0); fprintf(stderr, "Output at %u Hz.\n", demod.rate_in/demod.post_downsample); SoapySDRKwargs args = {0}; @@ -1369,7 +1369,8 @@ int main(int argc, char **argv) ACTUAL_BUF_LENGTH = lcm_post[demod.post_downsample] * DEFAULT_BUF_LENGTH; tmp_stdout = suppress_stdout_start(); - verbose_device_search(dongle.dev_query, &dongle.dev, &dongle.stream, SOAPY_SDR_CS16); + verbose_device_search(dongle.dev_query, &dongle.dev, &dongle.stream, SOAPY_SDR_CS16, + NULL, 0); if (!dongle.dev) { fprintf(stderr, "Failed to open rtlsdr device matching %s.\n", dongle.dev_query); @@ -1397,16 +1398,16 @@ int main(int argc, char **argv) /* Set the tuner gain */ if (dongle.gain_str == NULL) { - verbose_auto_gain(dongle.dev); + verbose_auto_gain(dongle.dev, 0); } else { - verbose_gain_str_set(dongle.dev, dongle.gain_str); + verbose_gain_str_set(dongle.dev, dongle.gain_str, 0); } SoapySDRDevice_setGainMode(dongle.dev, SOAPY_SDR_RX, 0, rtlagc); - verbose_ppm_set(dongle.dev, dongle.ppm_error); + verbose_ppm_set(dongle.dev, dongle.ppm_error, 0); - verbose_set_bandwidth(dongle.dev, dongle.bandwidth); + verbose_set_bandwidth(dongle.dev, dongle.bandwidth, 0); if (verbosity && dongle.bandwidth) { diff --git a/src/rtl_power.c b/src/rtl_power.c index ad7fee4..23373b8 100644 --- a/src/rtl_power.c +++ b/src/rtl_power.c @@ -946,7 +946,7 @@ int main(int argc, char **argv) fprintf(stderr, "Reporting every %i seconds\n", interval); - r = verbose_device_search(dev_query, &dev, &stream, SOAPY_SDR_CS16); + r = verbose_device_search(dev_query, &dev, &stream, SOAPY_SDR_CS16, NULL, 0); if (r != 0) { fprintf(stderr, "Failed to open rtlsdr device matching %s.\n", dev_query); @@ -978,12 +978,12 @@ int main(int argc, char **argv) /* Set the tuner gain */ if (gain_str == NULL) { - verbose_auto_gain(dev); + verbose_auto_gain(dev, 0); } else { - verbose_gain_str_set(dev, gain_str); + verbose_gain_str_set(dev, gain_str, 0); } - verbose_ppm_set(dev, ppm_error); + verbose_ppm_set(dev, ppm_error, 0); if (strcmp(filename, "-") == 0) { /* Write log to stdout */ file = stdout; diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 1ea5936..2b27ef8 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -61,6 +61,7 @@ void usage(void) "\t[-S force sync output (default: async)]\n" "\t[-D direct_sampling_mode, 0 (default/off), 1 (I), 2 (Q), 3 (no-mod)]\n" "\t[-A Name of antenna to use]\n" + "\t[-N Number of receive channels to use]\n" "\tfilename0 filename1 (a '-' dumps samples to stdout)\n\n"); exit(1); } @@ -110,8 +111,11 @@ int main(int argc, char **argv) uint32_t out_block_size = DEFAULT_BUF_LENGTH; char *output_format = SOAPY_SDR_CU8; char * ant = NULL; + size_t * channels; + size_t nchan = 0; + size_t ch; - while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:A:")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:A:N:")) != -1) { switch (opt) { case 'd': dev_query = optarg; @@ -141,6 +145,9 @@ int main(int argc, char **argv) case 'A': ant = optarg; break; + case 'N': + nchan = atoi(optarg); + break; case 'F': if (strcasecmp(optarg, "CU8") == 0) { output_format = SOAPY_SDR_CU8; @@ -194,7 +201,14 @@ int main(int argc, char **argv) int tmp_stdout = suppress_stdout_start(); // TODO: allow choosing input format, see https://www.reddit.com/r/RTLSDR/comments/4tpxv7/rx_tools_commandline_sdr_tools_for_rtlsdr_bladerf/d5ohfse?context=3 - r = verbose_device_search(dev_query, &dev, &stream, SOAPY_SDR_CS16); + + if (nchan > 0) { + channels = calloc(nchan, sizeof(size_t)); + } else { + channels = NULL; + } + + r = verbose_device_search(dev_query, &dev, &stream, SOAPY_SDR_CS16, channels, nchan); if (r != 0) { fprintf(stderr, "Failed to open rtlsdr device matching %s.\n", dev_query); @@ -203,6 +217,8 @@ int main(int argc, char **argv) fprintf(stderr, "Using output format: %s (input format %s)\n", output_format, SOAPY_SDR_CS16); + printf("****Number of channels: %d\n", SoapySDRDevice_getNumChannels(dev, SOAPY_SDR_RX)); + #ifndef _WIN32 sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); @@ -220,25 +236,37 @@ int main(int argc, char **argv) } /* Set the sample rate */ - verbose_set_sample_rate(dev, samp_rate); - /* Set the frequency */ - verbose_set_frequency(dev, frequency); - /* Set the antenna */ - verbose_set_antenna(dev, ant); - - printf("****Number of channels: %d\n", SoapySDRDevice_getNumChannels(dev, SOAPY_SDR_RX)); - - if (NULL == gain_str) { - /* Enable automatic gain */ - verbose_auto_gain(dev); + if (channels == NULL) { + verbose_set_sample_rate(dev, samp_rate, 0); + verbose_set_frequency(dev, frequency, 0); + verbose_set_antenna(dev, ant, 0); + if (NULL == gain_str) { + /* Enable automatic gain */ + verbose_auto_gain(dev, 0); + } else { + /* Enable manual gain */ + verbose_gain_str_set(dev, gain_str, 0); + } + verbose_ppm_set(dev, ppm_error, 0); } else { - /* Enable manual gain */ - verbose_gain_str_set(dev, gain_str); + for(ch = 0; ch < nchan; ch++) { + verbose_set_sample_rate(dev, samp_rate, channels[ch]); + verbose_set_frequency(dev, frequency, channels[ch]); + verbose_set_antenna(dev, ant, channels[ch]); + if (NULL == gain_str) { + /* Enable automatic gain */ + verbose_auto_gain(dev, channels[ch]); + } else { + /* Enable manual gain */ + verbose_gain_str_set(dev, gain_str, channels[ch]); + } + verbose_ppm_set(dev, ppm_error, channels[ch]); + + } } - - verbose_ppm_set(dev, ppm_error); + if(strcmp(filename0, "-") == 0) { /* Write samples to stdout */ file_ch0 = stdout; From 0e4f0b2987dc46c9b1e20c41a25ccb89df19b6ba Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Thu, 16 Mar 2017 19:49:54 +0000 Subject: [PATCH 04/17] Fix a bunch of bugs. --- src/rtl_sdr.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 2b27ef8..cd8a818 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -172,11 +172,15 @@ int main(int argc, char **argv) } } - if (argc <= optind+1) { + if (argc <= optind) { usage(); } else { filename0 = argv[optind]; - filename1 = argv[optind+1]; + if (argc > optind) { + filename1 = argv[optind+1]; + } else { + filename1 = NULL; + } } if(out_block_size < MINIMAL_BUF_LENGTH || @@ -279,11 +283,15 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to open %s\n", filename0); goto out; } - file_ch1 = fopen(filename1, "wb"); - if (!file_ch1) { - fprintf(stderr, "Failed to open %s\n", filename1); - goto out; - } + if (filename1 != NULL) { + file_ch1 = fopen(filename1, "wb"); + if (!file_ch1) { + fprintf(stderr, "Failed to open %s\n", filename1); + goto out; + } + } else { + file_ch1 = NULL; + } } @@ -333,10 +341,12 @@ int main(int argc, char **argv) fprintf(stderr, "Short write, samples lost, exiting!\n"); break; } - if (fwrite(buffer_ch1, sizeof(int16_t), n_read, file_ch1) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; - } + if (file_ch1 != NULL) { + if (fwrite(buffer_ch1, sizeof(int16_t), n_read, file_ch1) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + break; + } + } } else if (output_format == SOAPY_SDR_CS8) { for (i = 0; i < n_read; ++i) { @@ -385,8 +395,10 @@ int main(int argc, char **argv) if (file_ch0 != stdout) fclose(file_ch0); - fclose(file_ch1); - + if (file_ch1 != NULL) { + fclose(file_ch1); + } + SoapySDRDevice_deactivateStream(dev, stream, 0, 0); SoapySDRDevice_closeStream(dev, stream); SoapySDRDevice_unmake(dev); From 846545ab2115c4b4a1f941d9abebe0411f769860 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Thu, 16 Mar 2017 19:57:18 +0000 Subject: [PATCH 05/17] Fix multi-channel bug. --- src/rtl_sdr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index cd8a818..d6c9757 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -208,6 +208,9 @@ int main(int argc, char **argv) if (nchan > 0) { channels = calloc(nchan, sizeof(size_t)); + for(ch = 0; ch < nchan; ch++) { + channels[ch] = ch; + } } else { channels = NULL; } From feac5f13eda817334b0a487d8b72c19a228acc36 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sun, 19 Mar 2017 13:15:02 +0000 Subject: [PATCH 06/17] Add optional bandwidth arg. --- src/convenience/convenience.h | 7 +++++++ src/rtl_sdr.c | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/convenience/convenience.h b/src/convenience/convenience.h index 511a6ba..93b30cb 100644 --- a/src/convenience/convenience.h +++ b/src/convenience/convenience.h @@ -77,6 +77,7 @@ int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency, size_t chan); * * \param dev the device handle * \param samp_rate in samples/second + * \param chan the channel humber * \return 0 on success */ @@ -87,6 +88,7 @@ int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate, size_t chan * * \param dev the device handle * \param frequency in Hz + * \param chan the channel humber * \return 0 on success */ @@ -116,6 +118,7 @@ int verbose_offset_tuning(SoapySDRDevice *dev); * Enable auto gain and report status on stderr * * \param dev the device handle + * \param chan the channel humber * \return 0 on success */ @@ -126,6 +129,7 @@ int verbose_auto_gain(SoapySDRDevice *dev, size_t chan); * * \param dev the device handle * \param gain in tenths of a dB + * \param chan the channel humber * \return 0 on success */ @@ -136,6 +140,7 @@ int verbose_gain_set(SoapySDRDevice *dev, int gain, size_t chan); * * \param dev the device handle * \param gain_str string of gain element pairs (example LNA=40,VGA=20,AMP=0), or string of overall gain, in dB + * \param chan the channel humber * \return 0 on success */ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan); @@ -145,6 +150,7 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan); * * \param dev the device handle * \param ppm_error correction value in parts per million (ppm) + * \param chan the channel humber * \return 0 on success */ @@ -155,6 +161,7 @@ int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error, size_t chan); * * \param dev the device handle * \param ant string name of the antenna to use + * \param chan the channel humber * \return 0 on success */ diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index d6c9757..54efa32 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -102,7 +102,8 @@ int main(int argc, char **argv) FILE *file_ch1; int16_t *buffer_ch0; int16_t *buffer_ch1; - + double bw = -1; + uint8_t *buf8 = NULL; float *fbuf = NULL; // assumed 32-bit char *dev_query = NULL; @@ -115,7 +116,7 @@ int main(int argc, char **argv) size_t nchan = 0; size_t ch; - while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:A:N:")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:A:N:B:")) != -1) { switch (opt) { case 'd': dev_query = optarg; @@ -145,6 +146,9 @@ int main(int argc, char **argv) case 'A': ant = optarg; break; + case 'B': + bw = atofs(optarg); + break; case 'N': nchan = atoi(optarg); break; @@ -242,13 +246,18 @@ int main(int argc, char **argv) verbose_direct_sampling(dev, direct_sampling); } + if (bw < 0) { + bw = 0.9 * samp_rate; + } /* Set the sample rate */ /* Set the frequency */ /* Set the antenna */ + /* Set the bandwidth */ if (channels == NULL) { verbose_set_sample_rate(dev, samp_rate, 0); verbose_set_frequency(dev, frequency, 0); verbose_set_antenna(dev, ant, 0); + verbose_set_bandwidth(dev, bw, 0); if (NULL == gain_str) { /* Enable automatic gain */ verbose_auto_gain(dev, 0); @@ -262,6 +271,7 @@ int main(int argc, char **argv) verbose_set_sample_rate(dev, samp_rate, channels[ch]); verbose_set_frequency(dev, frequency, channels[ch]); verbose_set_antenna(dev, ant, channels[ch]); + verbose_set_bandwidth(dev, bw, channels[ch]); if (NULL == gain_str) { /* Enable automatic gain */ verbose_auto_gain(dev, channels[ch]); From ad5f35563f1e7bc2d05a363b47706669a4d3511b Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sun, 19 Mar 2017 15:32:23 +0000 Subject: [PATCH 07/17] Make sample count a 64 bit variable. --- src/rtl_sdr.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 54efa32..c4f3af8 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -42,7 +42,7 @@ #define MAXIMAL_BUF_LENGTH (256 * 16384) static int do_exit = 0; -static uint32_t samples_to_read = 0; +static uint64_t samples_to_read = 0; static SoapySDRDevice *dev = NULL; static SoapySDRStream *stream = NULL; @@ -62,6 +62,7 @@ void usage(void) "\t[-D direct_sampling_mode, 0 (default/off), 1 (I), 2 (Q), 3 (no-mod)]\n" "\t[-A Name of antenna to use]\n" "\t[-N Number of receive channels to use]\n" + "\t[-B Bandwidth of HW receive channel to use]\n" "\tfilename0 filename1 (a '-' dumps samples to stdout)\n\n"); exit(1); } @@ -92,7 +93,7 @@ int main(int argc, char **argv) #endif char *filename0 = NULL; char *filename1 = NULL; - int n_read; + int64_t n_read; int r, opt; char *gain_str = NULL; int ppm_error = 0; @@ -138,7 +139,7 @@ int main(int argc, char **argv) break; case 'n': // half of I/Q pair count (double for one each of I and Q) - samples_to_read = (uint32_t)atofs(optarg) * 2; + samples_to_read = (uint64_t)atofs(optarg) * 2; break; case 'S': sync_mode = 1; @@ -324,7 +325,7 @@ int main(int argc, char **argv) int flags = 0; long long timeNs = 0; long timeoutNs = 1000000; - int n_read = 0, r, i; + int64_t n_read = 0, r, i; r = SoapySDRDevice_readStream(dev, stream, buffs, out_block_size, &flags, &timeNs, timeoutNs); @@ -341,7 +342,7 @@ int main(int argc, char **argv) fprintf(stderr, "WARNING: sync read failed. %d\n", r); } - if ((samples_to_read > 0) && (samples_to_read < (uint32_t)n_read)) { + if ((samples_to_read > 0) && (samples_to_read < (uint64_t)n_read)) { n_read = samples_to_read; do_exit = 1; } From f52eb76320c0fa99f1e50d769b85392713827351 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sat, 25 Mar 2017 09:28:30 +0000 Subject: [PATCH 08/17] Add the channel aware long options. --- src/rtl_sdr.c | 301 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 193 insertions(+), 108 deletions(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 54efa32..b1f532d 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -25,6 +25,7 @@ #ifndef _WIN32 #include +#include #else #include #include @@ -40,6 +41,7 @@ #define DEFAULT_BUF_LENGTH (16 * 16384) #define MINIMAL_BUF_LENGTH 512 #define MAXIMAL_BUF_LENGTH (256 * 16384) +#define MAX_NUM_CHANNELS (8) static int do_exit = 0; static uint32_t samples_to_read = 0; @@ -50,19 +52,25 @@ void usage(void) { fprintf(stderr, "rx_sdr (based on rtl_sdr), an I/Q recorder for RTL2832 based DVB-T receivers\n\n" - "Usage:\t -f frequency_to_tune_to [Hz]\n" - "\t[-s samplerate (default: 2048000 Hz)]\n" + "Usage:\t -f/--freq frequency_to_tune_to [Hz]\n" + "\t[-s/--srate samplerate (default: 2048000 Hz)]\n" "\t[-d device key/value query (ex: 0, 1, driver=rtlsdr, driver=hackrf)]\n" - "\t[-g tuner gain(s) (ex: 20, 40, LNA=40,VGA=20,AMP=0)]\n" + "\t[-g/--gain tuner gain(s) (ex: 20, 40, LNA=40,VGA=20,AMP=0)]\n" "\t[-p ppm_error (default: 0)]\n" "\t[-b output_block_size (default: 16 * 16384)]\n" "\t[-n number of samples to read (default: 0, infinite)]\n" "\t[-F output format, CU8|CS8|CS16|CF32 (default: CU8)]\n" "\t[-S force sync output (default: async)]\n" "\t[-D direct_sampling_mode, 0 (default/off), 1 (I), 2 (Q), 3 (no-mod)]\n" - "\t[-A Name of antenna to use]\n" + "\t[-A/--Antenna ant Name of antenna to use]\n" + "\t[-B/--Bandwidth bw Receiver bandwidth to use]\n" "\t[-N Number of receive channels to use]\n" - "\tfilename0 filename1 (a '-' dumps samples to stdout)\n\n"); + "\tfilename0 [filename1.....] (a '-' dumps samples to stdout)\n" + "\n" + "\tAll long options have optional channel number, so --gain3 10 sets the\n" + "\tgain of channel 3 (starting from 0) to be '10'. -g/--gain would set the gain\n" + "\tof all the channels, for example.\n\n" + ); exit(1); } @@ -90,45 +98,121 @@ int main(int argc, char **argv) #ifndef _WIN32 struct sigaction sigact; #endif - char *filename0 = NULL; - char *filename1 = NULL; + char *filename[MAX_NUM_CHANNELS]; int n_read; int r, opt; - char *gain_str = NULL; + char *gain_str[MAX_NUM_CHANNELS]; int ppm_error = 0; int sync_mode = 0; int direct_sampling = 0; - FILE *file_ch0; - FILE *file_ch1; - int16_t *buffer_ch0; - int16_t *buffer_ch1; - double bw = -1; + FILE *file_ch[MAX_NUM_CHANNELS]; + int16_t *buffer_ch[MAX_NUM_CHANNELS]; + double bw[MAX_NUM_CHANNELS]; uint8_t *buf8 = NULL; float *fbuf = NULL; // assumed 32-bit char *dev_query = NULL; - uint32_t frequency = 100000000; - uint32_t samp_rate = DEFAULT_SAMPLE_RATE; + uint32_t frequency[MAX_NUM_CHANNELS]; + uint32_t samp_rate[MAX_NUM_CHANNELS]; uint32_t out_block_size = DEFAULT_BUF_LENGTH; char *output_format = SOAPY_SDR_CU8; - char * ant = NULL; + char * ant[MAX_NUM_CHANNELS]; size_t * channels; size_t nchan = 0; size_t ch; + struct option *lg_opts = NULL; + char * base_opt[] = {"freq", "gain", "srate", "Ant", "Bandwidth"}; + int o, count; + int option_idx; - while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:D:SF:A:N:B:")) != -1) { + lg_opts = malloc(sizeof(struct option) * (MAX_NUM_CHANNELS * (sizeof(base_opt) / sizeof(char *) + 2))); + + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + filename[ch] = NULL; + gain_str[ch] = NULL; + file_ch[ch] = NULL; + buffer_ch[ch] = NULL; + bw[ch] = -1; + frequency[ch] = 40000000; + samp_rate[ch] = DEFAULT_SAMPLE_RATE; + ant[ch] = NULL; + } + + count = 0; + for (o = 0; o < sizeof(base_opt) / sizeof(char *); o++) { + char * tmp_name; + + lg_opts[count].name = base_opt[o]; + lg_opts[count].has_arg = 1; + lg_opts[count].flag = NULL; + lg_opts[count].val = base_opt[0][0]; + count++; + for(ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + tmp_name = malloc(strlen(base_opt[o]) + 10); + if (MAX_NUM_CHANNELS > 9) { + snprintf(tmp_name, strlen(base_opt[o]) + 10, "%s%02d", base_opt[o], ch); + } else { + snprintf(tmp_name, strlen(base_opt[o]) + 10, "%s%d", base_opt[o], ch); + } + lg_opts[count].name = tmp_name; + lg_opts[count].has_arg = 1; + lg_opts[count].flag = NULL; + lg_opts[count].val = 0; + count++; + } + + } + lg_opts[count].name = NULL; + lg_opts[count].has_arg = 0; + lg_opts[count].flag = NULL; + lg_opts[count].val = 0; + + while ((opt = getopt_long(argc, argv, "d:f:g:s:b:n:p:D:SF:A:N:B:", lg_opts, &option_idx)) != -1) { switch (opt) { + case 0: + printf("We got %s\n", lg_opts[option_idx].name); + for (o = 0; o < sizeof(base_opt) / sizeof(char *); o++) { + if (strncmp(base_opt[o], lg_opts[option_idx].name, strlen(base_opt[o])) == 0) { + sscanf(&lg_opts[option_idx].name[strlen(base_opt[o])], "%d", &ch); + printf(" for channel %d\n", ch); + + switch (base_opt[o][0]) { + case 'f': + frequency[ch] = (uint32_t)atofs(optarg); + break; + case 'g': + gain_str[ch] = optarg; + break; + case 's': + samp_rate[ch] = (uint32_t)atofs(optarg); + break; + case 'A': + ant[ch] = optarg; + break; + case 'B': + bw[ch] = atofs(optarg); + break; + } + } + } + break; case 'd': dev_query = optarg; break; case 'f': - frequency = (uint32_t)atofs(optarg); + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + frequency[ch] = (uint32_t)atofs(optarg); + } break; case 'g': - gain_str = optarg; + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + gain_str[ch] = optarg; + } break; case 's': - samp_rate = (uint32_t)atofs(optarg); + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + samp_rate[ch] = (uint32_t)atofs(optarg); + } break; case 'p': ppm_error = atoi(optarg); @@ -144,10 +228,14 @@ int main(int argc, char **argv) sync_mode = 1; break; case 'A': - ant = optarg; + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + ant[ch] = optarg; + } break; case 'B': - bw = atofs(optarg); + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + bw[ch] = atofs(optarg); + } break; case 'N': nchan = atoi(optarg); @@ -176,15 +264,12 @@ int main(int argc, char **argv) } } - if (argc <= optind) { + if (argc <= optind + nchan) { usage(); } else { - filename0 = argv[optind]; - if (argc > optind) { - filename1 = argv[optind+1]; - } else { - filename1 = NULL; - } + for (ch = 0; ch < nchan; ch++) { + filename[ch] = argv[optind + ch]; + } } if(out_block_size < MINIMAL_BUF_LENGTH || @@ -198,9 +283,10 @@ int main(int argc, char **argv) out_block_size = DEFAULT_BUF_LENGTH; } - buffer_ch0 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); - buffer_ch1 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); - + for(ch = 0; ch < nchan; ch++) { + buffer_ch[ch] = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); + } + if (output_format == SOAPY_SDR_CS8 || output_format == SOAPY_SDR_CU8) { buf8 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS8)); } else if (output_format == SOAPY_SDR_CF32) { @@ -246,38 +332,41 @@ int main(int argc, char **argv) verbose_direct_sampling(dev, direct_sampling); } - if (bw < 0) { - bw = 0.9 * samp_rate; + for(ch = 0; ch < nchan; ch++) { + if (bw[ch] < 0) { + bw[ch] = 0.9 * samp_rate[ch]; + } } + /* Set the sample rate */ /* Set the frequency */ /* Set the antenna */ /* Set the bandwidth */ if (channels == NULL) { - verbose_set_sample_rate(dev, samp_rate, 0); - verbose_set_frequency(dev, frequency, 0); - verbose_set_antenna(dev, ant, 0); - verbose_set_bandwidth(dev, bw, 0); + verbose_set_sample_rate(dev, samp_rate[0], 0); + verbose_set_frequency(dev, frequency[0], 0); + verbose_set_antenna(dev, ant[0], 0); + verbose_set_bandwidth(dev, bw[0], 0); if (NULL == gain_str) { /* Enable automatic gain */ verbose_auto_gain(dev, 0); } else { /* Enable manual gain */ - verbose_gain_str_set(dev, gain_str, 0); + verbose_gain_str_set(dev, gain_str[0], 0); } verbose_ppm_set(dev, ppm_error, 0); } else { for(ch = 0; ch < nchan; ch++) { - verbose_set_sample_rate(dev, samp_rate, channels[ch]); - verbose_set_frequency(dev, frequency, channels[ch]); - verbose_set_antenna(dev, ant, channels[ch]); - verbose_set_bandwidth(dev, bw, channels[ch]); + verbose_set_sample_rate(dev, samp_rate[ch], channels[ch]); + verbose_set_frequency(dev, frequency[ch], channels[ch]); + verbose_set_antenna(dev, ant[ch], channels[ch]); + verbose_set_bandwidth(dev, bw[ch], channels[ch]); if (NULL == gain_str) { /* Enable automatic gain */ verbose_auto_gain(dev, channels[ch]); } else { /* Enable manual gain */ - verbose_gain_str_set(dev, gain_str, channels[ch]); + verbose_gain_str_set(dev, gain_str[ch], channels[ch]); } verbose_ppm_set(dev, ppm_error, channels[ch]); @@ -285,29 +374,20 @@ int main(int argc, char **argv) } - if(strcmp(filename0, "-") == 0) { /* Write samples to stdout */ - file_ch0 = stdout; + for(ch = 0; ch < nchan; ch++) { + if(strcmp(filename[ch], "-") == 0) { /* Write samples to stdout */ + file_ch[ch] = stdout; #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif - } else { - file_ch0 = fopen(filename0, "wb"); - if (!file_ch0) { - fprintf(stderr, "Failed to open %s\n", filename0); + } else { + file_ch[ch] = fopen(filename[ch], "wb"); + if (!file_ch[ch]) { + fprintf(stderr, "Failed to open %s\n", filename[ch]); goto out; } - if (filename1 != NULL) { - file_ch1 = fopen(filename1, "wb"); - if (!file_ch1) { - fprintf(stderr, "Failed to open %s\n", filename1); - goto out; - } - } else { - file_ch1 = NULL; - } - + } } - /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dev); @@ -320,13 +400,13 @@ int main(int argc, char **argv) } suppress_stdout_stop(tmp_stdout); while (!do_exit) { - void *buffs[] = {buffer_ch0, buffer_ch1}; int flags = 0; long long timeNs = 0; long timeoutNs = 1000000; int n_read = 0, r, i; - r = SoapySDRDevice_readStream(dev, stream, buffs, out_block_size, &flags, &timeNs, timeoutNs); + r = SoapySDRDevice_readStream(dev, stream, (void *) buffer_ch, out_block_size, + &flags, &timeNs, timeoutNs); //fprintf(stderr, "readStream ret=%d, flags=%d, timeNs=%lld\n", r, flags, timeNs); if (r >= 0) { @@ -347,47 +427,42 @@ int main(int argc, char **argv) } // TODO: read these formats natively from SoapySDR (setupStream) instead of converting ourselves? - if (output_format == SOAPY_SDR_CS16) { - // The "native" format we read in, write out no conversion needed - // (Always reading in CS16 to support >8-bit devices) - if (fwrite(buffer_ch0, sizeof(int16_t), n_read, file_ch0) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; - } - if (file_ch1 != NULL) { - if (fwrite(buffer_ch1, sizeof(int16_t), n_read, file_ch1) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; - } - } - - } else if (output_format == SOAPY_SDR_CS8) { - for (i = 0; i < n_read; ++i) { - buf8[i] = ( (int16_t)buffer_ch0[i] / 32767.0 * 128.0 + 0.4); - } - if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch0) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; - } - } else if (output_format == SOAPY_SDR_CU8) { - for (i = 0; i < n_read; ++i) { - buf8[i] = ( (int16_t)buffer_ch0[i] / 32767.0 * 128.0 + 127.4); - } - if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch0) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; - } - } else if (output_format == SOAPY_SDR_CF32) { - for (i = 0; i < n_read; ++i) { - fbuf[i] = buffer_ch0[i] * 1.0f / SHRT_MAX; - } - if (fwrite(fbuf, sizeof(float), n_read, file_ch0) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; - } + for(ch = 0; ch < nchan; ch++) { + if (output_format == SOAPY_SDR_CS16) { + // The "native" format we read in, write out no conversion needed + // (Always reading in CS16 to support >8-bit devices) + if (fwrite(buffer_ch[ch], sizeof(int16_t), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + break; + } + + } else if (output_format == SOAPY_SDR_CS8) { + for (i = 0; i < n_read; ++i) { + buf8[i] = ( (int16_t)buffer_ch[ch][i] / 32767.0 * 128.0 + 0.4); + } + if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + break; + } + } else if (output_format == SOAPY_SDR_CU8) { + for (i = 0; i < n_read; ++i) { + buf8[i] = ( (int16_t)buffer_ch[ch][i] / 32767.0 * 128.0 + 127.4); + } + if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + break; + } + } else if (output_format == SOAPY_SDR_CF32) { + for (i = 0; i < n_read; ++i) { + fbuf[i] = buffer_ch[ch][i] * 1.0f / SHRT_MAX; + } + if (fwrite(fbuf, sizeof(float), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + break; + } + } } - // TODO: hmm.. n_read 8192, but out_block_size (16 * 16384) is much larger TODO: loop? or accept 8192? rtl_fm ok with it /* if ((uint32_t)n_read < out_block_size) { @@ -406,17 +481,27 @@ int main(int argc, char **argv) else fprintf(stderr, "\nLibrary error %d, exiting...\n", r); - if (file_ch0 != stdout) - fclose(file_ch0); - if (file_ch1 != NULL) { - fclose(file_ch1); + for(ch = 0; ch < nchan; ch++) { + if (file_ch[ch] != stdout) { + fclose(file_ch[ch]); + } } SoapySDRDevice_deactivateStream(dev, stream, 0, 0); SoapySDRDevice_closeStream(dev, stream); SoapySDRDevice_unmake(dev); - free (buffer_ch0); - free(buffer_ch1); + + for(ch = 0; ch < nchan; ch++) { + free(buffer_ch[ch]); + } + + if (buf8 != NULL) { + free(buf8); + } + + if (fbuf != NULL) { + free(fbuf); + } out: return r >= 0 ? r : -r; } From dbe51b51ad062522f9af3a8067b8d96ee3d93977 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sat, 25 Mar 2017 09:36:05 +0000 Subject: [PATCH 09/17] Check all mallocs actually worked. --- src/rtl_sdr.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 20fffd9..1349de6 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -127,6 +127,10 @@ int main(int argc, char **argv) int option_idx; lg_opts = malloc(sizeof(struct option) * (MAX_NUM_CHANNELS * (sizeof(base_opt) / sizeof(char *) + 2))); + if (lg_opts == NULL) { + fprintf(stderr, "Failed to malloc data for lg_opts!!\n"); + exit(10); + } for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { filename[ch] = NULL; @@ -150,6 +154,11 @@ int main(int argc, char **argv) count++; for(ch = 0; ch < MAX_NUM_CHANNELS; ch++) { tmp_name = malloc(strlen(base_opt[o]) + 10); + if (tmp_name == NULL) { + fprintf(stderr, "Failed to malloc data for tmp_name!!\n"); + exit(10); + } + if (MAX_NUM_CHANNELS > 9) { snprintf(tmp_name, strlen(base_opt[o]) + 10, "%s%02d", base_opt[o], ch); } else { @@ -286,12 +295,24 @@ int main(int argc, char **argv) for(ch = 0; ch < nchan; ch++) { buffer_ch[ch] = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); + if (buffer_ch[ch] == NULL) { + fprintf(stderr, "Failed to malloc data for buffer_ch[%d]!!\n", ch); + exit(10); + } } if (output_format == SOAPY_SDR_CS8 || output_format == SOAPY_SDR_CU8) { buf8 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS8)); + if (buf8 == NULL) { + fprintf(stderr, "Failed to malloc data for buf8!!\n"); + exit(10); + } } else if (output_format == SOAPY_SDR_CF32) { fbuf = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CF32)); + if (fbuf == NULL) { + fprintf(stderr, "Failed to malloc data for fbuf!!\n"); + exit(10); + } } int tmp_stdout = suppress_stdout_start(); @@ -299,6 +320,10 @@ int main(int argc, char **argv) if (nchan > 0) { channels = calloc(nchan, sizeof(size_t)); + if (channels == NULL) { + fprintf(stderr, "Failed to malloc data for channels!!\n"); + exit(10); + } for(ch = 0; ch < nchan; ch++) { channels[ch] = ch; } From 583f965e1b4a520edb841df287c0001a5b8268c4 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sat, 25 Mar 2017 10:21:59 +0000 Subject: [PATCH 10/17] Fix issue with counting args --- src/rtl_sdr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 1349de6..fa785f0 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -180,11 +180,9 @@ int main(int argc, char **argv) while ((opt = getopt_long(argc, argv, "d:f:g:s:b:n:p:D:SF:A:N:B:", lg_opts, &option_idx)) != -1) { switch (opt) { case 0: - printf("We got %s\n", lg_opts[option_idx].name); for (o = 0; o < sizeof(base_opt) / sizeof(char *); o++) { if (strncmp(base_opt[o], lg_opts[option_idx].name, strlen(base_opt[o])) == 0) { sscanf(&lg_opts[option_idx].name[strlen(base_opt[o])], "%d", &ch); - printf(" for channel %d\n", ch); switch (base_opt[o][0]) { case 'f': @@ -269,12 +267,14 @@ int main(int argc, char **argv) direct_sampling = atoi(optarg); break; default: + printf("unknown option! - %d\n", opt); usage(); break; } } - if (argc <= optind + nchan) { + if (argc != optind + nchan) { + printf("\nNot enough args for channel count\n\n"); usage(); } else { for (ch = 0; ch < nchan; ch++) { From ab2afa5e2bbfd0b1b535e30ed5df3ab615cc3df6 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sat, 25 Mar 2017 20:52:33 +0000 Subject: [PATCH 11/17] Handle case of failed write --- src/rtl_sdr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index fa785f0..adb9c80 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -459,7 +459,7 @@ int main(int argc, char **argv) // (Always reading in CS16 to support >8-bit devices) if (fwrite(buffer_ch[ch], sizeof(int16_t), n_read, file_ch[ch]) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; + do_exit = 1; } } else if (output_format == SOAPY_SDR_CS8) { @@ -468,7 +468,7 @@ int main(int argc, char **argv) } if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; + do_exit = 1; } } else if (output_format == SOAPY_SDR_CU8) { for (i = 0; i < n_read; ++i) { @@ -476,7 +476,7 @@ int main(int argc, char **argv) } if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; + do_exit = 1; } } else if (output_format == SOAPY_SDR_CF32) { for (i = 0; i < n_read; ++i) { @@ -484,7 +484,7 @@ int main(int argc, char **argv) } if (fwrite(fbuf, sizeof(float), n_read, file_ch[ch]) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); - break; + do_exit = 1; } } } From 5704bc072d306585b35833197927d76a4c7a2a4b Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Mon, 27 Mar 2017 08:21:47 +0100 Subject: [PATCH 12/17] Fix indentation. Add channel number to log statements. --- src/convenience/convenience.c | 63 +++--- src/rtl_sdr.c | 372 +++++++++++++++++----------------- 2 files changed, 219 insertions(+), 216 deletions(-) diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c index 6ae2cfa..b038312 100644 --- a/src/convenience/convenience.c +++ b/src/convenience/convenience.c @@ -42,22 +42,22 @@ #ifdef _MSC_VER struct tm *localtime_r (const time_t *timer, struct tm *result) { - struct tm *local_result = localtime (timer); - if (local_result == NULL || result == NULL) return NULL; - memcpy (result, local_result, sizeof (struct tm)); - return result; + struct tm *local_result = localtime (timer); + if (local_result == NULL || result == NULL) return NULL; + memcpy (result, local_result, sizeof (struct tm)); + return result; } //http://unixpapa.com/incnote/string.html char * strsep(char **sp, char *sep) { - char *p, *s; - if (sp == NULL || *sp == NULL || **sp == '\0') return(NULL); - s = *sp; - p = s + strcspn(s, sep); - if (*p != '\0') *p++ = '\0'; - *sp = p; - return(s); + char *p, *s; + if (sp == NULL || *sp == NULL || **sp == '\0') return(NULL); + s = *sp; + p = s + strcspn(s, sep); + if (*p != '\0') *p++ = '\0'; + *sp = p; + return(s); } #endif @@ -137,13 +137,13 @@ double atofp(char *s) int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency, size_t chan) { int r; - + SoapySDRKwargs args = {0}; r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, chan, (double)frequency, &args); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set center freq. (chan 0)\n"); + fprintf(stderr, "WARNING: Failed to set center freq. for chan %zd\n", chan); } else { - fprintf(stderr, "Tuned to %u Hz.\n", frequency); + fprintf(stderr, "Tuned to %u Hz on channel %zd.\n", frequency, chan); } return r; @@ -153,16 +153,16 @@ int verbose_set_antenna(SoapySDRDevice *dev, const char * ant, size_t chan) { int r; if (ant != NULL) { - r = (int)SoapySDRDevice_setAntenna(dev, SOAPY_SDR_RX, chan, ant); + r = (int)SoapySDRDevice_setAntenna(dev, SOAPY_SDR_RX, chan, ant); } else { - r = 0; + r = 0; } if (r != 0) { - fprintf(stderr, "WARNING: Failed to set antenna.\n"); + fprintf(stderr, "WARNING: Failed to set antenna for chan %zd.\n", chan); } else { char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, chan); - fprintf(stderr, "****Antenna set to %s\n", antval); + fprintf(stderr, "****Antenna set to %s on chan %zd\n", antval, chan); } return r; @@ -173,9 +173,9 @@ int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate, size_t chan int r; r = (int)SoapySDRDevice_setSampleRate(dev, SOAPY_SDR_RX, chan, (double)samp_rate); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set sample rate.\n"); + fprintf(stderr, "WARNING: Failed to set sample rate for chan %zd.\n", chan); } else { - fprintf(stderr, "Sampling at %u S/s.\n", samp_rate); + fprintf(stderr, "Sampling at %u S/s on chan %zd.\n", samp_rate, chan); } return r; @@ -187,15 +187,17 @@ int verbose_set_bandwidth(SoapySDRDevice *dev, uint32_t bandwidth, size_t chan) r = (int)SoapySDRDevice_setBandwidth(dev, SOAPY_SDR_RX, chan, (double)bandwidth); uint32_t applied_bw = 0; if (r != 0) { - fprintf(stderr, "WARNING: Failed to set bandwidth.\n"); + fprintf(stderr, "WARNING: Failed to set bandwidth on chan %zd.\n", chan); } else if (bandwidth > 0) { applied_bw = (uint32_t)SoapySDRDevice_getBandwidth(dev, SOAPY_SDR_RX, chan); if (applied_bw) - fprintf(stderr, "Bandwidth parameter %u Hz resulted in %u Hz.\n", bandwidth, applied_bw); + fprintf(stderr, "Bandwidth parameter %u Hz resulted in %u Hz on chan %zd.\n", + bandwidth, applied_bw, chan); else - fprintf(stderr, "Set bandwidth parameter %u Hz.\n", bandwidth); + fprintf(stderr, "Set bandwidth parameter %u Hz on chan %zd.\n", bandwidth, chan); } else { - fprintf(stderr, "Bandwidth set to automatic resulted in %u Hz.\n", applied_bw); + fprintf(stderr, "Bandwidth set to automatic resulted in %u Hz on chan %zd.\n", + applied_bw, chan); } return r; } @@ -322,10 +324,11 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan) char *name = args.keys[i]; double value = atof(args.vals[i]); - fprintf(stderr, "Setting gain element %s: %f dB\n", name, value); + fprintf(stderr, "Setting gain element %s: %f dB on chan %zd\n", name, value, chan); r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, chan, name, value); if (r != 0) { - fprintf(stderr, "WARNING: setGainElement(%s, %f) failed: %d\n", name, value, r); + fprintf(stderr, "WARNING: setGainElement(%s, %f, %zd) failed: %d\n", + name, value, chan, r); } } @@ -334,9 +337,9 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan) double value = atof(gain_str); r = SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, chan, value); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); + fprintf(stderr, "WARNING: Failed to set tuner gain for chan %zd.\n", chan); } else { - fprintf(stderr, "Tuner gain set to %0.2f dB.\n", value); + fprintf(stderr, "Tuner gain set to %0.2f dB on chan %zd.\n", value, chan); } // TODO: read back and print each individual getGainElement()s @@ -352,9 +355,9 @@ int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error, size_t chan) return 0;} r = (int)SoapySDRDevice_setFrequencyComponent(dev, SOAPY_SDR_RX, chan, "CORR", (double)ppm_error, NULL); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set ppm error.\n"); + fprintf(stderr, "WARNING: Failed to set ppm error for chan %zd.\n", chan); } else { - fprintf(stderr, "Tuner error set to %i ppm.\n", ppm_error); + fprintf(stderr, "Tuner error set to %i ppm for chan %zd.\n", ppm_error, chan); } return r; } diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index adb9c80..0f6b21f 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -128,49 +128,49 @@ int main(int argc, char **argv) lg_opts = malloc(sizeof(struct option) * (MAX_NUM_CHANNELS * (sizeof(base_opt) / sizeof(char *) + 2))); if (lg_opts == NULL) { - fprintf(stderr, "Failed to malloc data for lg_opts!!\n"); - exit(10); + fprintf(stderr, "Failed to malloc data for lg_opts!!\n"); + exit(10); } for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { - filename[ch] = NULL; - gain_str[ch] = NULL; - file_ch[ch] = NULL; - buffer_ch[ch] = NULL; - bw[ch] = -1; - frequency[ch] = 40000000; - samp_rate[ch] = DEFAULT_SAMPLE_RATE; - ant[ch] = NULL; + filename[ch] = NULL; + gain_str[ch] = NULL; + file_ch[ch] = NULL; + buffer_ch[ch] = NULL; + bw[ch] = -1; + frequency[ch] = 40000000; + samp_rate[ch] = DEFAULT_SAMPLE_RATE; + ant[ch] = NULL; } count = 0; for (o = 0; o < sizeof(base_opt) / sizeof(char *); o++) { - char * tmp_name; - - lg_opts[count].name = base_opt[o]; - lg_opts[count].has_arg = 1; - lg_opts[count].flag = NULL; - lg_opts[count].val = base_opt[0][0]; - count++; - for(ch = 0; ch < MAX_NUM_CHANNELS; ch++) { - tmp_name = malloc(strlen(base_opt[o]) + 10); - if (tmp_name == NULL) { - fprintf(stderr, "Failed to malloc data for tmp_name!!\n"); - exit(10); - } - - if (MAX_NUM_CHANNELS > 9) { - snprintf(tmp_name, strlen(base_opt[o]) + 10, "%s%02d", base_opt[o], ch); - } else { - snprintf(tmp_name, strlen(base_opt[o]) + 10, "%s%d", base_opt[o], ch); - } - lg_opts[count].name = tmp_name; - lg_opts[count].has_arg = 1; - lg_opts[count].flag = NULL; - lg_opts[count].val = 0; - count++; - } - + char * tmp_name; + + lg_opts[count].name = base_opt[o]; + lg_opts[count].has_arg = 1; + lg_opts[count].flag = NULL; + lg_opts[count].val = base_opt[0][0]; + count++; + for(ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + tmp_name = malloc(strlen(base_opt[o]) + 10); + if (tmp_name == NULL) { + fprintf(stderr, "Failed to malloc data for tmp_name!!\n"); + exit(10); + } + + if (MAX_NUM_CHANNELS > 9) { + snprintf(tmp_name, strlen(base_opt[o]) + 10, "%s%02d", base_opt[o], ch); + } else { + snprintf(tmp_name, strlen(base_opt[o]) + 10, "%s%d", base_opt[o], ch); + } + lg_opts[count].name = tmp_name; + lg_opts[count].has_arg = 1; + lg_opts[count].flag = NULL; + lg_opts[count].val = 0; + count++; + } + } lg_opts[count].name = NULL; lg_opts[count].has_arg = 0; @@ -180,47 +180,47 @@ int main(int argc, char **argv) while ((opt = getopt_long(argc, argv, "d:f:g:s:b:n:p:D:SF:A:N:B:", lg_opts, &option_idx)) != -1) { switch (opt) { case 0: - for (o = 0; o < sizeof(base_opt) / sizeof(char *); o++) { - if (strncmp(base_opt[o], lg_opts[option_idx].name, strlen(base_opt[o])) == 0) { - sscanf(&lg_opts[option_idx].name[strlen(base_opt[o])], "%d", &ch); - - switch (base_opt[o][0]) { - case 'f': - frequency[ch] = (uint32_t)atofs(optarg); - break; - case 'g': - gain_str[ch] = optarg; - break; - case 's': - samp_rate[ch] = (uint32_t)atofs(optarg); - break; - case 'A': - ant[ch] = optarg; - break; - case 'B': - bw[ch] = atofs(optarg); + for (o = 0; o < sizeof(base_opt) / sizeof(char *); o++) { + if (strncmp(base_opt[o], lg_opts[option_idx].name, strlen(base_opt[o])) == 0) { + sscanf(&lg_opts[option_idx].name[strlen(base_opt[o])], "%d", &ch); + + switch (base_opt[o][0]) { + case 'f': + frequency[ch] = (uint32_t)atofs(optarg); + break; + case 'g': + gain_str[ch] = optarg; + break; + case 's': + samp_rate[ch] = (uint32_t)atofs(optarg); + break; + case 'A': + ant[ch] = optarg; + break; + case 'B': + bw[ch] = atofs(optarg); + break; + } + } + } break; - } - } - } - break; case 'd': dev_query = optarg; break; case 'f': for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { - frequency[ch] = (uint32_t)atofs(optarg); + frequency[ch] = (uint32_t)atofs(optarg); } break; case 'g': for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { - gain_str[ch] = optarg; + gain_str[ch] = optarg; } break; case 's': - for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { - samp_rate[ch] = (uint32_t)atofs(optarg); - } + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + samp_rate[ch] = (uint32_t)atofs(optarg); + } break; case 'p': ppm_error = atoi(optarg); @@ -236,14 +236,14 @@ int main(int argc, char **argv) sync_mode = 1; break; case 'A': - for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { - ant[ch] = optarg; - } + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + ant[ch] = optarg; + } break; case 'B': - for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { - bw[ch] = atofs(optarg); - } + for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { + bw[ch] = atofs(optarg); + } break; case 'N': nchan = atoi(optarg); @@ -277,11 +277,11 @@ int main(int argc, char **argv) printf("\nNot enough args for channel count\n\n"); usage(); } else { - for (ch = 0; ch < nchan; ch++) { - filename[ch] = argv[optind + ch]; - } + for (ch = 0; ch < nchan; ch++) { + filename[ch] = argv[optind + ch]; + } } - + if(out_block_size < MINIMAL_BUF_LENGTH || out_block_size > MAXIMAL_BUF_LENGTH ){ fprintf(stderr, @@ -294,52 +294,52 @@ int main(int argc, char **argv) } for(ch = 0; ch < nchan; ch++) { - buffer_ch[ch] = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); - if (buffer_ch[ch] == NULL) { - fprintf(stderr, "Failed to malloc data for buffer_ch[%d]!!\n", ch); - exit(10); - } + buffer_ch[ch] = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS16)); + if (buffer_ch[ch] == NULL) { + fprintf(stderr, "Failed to malloc data for buffer_ch[%d]!!\n", ch); + exit(10); + } } if (output_format == SOAPY_SDR_CS8 || output_format == SOAPY_SDR_CU8) { buf8 = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CS8)); if (buf8 == NULL) { - fprintf(stderr, "Failed to malloc data for buf8!!\n"); - exit(10); + fprintf(stderr, "Failed to malloc data for buf8!!\n"); + exit(10); } } else if (output_format == SOAPY_SDR_CF32) { fbuf = malloc(out_block_size * SoapySDR_formatToSize(SOAPY_SDR_CF32)); if (fbuf == NULL) { - fprintf(stderr, "Failed to malloc data for fbuf!!\n"); - exit(10); + fprintf(stderr, "Failed to malloc data for fbuf!!\n"); + exit(10); } } - + int tmp_stdout = suppress_stdout_start(); // TODO: allow choosing input format, see https://www.reddit.com/r/RTLSDR/comments/4tpxv7/rx_tools_commandline_sdr_tools_for_rtlsdr_bladerf/d5ohfse?context=3 - + if (nchan > 0) { - channels = calloc(nchan, sizeof(size_t)); - if (channels == NULL) { - fprintf(stderr, "Failed to malloc data for channels!!\n"); - exit(10); - } - for(ch = 0; ch < nchan; ch++) { - channels[ch] = ch; - } + channels = calloc(nchan, sizeof(size_t)); + if (channels == NULL) { + fprintf(stderr, "Failed to malloc data for channels!!\n"); + exit(10); + } + for(ch = 0; ch < nchan; ch++) { + channels[ch] = ch; + } } else { - channels = NULL; + channels = NULL; } r = verbose_device_search(dev_query, &dev, &stream, SOAPY_SDR_CS16, channels, nchan); - + if (r != 0) { fprintf(stderr, "Failed to open rtlsdr device matching %s.\n", dev_query); exit(1); } - + fprintf(stderr, "Using output format: %s (input format %s)\n", output_format, SOAPY_SDR_CS16); - + printf("****Number of channels: %d\n", SoapySDRDevice_getNumChannels(dev, SOAPY_SDR_RX)); #ifndef _WIN32 @@ -353,15 +353,15 @@ int main(int argc, char **argv) #else SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE ); #endif - + if (direct_sampling) { verbose_direct_sampling(dev, direct_sampling); } - + for(ch = 0; ch < nchan; ch++) { - if (bw[ch] < 0) { - bw[ch] = 0.9 * samp_rate[ch]; - } + if (bw[ch] < 0) { + bw[ch] = 0.9 * samp_rate[ch]; + } } /* Set the sample rate */ @@ -375,48 +375,48 @@ int main(int argc, char **argv) verbose_set_bandwidth(dev, bw[0], 0); if (NULL == gain_str) { /* Enable automatic gain */ - verbose_auto_gain(dev, 0); + verbose_auto_gain(dev, 0); } else { - /* Enable manual gain */ - verbose_gain_str_set(dev, gain_str[0], 0); + /* Enable manual gain */ + verbose_gain_str_set(dev, gain_str[0], 0); } verbose_ppm_set(dev, ppm_error, 0); } else { - for(ch = 0; ch < nchan; ch++) { - verbose_set_sample_rate(dev, samp_rate[ch], channels[ch]); - verbose_set_frequency(dev, frequency[ch], channels[ch]); - verbose_set_antenna(dev, ant[ch], channels[ch]); - verbose_set_bandwidth(dev, bw[ch], channels[ch]); - if (NULL == gain_str) { - /* Enable automatic gain */ - verbose_auto_gain(dev, channels[ch]); - } else { - /* Enable manual gain */ - verbose_gain_str_set(dev, gain_str[ch], channels[ch]); - } - verbose_ppm_set(dev, ppm_error, channels[ch]); - - } + for(ch = 0; ch < nchan; ch++) { + verbose_set_sample_rate(dev, samp_rate[ch], channels[ch]); + verbose_set_frequency(dev, frequency[ch], channels[ch]); + verbose_set_antenna(dev, ant[ch], channels[ch]); + verbose_set_bandwidth(dev, bw[ch], channels[ch]); + if (NULL == gain_str) { + /* Enable automatic gain */ + verbose_auto_gain(dev, channels[ch]); + } else { + /* Enable manual gain */ + verbose_gain_str_set(dev, gain_str[ch], channels[ch]); + } + verbose_ppm_set(dev, ppm_error, channels[ch]); + + } } - + for(ch = 0; ch < nchan; ch++) { - if(strcmp(filename[ch], "-") == 0) { /* Write samples to stdout */ - file_ch[ch] = stdout; + if(strcmp(filename[ch], "-") == 0) { /* Write samples to stdout */ + file_ch[ch] = stdout; #ifdef _WIN32 - _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdin), _O_BINARY); #endif - } else { - file_ch[ch] = fopen(filename[ch], "wb"); - if (!file_ch[ch]) { - fprintf(stderr, "Failed to open %s\n", filename[ch]); - goto out; + } else { + file_ch[ch] = fopen(filename[ch], "wb"); + if (!file_ch[ch]) { + fprintf(stderr, "Failed to open %s\n", filename[ch]); + goto out; + } } - } } /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dev); - + if (true || sync_mode) { fprintf(stderr, "Reading samples in sync mode...\n"); SoapySDRKwargs args = {0}; @@ -430,10 +430,10 @@ int main(int argc, char **argv) long long timeNs = 0; long timeoutNs = 1000000; int64_t n_read = 0, r, i; - + r = SoapySDRDevice_readStream(dev, stream, (void *) buffer_ch, out_block_size, &flags, &timeNs, timeoutNs); - + //fprintf(stderr, "readStream ret=%d, flags=%d, timeNs=%lld\n", r, flags, timeNs); if (r >= 0) { // r is number of elements read, elements=complex pairs of 8-bits, so buffer length in bytes is twice @@ -446,88 +446,88 @@ int main(int argc, char **argv) } fprintf(stderr, "WARNING: sync read failed. %d\n", r); } - + if ((samples_to_read > 0) && (samples_to_read < (uint64_t)n_read)) { n_read = samples_to_read; do_exit = 1; } - + // TODO: read these formats natively from SoapySDR (setupStream) instead of converting ourselves? for(ch = 0; ch < nchan; ch++) { - if (output_format == SOAPY_SDR_CS16) { - // The "native" format we read in, write out no conversion needed - // (Always reading in CS16 to support >8-bit devices) - if (fwrite(buffer_ch[ch], sizeof(int16_t), n_read, file_ch[ch]) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - do_exit = 1; - } - - } else if (output_format == SOAPY_SDR_CS8) { - for (i = 0; i < n_read; ++i) { - buf8[i] = ( (int16_t)buffer_ch[ch][i] / 32767.0 * 128.0 + 0.4); - } - if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - do_exit = 1; - } - } else if (output_format == SOAPY_SDR_CU8) { - for (i = 0; i < n_read; ++i) { - buf8[i] = ( (int16_t)buffer_ch[ch][i] / 32767.0 * 128.0 + 127.4); - } - if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - do_exit = 1; - } - } else if (output_format == SOAPY_SDR_CF32) { - for (i = 0; i < n_read; ++i) { - fbuf[i] = buffer_ch[ch][i] * 1.0f / SHRT_MAX; - } - if (fwrite(fbuf, sizeof(float), n_read, file_ch[ch]) != (size_t)n_read) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - do_exit = 1; - } - } + if (output_format == SOAPY_SDR_CS16) { + // The "native" format we read in, write out no conversion needed + // (Always reading in CS16 to support >8-bit devices) + if (fwrite(buffer_ch[ch], sizeof(int16_t), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + do_exit = 1; + } + + } else if (output_format == SOAPY_SDR_CS8) { + for (i = 0; i < n_read; ++i) { + buf8[i] = ( (int16_t)buffer_ch[ch][i] / 32767.0 * 128.0 + 0.4); + } + if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + do_exit = 1; + } + } else if (output_format == SOAPY_SDR_CU8) { + for (i = 0; i < n_read; ++i) { + buf8[i] = ( (int16_t)buffer_ch[ch][i] / 32767.0 * 128.0 + 127.4); + } + if (fwrite(buf8, sizeof(uint8_t), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + do_exit = 1; + } + } else if (output_format == SOAPY_SDR_CF32) { + for (i = 0; i < n_read; ++i) { + fbuf[i] = buffer_ch[ch][i] * 1.0f / SHRT_MAX; + } + if (fwrite(fbuf, sizeof(float), n_read, file_ch[ch]) != (size_t)n_read) { + fprintf(stderr, "Short write, samples lost, exiting!\n"); + do_exit = 1; + } + } } - + // TODO: hmm.. n_read 8192, but out_block_size (16 * 16384) is much larger TODO: loop? or accept 8192? rtl_fm ok with it /* - if ((uint32_t)n_read < out_block_size) { - fprintf(stderr, "Short read, samples lost, exiting! (%d < %d)\n", n_read, out_block_size); - break; - } + if ((uint32_t)n_read < out_block_size) { + fprintf(stderr, "Short read, samples lost, exiting! (%d < %d)\n", n_read, out_block_size); + break; + } */ - + if (samples_to_read > 0) samples_to_read -= n_read; } } - + if (do_exit) fprintf(stderr, "\nUser cancel, exiting...\n"); else fprintf(stderr, "\nLibrary error %d, exiting...\n", r); - + for(ch = 0; ch < nchan; ch++) { - if (file_ch[ch] != stdout) { - fclose(file_ch[ch]); - } + if (file_ch[ch] != stdout) { + fclose(file_ch[ch]); + } } SoapySDRDevice_deactivateStream(dev, stream, 0, 0); SoapySDRDevice_closeStream(dev, stream); SoapySDRDevice_unmake(dev); - + for(ch = 0; ch < nchan; ch++) { - free(buffer_ch[ch]); + free(buffer_ch[ch]); } - + if (buf8 != NULL) { - free(buf8); + free(buf8); } - + if (fbuf != NULL) { - free(fbuf); + free(fbuf); } -out: + out: return r >= 0 ? r : -r; } From 176dc79420ae068435704cf3dc05c9373f78b2f3 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Mon, 27 Mar 2017 08:27:48 +0100 Subject: [PATCH 13/17] Use right format for size_t! --- src/convenience/convenience.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c index b038312..c8189a1 100644 --- a/src/convenience/convenience.c +++ b/src/convenience/convenience.c @@ -141,9 +141,9 @@ int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency, size_t chan) SoapySDRKwargs args = {0}; r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, chan, (double)frequency, &args); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set center freq. for chan %zd\n", chan); + fprintf(stderr, "WARNING: Failed to set center freq. for chan %zu\n", chan); } else { - fprintf(stderr, "Tuned to %u Hz on channel %zd.\n", frequency, chan); + fprintf(stderr, "Tuned to %u Hz on channel %zu.\n", frequency, chan); } return r; @@ -159,10 +159,10 @@ int verbose_set_antenna(SoapySDRDevice *dev, const char * ant, size_t chan) } if (r != 0) { - fprintf(stderr, "WARNING: Failed to set antenna for chan %zd.\n", chan); + fprintf(stderr, "WARNING: Failed to set antenna for chan %zu.\n", chan); } else { char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, chan); - fprintf(stderr, "****Antenna set to %s on chan %zd\n", antval, chan); + fprintf(stderr, "****Antenna set to %s on chan %zu\n", antval, chan); } return r; @@ -173,9 +173,9 @@ int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate, size_t chan int r; r = (int)SoapySDRDevice_setSampleRate(dev, SOAPY_SDR_RX, chan, (double)samp_rate); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set sample rate for chan %zd.\n", chan); + fprintf(stderr, "WARNING: Failed to set sample rate for chan %zu.\n", chan); } else { - fprintf(stderr, "Sampling at %u S/s on chan %zd.\n", samp_rate, chan); + fprintf(stderr, "Sampling at %u S/s on chan %zu.\n", samp_rate, chan); } return r; @@ -187,16 +187,16 @@ int verbose_set_bandwidth(SoapySDRDevice *dev, uint32_t bandwidth, size_t chan) r = (int)SoapySDRDevice_setBandwidth(dev, SOAPY_SDR_RX, chan, (double)bandwidth); uint32_t applied_bw = 0; if (r != 0) { - fprintf(stderr, "WARNING: Failed to set bandwidth on chan %zd.\n", chan); + fprintf(stderr, "WARNING: Failed to set bandwidth on chan %zu.\n", chan); } else if (bandwidth > 0) { applied_bw = (uint32_t)SoapySDRDevice_getBandwidth(dev, SOAPY_SDR_RX, chan); if (applied_bw) - fprintf(stderr, "Bandwidth parameter %u Hz resulted in %u Hz on chan %zd.\n", + fprintf(stderr, "Bandwidth parameter %u Hz resulted in %u Hz on chan %zu.\n", bandwidth, applied_bw, chan); else - fprintf(stderr, "Set bandwidth parameter %u Hz on chan %zd.\n", bandwidth, chan); + fprintf(stderr, "Set bandwidth parameter %u Hz on chan %zu.\n", bandwidth, chan); } else { - fprintf(stderr, "Bandwidth set to automatic resulted in %u Hz on chan %zd.\n", + fprintf(stderr, "Bandwidth set to automatic resulted in %u Hz on chan %zu.\n", applied_bw, chan); } return r; @@ -324,10 +324,10 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan) char *name = args.keys[i]; double value = atof(args.vals[i]); - fprintf(stderr, "Setting gain element %s: %f dB on chan %zd\n", name, value, chan); + fprintf(stderr, "Setting gain element %s: %f dB on chan %zu\n", name, value, chan); r = SoapySDRDevice_setGainElement(dev, SOAPY_SDR_RX, chan, name, value); if (r != 0) { - fprintf(stderr, "WARNING: setGainElement(%s, %f, %zd) failed: %d\n", + fprintf(stderr, "WARNING: setGainElement(%s, %f, %zu) failed: %d\n", name, value, chan, r); } @@ -337,9 +337,9 @@ int verbose_gain_str_set(SoapySDRDevice *dev, char *gain_str, size_t chan) double value = atof(gain_str); r = SoapySDRDevice_setGain(dev, SOAPY_SDR_RX, chan, value); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set tuner gain for chan %zd.\n", chan); + fprintf(stderr, "WARNING: Failed to set tuner gain for chan %zu.\n", chan); } else { - fprintf(stderr, "Tuner gain set to %0.2f dB on chan %zd.\n", value, chan); + fprintf(stderr, "Tuner gain set to %0.2f dB on chan %zu.\n", value, chan); } // TODO: read back and print each individual getGainElement()s @@ -355,9 +355,9 @@ int verbose_ppm_set(SoapySDRDevice *dev, int ppm_error, size_t chan) return 0;} r = (int)SoapySDRDevice_setFrequencyComponent(dev, SOAPY_SDR_RX, chan, "CORR", (double)ppm_error, NULL); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set ppm error for chan %zd.\n", chan); + fprintf(stderr, "WARNING: Failed to set ppm error for chan %zu.\n", chan); } else { - fprintf(stderr, "Tuner error set to %i ppm for chan %zd.\n", ppm_error, chan); + fprintf(stderr, "Tuner error set to %i ppm for chan %zu.\n", ppm_error, chan); } return r; } From e7fa18644fc22b6c12408ece3fe361a1cf5010af Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sat, 20 May 2017 09:28:14 +0100 Subject: [PATCH 14/17] Update error message. --- src/rtl_sdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index 0f6b21f..a111a34 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -334,7 +334,7 @@ int main(int argc, char **argv) r = verbose_device_search(dev_query, &dev, &stream, SOAPY_SDR_CS16, channels, nchan); if (r != 0) { - fprintf(stderr, "Failed to open rtlsdr device matching %s.\n", dev_query); + fprintf(stderr, "Failed to open SDR device matching %s.\n", dev_query); exit(1); } From 827d78b42d632f47ea9dd8dcbb1d8e580bfdbfb9 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Fri, 23 Jun 2017 15:22:08 +0100 Subject: [PATCH 15/17] Fix issue if no gain selected. --- src/rtl_sdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index a111a34..b3a74ce 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -387,7 +387,7 @@ int main(int argc, char **argv) verbose_set_frequency(dev, frequency[ch], channels[ch]); verbose_set_antenna(dev, ant[ch], channels[ch]); verbose_set_bandwidth(dev, bw[ch], channels[ch]); - if (NULL == gain_str) { + if (NULL == gain_str[ch]) { /* Enable automatic gain */ verbose_auto_gain(dev, channels[ch]); } else { From 6a68525dfcdf9af34b890046a576c7bcf145a322 Mon Sep 17 00:00:00 2001 From: Matt Nottingham Date: Sat, 24 Jun 2017 10:47:47 +0100 Subject: [PATCH 16/17] Another gain fix. --- src/rtl_sdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index b3a74ce..f8446f2 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -373,7 +373,7 @@ int main(int argc, char **argv) verbose_set_frequency(dev, frequency[0], 0); verbose_set_antenna(dev, ant[0], 0); verbose_set_bandwidth(dev, bw[0], 0); - if (NULL == gain_str) { + if (NULL == gain_str[0]) { /* Enable automatic gain */ verbose_auto_gain(dev, 0); } else { From ee206f2ce9f55705824cc6f51be8a3af6f1b9ad9 Mon Sep 17 00:00:00 2001 From: matt Date: Sun, 13 May 2018 11:17:22 +0100 Subject: [PATCH 17/17] Turn warnings into errors. --- src/convenience/convenience.c | 24 ++++++++++++++++++------ src/rtl_sdr.c | 1 + 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c index c8189a1..cfddc9f 100644 --- a/src/convenience/convenience.c +++ b/src/convenience/convenience.c @@ -141,7 +141,8 @@ int verbose_set_frequency(SoapySDRDevice *dev, uint32_t frequency, size_t chan) SoapySDRKwargs args = {0}; r = (int)SoapySDRDevice_setFrequency(dev, SOAPY_SDR_RX, chan, (double)frequency, &args); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set center freq. for chan %zu\n", chan); + fprintf(stderr, "ERROR: Failed to set center freq. for chan %zu\n", chan); + exit(10); } else { fprintf(stderr, "Tuned to %u Hz on channel %zu.\n", frequency, chan); } @@ -159,7 +160,8 @@ int verbose_set_antenna(SoapySDRDevice *dev, const char * ant, size_t chan) } if (r != 0) { - fprintf(stderr, "WARNING: Failed to set antenna for chan %zu.\n", chan); + fprintf(stderr, "ERROR: Failed to set antenna for chan %zu.\n", chan); + exit(11); } else { char * antval = SoapySDRDevice_getAntenna(dev, SOAPY_SDR_RX, chan); fprintf(stderr, "****Antenna set to %s on chan %zu\n", antval, chan); @@ -173,7 +175,8 @@ int verbose_set_sample_rate(SoapySDRDevice *dev, uint32_t samp_rate, size_t chan int r; r = (int)SoapySDRDevice_setSampleRate(dev, SOAPY_SDR_RX, chan, (double)samp_rate); if (r != 0) { - fprintf(stderr, "WARNING: Failed to set sample rate for chan %zu.\n", chan); + fprintf(stderr, "ERROR: Failed to set sample rate for chan %zu.\n", chan); + exit(12); } else { fprintf(stderr, "Sampling at %u S/s on chan %zu.\n", samp_rate, chan); } @@ -187,7 +190,8 @@ int verbose_set_bandwidth(SoapySDRDevice *dev, uint32_t bandwidth, size_t chan) r = (int)SoapySDRDevice_setBandwidth(dev, SOAPY_SDR_RX, chan, (double)bandwidth); uint32_t applied_bw = 0; if (r != 0) { - fprintf(stderr, "WARNING: Failed to set bandwidth on chan %zu.\n", chan); + fprintf(stderr, "ERROR: Failed to set bandwidth on chan %zu.\n", chan); + exit(13); } else if (bandwidth > 0) { applied_bw = (uint32_t)SoapySDRDevice_getBandwidth(dev, SOAPY_SDR_RX, chan); if (applied_bw) @@ -218,8 +222,8 @@ int verbose_direct_sampling(SoapySDRDevice *dev, int on) set_value = SoapySDRDevice_readSetting(dev, "direct_samp"); if (set_value == NULL) { - fprintf(stderr, "WARNING: Failed to set direct sampling mode.\n"); - return r; + fprintf(stderr, "ERROR: Failed to set direct sampling mode.\n"); + exit(14); } if (atoi(set_value) == 0) { fprintf(stderr, "Direct sampling mode disabled.\n");} @@ -432,6 +436,14 @@ static void show_device_info(SoapySDRDevice *dev) fprintf(stderr, "%.0f ", bandwidths[i]); } fprintf(stderr, "\n"); + + args = SoapySDRDevice_getChannelInfo(dev, direction, channel); + fprintf(stderr, "Channel info: "); + for (i = 0; i < args.size; ++i) { + fprintf(stderr, "%s=%s ", args.keys[i], args.vals[i]); + } + fprintf(stderr, "\n"); + } int suppress_stdout_start(void) { diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index f8446f2..8378f3c 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -239,6 +239,7 @@ int main(int argc, char **argv) for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) { ant[ch] = optarg; } + printf("Setting antenna to %s\n", optarg); break; case 'B': for (ch = 0; ch < MAX_NUM_CHANNELS; ch++) {