From 9f901384deda96a7dd021923841885ec1e4f2d67 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 4 Dec 2017 14:12:11 +0100 Subject: SDR: Add option to set local oscillator (LO) offset By default it is set to -1 MHz. --- docs/sdr.html | 10 +++------- src/libmobile/main_mobile.c | 4 +++- src/libsdr/sdr.c | 6 ++++-- src/libsdr/sdr_config.c | 26 ++++++++++++++++++-------- src/libsdr/sdr_config.h | 3 ++- src/libsdr/soapy.c | 9 ++++++++- src/libsdr/soapy.h | 2 +- src/libsdr/uhd.c | 22 +++++++++++++++------- src/libsdr/uhd.h | 2 +- src/tv/main.c | 4 +++- 10 files changed, 58 insertions(+), 30 deletions(-) diff --git a/docs/sdr.html b/docs/sdr.html index 03bf8e1..687a10e 100644 --- a/docs/sdr.html +++ b/docs/sdr.html @@ -77,9 +77,7 @@ In case of B-Netz, I use the following parameters: # bnetz --sdr-soapy \ --sdr-tx-gain 50 \ --sdr-rx-gain 30 \ - --sdr-bandwidth 5000000 \ --sdr-samplerate 5000000 \ - --sdr-tune-args "OFFSET=1000000" \ -s 100000 \ -k 17 @@ -89,10 +87,10 @@ In case of B-Netz, I use the following parameters: In order to change from analog sound card to SDR, you need --sdr-soapy option. In my setup I use antennas directly connected to the SDR. Being about 1-10 meters away, I use the gain as defined above. -The IF filter requires a minimum bandwidth of 5 MHz. The sample rate must be 5 MHz minimum. +The default bandwidth follows the sample rate, if not specified using --sdr-bandwidth. Higher sample rate causes more CPU, RAM and USB load. -The local oscillator frequency causes the transmitted signal to be noisy, so I shift it 1 MHz away, using an offset. +The local oscillator frequency causes the transmitted signal to be noisy, so I shift it 1 MHz away, using the default --sdr-lo-offset. The audio processing rate of 100 KHz (-s 100000) is used to generate two channels: 17 and 19. Note that channel 19 is not given here, but will be used automatically. With B-Netz, the transmitter switches from any voice channel to the paging channel (19) whenever the phone gets paged. @@ -174,9 +172,7 @@ Because C-Netz uses only odd channel numbers for 10 KHz spacing, we use channel # cnetz --sdr-soapy \ --sdr-rx-gain 50 \ --sdr-tx-gain 30 \ - --sdr-bandwidth 5000000 \ --sdr-samplerate 5000000 \ - --sdr-tune-args "OFFSET=1000000" \ -s 100000 \ -k 131 -k 135 \ -C 0,0 @@ -192,7 +188,7 @@ Give PAL 'FUBK' test image on TV channel 21. # osmotv --sdr-soapy \ --sdr-tx-gain 60 \ - --sdr-tune-args "OFFSET=-3000000" \ + --sdr-bandwidth 60000000 \ -r 13750000 \ -c 21 \ tx-fubk diff --git a/src/libmobile/main_mobile.c b/src/libmobile/main_mobile.c index 0654ae9..a66e038 100644 --- a/src/libmobile/main_mobile.c +++ b/src/libmobile/main_mobile.c @@ -43,6 +43,8 @@ #include "../libsdr/sdr_config.h" #endif +#define DEFAULT_LO_OFFSET -1000000.0 + static int got_init = 0; /* common mobile settings */ @@ -77,7 +79,7 @@ void main_mobile_init(void) { got_init = 1; #ifdef HAVE_SDR - sdr_config_init(); + sdr_config_init(DEFAULT_LO_OFFSET); #endif } diff --git a/src/libsdr/sdr.c b/src/libsdr/sdr.c index 9a33697..1333a6a 100644 --- a/src/libsdr/sdr.c +++ b/src/libsdr/sdr.c @@ -368,9 +368,11 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq display_iq_init(samplerate); display_spectrum_init(samplerate, rx_center_frequency); + PDEBUG(DSDR, DEBUG_INFO, "Using local oscillator offseet: %.0f Hz\n", sdr_config->lo_offset); + #ifdef HAVE_UHD if (sdr_config->uhd) { - rc = uhd_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, tx_center_frequency, rx_center_frequency, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth, sdr_config->uhd_tx_timestamps); + rc = uhd_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, tx_center_frequency, rx_center_frequency, sdr_config->lo_offset, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth, sdr_config->uhd_tx_timestamps); if (rc) goto error; } @@ -378,7 +380,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq #ifdef HAVE_SOAPY if (sdr_config->soapy) { - rc = soapy_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, tx_center_frequency, rx_center_frequency, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth); + rc = soapy_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, tx_center_frequency, rx_center_frequency, sdr_config->lo_offset, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth); if (rc) goto error; } diff --git a/src/libsdr/sdr_config.c b/src/libsdr/sdr_config.c index 1c2297b..8fbb87c 100644 --- a/src/libsdr/sdr_config.c +++ b/src/libsdr/sdr_config.c @@ -32,13 +32,14 @@ static int got_init = 0; extern int use_sdr; sdr_config_t *sdr_config = NULL; -void sdr_config_init(void) +void sdr_config_init(double lo_offset) { sdr_config = calloc(1, sizeof(*sdr_config)); memset(sdr_config, 0, sizeof(*sdr_config)); sdr_config->device_args = ""; sdr_config->stream_args = ""; sdr_config->tune_args = ""; + sdr_config->lo_offset = lo_offset; got_init = 1; } @@ -65,6 +66,9 @@ void sdr_config_print_help(void) printf(" --sdr-samplerate \n"); printf(" Sample rate to use with SDR. By default it equals the regular sample\n"); printf(" rate.\n"); + printf(" --sdr-lo-offset \n"); + printf(" Give frequency offset in Hz to move the local oscillator away from the\n"); + printf(" target frequency. (default = %.0f)\n", sdr_config->lo_offset); printf(" --sdr-bandwidth \n"); printf(" Give IF filter bandwidth to use. If not, sample rate is used.\n"); printf(" --sdr-rx-antenna \n"); @@ -109,13 +113,14 @@ void sdr_config_print_hotkeys(void) #define OPT_SDR_RX_GAIN 1508 #define OPT_SDR_TX_GAIN 1509 #define OPT_SDR_SAMPLERATE 1510 -#define OPT_SDR_BANDWIDTH 1511 -#define OPT_WRITE_IQ_RX_WAVE 1512 -#define OPT_WRITE_IQ_TX_WAVE 1513 -#define OPT_READ_IQ_RX_WAVE 1514 -#define OPT_READ_IQ_TX_WAVE 1515 -#define OPT_SDR_SWAP_LINKS 1516 -#define OPT_SDR_UHD_TX_TS 1517 +#define OPT_SDR_LO_OFFSET 1511 +#define OPT_SDR_BANDWIDTH 1512 +#define OPT_WRITE_IQ_RX_WAVE 1513 +#define OPT_WRITE_IQ_TX_WAVE 1514 +#define OPT_READ_IQ_RX_WAVE 1515 +#define OPT_READ_IQ_TX_WAVE 1516 +#define OPT_SDR_SWAP_LINKS 1517 +#define OPT_SDR_UHD_TX_TS 1518 struct option sdr_config_long_options[] = { {"sdr-uhd", 0, 0, OPT_SDR_UHD}, @@ -125,6 +130,7 @@ struct option sdr_config_long_options[] = { {"sdr-stream-args", 1, 0, OPT_SDR_STREAM_ARGS}, {"sdr-tune-args", 1, 0, OPT_SDR_TUNE_ARGS}, {"sdr-samplerate", 1, 0, OPT_SDR_SAMPLERATE}, + {"sdr-lo-offset", 1, 0, OPT_SDR_LO_OFFSET}, {"sdr-bandwidth", 1, 0, OPT_SDR_BANDWIDTH}, {"sdr-rx-antenna", 1, 0, OPT_SDR_RX_ANTENNA}, {"sdr-tx-antenna", 1, 0, OPT_SDR_TX_ANTENNA}, @@ -184,6 +190,10 @@ int sdr_config_opt_switch(int c, int *skip_args) sdr_config->samplerate = atoi(optarg); *skip_args += 2; break; + case OPT_SDR_LO_OFFSET: + sdr_config->lo_offset = atof(optarg); + *skip_args += 2; + break; case OPT_SDR_BANDWIDTH: sdr_config->bandwidth = atof(optarg); *skip_args += 2; diff --git a/src/libsdr/sdr_config.h b/src/libsdr/sdr_config.h index b64424d..9bfba1f 100644 --- a/src/libsdr/sdr_config.h +++ b/src/libsdr/sdr_config.h @@ -7,6 +7,7 @@ typedef struct sdr_config { *stream_args, *tune_args; int samplerate; /* ADC/DAC sample rate */ + double lo_offset; /* LO frequency offset */ double bandwidth; /* IF bandwidth */ double tx_gain, /* gain */ rx_gain; @@ -22,7 +23,7 @@ typedef struct sdr_config { extern sdr_config_t *sdr_config; -void sdr_config_init(void); +void sdr_config_init(double lo_offset); void sdr_config_print_help(void); void sdr_config_print_hotkeys(void); extern struct option sdr_config_long_options[]; diff --git a/src/libsdr/soapy.c b/src/libsdr/soapy.c index 13797d1..ba330be 100644 --- a/src/libsdr/soapy.c +++ b/src/libsdr/soapy.c @@ -62,7 +62,7 @@ static int parse_args(SoapySDRKwargs *args, const char *_args_string) return 0; } -int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double rate, double tx_gain, double rx_gain, double bandwidth) +int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth) { double got_frequency, got_rate, got_gain, got_bandwidth; const char *got_antenna; @@ -88,6 +88,13 @@ int soapy_open(size_t channel, const char *_device_args, const char *_stream_arg if (rc < 0) return rc; + if (lo_offset) { + char val[32]; + snprintf(val, sizeof(val), "%.0f", lo_offset); + val[sizeof(val) - 1] = '\0'; + SoapySDRKwargs_set(&tune_args, "OFFSET", val); + } + /* create SoapySDR device */ sdr = SoapySDRDevice_make(&device_args); if (!sdr) { diff --git a/src/libsdr/soapy.h b/src/libsdr/soapy.h index 702890b..755d0ca 100644 --- a/src/libsdr/soapy.h +++ b/src/libsdr/soapy.h @@ -1,5 +1,5 @@ -int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double rate, double tx_gain, double rx_gain, double bandwidth); +int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth); int soapy_start(void); void soapy_close(void); int soapy_send(float *buff, int num); diff --git a/src/libsdr/uhd.c b/src/libsdr/uhd.c index 3f29cd0..624146f 100644 --- a/src/libsdr/uhd.c +++ b/src/libsdr/uhd.c @@ -49,7 +49,7 @@ static time_t tx_time_secs = 0; static double tx_time_fract_sec = 0.0; static int tx_timestamps; -int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps) +int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps) { uhd_error error; double got_frequency, got_rate, got_gain, got_bandwidth; @@ -153,7 +153,7 @@ int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, uhd_close(); return -EIO; } - if (fabs(got_rate - rate) > 0.001) { + if (fabs(got_rate - rate) > 1.0) { PDEBUG(DUHD, DEBUG_ERROR, "Given TX rate %.0f Hz is not supported, try %.0f Hz\n", rate, got_rate); uhd_close(); return -EINVAL; @@ -182,7 +182,11 @@ int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, /* set frequency */ memset(&tune_request, 0, sizeof(tune_request)); tune_request.target_freq = tx_frequency; - tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO; + if (lo_offset) { + tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_MANUAL; + tune_request.rf_freq = tx_frequency + lo_offset; + } else + tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO; tune_request.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO; tune_request.args = strdup(_tune_args); error = uhd_usrp_set_tx_freq(usrp, &tune_request, channel, &tune_result); @@ -219,7 +223,7 @@ int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, uhd_close(); return -EIO; } - if (fabs(got_bandwidth - bandwidth) > 0.001) { + if (fabs(got_bandwidth - bandwidth) > 100.0) { PDEBUG(DUHD, DEBUG_ERROR, "Given TX bandwidth %.0f Hz is not supported, try %.0f Hz\n", bandwidth, got_bandwidth); uhd_close(); return -EINVAL; @@ -337,7 +341,7 @@ int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, uhd_close(); return -EIO; } - if (fabs(got_rate - rate) > 0.001) { + if (fabs(got_rate - rate) > 1.0) { PDEBUG(DUHD, DEBUG_ERROR, "Given RX rate %.0f Hz is not supported, try %.0f Hz\n", rate, got_rate); uhd_close(); return -EINVAL; @@ -366,7 +370,11 @@ int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, /* set frequency */ memset(&tune_request, 0, sizeof(tune_request)); tune_request.target_freq = rx_frequency; - tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO; + if (lo_offset) { + tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_MANUAL; + tune_request.rf_freq = rx_frequency + lo_offset; + } else + tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO; tune_request.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO; tune_request.args = strdup(_tune_args); error = uhd_usrp_set_rx_freq(usrp, &tune_request, channel, &tune_result); @@ -403,7 +411,7 @@ int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, uhd_close(); return -EIO; } - if (fabs(got_bandwidth - bandwidth) > 0.001) { + if (fabs(got_bandwidth - bandwidth) > 100.0) { PDEBUG(DUHD, DEBUG_ERROR, "Given RX bandwidth %.0f Hz is not supported, try %.0f Hz\n", bandwidth, got_bandwidth); uhd_close(); return -EINVAL; diff --git a/src/libsdr/uhd.h b/src/libsdr/uhd.h index 60eb94f..36ce1ba 100644 --- a/src/libsdr/uhd.h +++ b/src/libsdr/uhd.h @@ -1,5 +1,5 @@ -int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps); +int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps); int uhd_start(void); void uhd_close(void); int uhd_send(float *buff, int num); diff --git a/src/tv/main.c b/src/tv/main.c index 3423ae3..1a1d0be 100644 --- a/src/tv/main.c +++ b/src/tv/main.c @@ -41,6 +41,8 @@ enum paging_signal; #include "tv_modulate.h" #include "channels.h" +#define DEFAULT_LO_OFFSET -3000000.0 + void *sender_head = NULL; int use_sdr = 0; int num_kanal = 1; /* only one channel used for debugging */ @@ -454,7 +456,7 @@ int main(int argc, char *argv[]) debuglevel = 0; #ifdef HAVE_SDR - sdr_config_init(); + sdr_config_init(DEFAULT_LO_OFFSET); #endif skip_args = handle_options(argc, argv); -- cgit v1.2.3