SDR: Add option to set local oscillator (LO) offset

By default it is set to -1 MHz.
This commit is contained in:
Andreas Eversberg 2017-12-04 14:12:11 +01:00
parent c49ee3b2a8
commit 9f901384de
10 changed files with 58 additions and 30 deletions

View File

@ -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 <b>--sdr-soapy</b> option.
In my setup I use antennas directly connected to the SDR.
Being about 1-10 meters away, I use the <b>gain</b> as defined above.
The IF filter requires a minimum <b>bandwidth</b> of 5 MHz.
The <b>sample rate</b> must be 5 MHz minimum.
The default <b>bandwidth</b> follows the sample rate, if not specified using <b>--sdr-bandwidth</b>.
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 <b>offset</b>.
The local oscillator frequency causes the transmitted signal to be noisy, so I shift it 1 MHz away, using the default <b>--sdr-lo-offset</b>.
The audio processing rate of 100 KHz (<b>-s 100000</b>) is used to generate two channels: <b>17</b> 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

View File

@ -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
}

View File

@ -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;
}

View File

@ -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 <samplerate>\n");
printf(" Sample rate to use with SDR. By default it equals the regular sample\n");
printf(" rate.\n");
printf(" --sdr-lo-offset <Hz>\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 <bandwidth>\n");
printf(" Give IF filter bandwidth to use. If not, sample rate is used.\n");
printf(" --sdr-rx-antenna <name>\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;

View File

@ -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[];

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);