SDR: Split SDR config from main_mobile.c to sdr_config.c
This commit is contained in:
parent
94ed39f5e2
commit
a52c89800c
|
@ -45,9 +45,9 @@ int tolerant = 0;
|
|||
void print_help(const char *arg0)
|
||||
{
|
||||
if (!tacs)
|
||||
print_help_common(arg0, "-p -d -F yes | no [-S sid=<sid>] ");
|
||||
main_mobile_print_help(arg0, "-p -d -F yes | no [-S sid=<sid>] ");
|
||||
else
|
||||
print_help_common(arg0, "-p -d -F yes | no [-S aid=<aid>] ");
|
||||
main_mobile_print_help(arg0, "-p -d -F yes | no [-S aid=<aid>] ");
|
||||
/* - - */
|
||||
printf(" -T --channel-type <channel type> | list\n");
|
||||
printf(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(chan_type[0]));
|
||||
|
@ -102,7 +102,7 @@ void print_help(const char *arg0)
|
|||
printf(" Be more tolerant when hunting for sync sequence\n");
|
||||
printf("\nstation-id: Give 10 digit station-id, you don't need to enter it for every\n");
|
||||
printf(" start of this program.\n");
|
||||
print_hotkeys_common();
|
||||
main_mobile_print_hotkeys();
|
||||
}
|
||||
|
||||
static int handle_options(int argc, char **argv)
|
||||
|
@ -121,7 +121,7 @@ static int handle_options(int argc, char **argv)
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
set_options_common("T:F:P:D:S:O", long_options_special);
|
||||
main_mobile_set_options("T:F:P:D:S:O", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
|
@ -238,7 +238,7 @@ static int handle_options(int argc, char **argv)
|
|||
skip_args += 1;
|
||||
break;
|
||||
default:
|
||||
opt_switch_common(c, argv[0], &skip_args);
|
||||
main_mobile_opt_switch(c, argv[0], &skip_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,8 @@ int main_amps_tacs(int argc, char *argv[])
|
|||
/* override default */
|
||||
samplerate = 96000;
|
||||
|
||||
main_mobile_init();
|
||||
|
||||
skip_args = handle_options(argc, argv);
|
||||
argc -= skip_args;
|
||||
argv += skip_args;
|
||||
|
|
|
@ -43,7 +43,7 @@ double lossdetect = 0;
|
|||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
print_help_common(arg0, "[-V 12] ");
|
||||
main_mobile_print_help(arg0, "[-V 12] ");
|
||||
/* - - */
|
||||
printf(" -G --geo <lat>,<lon>\n");
|
||||
printf(" Give your coordinates of your location, to find closest base station.\n");
|
||||
|
@ -60,7 +60,7 @@ void print_help(const char *arg0)
|
|||
printf(" percent. (disabled by default)\n");
|
||||
printf("\nstation-id: Give (last) 5 digits of station-id, you don't need to enter it\n");
|
||||
printf(" for every start of this program.\n");
|
||||
print_hotkeys_common();
|
||||
main_mobile_print_hotkeys();
|
||||
}
|
||||
|
||||
static int handle_options(int argc, char **argv)
|
||||
|
@ -77,7 +77,7 @@ static int handle_options(int argc, char **argv)
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
set_options_common("G:V:P:L:", long_options_special);
|
||||
main_mobile_set_options("G:V:P:L:", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
|
@ -114,7 +114,7 @@ static int handle_options(int argc, char **argv)
|
|||
skip_args += 2;
|
||||
break;
|
||||
default:
|
||||
opt_switch_common(c, argv[0], &skip_args);
|
||||
main_mobile_opt_switch(c, argv[0], &skip_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,6 +137,8 @@ int main(int argc, char *argv[])
|
|||
init_freiton();
|
||||
init_besetzton();
|
||||
|
||||
main_mobile_init();
|
||||
|
||||
skip_args = handle_options(argc, argv);
|
||||
argc -= skip_args;
|
||||
argv += skip_args;
|
||||
|
|
|
@ -43,7 +43,7 @@ double lossdetect = 0;
|
|||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
print_help_common(arg0, "[-G <gfs>] ");
|
||||
main_mobile_print_help(arg0, "[-G <gfs>] ");
|
||||
/* - - */
|
||||
printf(" -G --gfs <gruppenfreisignal> | <lat>,<lon>\n");
|
||||
printf(" Gruppenfreisignal\" 1..9 | 19 | 10..18 (default = '%d')\n", gfs);
|
||||
|
@ -75,7 +75,7 @@ void print_help(const char *arg0)
|
|||
printf(" percent. (disabled by default)\n");
|
||||
printf("\nstation-id: Give 5 digit station-id, you don't need to enter it for every\n");
|
||||
printf(" start of this program.\n");
|
||||
print_hotkeys_common();
|
||||
main_mobile_print_hotkeys();
|
||||
}
|
||||
|
||||
static int handle_options(int argc, char **argv)
|
||||
|
@ -91,7 +91,7 @@ static int handle_options(int argc, char **argv)
|
|||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
set_options_common("G:M:P:L:", long_options_special);
|
||||
main_mobile_set_options("G:M:P:L:", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
|
@ -128,7 +128,7 @@ static int handle_options(int argc, char **argv)
|
|||
skip_args += 2;
|
||||
break;
|
||||
default:
|
||||
opt_switch_common(c, argv[0], &skip_args);
|
||||
main_mobile_opt_switch(c, argv[0], &skip_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,8 @@ int main(int argc, char *argv[])
|
|||
init_besetzton();
|
||||
init_ansage();
|
||||
|
||||
main_mobile_init();
|
||||
|
||||
skip_args = handle_options(argc, argv);
|
||||
argc -= skip_args;
|
||||
argv += skip_args;
|
||||
|
|
|
@ -71,7 +71,7 @@ int metering = 20;
|
|||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
print_help_common(arg0, "[-M] -S <rx ppm>,<tx ppm> -p -d ");
|
||||
main_mobile_print_help(arg0, "[-M] -S <rx ppm>,<tx ppm> -p -d ");
|
||||
/* - - */
|
||||
printf(" -T --channel-type <channel type> | list\n");
|
||||
printf(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(chan_type[0]));
|
||||
|
@ -192,7 +192,7 @@ void print_help(const char *arg0)
|
|||
printf(" input. (default = '%s')\n", (demod == FSK_DEMOD_LEVEL) ? "level" : (demod == FSK_DEMOD_SLOPE) ? "slope" : "auto");
|
||||
printf("\nstation-id: Give 7 digit station-id, you don't need to enter it for every\n");
|
||||
printf(" start of this program.\n");
|
||||
print_hotkeys_common();
|
||||
main_mobile_print_hotkeys();
|
||||
printf("Press 'i' key to dump list of currently attached subscribers.\n");
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ static int handle_options(int argc, char **argv)
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
set_options_common("T:MC:F:P:AQ:G:S:D:", long_options_special);
|
||||
main_mobile_set_options("T:MC:F:P:AQ:G:S:D:", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
|
@ -396,7 +396,7 @@ static int handle_options(int argc, char **argv)
|
|||
skip_args += 2;
|
||||
break;
|
||||
default:
|
||||
opt_switch_common(c, argv[0], &skip_args);
|
||||
main_mobile_opt_switch(c, argv[0], &skip_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,6 +421,8 @@ int main(int argc, char *argv[])
|
|||
init_besetzton();
|
||||
init_ansage();
|
||||
|
||||
main_mobile_init();
|
||||
|
||||
skip_args = handle_options(argc, argv);
|
||||
argc -= skip_args;
|
||||
argv += skip_args;
|
||||
|
|
|
@ -35,6 +35,7 @@ if HAVE_SDR
|
|||
AM_CPPFLAGS += -DHAVE_SDR
|
||||
|
||||
libcommon_a_SOURCES += \
|
||||
sdr_config.c \
|
||||
sdr.c \
|
||||
display_iq.c \
|
||||
display_spectrum.c
|
||||
|
|
|
@ -528,14 +528,14 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int call_open_audio(void)
|
||||
int call_open_audio(int latspl)
|
||||
{
|
||||
if (!call.audiodev[0])
|
||||
return 0;
|
||||
|
||||
/* open sound device for call control */
|
||||
/* use factor 1.4 of speech level for complete range of sound card */
|
||||
call.sound = sound_open(call.audiodev, NULL, NULL, 1, 0.0, call.samplerate, 1.4, 4000.0);
|
||||
call.sound = sound_open(call.audiodev, NULL, NULL, 1, 0.0, call.samplerate, latspl, 1.4, 4000.0);
|
||||
if (!call.sound) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n");
|
||||
return -EIO;
|
||||
|
|
|
@ -11,7 +11,7 @@ enum number_type {
|
|||
|
||||
int call_init(const char *station_id, const char *audiodev, int samplerate, int latency, int dial_digits, int loopback, int use_mncc_sock, int send_patterns, int release_on_disconnect);
|
||||
void call_cleanup(void);
|
||||
int call_open_audio(void);
|
||||
int call_open_audio(int latspl);
|
||||
int call_start_audio(void);
|
||||
void process_call(int c);
|
||||
void clear_console_text(void);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <math.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include "sample.h"
|
||||
#include "main_mobile.h"
|
||||
#include "debug.h"
|
||||
|
@ -37,13 +38,17 @@
|
|||
#include "mncc_sock.h"
|
||||
#ifdef HAVE_SDR
|
||||
#include "sdr.h"
|
||||
#include "sdr_config.h"
|
||||
#endif
|
||||
|
||||
/* common settings */
|
||||
static int got_init = 0;
|
||||
|
||||
/* common mobile settings */
|
||||
int num_kanal = 0;
|
||||
int kanal[MAX_SENDER];
|
||||
int num_audiodev = 0;
|
||||
const char *audiodev[MAX_SENDER] = { "hw:0,0" };
|
||||
int use_sdr = 0;
|
||||
const char *call_audiodev = "";
|
||||
int samplerate = 48000;
|
||||
int call_samplerate = 48000;
|
||||
|
@ -63,25 +68,16 @@ const char *write_tx_wave = NULL;
|
|||
const char *write_rx_wave = NULL;
|
||||
const char *read_tx_wave = NULL;
|
||||
const char *read_rx_wave = NULL;
|
||||
int use_sdr = 0;
|
||||
int sdr_channel = 0;
|
||||
static const char *sdr_device_args = "", *sdr_stream_args = "", *sdr_tune_args = "";
|
||||
static int sdr_samplerate = 0;
|
||||
static double sdr_bandwidth = 0.0;
|
||||
#ifdef HAVE_SDR
|
||||
static int sdr_uhd = 0;
|
||||
static int sdr_soapy = 0;
|
||||
#endif
|
||||
double sdr_tx_gain = 0, sdr_rx_gain = 0;
|
||||
const char *sdr_tx_antenna = "", *sdr_rx_antenna = "";
|
||||
const char *write_iq_tx_wave = NULL;
|
||||
const char *write_iq_rx_wave = NULL;
|
||||
const char *read_iq_tx_wave = NULL;
|
||||
const char *read_iq_rx_wave = NULL;
|
||||
int sdr_swap_links = 0;
|
||||
int sdr_uhd_tx_timestamps = 0;
|
||||
|
||||
void print_help_common(const char *arg0, const char *ext_usage)
|
||||
void main_mobile_init(void)
|
||||
{
|
||||
got_init = 1;
|
||||
#ifdef HAVE_SDR
|
||||
sdr_config_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void main_mobile_print_help(const char *arg0, const char *ext_usage)
|
||||
{
|
||||
printf("Usage: %s -k <kanal/channel> %s[options] [station-id]\n", arg0, ext_usage);
|
||||
printf("\nGlobal options:\n");
|
||||
|
@ -144,55 +140,12 @@ void print_help_common(const char *arg0, const char *ext_usage)
|
|||
printf(" --read-tx-wave <file>\n");
|
||||
printf(" Replace transmitted audio by given wave file.\n");
|
||||
#ifdef HAVE_SDR
|
||||
printf("\nSDR options:\n");
|
||||
/* - - */
|
||||
#ifdef HAVE_UHD
|
||||
printf(" --sdr-uhd\n");
|
||||
printf(" Force UHD driver\n");
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
printf(" --sdr-soapy\n");
|
||||
printf(" Force SoapySDR driver\n");
|
||||
#endif
|
||||
printf(" --sdr-channel <channel #>\n");
|
||||
printf(" Give channel number for multi channel SDR device (default = %d)\n", sdr_channel);
|
||||
printf(" --sdr-device-args <args>\n");
|
||||
printf(" --sdr-stream-args <args>\n");
|
||||
printf(" --sdr-tune-args <args>\n");
|
||||
printf(" Optional SDR device arguments, seperated by comma\n");
|
||||
printf(" e.g. --sdr-device-args <key>=<value>[,<key>=<value>[,...]]\n");
|
||||
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-bandwidth <bandwidth>\n");
|
||||
printf(" Give IF filter bandwidth to use. If not, sample rate is used.\n");
|
||||
printf(" --sdr-rx-antenna <name>\n");
|
||||
printf(" SDR device's RX antenna name, use 'list' to get a list\n");
|
||||
printf(" --sdr-tx-antenna <name>\n");
|
||||
printf(" SDR device's TX antenna name, use 'list' to get a list\n");
|
||||
printf(" --sdr-rx-gain <gain>\n");
|
||||
printf(" SDR device's RX gain in dB (default = %.1f)\n", sdr_rx_gain);
|
||||
printf(" --sdr-tx-gain <gain>\n");
|
||||
printf(" SDR device's TX gain in dB (default = %.1f)\n", sdr_tx_gain);
|
||||
printf(" --write-iq-rx-wave <file>\n");
|
||||
printf(" Write received IQ data to given wave file.\n");
|
||||
printf(" --write-iq-tx-wave <file>\n");
|
||||
printf(" Write transmitted IQ data to given wave file.\n");
|
||||
printf(" --read-iq-rx-wave <file>\n");
|
||||
printf(" Replace received IQ data by given wave file.\n");
|
||||
printf(" --read-iq-tx-wave <file>\n");
|
||||
printf(" Replace transmitted IQ data by given wave file.\n");
|
||||
printf(" --sdr-swap-links\n");
|
||||
printf(" Swap RX and TX frequencies for loopback tests over the air.r\n");
|
||||
#ifdef HAVE_UHD
|
||||
printf(" --sdr-uhd-tx-timestamps\n");
|
||||
printf(" Use TX timestamps on UHD device. (May not work with some devices!)\n");
|
||||
#endif
|
||||
sdr_config_print_help();
|
||||
#endif
|
||||
printf("\nNetwork specific options:\n");
|
||||
}
|
||||
|
||||
void print_hotkeys_common(void)
|
||||
void main_mobile_print_hotkeys(void)
|
||||
{
|
||||
printf("\n");
|
||||
printf("Press digits '0'..'9' and then 'd' key to dial towards mobile station\n");
|
||||
|
@ -200,8 +153,7 @@ void print_hotkeys_common(void)
|
|||
printf("Press 'w' key to toggle display of RX wave form.\n");
|
||||
printf("Press 'c' key to toggle display of channel status.\n");
|
||||
#ifdef HAVE_SDR
|
||||
printf("Press 'i' key to toggle display of RX I/Q vector.\n");
|
||||
printf("Press 's' key to toggle display of RX spectrum.\n");
|
||||
sdr_config_print_hotkeys();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -213,26 +165,7 @@ void print_hotkeys_common(void)
|
|||
#define OPT_CALL_SAMPLERATE 1005
|
||||
#define OPT_MNCC_NAME 1006
|
||||
|
||||
#define OPT_SDR_UHD 1100
|
||||
#define OPT_SDR_SOAPY 1101
|
||||
#define OPT_SDR_CHANNEL 1102
|
||||
#define OPT_SDR_DEVICE_ARGS 1103
|
||||
#define OPT_SDR_STREAM_ARGS 1104
|
||||
#define OPT_SDR_TUNE_ARGS 1105
|
||||
#define OPT_SDR_RX_ANTENNA 1106
|
||||
#define OPT_SDR_TX_ANTENNA 1107
|
||||
#define OPT_SDR_RX_GAIN 1108
|
||||
#define OPT_SDR_TX_GAIN 1109
|
||||
#define OPT_SDR_SAMPLERATE 1110
|
||||
#define OPT_SDR_BANDWIDTH 1111
|
||||
#define OPT_WRITE_IQ_RX_WAVE 1112
|
||||
#define OPT_WRITE_IQ_TX_WAVE 1113
|
||||
#define OPT_READ_IQ_RX_WAVE 1114
|
||||
#define OPT_READ_IQ_TX_WAVE 1115
|
||||
#define OPT_SDR_SWAP_LINKS 1116
|
||||
#define OPT_SDR_UHD_TX_TS 1117
|
||||
|
||||
static struct option long_options_common[] = {
|
||||
static struct option main_mobile_long_options[] = {
|
||||
{"help", 0, 0, 'h'},
|
||||
{"debug", 1, 0, 'v'},
|
||||
{"kanal", 1, 0, 'k'},
|
||||
|
@ -255,28 +188,10 @@ static struct option long_options_common[] = {
|
|||
{"write-tx-wave", 1, 0, OPT_WRITE_TX_WAVE},
|
||||
{"read-rx-wave", 1, 0, OPT_READ_RX_WAVE},
|
||||
{"read-tx-wave", 1, 0, OPT_READ_TX_WAVE},
|
||||
{"sdr-uhd", 0, 0, OPT_SDR_UHD},
|
||||
{"sdr-soapy", 0, 0, OPT_SDR_SOAPY},
|
||||
{"sdr-channel", 1, 0, OPT_SDR_CHANNEL},
|
||||
{"sdr-device-args", 1, 0, OPT_SDR_DEVICE_ARGS},
|
||||
{"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-bandwidth", 1, 0, OPT_SDR_BANDWIDTH},
|
||||
{"sdr-rx-antenna", 1, 0, OPT_SDR_RX_ANTENNA},
|
||||
{"sdr-tx-antenna", 1, 0, OPT_SDR_TX_ANTENNA},
|
||||
{"sdr-rx-gain", 1, 0, OPT_SDR_RX_GAIN},
|
||||
{"sdr-tx-gain", 1, 0, OPT_SDR_TX_GAIN},
|
||||
{"write-iq-rx-wave", 1, 0, OPT_WRITE_IQ_RX_WAVE},
|
||||
{"write-iq-tx-wave", 1, 0, OPT_WRITE_IQ_TX_WAVE},
|
||||
{"read-iq-rx-wave", 1, 0, OPT_READ_IQ_RX_WAVE},
|
||||
{"read-iq-tx-wave", 1, 0, OPT_READ_IQ_TX_WAVE},
|
||||
{"sdr-swap-links", 0, 0, OPT_SDR_SWAP_LINKS},
|
||||
{"sdr-uhd-tx-timestamps", 0, 0, OPT_SDR_UHD_TX_TS},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
const char *optstring_common = "hv:k:a:s:i:b:pdg:mc:t:l:r:";
|
||||
static const char *main_mobile_optstring = "hv:k:a:s:i:b:pdg:mc:t:l:r:";
|
||||
|
||||
struct option *long_options;
|
||||
char *optstring;
|
||||
|
@ -293,28 +208,42 @@ static void check_duplicate_option(int num, struct option *option)
|
|||
}
|
||||
}
|
||||
|
||||
void set_options_common(const char *optstring_special, struct option *long_options_special)
|
||||
void main_mobile_set_options(const char *optstring_special, struct option *long_options_special)
|
||||
{
|
||||
int i;
|
||||
int i = 0, j;
|
||||
|
||||
long_options = calloc(sizeof(*long_options), 100);
|
||||
for (i = 0; long_options_common[i].name; i++) {
|
||||
check_duplicate_option(i, &long_options_common[i]);
|
||||
memcpy(&long_options[i], &long_options_common[i], sizeof(*long_options));
|
||||
long_options = calloc(sizeof(*long_options), 256);
|
||||
for (j = 0; main_mobile_long_options[j].name; i++, j++) {
|
||||
check_duplicate_option(i, &main_mobile_long_options[j]);
|
||||
memcpy(&long_options[i], &main_mobile_long_options[j], sizeof(*long_options));
|
||||
}
|
||||
#ifdef HAVE_SDR
|
||||
for (j = 0; sdr_config_long_options[j].name; i++, j++) {
|
||||
check_duplicate_option(i, &sdr_config_long_options[j]);
|
||||
memcpy(&long_options[i], &sdr_config_long_options[j], sizeof(*long_options));
|
||||
}
|
||||
#endif
|
||||
for (; long_options_special->name; i++) {
|
||||
check_duplicate_option(i, long_options_special);
|
||||
memcpy(&long_options[i], long_options_special++, sizeof(*long_options));
|
||||
}
|
||||
|
||||
optstring = calloc(strlen(optstring_common) + strlen(optstring_special) + 1, 1);
|
||||
strcpy(optstring, optstring_common);
|
||||
optstring = calloc(256, 2);
|
||||
strcpy(optstring, main_mobile_optstring);
|
||||
#ifdef HAVE_SDR
|
||||
strcat(optstring, sdr_config_optstring);
|
||||
#endif
|
||||
strcat(optstring, optstring_special);
|
||||
}
|
||||
|
||||
void opt_switch_common(int c, char *arg0, int *skip_args)
|
||||
void print_help(const char *arg0);
|
||||
|
||||
void main_mobile_opt_switch(int c, char *arg0, int *skip_args)
|
||||
{
|
||||
double gain_db;
|
||||
#ifdef HAVE_SDR
|
||||
int rc;
|
||||
#endif
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
|
@ -424,92 +353,14 @@ void opt_switch_common(int c, char *arg0, int *skip_args)
|
|||
read_tx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_UHD:
|
||||
#ifdef HAVE_SDR
|
||||
use_sdr = 1;
|
||||
sdr_uhd = 1;
|
||||
#else
|
||||
fprintf(stderr, "UHD SDR support not compiled in!\n");
|
||||
exit(0);
|
||||
#endif
|
||||
*skip_args += 1;
|
||||
break;
|
||||
case OPT_SDR_SOAPY:
|
||||
#ifdef HAVE_SDR
|
||||
use_sdr = 1;
|
||||
sdr_soapy = 1;
|
||||
#else
|
||||
fprintf(stderr, "SoapySDR support not compiled in!\n");
|
||||
exit(0);
|
||||
#endif
|
||||
*skip_args += 1;
|
||||
break;
|
||||
case OPT_SDR_CHANNEL:
|
||||
sdr_channel = atoi(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_DEVICE_ARGS:
|
||||
sdr_device_args = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_STREAM_ARGS:
|
||||
sdr_stream_args = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_TUNE_ARGS:
|
||||
sdr_tune_args = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_SAMPLERATE:
|
||||
sdr_samplerate = atoi(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_BANDWIDTH:
|
||||
sdr_bandwidth = atof(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_RX_ANTENNA:
|
||||
sdr_rx_antenna = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_TX_ANTENNA:
|
||||
sdr_tx_antenna = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_RX_GAIN:
|
||||
sdr_rx_gain = atof(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_TX_GAIN:
|
||||
sdr_tx_gain = atof(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_WRITE_IQ_RX_WAVE:
|
||||
write_iq_rx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_WRITE_IQ_TX_WAVE:
|
||||
write_iq_tx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_READ_IQ_RX_WAVE:
|
||||
read_iq_rx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_READ_IQ_TX_WAVE:
|
||||
read_iq_tx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_SWAP_LINKS:
|
||||
sdr_swap_links = 1;
|
||||
*skip_args += 1;
|
||||
break;
|
||||
case OPT_SDR_UHD_TX_TS:
|
||||
sdr_uhd_tx_timestamps = 1;
|
||||
*skip_args += 1;
|
||||
break;
|
||||
default:
|
||||
exit (0);
|
||||
#ifdef HAVE_SDR
|
||||
rc = sdr_config_opt_switch(c, skip_args);
|
||||
if (rc < 0)
|
||||
exit (0);
|
||||
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,6 +407,11 @@ void main_mobile(int *quit, int latency, int interval, void (*myhandler)(void),
|
|||
int c;
|
||||
int rc;
|
||||
|
||||
if (!got_init) {
|
||||
fprintf(stderr, "main_mobile_init was not called, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* latency of send buffer in samples */
|
||||
latspl = samplerate * latency / 1000;
|
||||
|
||||
|
@ -582,24 +438,15 @@ void main_mobile(int *quit, int latency, int interval, void (*myhandler)(void),
|
|||
}
|
||||
|
||||
#ifdef HAVE_SDR
|
||||
if ((sdr_uhd == 1 && sdr_soapy == 1)) {
|
||||
fprintf(stderr, "You must choose which one you want: --sdr-uhd or --sdr-soapy\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sdr_samplerate == 0.0)
|
||||
sdr_samplerate = samplerate;
|
||||
if (sdr_bandwidth == 0.0)
|
||||
sdr_bandwidth = sdr_samplerate;
|
||||
rc = sdr_init(sdr_uhd, sdr_soapy, sdr_channel, sdr_device_args, sdr_stream_args, sdr_tune_args, sdr_tx_antenna, sdr_rx_antenna, sdr_tx_gain, sdr_rx_gain, sdr_samplerate, sdr_bandwidth, write_iq_tx_wave, write_iq_rx_wave, read_iq_tx_wave, read_iq_rx_wave, latspl, sdr_swap_links, sdr_uhd_tx_timestamps);
|
||||
rc = sdr_configure(samplerate);
|
||||
if (rc < 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* open audio */
|
||||
if (sender_open_audio())
|
||||
if (sender_open_audio(latspl))
|
||||
return;
|
||||
if (call_open_audio())
|
||||
if (call_open_audio(latspl))
|
||||
return;
|
||||
|
||||
/* real time priority */
|
||||
|
|
|
@ -22,13 +22,13 @@ extern const char *write_tx_wave;
|
|||
extern const char *read_rx_wave;
|
||||
extern const char *read_tx_wave;
|
||||
|
||||
void print_help(const char *arg0);
|
||||
void print_help_common(const char *arg0, const char *ext_usage);
|
||||
void print_hotkeys_common(void);
|
||||
void main_mobile_init(void);
|
||||
void main_mobile_print_help(const char *arg0, const char *ext_usage);
|
||||
void main_mobile_print_hotkeys(void);
|
||||
extern struct option *long_options;
|
||||
extern char *optstring;
|
||||
void set_options_common(const char *optstring_special, struct option *long_options_special);
|
||||
void opt_switch_common(int c, char *arg0, int *skip_args);
|
||||
void main_mobile_set_options(const char *optstring_special, struct option *long_options_special);
|
||||
void main_mobile_opt_switch(int c, char *arg0, int *skip_args);
|
||||
|
||||
#define OPT_ARRAY(num_name, name, value) \
|
||||
{ \
|
||||
|
|
428
src/common/sdr.c
428
src/common/sdr.c
|
@ -17,19 +17,25 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
enum paging_signal;
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <getopt.h>
|
||||
#define __USE_GNU
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "sample.h"
|
||||
#include "fm_modulation.h"
|
||||
#include "sender.h"
|
||||
#include "timer.h"
|
||||
#include "wave.h"
|
||||
#include "display.h"
|
||||
#include "sdr_config.h"
|
||||
#include "sdr.h"
|
||||
#ifdef HAVE_UHD
|
||||
#include "uhd.h"
|
||||
#endif
|
||||
|
@ -41,31 +47,6 @@
|
|||
/* enable to debug buffer handling */
|
||||
//#define DEBUG_BUFFER
|
||||
|
||||
typedef struct sdr_chan {
|
||||
double tx_frequency; /* frequency used */
|
||||
double rx_frequency; /* frequency used */
|
||||
fm_mod_t mod; /* modulator instance */
|
||||
fm_demod_t demod; /* demodulator instance */
|
||||
} sdr_chan_t;
|
||||
|
||||
typedef struct sdr {
|
||||
sdr_chan_t *chan; /* settings for all channels */
|
||||
int paging_channel; /* if set, points to paging channel */
|
||||
sdr_chan_t paging_chan; /* settings for extra paging channel */
|
||||
int channels; /* number of frequencies */
|
||||
double amplitude; /* amplitude of each carrier */
|
||||
int samplerate; /* sample rate of audio data */
|
||||
wave_rec_t wave_rx_rec;
|
||||
wave_rec_t wave_tx_rec;
|
||||
wave_play_t wave_rx_play;
|
||||
wave_play_t wave_tx_play;
|
||||
float *modbuff; /* buffer for FM transmodulation */
|
||||
sample_t *modbuff_I;
|
||||
sample_t *modbuff_Q;
|
||||
sample_t *wavespl0; /* sample buffer for wave generation */
|
||||
sample_t *wavespl1;
|
||||
} sdr_t;
|
||||
|
||||
typedef struct sdr_thread {
|
||||
int use;
|
||||
volatile int running, exit; /* flags to control exit of threads */
|
||||
|
@ -77,54 +58,40 @@ typedef struct sdr_thread {
|
|||
double max_fill_timer; /* timer to display/reset maximum fill */
|
||||
} sdr_thread_t;
|
||||
|
||||
/* preferences */
|
||||
static int sdr_use_uhd, sdr_use_soapy;
|
||||
static int sdr_channel;
|
||||
static const char *sdr_device_args, *sdr_stream_args, *sdr_tune_args;
|
||||
static const char *sdr_rx_antenna, *sdr_tx_antenna;
|
||||
static double sdr_rx_gain, sdr_tx_gain;
|
||||
static const char *sdr_write_iq_rx_wave, *sdr_write_iq_tx_wave, *sdr_read_iq_rx_wave, *sdr_read_iq_tx_wave;
|
||||
static int sdr_samplerate; /* sample rate of IQ data */
|
||||
static double sdr_bandwidth;
|
||||
static int sdr_oversample;
|
||||
static int sdr_latspl;
|
||||
static int sdr_threads;
|
||||
static sdr_thread_t sdr_thread_read, sdr_thread_write;
|
||||
static int sdr_swap_links;
|
||||
static int sdr_uhd_tx_timestamps;
|
||||
typedef struct sdr_chan {
|
||||
double tx_frequency; /* frequency used */
|
||||
double rx_frequency; /* frequency used */
|
||||
fm_mod_t mod; /* modulator instance */
|
||||
fm_demod_t demod; /* demodulator instance */
|
||||
} sdr_chan_t;
|
||||
|
||||
int sdr_init(int sdr_uhd, int sdr_soapy, int channel, const char *device_args, const char *stream_args, const char *tune_args, const char *tx_antenna, const char *rx_antenna, double tx_gain, double rx_gain, int samplerate, double bandwidth, const char *write_iq_tx_wave, const char *write_iq_rx_wave, const char *read_iq_tx_wave, const char *read_iq_rx_wave, int latspl, int swap_links, int uhd_tx_timestamps)
|
||||
{
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Init SDR\n");
|
||||
typedef struct sdr {
|
||||
int threads; /* use threads */
|
||||
int oversample; /* oversample IQ rate */
|
||||
sdr_thread_t thread_read,
|
||||
thread_write;
|
||||
sdr_chan_t *chan; /* settings for all channels */
|
||||
int paging_channel; /* if set, points to paging channel */
|
||||
sdr_chan_t paging_chan; /* settings for extra paging channel */
|
||||
int channels; /* number of frequencies */
|
||||
double amplitude; /* amplitude of each carrier */
|
||||
int samplerate; /* sample rate of audio data */
|
||||
int latspl; /* latency in audio samples */
|
||||
wave_rec_t wave_rx_rec;
|
||||
wave_rec_t wave_tx_rec;
|
||||
wave_play_t wave_rx_play;
|
||||
wave_play_t wave_tx_play;
|
||||
float *modbuff; /* buffer for FM transmodulation */
|
||||
sample_t *modbuff_I;
|
||||
sample_t *modbuff_Q;
|
||||
sample_t *wavespl0; /* sample buffer for wave generation */
|
||||
sample_t *wavespl1;
|
||||
} sdr_t;
|
||||
|
||||
sdr_threads = 0; /* only requried for oversampling */
|
||||
sdr_use_uhd = sdr_uhd;
|
||||
sdr_use_soapy = sdr_soapy;
|
||||
sdr_channel = channel;
|
||||
sdr_device_args = strdup(device_args);
|
||||
sdr_stream_args = strdup(stream_args);
|
||||
sdr_tune_args = strdup(tune_args);
|
||||
sdr_tx_antenna = strdup(tx_antenna);
|
||||
sdr_rx_antenna = strdup(rx_antenna);
|
||||
sdr_tx_gain = tx_gain;
|
||||
sdr_rx_gain = rx_gain;
|
||||
sdr_bandwidth = bandwidth;
|
||||
sdr_write_iq_tx_wave = write_iq_tx_wave;
|
||||
sdr_write_iq_rx_wave = write_iq_rx_wave;
|
||||
sdr_read_iq_tx_wave = read_iq_tx_wave;
|
||||
sdr_read_iq_rx_wave = read_iq_rx_wave;
|
||||
sdr_samplerate = samplerate;
|
||||
sdr_oversample = 1;
|
||||
sdr_latspl = latspl;
|
||||
sdr_swap_links = swap_links;
|
||||
sdr_uhd_tx_timestamps = uhd_tx_timestamps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double max_deviation, double max_modulation)
|
||||
void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, int latspl, double max_deviation, double max_modulation)
|
||||
{
|
||||
sdr_t *sdr;
|
||||
int threads = 1, oversample = 1; /* always use threads */
|
||||
double bandwidth;
|
||||
double tx_center_frequency = 0.0, rx_center_frequency = 0.0;
|
||||
int rc;
|
||||
|
@ -132,48 +99,19 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Open SDR device\n");
|
||||
|
||||
if (sdr_samplerate != samplerate) {
|
||||
if (samplerate > sdr_samplerate) {
|
||||
if (sdr_config->samplerate != samplerate) {
|
||||
if (samplerate > sdr_config->samplerate) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "SDR sample rate must be greater than audio sample rate!\n");
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "You selected an SDR rate of %d and an audio rate of %d.\n", sdr_samplerate, samplerate);
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "You selected an SDR rate of %d and an audio rate of %d.\n", sdr_config->samplerate, samplerate);
|
||||
return NULL;
|
||||
}
|
||||
if ((sdr_samplerate % samplerate)) {
|
||||
if ((sdr_config->samplerate % samplerate)) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "SDR sample rate must be a multiple of audio sample rate!\n");
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "You selected an SDR rate of %d and an audio rate of %d.\n", sdr_samplerate, samplerate);
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "You selected an SDR rate of %d and an audio rate of %d.\n", sdr_config->samplerate, samplerate);
|
||||
return NULL;
|
||||
}
|
||||
sdr_oversample = sdr_samplerate / samplerate;
|
||||
sdr_threads = 1;
|
||||
}
|
||||
|
||||
if (sdr_threads) {
|
||||
memset(&sdr_thread_read, 0, sizeof(sdr_thread_read));
|
||||
sdr_thread_read.buffer_size = sdr_latspl * 2 * sdr_oversample + 2;
|
||||
sdr_thread_read.buffer = calloc(sdr_thread_read.buffer_size, sizeof(*sdr_thread_read.buffer));
|
||||
if (!sdr_thread_read.buffer) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr_thread_read.buffer2 = calloc(sdr_thread_read.buffer_size, sizeof(*sdr_thread_read.buffer2));
|
||||
if (!sdr_thread_read.buffer2) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr_thread_read.in = sdr_thread_read.out = 0;
|
||||
memset(&sdr_thread_write, 0, sizeof(sdr_thread_write));
|
||||
sdr_thread_write.buffer_size = sdr_latspl * 2 + 2;
|
||||
sdr_thread_write.buffer = calloc(sdr_thread_write.buffer_size, sizeof(*sdr_thread_write.buffer));
|
||||
if (!sdr_thread_write.buffer) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr_thread_write.buffer2 = calloc(sdr_thread_write.buffer_size * sdr_oversample, sizeof(*sdr_thread_write.buffer2));
|
||||
if (!sdr_thread_write.buffer2) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr_thread_write.in = sdr_thread_write.out = 0;
|
||||
oversample = sdr_config->samplerate / samplerate;
|
||||
threads = 1;
|
||||
}
|
||||
|
||||
display_iq_init(samplerate);
|
||||
|
@ -195,29 +133,61 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
sdr->channels = channels;
|
||||
sdr->amplitude = 1.0 / (double)channels;
|
||||
sdr->samplerate = samplerate;
|
||||
sdr->latspl = latspl;
|
||||
sdr->threads = threads; /* always requried, because write may block */
|
||||
sdr->oversample = oversample;
|
||||
|
||||
if (threads) {
|
||||
memset(&sdr->thread_read, 0, sizeof(sdr->thread_read));
|
||||
sdr->thread_read.buffer_size = sdr->latspl * 2 * sdr->oversample + 2;
|
||||
sdr->thread_read.buffer = calloc(sdr->thread_read.buffer_size, sizeof(*sdr->thread_read.buffer));
|
||||
if (!sdr->thread_read.buffer) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr->thread_read.buffer2 = calloc(sdr->thread_read.buffer_size, sizeof(*sdr->thread_read.buffer2));
|
||||
if (!sdr->thread_read.buffer2) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr->thread_read.in = sdr->thread_read.out = 0;
|
||||
memset(&sdr->thread_write, 0, sizeof(sdr->thread_write));
|
||||
sdr->thread_write.buffer_size = sdr->latspl * 2 + 2;
|
||||
sdr->thread_write.buffer = calloc(sdr->thread_write.buffer_size, sizeof(*sdr->thread_write.buffer));
|
||||
if (!sdr->thread_write.buffer) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr->thread_write.buffer2 = calloc(sdr->thread_write.buffer_size * sdr->oversample, sizeof(*sdr->thread_write.buffer2));
|
||||
if (!sdr->thread_write.buffer2) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
return NULL;
|
||||
}
|
||||
sdr->thread_write.in = sdr->thread_write.out = 0;
|
||||
}
|
||||
|
||||
/* alloc fm modulation buffers */
|
||||
sdr->modbuff = calloc(sdr_latspl * 2, sizeof(*sdr->modbuff));
|
||||
sdr->modbuff = calloc(sdr->latspl * 2, sizeof(*sdr->modbuff));
|
||||
if (!sdr->modbuff) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->modbuff_I = calloc(sdr_latspl, sizeof(*sdr->modbuff_I));
|
||||
sdr->modbuff_I = calloc(sdr->latspl, sizeof(*sdr->modbuff_I));
|
||||
if (!sdr->modbuff_I) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->modbuff_Q = calloc(sdr_latspl, sizeof(*sdr->modbuff_Q));
|
||||
sdr->modbuff_Q = calloc(sdr->latspl, sizeof(*sdr->modbuff_Q));
|
||||
if (!sdr->modbuff_Q) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->wavespl0 = calloc(sdr_latspl, sizeof(*sdr->wavespl0));
|
||||
sdr->wavespl0 = calloc(sdr->latspl, sizeof(*sdr->wavespl0));
|
||||
if (!sdr->wavespl0) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->wavespl1 = calloc(sdr_latspl, sizeof(*sdr->wavespl1));
|
||||
sdr->wavespl1 = calloc(sdr->latspl, sizeof(*sdr->wavespl1));
|
||||
if (!sdr->wavespl1) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
|
@ -291,17 +261,17 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
goto error;
|
||||
}
|
||||
/* show gain */
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB\n", sdr_tx_gain);
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB\n", sdr_config->tx_gain);
|
||||
/* open wave */
|
||||
if (sdr_write_iq_tx_wave) {
|
||||
rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, samplerate, 2, 1.0);
|
||||
if (sdr_config->write_iq_tx_wave) {
|
||||
rc = wave_create_record(&sdr->wave_tx_rec, sdr_config->write_iq_tx_wave, samplerate, 2, 1.0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (sdr_read_iq_tx_wave) {
|
||||
rc = wave_create_playback(&sdr->wave_tx_play, sdr_read_iq_tx_wave, samplerate, 2, 1.0);
|
||||
if (sdr_config->read_iq_tx_wave) {
|
||||
rc = wave_create_playback(&sdr->wave_tx_play, sdr_config->read_iq_tx_wave, samplerate, 2, 1.0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||
goto error;
|
||||
|
@ -344,17 +314,17 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
goto error;
|
||||
}
|
||||
/* show gain */
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Using gain: RX %.1f dB\n", sdr_rx_gain);
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Using gain: RX %.1f dB\n", sdr_config->rx_gain);
|
||||
/* open wave */
|
||||
if (sdr_write_iq_rx_wave) {
|
||||
rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, samplerate, 2, 1.0);
|
||||
if (sdr_config->write_iq_rx_wave) {
|
||||
rc = wave_create_record(&sdr->wave_rx_rec, sdr_config->write_iq_rx_wave, samplerate, 2, 1.0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (sdr_read_iq_rx_wave) {
|
||||
rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, samplerate, 2, 1.0);
|
||||
if (sdr_config->read_iq_rx_wave) {
|
||||
rc = wave_create_playback(&sdr->wave_rx_play, sdr_config->read_iq_rx_wave, samplerate, 2, 1.0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||
goto error;
|
||||
|
@ -362,7 +332,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
}
|
||||
}
|
||||
|
||||
if (sdr_swap_links) {
|
||||
if (sdr_config->swap_links) {
|
||||
double temp;
|
||||
PDEBUG(DSDR, DEBUG_NOTICE, "Sapping RX and TX frequencies!\n");
|
||||
temp = rx_center_frequency;
|
||||
|
@ -371,16 +341,16 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
}
|
||||
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd) {
|
||||
rc = uhd_open(sdr_channel, sdr_device_args, sdr_stream_args, sdr_tune_args, sdr_tx_antenna, sdr_rx_antenna, tx_center_frequency, rx_center_frequency, sdr_samplerate, sdr_tx_gain, sdr_rx_gain, sdr_bandwidth, sdr_uhd_tx_timestamps);
|
||||
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);
|
||||
if (rc)
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy) {
|
||||
rc = soapy_open(sdr_channel, sdr_device_args, sdr_stream_args, sdr_tune_args, sdr_tx_antenna, sdr_rx_antenna, tx_center_frequency, rx_center_frequency, sdr_samplerate, sdr_tx_gain, sdr_rx_gain, sdr_bandwidth);
|
||||
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);
|
||||
if (rc)
|
||||
goto error;
|
||||
}
|
||||
|
@ -393,25 +363,25 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void *sdr_write_child(void __attribute__((__unused__)) *arg)
|
||||
static void *sdr_write_child(void *arg)
|
||||
{
|
||||
sdr_t *sdr = (sdr_t *)arg;
|
||||
int num;
|
||||
int fill, out;
|
||||
int s, ss, o;
|
||||
|
||||
while (sdr_thread_write.running) {
|
||||
while (sdr->thread_write.running) {
|
||||
/* write to SDR */
|
||||
fill = (sdr_thread_write.in - sdr_thread_write.out + sdr_thread_write.buffer_size) % sdr_thread_write.buffer_size;
|
||||
if (fill > sdr_thread_write.max_fill)
|
||||
sdr_thread_write.max_fill = fill;
|
||||
if (sdr_thread_write.max_fill_timer == 0.0)
|
||||
sdr_thread_write.max_fill_timer = get_time();
|
||||
if (get_time() - sdr_thread_write.max_fill_timer > 1.0) {
|
||||
fill = (sdr->thread_write.in - sdr->thread_write.out + sdr->thread_write.buffer_size) % sdr->thread_write.buffer_size;
|
||||
if (fill > sdr->thread_write.max_fill)
|
||||
sdr->thread_write.max_fill = fill;
|
||||
if (sdr->thread_write.max_fill_timer == 0.0)
|
||||
sdr->thread_write.max_fill_timer = get_time();
|
||||
if (get_time() - sdr->thread_write.max_fill_timer > 1.0) {
|
||||
double delay;
|
||||
delay = (double)sdr_thread_write.max_fill / 2.0 / (double)sdr->samplerate;
|
||||
sdr_thread_write.max_fill = 0;
|
||||
sdr_thread_write.max_fill_timer += 1.0;
|
||||
delay = (double)sdr->thread_write.max_fill / 2.0 / (double)sdr->samplerate;
|
||||
sdr->thread_write.max_fill = 0;
|
||||
sdr->thread_write.max_fill_timer += 1.0;
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "write delay = %.3f ms\n", delay * 1000.0);
|
||||
}
|
||||
num = fill / 2;
|
||||
|
@ -419,23 +389,23 @@ static void *sdr_write_child(void __attribute__((__unused__)) *arg)
|
|||
#ifdef DEBUG_BUFFER
|
||||
printf("Thread found %d samples in write buffer and forwards them to SDR.\n", num);
|
||||
#endif
|
||||
out = sdr_thread_write.out;
|
||||
out = sdr->thread_write.out;
|
||||
for (s = 0, ss = 0; s < num; s++) {
|
||||
for (o = 0; o < sdr_oversample; o++) {
|
||||
sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out];
|
||||
sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out + 1];
|
||||
for (o = 0; o < sdr->oversample; o++) {
|
||||
sdr->thread_write.buffer2[ss++] = sdr->thread_write.buffer[out];
|
||||
sdr->thread_write.buffer2[ss++] = sdr->thread_write.buffer[out + 1];
|
||||
}
|
||||
out = (out + 2) % sdr_thread_write.buffer_size;
|
||||
out = (out + 2) % sdr->thread_write.buffer_size;
|
||||
}
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd)
|
||||
uhd_send(sdr_thread_write.buffer2, num * sdr_oversample);
|
||||
if (sdr_config->uhd)
|
||||
uhd_send(sdr->thread_write.buffer2, num * sdr->oversample);
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy)
|
||||
soapy_send(sdr_thread_write.buffer2, num * sdr_oversample);
|
||||
if (sdr_config->soapy)
|
||||
soapy_send(sdr->thread_write.buffer2, num * sdr->oversample);
|
||||
#endif
|
||||
sdr_thread_write.out = out;
|
||||
sdr->thread_write.out = out;
|
||||
}
|
||||
|
||||
/* delay some time */
|
||||
|
@ -443,41 +413,41 @@ static void *sdr_write_child(void __attribute__((__unused__)) *arg)
|
|||
}
|
||||
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Thread received exit!\n");
|
||||
sdr_thread_write.exit = 1;
|
||||
sdr->thread_write.exit = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *sdr_read_child(void __attribute__((__unused__)) *arg)
|
||||
static void *sdr_read_child(void *arg)
|
||||
{
|
||||
// sdr_t *sdr = (sdr_t *)arg;
|
||||
sdr_t *sdr = (sdr_t *)arg;
|
||||
int num, count = 0;
|
||||
int space, in;
|
||||
int s, ss;
|
||||
|
||||
while (sdr_thread_read.running) {
|
||||
while (sdr->thread_read.running) {
|
||||
/* read from SDR */
|
||||
space = (sdr_thread_read.out - sdr_thread_read.in - 2 + sdr_thread_read.buffer_size) % sdr_thread_read.buffer_size;
|
||||
space = (sdr->thread_read.out - sdr->thread_read.in - 2 + sdr->thread_read.buffer_size) % sdr->thread_read.buffer_size;
|
||||
num = space / 2;
|
||||
if (num) {
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd)
|
||||
count = uhd_receive(sdr_thread_read.buffer2, num);
|
||||
if (sdr_config->uhd)
|
||||
count = uhd_receive(sdr->thread_read.buffer2, num);
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy)
|
||||
count = soapy_receive(sdr_thread_read.buffer2, num);
|
||||
if (sdr_config->soapy)
|
||||
count = soapy_receive(sdr->thread_read.buffer2, num);
|
||||
#endif
|
||||
if (count > 0) {
|
||||
#ifdef DEBUG_BUFFER
|
||||
printf("Thread read %d samples from SDR and writes them to read buffer.\n", count);
|
||||
#endif
|
||||
in = sdr_thread_read.in;
|
||||
in = sdr->thread_read.in;
|
||||
for (s = 0, ss = 0; s < count; s++) {
|
||||
sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
|
||||
sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
|
||||
in %= sdr_thread_read.buffer_size;
|
||||
sdr->thread_read.buffer[in++] = sdr->thread_read.buffer2[ss++];
|
||||
sdr->thread_read.buffer[in++] = sdr->thread_read.buffer2[ss++];
|
||||
in %= sdr->thread_read.buffer_size;
|
||||
}
|
||||
sdr_thread_read.in = in;
|
||||
sdr->thread_read.in = in;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,38 +456,38 @@ static void *sdr_read_child(void __attribute__((__unused__)) *arg)
|
|||
}
|
||||
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Thread received exit!\n");
|
||||
sdr_thread_read.exit = 1;
|
||||
sdr->thread_read.exit = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* start streaming */
|
||||
int sdr_start(void __attribute__((__unused__)) *inst)
|
||||
int sdr_start(void *inst)
|
||||
{
|
||||
// sdr_t *sdr = (sdr_t *)inst;
|
||||
sdr_t *sdr = (sdr_t *)inst;
|
||||
int rc = -EINVAL;
|
||||
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd)
|
||||
if (sdr_config->uhd)
|
||||
rc = uhd_start();
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy)
|
||||
if (sdr_config->soapy)
|
||||
rc = soapy_start();
|
||||
#endif
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (sdr_threads) {
|
||||
if (sdr->threads) {
|
||||
int rc;
|
||||
pthread_t tid;
|
||||
char tname[64];
|
||||
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Create threads!\n");
|
||||
sdr_thread_write.running = 1;
|
||||
sdr_thread_write.exit = 0;
|
||||
sdr->thread_write.running = 1;
|
||||
sdr->thread_write.exit = 0;
|
||||
rc = pthread_create(&tid, NULL, sdr_write_child, inst);
|
||||
if (rc < 0) {
|
||||
sdr_thread_write.running = 0;
|
||||
sdr->thread_write.running = 0;
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "Failed to create thread!\n");
|
||||
return rc;
|
||||
}
|
||||
|
@ -525,11 +495,11 @@ int sdr_start(void __attribute__((__unused__)) *inst)
|
|||
strncat(tname, "-sdr_tx", sizeof(tname));
|
||||
tname[sizeof(tname) - 1] = '\0';
|
||||
pthread_setname_np(tid, tname);
|
||||
sdr_thread_read.running = 1;
|
||||
sdr_thread_read.exit = 0;
|
||||
sdr->thread_read.running = 1;
|
||||
sdr->thread_read.exit = 0;
|
||||
rc = pthread_create(&tid, NULL, sdr_read_child, inst);
|
||||
if (rc < 0) {
|
||||
sdr_thread_read.running = 0;
|
||||
sdr->thread_read.running = 0;
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "Failed to create thread!\n");
|
||||
return rc;
|
||||
}
|
||||
|
@ -548,37 +518,37 @@ void sdr_close(void *inst)
|
|||
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Close SDR device\n");
|
||||
|
||||
if (sdr_threads) {
|
||||
if (sdr_thread_write.running) {
|
||||
if (sdr->threads) {
|
||||
if (sdr->thread_write.running) {
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Thread sending exit!\n");
|
||||
sdr_thread_write.running = 0;
|
||||
while (sdr_thread_write.exit == 0)
|
||||
sdr->thread_write.running = 0;
|
||||
while (sdr->thread_write.exit == 0)
|
||||
usleep(1000);
|
||||
}
|
||||
if (sdr_thread_read.running) {
|
||||
if (sdr->thread_read.running) {
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Thread sending exit!\n");
|
||||
sdr_thread_read.running = 0;
|
||||
while (sdr_thread_read.exit == 0)
|
||||
sdr->thread_read.running = 0;
|
||||
while (sdr->thread_read.exit == 0)
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (sdr_thread_read.buffer)
|
||||
free((void *)sdr_thread_read.buffer);
|
||||
if (sdr_thread_read.buffer2)
|
||||
free((void *)sdr_thread_read.buffer2);
|
||||
if (sdr_thread_write.buffer)
|
||||
free((void *)sdr_thread_write.buffer);
|
||||
if (sdr_thread_write.buffer2)
|
||||
free((void *)sdr_thread_write.buffer2);
|
||||
if (sdr->thread_read.buffer)
|
||||
free((void *)sdr->thread_read.buffer);
|
||||
if (sdr->thread_read.buffer2)
|
||||
free((void *)sdr->thread_read.buffer2);
|
||||
if (sdr->thread_write.buffer)
|
||||
free((void *)sdr->thread_write.buffer);
|
||||
if (sdr->thread_write.buffer2)
|
||||
free((void *)sdr->thread_write.buffer2);
|
||||
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd)
|
||||
if (sdr_config->uhd)
|
||||
uhd_close();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy)
|
||||
if (sdr_config->soapy)
|
||||
soapy_close();
|
||||
#endif
|
||||
|
||||
|
@ -615,7 +585,7 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
|
|||
int c, s, ss;
|
||||
int sent = 0;
|
||||
|
||||
if (num > sdr_latspl) {
|
||||
if (num > sdr->latspl) {
|
||||
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
|
@ -656,11 +626,11 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
|
|||
}
|
||||
}
|
||||
|
||||
if (sdr_threads) {
|
||||
if (sdr->threads) {
|
||||
/* store data towards SDR in ring buffer */
|
||||
int space, in;
|
||||
|
||||
space = (sdr_thread_write.out - sdr_thread_write.in - 2 + sdr_thread_write.buffer_size) % sdr_thread_write.buffer_size;
|
||||
space = (sdr->thread_write.out - sdr->thread_write.in - 2 + sdr->thread_write.buffer_size) % sdr->thread_write.buffer_size;
|
||||
if (space < num * 2) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "Write SDR buffer overflow!\n");
|
||||
num = space / 2;
|
||||
|
@ -668,21 +638,21 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
|
|||
#ifdef DEBUG_BUFFER
|
||||
printf("Writing %d samples to write buffer.\n", num);
|
||||
#endif
|
||||
in = sdr_thread_write.in;
|
||||
in = sdr->thread_write.in;
|
||||
for (s = 0, ss = 0; s < num; s++) {
|
||||
sdr_thread_write.buffer[in++] = buff[ss++];
|
||||
sdr_thread_write.buffer[in++] = buff[ss++];
|
||||
in %= sdr_thread_write.buffer_size;
|
||||
sdr->thread_write.buffer[in++] = buff[ss++];
|
||||
sdr->thread_write.buffer[in++] = buff[ss++];
|
||||
in %= sdr->thread_write.buffer_size;
|
||||
}
|
||||
sdr_thread_write.in = in;
|
||||
sdr->thread_write.in = in;
|
||||
sent = num;
|
||||
} else {
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd)
|
||||
if (sdr_config->uhd)
|
||||
sent = uhd_send(buff, num);
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy)
|
||||
if (sdr_config->soapy)
|
||||
sent = soapy_send(buff, num);
|
||||
#endif
|
||||
if (sent < 0)
|
||||
|
@ -699,7 +669,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
|||
int count = 0;
|
||||
int c, s, ss;
|
||||
|
||||
if (num > sdr_latspl) {
|
||||
if (num > sdr->latspl) {
|
||||
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
|
@ -710,42 +680,42 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
|||
buff = (float *)samples;
|
||||
}
|
||||
|
||||
if (sdr_threads) {
|
||||
if (sdr->threads) {
|
||||
/* load data from SDR out of ring buffer */
|
||||
int fill, out;
|
||||
|
||||
fill = (sdr_thread_read.in - sdr_thread_read.out + sdr_thread_read.buffer_size) % sdr_thread_read.buffer_size;
|
||||
if (fill > sdr_thread_read.max_fill)
|
||||
sdr_thread_read.max_fill = fill;
|
||||
if (sdr_thread_read.max_fill_timer == 0.0)
|
||||
sdr_thread_read.max_fill_timer = get_time();
|
||||
if (get_time() - sdr_thread_read.max_fill_timer > 1.0) {
|
||||
fill = (sdr->thread_read.in - sdr->thread_read.out + sdr->thread_read.buffer_size) % sdr->thread_read.buffer_size;
|
||||
if (fill > sdr->thread_read.max_fill)
|
||||
sdr->thread_read.max_fill = fill;
|
||||
if (sdr->thread_read.max_fill_timer == 0.0)
|
||||
sdr->thread_read.max_fill_timer = get_time();
|
||||
if (get_time() - sdr->thread_read.max_fill_timer > 1.0) {
|
||||
double delay;
|
||||
delay = (double)sdr_thread_read.max_fill / 2.0 / (double)sdr_samplerate;
|
||||
sdr_thread_read.max_fill = 0;
|
||||
sdr_thread_read.max_fill_timer += 1.0;
|
||||
delay = (double)sdr->thread_read.max_fill / 2.0 / (double)sdr_config->samplerate;
|
||||
sdr->thread_read.max_fill = 0;
|
||||
sdr->thread_read.max_fill_timer += 1.0;
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "read delay = %.3f ms\n", delay * 1000.0);
|
||||
}
|
||||
if (fill / 2 / sdr_oversample < num)
|
||||
num = fill / 2 / sdr_oversample;
|
||||
if (fill / 2 / sdr->oversample < num)
|
||||
num = fill / 2 / sdr->oversample;
|
||||
#ifdef DEBUG_BUFFER
|
||||
printf("Reading %d samples from read buffer.\n", num);
|
||||
#endif
|
||||
out = sdr_thread_read.out;
|
||||
out = sdr->thread_read.out;
|
||||
for (s = 0, ss = 0; s < num; s++) {
|
||||
buff[ss++] = sdr_thread_read.buffer[out];
|
||||
buff[ss++] = sdr_thread_read.buffer[out + 1];
|
||||
out = (out + 2 * sdr_oversample) % sdr_thread_read.buffer_size;
|
||||
buff[ss++] = sdr->thread_read.buffer[out];
|
||||
buff[ss++] = sdr->thread_read.buffer[out + 1];
|
||||
out = (out + 2 * sdr->oversample) % sdr->thread_read.buffer_size;
|
||||
}
|
||||
sdr_thread_read.out = out;
|
||||
sdr->thread_read.out = out;
|
||||
count = num;
|
||||
} else {
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd)
|
||||
if (sdr_config->uhd)
|
||||
count = uhd_receive(buff, num);
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy)
|
||||
if (sdr_config->soapy)
|
||||
count = soapy_receive(buff, num);
|
||||
#endif
|
||||
if (count <= 0)
|
||||
|
@ -780,28 +750,28 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
|||
}
|
||||
|
||||
/* how much do we need to send (in audio sample duration) to get the target delay (latspl) */
|
||||
int sdr_get_tosend(void __attribute__((__unused__)) *inst, int latspl)
|
||||
int sdr_get_tosend(void *inst, int latspl)
|
||||
{
|
||||
// sdr_t *sdr = (sdr_t *)inst;
|
||||
sdr_t *sdr = (sdr_t *)inst;
|
||||
int count = 0;
|
||||
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_use_uhd)
|
||||
count = uhd_get_tosend(latspl * sdr_oversample);
|
||||
if (sdr_config->uhd)
|
||||
count = uhd_get_tosend(latspl * sdr->oversample);
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_use_soapy)
|
||||
count = soapy_get_tosend(latspl * sdr_oversample);
|
||||
if (sdr_config->soapy)
|
||||
count = soapy_get_tosend(latspl * sdr->oversample);
|
||||
#endif
|
||||
if (count < 0)
|
||||
return count;
|
||||
count /= sdr_oversample;
|
||||
count /= sdr->oversample;
|
||||
|
||||
if (sdr_threads) {
|
||||
if (sdr->threads) {
|
||||
/* substract what we have in write buffer, because this is not jent sent to the SDR */
|
||||
int fill;
|
||||
|
||||
fill = (sdr_thread_write.in - sdr_thread_write.out + sdr_thread_write.buffer_size) % sdr_thread_write.buffer_size;
|
||||
fill = (sdr->thread_write.in - sdr->thread_write.out + sdr->thread_write.buffer_size) % sdr->thread_write.buffer_size;
|
||||
count -= fill / 2;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
int sdr_init(int sdr_uhd, int sdr_soapy, int channel, const char *device_args, const char *stream_args, const char *tune_args, const char *tx_antenna, const char *rx_antenna, double tx_gain, double rx_gain, int samplerate, double bandwidth, const char *write_iq_tx_wave, const char *write_iq_rx_wave, const char *read_iq_tx_wave, const char *read_iq_rx_wave, int latspl, int swap_links, int uhd_tx_timestamps);
|
||||
int sdr_start(void *inst);
|
||||
void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation);
|
||||
void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, int latspl, double bandwidth, double sample_deviation);
|
||||
void sdr_close(void *inst);
|
||||
int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal *paging_signal, int *on, int channels);
|
||||
int sdr_read(void *inst, sample_t **samples, int num, int channels);
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
/* Config for SDR
|
||||
*
|
||||
* (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
enum paging_signal;
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include "sample.h"
|
||||
#include "sdr.h"
|
||||
#include "sdr_config.h"
|
||||
|
||||
static int got_init = 0;
|
||||
extern int use_sdr;
|
||||
sdr_config_t *sdr_config = NULL;
|
||||
|
||||
void sdr_config_init(void)
|
||||
{
|
||||
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 = "";
|
||||
|
||||
got_init = 1;
|
||||
}
|
||||
|
||||
void sdr_config_print_help(void)
|
||||
{
|
||||
printf("\nSDR options:\n");
|
||||
/* - - */
|
||||
#ifdef HAVE_UHD
|
||||
printf(" --sdr-uhd\n");
|
||||
printf(" Force UHD driver\n");
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
printf(" --sdr-soapy\n");
|
||||
printf(" Force SoapySDR driver\n");
|
||||
#endif
|
||||
printf(" --sdr-channel <channel #>\n");
|
||||
printf(" Give channel number for multi channel SDR device (default = %d)\n", sdr_config->channel);
|
||||
printf(" --sdr-device-args <args>\n");
|
||||
printf(" --sdr-stream-args <args>\n");
|
||||
printf(" --sdr-tune-args <args>\n");
|
||||
printf(" Optional SDR device arguments, seperated by comma\n");
|
||||
printf(" e.g. --sdr-device-args <key>=<value>[,<key>=<value>[,...]]\n");
|
||||
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-bandwidth <bandwidth>\n");
|
||||
printf(" Give IF filter bandwidth to use. If not, sample rate is used.\n");
|
||||
printf(" --sdr-rx-antenna <name>\n");
|
||||
printf(" SDR device's RX antenna name, use 'list' to get a list\n");
|
||||
printf(" --sdr-tx-antenna <name>\n");
|
||||
printf(" SDR device's TX antenna name, use 'list' to get a list\n");
|
||||
printf(" --sdr-rx-gain <gain>\n");
|
||||
printf(" SDR device's RX gain in dB (default = %.1f)\n", sdr_config->rx_gain);
|
||||
printf(" --sdr-tx-gain <gain>\n");
|
||||
printf(" SDR device's TX gain in dB (default = %.1f)\n", sdr_config->tx_gain);
|
||||
printf(" --write-iq-rx-wave <file>\n");
|
||||
printf(" Write received IQ data to given wave file.\n");
|
||||
printf(" --write-iq-tx-wave <file>\n");
|
||||
printf(" Write transmitted IQ data to given wave file.\n");
|
||||
printf(" --read-iq-rx-wave <file>\n");
|
||||
printf(" Replace received IQ data by given wave file.\n");
|
||||
printf(" --read-iq-tx-wave <file>\n");
|
||||
printf(" Replace transmitted IQ data by given wave file.\n");
|
||||
printf(" --sdr-swap-links\n");
|
||||
printf(" Swap RX and TX frequencies for loopback tests over the air.\n");
|
||||
#ifdef HAVE_UHD
|
||||
printf(" --sdr-uhd-tx-timestamps\n");
|
||||
printf(" Use TX timestamps on UHD device. (May not work with some devices!)\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void sdr_config_print_hotkeys(void)
|
||||
{
|
||||
printf("Press 'i' key to toggle display of RX I/Q vector.\n");
|
||||
printf("Press 's' key to toggle display of RX spectrum.\n");
|
||||
}
|
||||
|
||||
#define OPT_SDR_UHD 1500
|
||||
#define OPT_SDR_SOAPY 1501
|
||||
#define OPT_SDR_CHANNEL 1502
|
||||
#define OPT_SDR_DEVICE_ARGS 1503
|
||||
#define OPT_SDR_STREAM_ARGS 1504
|
||||
#define OPT_SDR_TUNE_ARGS 1505
|
||||
#define OPT_SDR_RX_ANTENNA 1506
|
||||
#define OPT_SDR_TX_ANTENNA 1507
|
||||
#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
|
||||
|
||||
struct option sdr_config_long_options[] = {
|
||||
{"sdr-uhd", 0, 0, OPT_SDR_UHD},
|
||||
{"sdr-soapy", 0, 0, OPT_SDR_SOAPY},
|
||||
{"sdr-channel", 1, 0, OPT_SDR_CHANNEL},
|
||||
{"sdr-device-args", 1, 0, OPT_SDR_DEVICE_ARGS},
|
||||
{"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-bandwidth", 1, 0, OPT_SDR_BANDWIDTH},
|
||||
{"sdr-rx-antenna", 1, 0, OPT_SDR_RX_ANTENNA},
|
||||
{"sdr-tx-antenna", 1, 0, OPT_SDR_TX_ANTENNA},
|
||||
{"sdr-rx-gain", 1, 0, OPT_SDR_RX_GAIN},
|
||||
{"sdr-tx-gain", 1, 0, OPT_SDR_TX_GAIN},
|
||||
{"write-iq-rx-wave", 1, 0, OPT_WRITE_IQ_RX_WAVE},
|
||||
{"write-iq-tx-wave", 1, 0, OPT_WRITE_IQ_TX_WAVE},
|
||||
{"read-iq-rx-wave", 1, 0, OPT_READ_IQ_RX_WAVE},
|
||||
{"read-iq-tx-wave", 1, 0, OPT_READ_IQ_TX_WAVE},
|
||||
{"sdr-swap-links", 0, 0, OPT_SDR_SWAP_LINKS},
|
||||
{"sdr-uhd-tx-timestamps", 0, 0, OPT_SDR_UHD_TX_TS},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
const char *sdr_config_optstring = "";
|
||||
|
||||
int sdr_config_opt_switch(int c, int *skip_args)
|
||||
{
|
||||
switch (c) {
|
||||
case OPT_SDR_UHD:
|
||||
#ifdef HAVE_UHD
|
||||
sdr_config->uhd = 1;
|
||||
use_sdr = 1;
|
||||
#else
|
||||
fprintf(stderr, "UHD SDR support not compiled in!\n");
|
||||
exit(0);
|
||||
#endif
|
||||
*skip_args += 1;
|
||||
break;
|
||||
case OPT_SDR_SOAPY:
|
||||
#ifdef HAVE_SOAPY
|
||||
sdr_config->soapy = 1;
|
||||
use_sdr = 1;
|
||||
#else
|
||||
fprintf(stderr, "SoapySDR support not compiled in!\n");
|
||||
exit(0);
|
||||
#endif
|
||||
*skip_args += 1;
|
||||
break;
|
||||
case OPT_SDR_CHANNEL:
|
||||
sdr_config->channel = atoi(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_DEVICE_ARGS:
|
||||
sdr_config->device_args = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_STREAM_ARGS:
|
||||
sdr_config->stream_args = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_TUNE_ARGS:
|
||||
sdr_config->tune_args = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_SAMPLERATE:
|
||||
sdr_config->samplerate = atoi(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_BANDWIDTH:
|
||||
sdr_config->bandwidth = atof(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_RX_ANTENNA:
|
||||
sdr_config->rx_antenna = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_TX_ANTENNA:
|
||||
sdr_config->tx_antenna = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_RX_GAIN:
|
||||
sdr_config->rx_gain = atof(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_TX_GAIN:
|
||||
sdr_config->tx_gain = atof(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_WRITE_IQ_RX_WAVE:
|
||||
sdr_config->write_iq_rx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_WRITE_IQ_TX_WAVE:
|
||||
sdr_config->write_iq_tx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_READ_IQ_RX_WAVE:
|
||||
sdr_config->read_iq_rx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_READ_IQ_TX_WAVE:
|
||||
sdr_config->read_iq_tx_wave = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case OPT_SDR_SWAP_LINKS:
|
||||
sdr_config->swap_links = 1;
|
||||
*skip_args += 1;
|
||||
break;
|
||||
case OPT_SDR_UHD_TX_TS:
|
||||
sdr_config->uhd_tx_timestamps = 1;
|
||||
*skip_args += 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sdr_configure(int samplerate)
|
||||
{
|
||||
if (!got_init) {
|
||||
fprintf(stderr, "sdr_config_init was not called, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* no sdr selected -> return 0 */
|
||||
if (!sdr_config->uhd && !sdr_config->soapy)
|
||||
return 0;
|
||||
|
||||
if ((sdr_config->uhd == 1 && sdr_config->soapy == 1)) {
|
||||
fprintf(stderr, "You must choose which one you want: --sdr-uhd or --sdr-soapy\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (sdr_config->samplerate == 0)
|
||||
sdr_config->samplerate = samplerate;
|
||||
if (sdr_config->bandwidth == 0.0)
|
||||
sdr_config->bandwidth = (double)sdr_config->samplerate;
|
||||
|
||||
/* sdr selected -> return 1 */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
typedef struct sdr_config {
|
||||
int uhd, /* select UHD API */
|
||||
soapy; /* select Soapy SDR API */
|
||||
int channel; /* channel number */
|
||||
const char *device_args, /* arguments */
|
||||
*stream_args,
|
||||
*tune_args;
|
||||
int samplerate; /* ADC/DAC sample rate */
|
||||
double bandwidth; /* IF bandwidth */
|
||||
double tx_gain, /* gain */
|
||||
rx_gain;
|
||||
const char *tx_antenna, /* list/override antennas */
|
||||
*rx_antenna;
|
||||
const char *write_iq_tx_wave; /* wave recording and playback */
|
||||
const char *write_iq_rx_wave;
|
||||
const char *read_iq_tx_wave;
|
||||
const char *read_iq_rx_wave;
|
||||
int swap_links; /* swap DL and UL frequency */
|
||||
int uhd_tx_timestamps; /* use UHD time stamps */
|
||||
} sdr_config_t;
|
||||
|
||||
extern sdr_config_t *sdr_config;
|
||||
|
||||
void sdr_config_init(void);
|
||||
void sdr_config_print_help(void);
|
||||
void sdr_config_print_hotkeys(void);
|
||||
extern struct option sdr_config_long_options[];
|
||||
extern const char *sdr_config_optstring;
|
||||
int sdr_config_opt_switch(int c, int *skip_args);
|
||||
int sdr_configure(int samplerate);
|
||||
|
|
@ -153,7 +153,7 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int sender_open_audio(void)
|
||||
int sender_open_audio(int latspl)
|
||||
{
|
||||
sender_t *master, *inst;
|
||||
int channels;
|
||||
|
@ -212,7 +212,7 @@ int sender_open_audio(void)
|
|||
}
|
||||
|
||||
/* open device */
|
||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->max_deviation, master->max_modulation);
|
||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, latspl, master->max_deviation, master->max_modulation);
|
||||
if (!master->audio) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No audio device!\n");
|
||||
return -EIO;
|
||||
|
|
|
@ -41,7 +41,7 @@ typedef struct sender {
|
|||
/* audio */
|
||||
void *audio;
|
||||
char audiodev[64]; /* audio device name (alsa or sdr) */
|
||||
void *(*audio_open)(const char *, double *, double *, int, double, int, double, double);
|
||||
void *(*audio_open)(const char *, double *, double *, int, double, int, int, double, double);
|
||||
int (*audio_start)(void *);
|
||||
void (*audio_close)(void *);
|
||||
int (*audio_write)(void *, sample_t **, uint8_t **, int, enum paging_signal *, int *, int);
|
||||
|
@ -93,7 +93,7 @@ extern int cant_recover;
|
|||
int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int use_sdr, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, double loss_volume, enum paging_signal paging_signal);
|
||||
void sender_destroy(sender_t *sender);
|
||||
void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double dBm0_deviation, double max_display);
|
||||
int sender_open_audio(void);
|
||||
int sender_open_audio(int latspl);
|
||||
int sender_start_audio(void);
|
||||
void process_sender_audio(sender_t *sender, int *quit, int latspl);
|
||||
void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int count);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
enum paging_signal;
|
||||
|
||||
void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation);
|
||||
void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, int latspl, double bandwidth, double sample_deviation);
|
||||
int sound_start(void *inst);
|
||||
void sound_close(void *inst);
|
||||
int sound_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal *paging_signal, int *on, int channels);
|
||||
|
|
|
@ -128,7 +128,7 @@ static int sound_prepare(sound_t *sound)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, double __attribute__((unused)) paging_frequency, int samplerate, double max_deviation, double __attribute__((unused)) max_modulation)
|
||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, double __attribute__((unused)) paging_frequency, int samplerate, int __attribute((unused)) latspl, double max_deviation, double __attribute__((unused)) max_modulation)
|
||||
{
|
||||
sound_t *sound;
|
||||
int rc;
|
||||
|
|
|
@ -59,7 +59,7 @@ int send_callerid = 0;
|
|||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
print_help_common(arg0, "[-N 900] -Y <traffic area> | list [-I 1] [-0 1] ");
|
||||
main_mobile_print_help(arg0, "[-N 900] -Y <traffic area> | list [-I 1] [-0 1] ");
|
||||
/* - - */
|
||||
printf(" -N --nmt-system 450/900\n");
|
||||
printf(" Give NMT type as first paramer. (default = '%d')\n", nmt_system);
|
||||
|
@ -94,7 +94,7 @@ void print_help(const char *arg0)
|
|||
printf(" If set, the caller ID is sent while ringing the phone. (default = '%d')\n", send_callerid);
|
||||
printf("\nstation-id: Give 7 digits of station-id, you don't need to enter it\n");
|
||||
printf(" for every start of this program.\n");
|
||||
print_hotkeys_common();
|
||||
main_mobile_print_hotkeys();
|
||||
}
|
||||
|
||||
static int handle_options(int argc, char **argv)
|
||||
|
@ -116,7 +116,7 @@ static int handle_options(int argc, char **argv)
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
set_options_common("N:T:P:Y:A:C:0:S:I:", long_options_special);
|
||||
main_mobile_set_options("N:T:P:Y:A:C:0:S:I:", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c, rc;
|
||||
|
@ -224,7 +224,7 @@ error_ta:
|
|||
skip_args += 2;
|
||||
break;
|
||||
default:
|
||||
opt_switch_common(c, argv[0], &skip_args);
|
||||
main_mobile_opt_switch(c, argv[0], &skip_args);
|
||||
}
|
||||
first_option = 0;
|
||||
}
|
||||
|
@ -290,6 +290,8 @@ int main(int argc, char *argv[])
|
|||
init_nmt_tones();
|
||||
init_announcement();
|
||||
|
||||
main_mobile_init();
|
||||
|
||||
skip_args = handle_options(argc, argv);
|
||||
argc -= skip_args;
|
||||
argv += skip_args;
|
||||
|
|
|
@ -52,7 +52,7 @@ enum r2000_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_CC_TC };
|
|||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
print_help_common(arg0, "-R <relais number> [option] ");
|
||||
main_mobile_print_help(arg0, "-R <relais number> [option] ");
|
||||
/* - - */
|
||||
printf(" -B --band <number> | list\n");
|
||||
printf(" -B --bande <number> | list\n");
|
||||
|
@ -96,7 +96,7 @@ void print_help(const char *arg0)
|
|||
printf("\nstation-id: Give 1 digit of station mobile type + 3 digits of home relais ID\n");
|
||||
printf(" + 5 digits of mobile ID.\n");
|
||||
printf(" (e.g. 103200819 = type 1, relais ID 32, mobile ID 819)\n");
|
||||
print_hotkeys_common();
|
||||
main_mobile_print_hotkeys();
|
||||
}
|
||||
|
||||
#define OPT_BANDE 256
|
||||
|
@ -124,7 +124,7 @@ static int handle_options(int argc, char **argv)
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
set_options_common("B:T:R:I:P:C:N:S", long_options_special);
|
||||
main_mobile_set_options("B:T:R:I:P:C:N:S", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c, rc;
|
||||
|
@ -264,7 +264,7 @@ static int handle_options(int argc, char **argv)
|
|||
skip_args += 1;
|
||||
break;
|
||||
default:
|
||||
opt_switch_common(c, argv[0], &skip_args);
|
||||
main_mobile_opt_switch(c, argv[0], &skip_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,6 +284,8 @@ int main(int argc, char *argv[])
|
|||
/* init tones */
|
||||
init_radiocom_tones();
|
||||
|
||||
main_mobile_init();
|
||||
|
||||
skip_args = handle_options(argc, argv);
|
||||
argc -= skip_args;
|
||||
argv += skip_args;
|
||||
|
|
Loading…
Reference in New Issue