/* * This file is part of the bladeRF project: * http://www.github.com/nuand/bladeRF * * Copyright (C) 2014-2015 Nuand LLC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include "devcfg.h" #include "conversions.h" #define DEVCFG_DFLT_TX_FREQ 1000000000 #define DEVCFG_DFLT_TXVGA1 (-14) #define DEVCFG_DFLT_TXVGA2 0 #define DEVCFG_DFLT_RX_FREQ 1000000000 #define DEVCFG_DFLT_LNAGAIN BLADERF_LNA_GAIN_MAX #define DEVCFG_DFLT_RXVGA1 30 #define DEVCFG_DFLT_RXVGA2 0 #define DEVCFG_DFLT_SAMPLERATE 2000000 #define DEVCFG_DFLT_BANDWIDTH 1500000 #define DEVCFG_DFLT_SAMPLES_PER_BUF 8192 #define DEVCFG_DFLT_NUM_BUFFERS 64 #define DEVCFG_DFLT_NUM_TRANSFERS 16 #define DEVCFG_DFLT_STREAM_TIMEMOUT_MS 5000 #define DEVCFG_DFLT_SYNC_TIMEOUT_MS (2 * DEVCFG_DFLT_STREAM_TIMEMOUT_MS) #define OPTION_HELP 'h' #define OPTION_DEVICE 'd' #define OPTION_LOOPBACK 'l' #define OPTION_VERBOSITY 'v' #define OPTION_SAMPLERATE 's' #define OPTION_RX_SAMPLERATE 0x80 #define OPTION_TX_SAMPLERATE 0x81 #define OPTION_BANDWIDTH 'b' #define OPTION_RX_BANDWIDTH 0x82 #define OPTION_TX_BANDWIDTH 0x83 #define OPTION_FREQUENCY 'f' #define OPTION_RX_FREQUENCY 0x84 #define OPTION_TX_FREQUENCY 0x85 #define OPTION_LNAGAIN 0x86 #define OPTION_RXVGA1 0x87 #define OPTION_RXVGA2 0x88 #define OPTION_TXVGA1 0x89 #define OPTION_TXVGA2 0x8a #define OPTION_SAMPLES_PER_BUF 0x91 #define OPTION_NUM_BUFFERS 0x92 #define OPTION_NUM_TRANSFERS 0x93 #define OPTION_STREAM_TIMEOUT 0x94 #define OPTION_SYNC_TIMEOUT 0x95 #define OPTION_ENABLE_XB200 0x96 static const numeric_suffix hz_suffixes[] = { { "K", 1000 }, { "KHz", 1000 }, { "M", 1000000 }, { "MHz", 1000000 }, { "G", 1000000000 }, { "GHz", 1000000000 }, }; static const struct option devcfg_long_options[] = { { "help", no_argument, 0, OPTION_HELP }, { "device", required_argument, 0, OPTION_DEVICE }, { "verbosity", required_argument, 0, OPTION_VERBOSITY }, { "samplerate", required_argument, 0, OPTION_SAMPLERATE }, { "rx-samplerate", required_argument, 0, OPTION_RX_SAMPLERATE }, { "tx-samplerate", required_argument, 0, OPTION_TX_SAMPLERATE }, { "bandwidth", required_argument, 0, OPTION_BANDWIDTH }, { "rx-bandwidth", required_argument, 0, OPTION_RX_BANDWIDTH }, { "tx-bandwidth", required_argument, 0, OPTION_TX_BANDWIDTH }, { "frequency", required_argument, 0, OPTION_FREQUENCY }, { "rx-frequency", required_argument, 0, OPTION_RX_FREQUENCY }, { "tx-frequency", required_argument, 0, OPTION_TX_FREQUENCY }, { "lna-gain", required_argument, 0, OPTION_LNAGAIN }, { "rxvga1-gain", required_argument, 0, OPTION_RXVGA1 }, { "rxvga2-gain", required_argument, 0, OPTION_RXVGA2 }, { "txvga1-gain", required_argument, 0, OPTION_TXVGA1 }, { "txvga2-gain", required_argument, 0, OPTION_TXVGA2 }, { "loopback", required_argument, 0, OPTION_LOOPBACK }, { "xb200", no_argument, 0, OPTION_ENABLE_XB200 }, { "samples-per-buffer", required_argument, 0, OPTION_SAMPLES_PER_BUF }, { "num-buffers", required_argument, 0, OPTION_NUM_BUFFERS }, { "num-transfers", required_argument, 0, OPTION_NUM_TRANSFERS }, { "stream-timeout", required_argument, 0, OPTION_STREAM_TIMEOUT }, { "sync-timeout", required_argument, 0, OPTION_SYNC_TIMEOUT }, }; void devcfg_init(struct devcfg *c) { c->device_specifier = NULL; c->tx_frequency = DEVCFG_DFLT_TX_FREQ; c->tx_bandwidth = DEVCFG_DFLT_BANDWIDTH; c->tx_samplerate = DEVCFG_DFLT_SAMPLERATE; c->txvga1 = DEVCFG_DFLT_TXVGA1; c->txvga2 = DEVCFG_DFLT_TXVGA2; c->rx_frequency = DEVCFG_DFLT_TX_FREQ; c->rx_bandwidth = DEVCFG_DFLT_BANDWIDTH; c->rx_samplerate = DEVCFG_DFLT_SAMPLERATE; c->lnagain = DEVCFG_DFLT_LNAGAIN; c->rxvga1 = DEVCFG_DFLT_RXVGA1; c->rxvga2 = DEVCFG_DFLT_RXVGA2; c->loopback = BLADERF_LB_NONE; c->verbosity = BLADERF_LOG_LEVEL_INFO; c->enable_xb200 = false; c->samples_per_buffer = DEVCFG_DFLT_SAMPLES_PER_BUF; c->num_buffers = DEVCFG_DFLT_NUM_BUFFERS; c->num_transfers = DEVCFG_DFLT_NUM_TRANSFERS; c->stream_timeout_ms = DEVCFG_DFLT_STREAM_TIMEMOUT_MS; c->sync_timeout_ms = DEVCFG_DFLT_SYNC_TIMEOUT_MS; } void devcfg_deinit(struct devcfg *c) { free(c->device_specifier); } void devcfg_print_common_help(const char *title) { if (title != NULL) { printf("%s", title); } printf(" -h, --help Show this help text.\n"); printf(" -d, --device Open the specified device.\n"); printf(" -v, --verbosity Set the libbladeRF verbosity level.\n"); printf(" --xb200 Enable the XB-200. This will remain enabled\n"); printf(" until the device is power-cycled.\n"); printf("\n"); printf(" -f, --frequency Set RX and TX to the specified frequency.\n"); printf(" --rx-frequency Set RX to the specified frequency.\n"); printf(" --tx-frequency Set TX to the specified frequency.\n"); printf("\n"); printf(" -s, --samplerate Set RX and TX to the specified sample rate.\n"); printf(" --rx-samplerate Set RX to the specified sample rate.\n"); printf(" --tx-samplerate Set RX to the specified sample rate.\n"); printf("\n"); printf(" -b, --bandwidth Set RX and TX to the specified bandwidth.\n"); printf(" --rx-bandwidth Set RX to the specified bandwidth.\n"); printf(" --tx-bandwidth Set TX to the specified bandwidth.\n"); printf("\n"); printf(" --lna-gain Set the RX LNA to the specified gain.\n"); printf(" Options are: bypass, mid, max\n"); printf(" --rxvga1-gain Set RX VGA1 to the specified gain.\n"); printf(" --rxvga2-gain Set RX VGA2 to the specified gain.\n"); printf(" --txvga1-gain Set TX VGA1 to the specified gain.\n"); printf(" --txvga2-gain Set TX VGA2 to the specified gain.\n"); printf("\n"); printf(" --num-buffers Allocate sample buffers.\n"); printf(" --samples-per-buffer Allocate samples in each sample buffer.\n"); printf(" --num-transfers Utilize up to simultaneous USB transfers.\n"); printf(" --stream-timeout Set stream timeout to milliseconds.\n"); printf(" --sync-timeout Set sync function timeout to milliseconds.\n"); } struct option * devcfg_get_long_options(const struct option *app_options) { struct option *ret; size_t app_size = 0; const size_t devcfg_size = sizeof(devcfg_long_options); while (app_options[app_size].name != NULL) { app_size++; } /* Account for 0-entry */ app_size = (app_size + 1) * sizeof(app_options[0]); ret = malloc(devcfg_size + app_size); if (ret != NULL) { memcpy(ret, &devcfg_long_options, devcfg_size); memcpy(ret + ARRAY_SIZE(devcfg_long_options) , app_options, app_size); } return ret; } int devcfg_handle_args(int argc, char **argv, const char *option_str, const struct option *long_options, struct devcfg *config) { int c; bool ok; int status; unsigned int freq_min; while ((c = getopt_long(argc, argv, option_str, long_options, NULL)) >= 0) { if (config->enable_xb200) { freq_min = BLADERF_FREQUENCY_MIN_XB200; } else { freq_min = BLADERF_FREQUENCY_MIN; } switch (c) { case OPTION_HELP: return 1; break; case OPTION_DEVICE: if (config->device_specifier == NULL) { config->device_specifier = strdup(optarg); if (config->device_specifier == NULL) { perror("strdup"); return -1; } } break; case OPTION_LOOPBACK: status = str2loopback(optarg, &config->loopback); if (status != 0) { fprintf(stderr, "Invalid loopback mode: %s\n", optarg); return -1; } break; case OPTION_VERBOSITY: config->verbosity = str2loglevel(optarg, &ok); if (!ok) { fprintf(stderr, "Invalid verbosity level: %s\n", optarg); return -1; } break; case OPTION_ENABLE_XB200: config->enable_xb200 = true; break; case OPTION_FREQUENCY: config->rx_frequency = str2uint_suffix(optarg, freq_min, BLADERF_FREQUENCY_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid frequency: %s\n", optarg); return -1; } else { config->tx_frequency = config->rx_frequency; } break; case OPTION_RX_FREQUENCY: config->rx_frequency = str2uint_suffix(optarg, freq_min, BLADERF_FREQUENCY_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid RX frequency: %s\n", optarg); return -1; } break; case OPTION_TX_FREQUENCY: config->tx_frequency = str2uint_suffix(optarg, freq_min, BLADERF_FREQUENCY_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid TX frequency: %s\n", optarg); return -1; } break; case OPTION_SAMPLERATE: config->rx_samplerate = str2uint_suffix(optarg, BLADERF_SAMPLERATE_MIN, BLADERF_SAMPLERATE_REC_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid sample rate: %s\n", optarg); return -1; } else { config->tx_samplerate = config->rx_samplerate; } break; case OPTION_RX_SAMPLERATE: config->rx_samplerate = str2uint_suffix(optarg, BLADERF_SAMPLERATE_MIN, BLADERF_SAMPLERATE_REC_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid RX sample rate: %s\n", optarg); return -1; } break; case OPTION_TX_SAMPLERATE: config->tx_samplerate = str2uint_suffix(optarg, BLADERF_SAMPLERATE_MIN, BLADERF_SAMPLERATE_REC_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid TX sample rate: %s\n", optarg); return -1; } break; case OPTION_BANDWIDTH: config->rx_bandwidth = str2uint_suffix(optarg, BLADERF_BANDWIDTH_MIN, BLADERF_BANDWIDTH_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid bandwidth: %s\n", optarg); return -1; } else { config->tx_bandwidth = config->rx_bandwidth; } break; case OPTION_RX_BANDWIDTH: config->rx_bandwidth = str2uint_suffix(optarg, BLADERF_BANDWIDTH_MIN, BLADERF_BANDWIDTH_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid RX bandwidth: %s\n", optarg); return -1; } break; case OPTION_TX_BANDWIDTH: config->tx_bandwidth = str2uint_suffix(optarg, BLADERF_BANDWIDTH_MIN, BLADERF_BANDWIDTH_MAX, hz_suffixes, ARRAY_SIZE(hz_suffixes), &ok); if (!ok) { fprintf(stderr, "Invalid TX bandwidth: %s\n", optarg); return -1; } break; case OPTION_LNAGAIN: status = str2lnagain(optarg, &config->lnagain); if (status != 0) { fprintf(stderr, "Invalid RX LNA gain: %s\n", optarg); return -1; } break; case OPTION_RXVGA1: config->rxvga1 = str2int(optarg, BLADERF_RXVGA1_GAIN_MIN, BLADERF_RXVGA1_GAIN_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid RXVGA1 gain: %s\n", optarg); return -1; } break; case OPTION_RXVGA2: config->rxvga2 = str2int(optarg, BLADERF_RXVGA2_GAIN_MIN, BLADERF_RXVGA2_GAIN_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid RXVGA1 gain: %s\n", optarg); return -1; } break; case OPTION_TXVGA1: config->txvga1 = str2int(optarg, BLADERF_TXVGA1_GAIN_MIN, BLADERF_TXVGA1_GAIN_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid TXVGA1 gain: %s\n", optarg); return -1; } break; case OPTION_TXVGA2: config->txvga2 = str2int(optarg, BLADERF_TXVGA2_GAIN_MIN, BLADERF_TXVGA2_GAIN_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid TXVGA2 gain: %s\n", optarg); return -1; } break; case OPTION_NUM_BUFFERS: config->num_buffers = str2uint(optarg, 1, UINT_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid buffer count: %s\n", optarg); return -1; } break; case OPTION_SAMPLES_PER_BUF: config->samples_per_buffer = str2uint(optarg, 1024, UINT_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid buffer size (in samples): %s\n", optarg); return -1; } break; case OPTION_NUM_TRANSFERS: config->num_transfers = str2uint(optarg, 1, UINT_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid transfer count: %s\n", optarg); return -1; } break; case OPTION_STREAM_TIMEOUT: config->stream_timeout_ms = str2uint(optarg, 0, UINT_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid stream timeout: %s\n", optarg); return -1; } break; case OPTION_SYNC_TIMEOUT: config->sync_timeout_ms = str2uint(optarg, 0, UINT_MAX, &ok); if (!ok) { fprintf(stderr, "Invalid sync function timeout: %s\n", optarg); return -1; } break; } } return 0; } int devcfg_apply(struct bladerf *dev, const struct devcfg *c) { int status; const char *board_name; board_name = bladerf_get_board_name(dev); bladerf_log_set_verbosity(c->verbosity); status = bladerf_set_loopback(dev, c->loopback); if (status != 0) { fprintf(stderr, "Failed to set loopback: %s\n", bladerf_strerror(status)); return -1; } if (c->enable_xb200) { status = bladerf_expansion_attach(dev, BLADERF_XB_200); if (status != 0) { fprintf(stderr, "Failed to attach XB-200.\n"); return -1; } } status = bladerf_set_frequency(dev, BLADERF_MODULE_RX, c->rx_frequency); if (status != 0) { fprintf(stderr, "Failed to set RX frequency: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_frequency(dev, BLADERF_MODULE_TX, c->tx_frequency); if (status != 0) { fprintf(stderr, "Failed to set TX frequency: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_sample_rate(dev, BLADERF_MODULE_RX, c->rx_samplerate, NULL); if (status != 0) { fprintf(stderr, "Failed to set RX sample rate:%s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_sample_rate(dev, BLADERF_MODULE_TX, c->tx_samplerate, NULL); if (status != 0) { fprintf(stderr, "Failed to set TX sample rate: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_bandwidth(dev, BLADERF_MODULE_RX, c->rx_bandwidth, NULL); if (status != 0) { fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_bandwidth(dev, BLADERF_MODULE_TX, c->tx_bandwidth, NULL); if (status != 0) { fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); return -1; } if (strcasecmp(board_name, "bladerf1") == 0) { status = bladerf_set_lna_gain(dev, c->lnagain); if (status != 0) { fprintf(stderr, "Failed to set RX LNA gain: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_rxvga1(dev, c->rxvga1); if (status != 0) { fprintf(stderr, "Failed to set RX VGA1 gain: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_rxvga2(dev, c->rxvga2); if (status != 0) { fprintf(stderr, "Failed to set RX VGA2 gain: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_txvga1(dev, c->txvga1); if (status != 0) { fprintf(stderr, "Failed to set TX VGA1 gain: %s\n", bladerf_strerror(status)); return -1; } status = bladerf_set_txvga2(dev, c->txvga2); if (status != 0) { fprintf(stderr, "Failed to set TX VGA2 gain: %s\n", bladerf_strerror(status)); return -1; } } return 0; } int devcfg_perform_sync_config(struct bladerf *dev, bladerf_module module, bladerf_format format, const struct devcfg *config, bool enable_module) { int status = bladerf_sync_config(dev, module, format, config->num_buffers, config->samples_per_buffer, config->num_transfers, config->stream_timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure %s: %s\n", module == BLADERF_MODULE_RX ? "RX" : "TX", bladerf_strerror(status)); return -1; } if (enable_module) { status = bladerf_enable_module(dev, module, true); if (status != 0) { fprintf(stderr, "Failed to enable %s module: %s\n", module == BLADERF_MODULE_RX ? "RX" : "TX", bladerf_strerror(status)); } } return 0; }