diff options
Diffstat (limited to 'Radio/HW/BladeRF/common/src/conversions.c')
-rw-r--r-- | Radio/HW/BladeRF/common/src/conversions.c | 730 |
1 files changed, 730 insertions, 0 deletions
diff --git a/Radio/HW/BladeRF/common/src/conversions.c b/Radio/HW/BladeRF/common/src/conversions.c new file mode 100644 index 0000000..ad08520 --- /dev/null +++ b/Radio/HW/BladeRF/common/src/conversions.c @@ -0,0 +1,730 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (c) 2017-2018 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 "conversions.h" + +int str2version(const char *str, struct bladerf_version *version) +{ + unsigned long tmp; + const char *start = str; + char *end; + + /* Major version */ + errno = 0; + tmp = strtoul(start, &end, 10); + if (errno != 0 || tmp > UINT16_MAX || end == start || *end != '.') { + return -1; + } + version->major = (uint16_t)tmp; + + /* Minor version */ + if (end[0] == '\0' || end[1] == '\0') { + return -1; + } + errno = 0; + start = &end[1]; + tmp = strtoul(start, &end, 10); + if (errno != 0 || tmp > UINT16_MAX || end == start || *end != '.') { + return -1; + } + version->minor = (uint16_t)tmp; + + /* Patch version */ + if (end[0] == '\0' || end[1] == '\0') { + return -1; + } + errno = 0; + start = &end[1]; + tmp = strtoul(start, &end, 10); + if (errno != 0 || tmp > UINT16_MAX || end == start || + (*end != '-' && *end != '\0')) { + return -1; + } + version->patch = (uint16_t)tmp; + + version->describe = str; + + return 0; +} + +const char *devspeed2str(bladerf_dev_speed speed) +{ + switch (speed) { + case BLADERF_DEVICE_SPEED_HIGH: + /* Yeah, the USB IF actually spelled it "Hi" instead of "High". + * I know. It hurts me too. */ + return "Hi-Speed"; + + case BLADERF_DEVICE_SPEED_SUPER: + /* ...and no hyphen :( */ + return "SuperSpeed"; + + default: + return "Unknown"; + } +} + +bladerf_log_level str2loglevel(const char *str, bool *ok) +{ + bladerf_log_level level = BLADERF_LOG_LEVEL_ERROR; + bool valid = true; + + if (!strcasecmp(str, "critical")) { + level = BLADERF_LOG_LEVEL_CRITICAL; + } else if (!strcasecmp(str, "error")) { + level = BLADERF_LOG_LEVEL_ERROR; + } else if (!strcasecmp(str, "warning")) { + level = BLADERF_LOG_LEVEL_WARNING; + } else if (!strcasecmp(str, "info")) { + level = BLADERF_LOG_LEVEL_INFO; + } else if (!strcasecmp(str, "debug")) { + level = BLADERF_LOG_LEVEL_DEBUG; + } else if (!strcasecmp(str, "verbose")) { + level = BLADERF_LOG_LEVEL_VERBOSE; + } else { + valid = false; + } + + *ok = valid; + return level; +} + +const char *module2str(bladerf_module m) +{ + switch (m) { + case BLADERF_MODULE_RX: + return "RX"; + case BLADERF_MODULE_TX: + return "TX"; + default: + return "Unknown"; + } +} + +bladerf_module str2module(const char *str) +{ + if (!strcasecmp(str, "RX")) { + return BLADERF_MODULE_RX; + } else if (!strcasecmp(str, "TX")) { + return BLADERF_MODULE_TX; + } else { + return BLADERF_MODULE_INVALID; + } +} + +const char *channel2str(bladerf_channel ch) +{ + switch (ch) { + case BLADERF_CHANNEL_RX(0): + return "RX1"; + case BLADERF_CHANNEL_TX(0): + return "TX1"; + case BLADERF_CHANNEL_RX(1): + return "RX2"; + case BLADERF_CHANNEL_TX(1): + return "TX2"; + default: + return "Unknown"; + } +} + +bladerf_channel str2channel(char const *str) +{ + bladerf_channel rv; + + if (strcasecmp(str, "rx") == 0 || strcasecmp(str, "rx1") == 0) { + rv = BLADERF_CHANNEL_RX(0); + } else if (strcasecmp(str, "rx2") == 0) { + rv = BLADERF_CHANNEL_RX(1); + } else if (strcasecmp(str, "tx") == 0 || strcasecmp(str, "tx1") == 0) { + rv = BLADERF_CHANNEL_TX(0); + } else if (strcasecmp(str, "tx2") == 0) { + rv = BLADERF_CHANNEL_TX(1); + } else { + rv = BLADERF_CHANNEL_INVALID; + } + + return rv; +} + +bladerf_direction channel2direction (bladerf_channel ch) { + if (ch == BLADERF_CHANNEL_RX(0) || ch == BLADERF_CHANNEL_RX(1)) { + return BLADERF_RX; + } else { + return BLADERF_TX; + } +} + +const char *direction2str(bladerf_direction dir) +{ + switch (dir) { + case BLADERF_RX: + return "RX"; + case BLADERF_TX: + return "TX"; + default: + return "Unknown"; + } +} + +const char *trigger2str(bladerf_trigger_signal trigger) +{ + switch (trigger) { + case BLADERF_TRIGGER_J71_4: + return "J71-4"; + + case BLADERF_TRIGGER_J51_1: + return "J51-1"; + + case BLADERF_TRIGGER_MINI_EXP_1: + return "MiniExp-1"; + + case BLADERF_TRIGGER_USER_0: + return "User-0"; + + case BLADERF_TRIGGER_USER_1: + return "User-1"; + + case BLADERF_TRIGGER_USER_2: + return "User-2"; + + case BLADERF_TRIGGER_USER_3: + return "User-3"; + + case BLADERF_TRIGGER_USER_4: + return "User-4"; + + case BLADERF_TRIGGER_USER_5: + return "User-5"; + + case BLADERF_TRIGGER_USER_6: + return "User-6"; + + case BLADERF_TRIGGER_USER_7: + return "User-7"; + + default: + return "Unknown"; + } +} + +bladerf_trigger_signal str2trigger(const char *str) +{ + if (!strcasecmp("J71-4", str)) { + return BLADERF_TRIGGER_J71_4; + } else if (!strcasecmp("J51-1", str)) { + return BLADERF_TRIGGER_J51_1; + } else if (!strcasecmp("Miniexp-1", str)) { + return BLADERF_TRIGGER_MINI_EXP_1; + } else if (!strcasecmp("User-0", str)) { + return BLADERF_TRIGGER_USER_0; + } else if (!strcasecmp("User-1", str)) { + return BLADERF_TRIGGER_USER_1; + } else if (!strcasecmp("User-2", str)) { + return BLADERF_TRIGGER_USER_2; + } else if (!strcasecmp("User-3", str)) { + return BLADERF_TRIGGER_USER_3; + } else if (!strcasecmp("User-4", str)) { + return BLADERF_TRIGGER_USER_4; + } else if (!strcasecmp("User-5", str)) { + return BLADERF_TRIGGER_USER_5; + } else if (!strcasecmp("User-6", str)) { + return BLADERF_TRIGGER_USER_6; + } else if (!strcasecmp("User-7", str)) { + return BLADERF_TRIGGER_USER_7; + } else { + return BLADERF_TRIGGER_INVALID; + } +} + +const char *triggerrole2str(bladerf_trigger_role role) +{ + switch (role) { + case BLADERF_TRIGGER_ROLE_MASTER: + return "Master"; + case BLADERF_TRIGGER_ROLE_SLAVE: + return "Slave"; + case BLADERF_TRIGGER_ROLE_DISABLED: + return "Disabled"; + default: + return "Unknown"; + } +} + +bladerf_trigger_role str2triggerrole(const char *str) +{ + if (!strcasecmp("Master", str)) { + return BLADERF_TRIGGER_ROLE_MASTER; + } else if (!strcasecmp("Slave", str)) { + return BLADERF_TRIGGER_ROLE_SLAVE; + } else if (!strcasecmp("Disabled", str) || !strcasecmp("Off", str)) { + return BLADERF_TRIGGER_ROLE_DISABLED; + } else { + return BLADERF_TRIGGER_ROLE_INVALID; + } +} + +int str2loopback(const char *str, bladerf_loopback *loopback) +{ + int status = 0; + + if (!strcasecmp("firmware", str)) { + *loopback = BLADERF_LB_FIRMWARE; + } else if (!strcasecmp("bb_txlpf_rxvga2", str)) { + *loopback = BLADERF_LB_BB_TXLPF_RXVGA2; + } else if (!strcasecmp("bb_txlpf_rxlpf", str)) { + *loopback = BLADERF_LB_BB_TXLPF_RXLPF; + } else if (!strcasecmp("bb_txvga1_rxvga2", str)) { + *loopback = BLADERF_LB_BB_TXVGA1_RXVGA2; + } else if (!strcasecmp("bb_txvga1_rxlpf", str)) { + *loopback = BLADERF_LB_BB_TXVGA1_RXLPF; + } else if (!strcasecmp("rf_lna1", str)) { + *loopback = BLADERF_LB_RF_LNA1; + } else if (!strcasecmp("rf_lna2", str)) { + *loopback = BLADERF_LB_RF_LNA2; + } else if (!strcasecmp("rf_lna3", str)) { + *loopback = BLADERF_LB_RF_LNA3; + } else if (!strcasecmp("rfic_bist", str)) { + *loopback = BLADERF_LB_RFIC_BIST; + } else if (!strcasecmp("none", str)) { + *loopback = BLADERF_LB_NONE; + } else { + status = -1; + } + + return status; +} + +char const *loopback2str(bladerf_loopback loopback) +{ + switch (loopback) { + case BLADERF_LB_BB_TXLPF_RXVGA2: + return "bb_txlpf_rxvga2"; + + case BLADERF_LB_BB_TXLPF_RXLPF: + return "bb_txlpf_rxlpf"; + + case BLADERF_LB_BB_TXVGA1_RXVGA2: + return "bb_txvga1_rxvga2"; + + case BLADERF_LB_BB_TXVGA1_RXLPF: + return "bb_txvga1_rxlpf"; + + case BLADERF_LB_RF_LNA1: + return "rf_lna1"; + + case BLADERF_LB_RF_LNA2: + return "rf_lna2"; + + case BLADERF_LB_RF_LNA3: + return "rf_lna3"; + + case BLADERF_LB_FIRMWARE: + return "firmware"; + + case BLADERF_LB_NONE: + return "none"; + + case BLADERF_LB_RFIC_BIST: + return "rfic_bist"; + + default: + return "unknown"; + } +} + +int str2lnagain(const char *str, bladerf_lna_gain *gain) +{ + *gain = BLADERF_LNA_GAIN_MAX; + + if (!strcasecmp("max", str) || !strcasecmp("BLADERF_LNA_GAIN_MAX", str)) { + *gain = BLADERF_LNA_GAIN_MAX; + return 0; + } else if (!strcasecmp("mid", str) || + !strcasecmp("BLADERF_LNA_GAIN_MID", str)) { + *gain = BLADERF_LNA_GAIN_MID; + return 0; + } else if (!strcasecmp("bypass", str) || + !strcasecmp("BLADERF_LNA_GAIN_BYPASS", str)) { + *gain = BLADERF_LNA_GAIN_BYPASS; + return 0; + } else { + *gain = BLADERF_LNA_GAIN_UNKNOWN; + return -1; + } +} + +char const *tuningmode2str(bladerf_tuning_mode mode) +{ + switch (mode) { + case BLADERF_TUNING_MODE_HOST: + return "Host"; + case BLADERF_TUNING_MODE_FPGA: + return "FPGA"; + default: + return "Unknown"; + } +} + +const char *backend_description(bladerf_backend b) +{ + switch (b) { + case BLADERF_BACKEND_ANY: + return "Any"; + + case BLADERF_BACKEND_LINUX: + return "Linux kernel driver"; + + case BLADERF_BACKEND_LIBUSB: + return "libusb"; + + case BLADERF_BACKEND_CYPRESS: + return "Cypress driver"; + + case BLADERF_BACKEND_DUMMY: + return "Dummy"; + + default: + return "Unknown"; + } +} + +void sc16q11_to_float(const int16_t *in, float *out, unsigned int n) +{ + unsigned int i; + + for (i = 0; i < (2 * n); i += 2) { + out[i] = (float)in[i] * (1.0f / 2048.0f); + out[i + 1] = (float)in[i + 1] * (1.0f / 2048.0f); + } +} + +void float_to_sc16q11(const float *in, int16_t *out, unsigned int n) +{ + unsigned int i; + + for (i = 0; i < (2 * n); i += 2) { + out[i] = (int16_t)(in[i] * 2048.0f); + out[i + 1] = (int16_t)(in[i + 1] * 2048.0f); + } +} + +bladerf_cal_module str_to_bladerf_cal_module(const char *str) +{ + bladerf_cal_module module = BLADERF_DC_CAL_INVALID; + + if (!strcasecmp(str, "lpf_tuning") || !strcasecmp(str, "lpftuning") || + !strcasecmp(str, "tuning")) { + module = BLADERF_DC_CAL_LPF_TUNING; + } else if (!strcasecmp(str, "tx_lpf") || !strcasecmp(str, "txlpf")) { + module = BLADERF_DC_CAL_TX_LPF; + } else if (!strcasecmp(str, "rx_lpf") || !strcasecmp(str, "rxlpf")) { + module = BLADERF_DC_CAL_RX_LPF; + } else if (!strcasecmp(str, "rx_vga2") || !strcasecmp(str, "rxvga2")) { + module = BLADERF_DC_CAL_RXVGA2; + } + + return module; +} + +const char *smb_mode_to_str(bladerf_smb_mode mode) +{ + switch (mode) { + case BLADERF_SMB_MODE_DISABLED: + return "Disabled"; + + case BLADERF_SMB_MODE_OUTPUT: + return "Output"; + + case BLADERF_SMB_MODE_INPUT: + return "Input"; + + case BLADERF_SMB_MODE_UNAVAILBLE: + return "Unavailable"; + + default: + return "Unknown"; + } +}; + +bladerf_smb_mode str_to_smb_mode(const char *str) +{ + if (!strcasecmp(str, "disabled") || !strcasecmp(str, "off")) { + return BLADERF_SMB_MODE_DISABLED; + } else if (!strcasecmp(str, "output")) { + return BLADERF_SMB_MODE_OUTPUT; + } else if (!strcasecmp(str, "input")) { + return BLADERF_SMB_MODE_INPUT; + } else if (!strcasecmp(str, "unavailable")) { + return BLADERF_SMB_MODE_UNAVAILBLE; + } else { + return BLADERF_SMB_MODE_INVALID; + } +} + +bladerf_tuning_mode str_to_tuning_mode(const char *str) +{ + if (!strcasecmp(str, "fpga")) { + return BLADERF_TUNING_MODE_FPGA; + } else if (!strcasecmp(str, "host")) { + return BLADERF_TUNING_MODE_HOST; + } else { + return BLADERF_TUNING_MODE_INVALID; + } +} + +unsigned int str2uint(const char *str, + unsigned int min, + unsigned int max, + bool *ok) +{ + unsigned int ret; + char *optr; + + errno = 0; + ret = strtoul(str, &optr, 0); + + if (errno == ERANGE || (errno != 0 && ret == 0)) { + *ok = false; + return 0; + } + + if (str == optr) { + *ok = false; + return 0; + } + + if (ret >= min && ret <= max) { + *ok = true; + return (unsigned int)ret; + } + + *ok = false; + return 0; +} + +int str2int(const char *str, int min, int max, bool *ok) +{ + long int ret; + char *optr; + + errno = 0; + ret = strtol(str, &optr, 0); + + if ((errno == ERANGE && (ret == LONG_MAX || ret == LONG_MIN)) || + (errno != 0 && ret == 0)) { + *ok = false; + return 0; + } + + if (str == optr) { + *ok = false; + return 0; + } + + if (ret >= min && ret <= max) { + *ok = true; + return (int)ret; + } + + *ok = false; + return 0; +} + +uint64_t str2uint64(const char *str, uint64_t min, uint64_t max, bool *ok) +{ + uint64_t ret; + char *optr; + + errno = 0; + ret = (uint64_t)strtod(str, &optr); + + if ((errno == ERANGE && ret == ULONG_MAX) || (errno != 0 && ret == 0)) { + *ok = false; + return 0; + } + + if (str == optr) { + *ok = false; + return 0; + } + + if (ret >= min && ret <= max) { + *ok = true; + return ret; + } + + *ok = false; + return 0; +} + +double str2double(const char *str, double min, double max, bool *ok) +{ + double ret; + char *optr; + + errno = 0; + ret = strtod(str, &optr); + + if (errno == ERANGE || (errno != 0 && ret == 0)) { + *ok = false; + return NAN; + } + + if (str == optr) { + *ok = false; + return NAN; + } + + if (ret >= min && ret <= max) { + *ok = true; + return ret; + } + + *ok = false; + return NAN; +} + +static uint64_t suffix_multiplier(const char *str, + const struct numeric_suffix *suffixes, + const size_t num_suff, + bool *ok) +{ + unsigned i; + + *ok = true; + + if (!strlen(str)) + return 1; + + for (i = 0; i < num_suff; i++) { + if (!strcasecmp(suffixes[i].suffix, str)) { + return suffixes[i].multiplier; + } + } + + *ok = false; + return 0; +} + +unsigned int str2uint_suffix(const char *str, + unsigned int min, + unsigned int max, + const struct numeric_suffix *suffixes, + const size_t num_suff, + bool *ok) +{ + uint64_t mult; + unsigned int rv; + double val; + char *optr; + + errno = 0; + val = strtod(str, &optr); + + if (errno == ERANGE || (errno != 0 && val == 0)) { + *ok = false; + return 0; + } + + if (str == optr) { + *ok = false; + return 0; + } + + mult = suffix_multiplier(optr, suffixes, num_suff, ok); + if (!*ok) + return false; + + rv = (unsigned int)(val * mult); + + if (rv >= min && rv <= max) { + return rv; + } + + *ok = false; + return 0; +} + +uint64_t str2uint64_suffix(const char *str, + uint64_t min, + uint64_t max, + const struct numeric_suffix *suffixes, + const size_t num_suff, + bool *ok) +{ + uint64_t mult, rv; + long double val; + char *optr; + + errno = 0; + val = strtold(str, &optr); + + if (errno == ERANGE && (errno != 0 && val == 0)) { + *ok = false; + return 0; + } + + if (str == optr) { + *ok = false; + return 0; + } + + mult = suffix_multiplier(optr, suffixes, num_suff, ok); + if (!*ok) + return false; + + rv = (uint64_t)(val * mult); + if (rv >= min && rv <= max) { + return rv; + } + + *ok = false; + return 0; +} + +int str2bool(const char *str, bool *val) +{ + unsigned int i; + + char *str_true[] = { "true", "t", "one", "1", "enable", "en", "on" }; + char *str_false[] = { "false", "f", "zero", "0", "disable", "dis", "off" }; + + for (i = 0; i < ARRAY_SIZE(str_true); i++) { + if (!strcasecmp(str_true[i], str)) { + *val = true; + return 0; + } + } + + for (i = 0; i < ARRAY_SIZE(str_false); i++) { + if (!strcasecmp(str_false[i], str)) { + *val = false; + return 0; + } + } + + return BLADERF_ERR_INVAL; +} |