From 2fe3185f9d371e8d9226796009ab945677e6d56e Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 5 Aug 2022 16:25:31 +0100 Subject: [PATCH 1/5] Use an array of buffers for u64->ASCII conversions. --- host/hackrf-tools/src/hackrf_transfer.c | 45 ++++++++++++------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index f39f9517..2fd76268 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -194,8 +194,7 @@ typedef struct { char data[U64TOA_MAX_DIGIT + 1]; } t_u64toa; -t_u64toa ascii_u64_data1; -t_u64toa ascii_u64_data2; +t_u64toa ascii_u64_data[4]; static float TimevalDiff(const struct timeval* a, const struct timeval* b) { @@ -577,14 +576,14 @@ static void usage() printf("\t-w # Receive data into file with WAV header and automatic name.\n"); printf("\t # This is for SDR# compatibility and may not work with other software.\n"); printf("\t[-f freq_hz] # Frequency in Hz [%sMHz to %sMHz].\n", - u64toa((FREQ_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data1), - u64toa((FREQ_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data2)); + u64toa((FREQ_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), + u64toa((FREQ_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1])); printf("\t[-i if_freq_hz] # Intermediate Frequency (IF) in Hz [%sMHz to %sMHz].\n", - u64toa((IF_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data1), - u64toa((IF_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data2)); + u64toa((IF_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), + u64toa((IF_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1])); printf("\t[-o lo_freq_hz] # Front-end Local Oscillator (LO) frequency in Hz [%sMHz to %sMHz].\n", - u64toa((LO_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data1), - u64toa((LO_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data2)); + u64toa((LO_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), + u64toa((LO_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1])); printf("\t[-m image_reject] # Image rejection filter selection, 0=bypass, 1=low pass, 2=high pass.\n"); printf("\t[-a amp_enable] # RX/TX RF amplifier 1=Enable, 0=Disable.\n"); printf("\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable.\n"); @@ -592,7 +591,7 @@ static void usage() printf("\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); printf("\t[-x gain_db] # TX VGA (IF) gain, 0-47dB, 1dB steps\n"); printf("\t[-s sample_rate_hz] # Sample rate in Hz (2-20MHz, default %sMHz).\n", - u64toa((DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ), &ascii_u64_data1)); + u64toa((DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0])); printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n"); #ifndef _WIN32 /* The required atomic load/store functions aren't available when using C with MSVC */ @@ -795,8 +794,8 @@ int main(int argc, char** argv) if (samples_to_xfer >= SAMPLES_TO_XFER_MAX) { fprintf(stderr, "argument error: num_samples must be less than %s/%sMio\n", - u64toa(SAMPLES_TO_XFER_MAX, &ascii_u64_data1), - u64toa((SAMPLES_TO_XFER_MAX / FREQ_ONE_MHZ), &ascii_u64_data2)); + u64toa(SAMPLES_TO_XFER_MAX, &ascii_u64_data[0]), + u64toa((SAMPLES_TO_XFER_MAX / FREQ_ONE_MHZ), &ascii_u64_data[1])); usage(); return EXIT_FAILURE; } @@ -824,16 +823,16 @@ int main(int argc, char** argv) if ((if_freq_hz > IF_MAX_HZ) || (if_freq_hz < IF_MIN_HZ)) { fprintf(stderr, "argument error: if_freq_hz shall be between %s and %s.\n", - u64toa(IF_MIN_HZ, &ascii_u64_data1), - u64toa(IF_MAX_HZ, &ascii_u64_data2)); + u64toa(IF_MIN_HZ, &ascii_u64_data[0]), + u64toa(IF_MAX_HZ, &ascii_u64_data[1])); usage(); return EXIT_FAILURE; } if ((lo_freq_hz > LO_MAX_HZ) || (lo_freq_hz < LO_MIN_HZ)) { fprintf(stderr, "argument error: lo_freq_hz shall be between %s and %s.\n", - u64toa(LO_MIN_HZ, &ascii_u64_data1), - u64toa(LO_MAX_HZ, &ascii_u64_data2)); + u64toa(LO_MIN_HZ, &ascii_u64_data[0]), + u64toa(LO_MAX_HZ, &ascii_u64_data[1])); usage(); return EXIT_FAILURE; } @@ -864,14 +863,14 @@ int main(int argc, char** argv) } fprintf(stderr, "explicit tuning specified for %s Hz.\n", - u64toa(freq_hz, &ascii_u64_data1)); + u64toa(freq_hz, &ascii_u64_data[0])); } else if (automatic_tuning) { if (freq_hz > FREQ_MAX_HZ) { fprintf(stderr, "argument error: freq_hz shall be between %s and %s.\n", - u64toa(FREQ_MIN_HZ, &ascii_u64_data1), - u64toa(FREQ_MAX_HZ, &ascii_u64_data2)); + u64toa(FREQ_MIN_HZ, &ascii_u64_data[0]), + u64toa(FREQ_MAX_HZ, &ascii_u64_data[1])); usage(); return EXIT_FAILURE; } @@ -1115,7 +1114,7 @@ int main(int argc, char** argv) if (automatic_tuning) { fprintf(stderr, "call hackrf_set_freq(%s Hz/%.03f MHz)\n", - u64toa(freq_hz, &ascii_u64_data1), + u64toa(freq_hz, &ascii_u64_data[0]), ((double) freq_hz / (double) FREQ_ONE_MHZ)); result = hackrf_set_freq(device, freq_hz); if (result != HACKRF_SUCCESS) { @@ -1129,8 +1128,8 @@ int main(int argc, char** argv) } else { fprintf(stderr, "call hackrf_set_freq_explicit() with %s Hz IF, %s Hz LO, %s\n", - u64toa(if_freq_hz, &ascii_u64_data1), - u64toa(lo_freq_hz, &ascii_u64_data2), + u64toa(if_freq_hz, &ascii_u64_data[0]), + u64toa(lo_freq_hz, &ascii_u64_data[1]), hackrf_filter_path_name(image_reject_selection)); result = hackrf_set_freq_explicit( device, @@ -1176,8 +1175,8 @@ int main(int argc, char** argv) if (limit_num_samples) { fprintf(stderr, "samples_to_xfer %s/%sMio\n", - u64toa(samples_to_xfer, &ascii_u64_data1), - u64toa((samples_to_xfer / FREQ_ONE_MHZ), &ascii_u64_data2)); + u64toa(samples_to_xfer, &ascii_u64_data[0]), + u64toa((samples_to_xfer / FREQ_ONE_MHZ), &ascii_u64_data[1])); } gettimeofday(&t_start, NULL); From 8c12fa60073b7e5ffcd69233087b87a0a54ea58e Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 5 Aug 2022 13:19:13 +0100 Subject: [PATCH 2/5] Validate sample rates passed to hackrf_transfer. --- host/hackrf-tools/src/hackrf_transfer.c | 27 ++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 2fd76268..768523ce 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -97,6 +97,8 @@ int gettimeofday(struct timeval* tv, void* ignored) #define LO_MAX_HZ (5400000000ll) #define DEFAULT_LO_HZ (1000000000ll) +#define SAMPLE_RATE_MIN_HZ (2000000) /* 2MHz min sample rate */ +#define SAMPLE_RATE_MAX_HZ (20000000) /* 20MHz max sample rate */ #define DEFAULT_SAMPLE_RATE_HZ (10000000) /* 10MHz default sample rate */ #define DEFAULT_BASEBAND_FILTER_BANDWIDTH (5000000) /* 5MHz default */ @@ -590,8 +592,10 @@ static void usage() printf("\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"); printf("\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); printf("\t[-x gain_db] # TX VGA (IF) gain, 0-47dB, 1dB steps\n"); - printf("\t[-s sample_rate_hz] # Sample rate in Hz (2-20MHz, default %sMHz).\n", - u64toa((DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0])); + printf("\t[-s sample_rate_hz] # Sample rate in Hz (%s-%sMHz, default %sMHz).\n", + u64toa((SAMPLE_RATE_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), + u64toa((SAMPLE_RATE_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1]), + u64toa((DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ), &ascii_u64_data[2])); printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n"); #ifndef _WIN32 /* The required atomic load/store functions aren't available when using C with MSVC */ @@ -897,7 +901,24 @@ int main(int argc, char** argv) } } - if (sample_rate == false) { + if (sample_rate) { + if (sample_rate_hz > SAMPLE_RATE_MAX_HZ) { + fprintf(stderr, + "argument error: sample_rate_hz must be less than or equal to %u Hz/%.03f MHz\n", + SAMPLE_RATE_MAX_HZ, + (float) (SAMPLE_RATE_MAX_HZ / FREQ_ONE_MHZ)); + usage(); + return EXIT_FAILURE; + } + if (sample_rate_hz < SAMPLE_RATE_MIN_HZ) { + fprintf(stderr, + "argument error: sample_rate_hz must be greater than or equal to %u Hz/%.03f MHz\n", + SAMPLE_RATE_MIN_HZ, + (float) (SAMPLE_RATE_MIN_HZ / FREQ_ONE_MHZ)); + usage(); + return EXIT_FAILURE; + } + } else { sample_rate_hz = DEFAULT_SAMPLE_RATE_HZ; } From 2e1f55c2d5ecbab5a67019134fdd81cea75097ae Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 5 Aug 2022 13:32:47 +0100 Subject: [PATCH 3/5] Add hackrf_transfer -F option to force unsupported sample rates. --- host/hackrf-tools/src/hackrf_transfer.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 768523ce..6fad9fbe 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -379,6 +379,8 @@ uint32_t antenna_enable; bool sample_rate = false; uint32_t sample_rate_hz; +bool force_sample_rate = false; + bool limit_num_samples = false; uint64_t samples_to_xfer = 0; size_t bytes_to_xfer = 0; @@ -596,6 +598,7 @@ static void usage() u64toa((SAMPLE_RATE_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), u64toa((SAMPLE_RATE_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1]), u64toa((DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ), &ascii_u64_data[2])); + printf("\t[-F force] # Force use of a sample rate outside the supported range.\n"); printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n"); #ifndef _WIN32 /* The required atomic load/store functions aren't available when using C with MSVC */ @@ -652,8 +655,10 @@ int main(int argc, char** argv) hackrf_m0_state state; stats_t stats = {0, 0}; - while ((opt = getopt(argc, argv, "H:wr:t:f:i:o:m:a:p:s:n:b:l:g:x:c:d:C:RS:Bh?")) != - EOF) { + while ((opt = + getopt(argc, + argv, + "H:wr:t:f:i:o:m:a:p:s:Fn:b:l:g:x:c:d:C:RS:Bh?")) != EOF) { result = HACKRF_SUCCESS; switch (opt) { case 'H': @@ -733,6 +738,10 @@ int main(int argc, char** argv) sample_rate = true; break; + case 'F': + force_sample_rate = true; + break; + case 'n': limit_num_samples = true; result = parse_u64(optarg, &samples_to_xfer); @@ -902,7 +911,7 @@ int main(int argc, char** argv) } if (sample_rate) { - if (sample_rate_hz > SAMPLE_RATE_MAX_HZ) { + if (sample_rate_hz > SAMPLE_RATE_MAX_HZ && !force_sample_rate) { fprintf(stderr, "argument error: sample_rate_hz must be less than or equal to %u Hz/%.03f MHz\n", SAMPLE_RATE_MAX_HZ, @@ -910,7 +919,7 @@ int main(int argc, char** argv) usage(); return EXIT_FAILURE; } - if (sample_rate_hz < SAMPLE_RATE_MIN_HZ) { + if (sample_rate_hz < SAMPLE_RATE_MIN_HZ && !force_sample_rate) { fprintf(stderr, "argument error: sample_rate_hz must be greater than or equal to %u Hz/%.03f MHz\n", SAMPLE_RATE_MIN_HZ, From e88a0387cb2adc1493a39418d2462cd3bdbdfae5 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 5 Aug 2022 16:28:42 +0100 Subject: [PATCH 4/5] Extend force option to frequency ranges outside 1MHz-6GHz. --- host/hackrf-tools/src/hackrf_transfer.c | 40 ++++++++++++++++--------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 6fad9fbe..c7b1619f 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -89,8 +89,10 @@ int gettimeofday(struct timeval* tv, void* ignored) #define FREQ_ONE_MHZ (1000000ll) #define DEFAULT_FREQ_HZ (900000000ll) /* 900MHz */ -#define FREQ_MIN_HZ (0ull) /* 0 Hz */ -#define FREQ_MAX_HZ (7250000000ll) /* 7250MHz */ +#define FREQ_ABS_MIN_HZ (0ull) /* 0 Hz */ +#define FREQ_MIN_HZ (1000000ll) /* 1MHz */ +#define FREQ_MAX_HZ (6000000000ll) /* 6000MHz */ +#define FREQ_ABS_MAX_HZ (7250000000ll) /* 7250MHz */ #define IF_MIN_HZ (2150000000ll) #define IF_MAX_HZ (2750000000ll) #define LO_MIN_HZ (84375000ll) @@ -379,7 +381,7 @@ uint32_t antenna_enable; bool sample_rate = false; uint32_t sample_rate_hz; -bool force_sample_rate = false; +bool force_ranges = false; bool limit_num_samples = false; uint64_t samples_to_xfer = 0; @@ -579,9 +581,11 @@ static void usage() printf("\t-t # Transmit data from file (use '-' for stdin).\n"); printf("\t-w # Receive data into file with WAV header and automatic name.\n"); printf("\t # This is for SDR# compatibility and may not work with other software.\n"); - printf("\t[-f freq_hz] # Frequency in Hz [%sMHz to %sMHz].\n", + printf("\t[-f freq_hz] # Frequency in Hz [%sMHz to %sMHz supported, %sMHz to %sMHz forceable].\n", u64toa((FREQ_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), - u64toa((FREQ_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1])); + u64toa((FREQ_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1]), + u64toa((FREQ_ABS_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[2]), + u64toa((FREQ_ABS_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[3])); printf("\t[-i if_freq_hz] # Intermediate Frequency (IF) in Hz [%sMHz to %sMHz].\n", u64toa((IF_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), u64toa((IF_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1])); @@ -594,11 +598,11 @@ static void usage() printf("\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"); printf("\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); printf("\t[-x gain_db] # TX VGA (IF) gain, 0-47dB, 1dB steps\n"); - printf("\t[-s sample_rate_hz] # Sample rate in Hz (%s-%sMHz, default %sMHz).\n", + printf("\t[-s sample_rate_hz] # Sample rate in Hz (%s-%sMHz supported, default %sMHz).\n", u64toa((SAMPLE_RATE_MIN_HZ / FREQ_ONE_MHZ), &ascii_u64_data[0]), u64toa((SAMPLE_RATE_MAX_HZ / FREQ_ONE_MHZ), &ascii_u64_data[1]), u64toa((DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ), &ascii_u64_data[2])); - printf("\t[-F force] # Force use of a sample rate outside the supported range.\n"); + printf("\t[-F force] # Force use of parameters outside supported ranges.\n"); printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n"); #ifndef _WIN32 /* The required atomic load/store functions aren't available when using C with MSVC */ @@ -739,7 +743,7 @@ int main(int argc, char** argv) break; case 'F': - force_sample_rate = true; + force_ranges = true; break; case 'n': @@ -879,14 +883,22 @@ int main(int argc, char** argv) u64toa(freq_hz, &ascii_u64_data[0])); } else if (automatic_tuning) { - if (freq_hz > FREQ_MAX_HZ) { + if ((freq_hz > FREQ_MAX_HZ | freq_hz < FREQ_MIN_HZ) && !force_ranges) { fprintf(stderr, - "argument error: freq_hz shall be between %s and %s.\n", + "argument error: freq_hz should be between %s and %s.\n", u64toa(FREQ_MIN_HZ, &ascii_u64_data[0]), u64toa(FREQ_MAX_HZ, &ascii_u64_data[1])); usage(); return EXIT_FAILURE; } + if (freq_hz > FREQ_ABS_MAX_HZ) { + fprintf(stderr, + "argument error: freq_hz must be between %s and %s.\n", + u64toa(FREQ_ABS_MIN_HZ, &ascii_u64_data[0]), + u64toa(FREQ_ABS_MAX_HZ, &ascii_u64_data[1])); + usage(); + return EXIT_FAILURE; + } } else { /* Use default freq */ freq_hz = DEFAULT_FREQ_HZ; @@ -911,17 +923,17 @@ int main(int argc, char** argv) } if (sample_rate) { - if (sample_rate_hz > SAMPLE_RATE_MAX_HZ && !force_sample_rate) { + if (sample_rate_hz > SAMPLE_RATE_MAX_HZ && !force_ranges) { fprintf(stderr, - "argument error: sample_rate_hz must be less than or equal to %u Hz/%.03f MHz\n", + "argument error: sample_rate_hz should be less than or equal to %u Hz/%.03f MHz\n", SAMPLE_RATE_MAX_HZ, (float) (SAMPLE_RATE_MAX_HZ / FREQ_ONE_MHZ)); usage(); return EXIT_FAILURE; } - if (sample_rate_hz < SAMPLE_RATE_MIN_HZ && !force_sample_rate) { + if (sample_rate_hz < SAMPLE_RATE_MIN_HZ && !force_ranges) { fprintf(stderr, - "argument error: sample_rate_hz must be greater than or equal to %u Hz/%.03f MHz\n", + "argument error: sample_rate_hz should be greater than or equal to %u Hz/%.03f MHz\n", SAMPLE_RATE_MIN_HZ, (float) (SAMPLE_RATE_MIN_HZ / FREQ_ONE_MHZ)); usage(); From c703a72ac0beaec88b4ce51d83119a93367d0d0e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 22 Aug 2022 14:29:34 -0400 Subject: [PATCH 5/5] add parentheses to avoid compiler warning avoids a warning from -Wparentheses --- host/hackrf-tools/src/hackrf_transfer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index c7b1619f..00eada5a 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -883,7 +883,8 @@ int main(int argc, char** argv) u64toa(freq_hz, &ascii_u64_data[0])); } else if (automatic_tuning) { - if ((freq_hz > FREQ_MAX_HZ | freq_hz < FREQ_MIN_HZ) && !force_ranges) { + if (((freq_hz > FREQ_MAX_HZ) | (freq_hz < FREQ_MIN_HZ)) && + !force_ranges) { fprintf(stderr, "argument error: freq_hz should be between %s and %s.\n", u64toa(FREQ_MIN_HZ, &ascii_u64_data[0]),