From 14093fe73b6be44de0a0fdbc4d17a358dcb7f48d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 22 Sep 2022 01:53:49 +0100 Subject: [PATCH] Provide a callback for completion of a TX transfer. --- host/hackrf-tools/src/hackrf_transfer.c | 71 +++++++++---------------- host/libhackrf/src/hackrf.c | 34 ++++++++---- host/libhackrf/src/hackrf.h | 5 ++ 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index dd8aa9fa..4a54db15 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -324,15 +324,12 @@ char* u64toa(uint64_t val, t_u64toa* str) static volatile bool do_exit = false; static volatile bool interrupted = false; static volatile bool tx_complete = false; -static volatile bool flush_complete = false; #ifdef _WIN32 static HANDLE interrupt_handle; #endif FILE* file = NULL; -volatile uint32_t preload_transfers = 0; volatile uint32_t completed_byte_count = 0; -volatile uint32_t submitted_byte_count = 0; bool signalsource = false; uint32_t amplitude = 0; @@ -423,7 +420,6 @@ int rx_callback(hackrf_transfer* transfer) } /* Update all running totals at approximately the same time. */ - submitted_byte_count += transfer->valid_length; completed_byte_count += transfer->valid_length; stream_power += sum; @@ -490,16 +486,8 @@ int tx_callback(hackrf_transfer* transfer) return -1; } - /* The first few TX callbacks are filling empty transfer buffers, not - * reusing existing ones that have completed. */ - if (preload_transfers > 0) { - transfer->valid_length = 0; - preload_transfers--; - } - /* If the last data was already buffered, stop. */ if (tx_complete) { - completed_byte_count += transfer->valid_length; return -1; } @@ -526,24 +514,11 @@ int tx_callback(hackrf_transfer* transfer) /* If no more bytes, error or file empty, treat as end. */ if (bytes_read == 0) { - completed_byte_count += transfer->valid_length; tx_complete = true; return 0; } } - /* Accumulate power (magnitude squared). */ - uint64_t sum = 0; - for (i = 0; i < bytes_read; i++) { - int8_t value = transfer->buffer[i]; - sum += value * value; - } - - /* Update all running totals at approximately the same time. */ - completed_byte_count += transfer->valid_length; - submitted_byte_count += bytes_read; - stream_power += sum; - /* Now set the valid length to the bytes we put in the buffer. */ transfer->valid_length = bytes_read; @@ -582,27 +557,37 @@ int tx_callback(hackrf_transfer* transfer) return 0; } - /* Accumulate power for the additional samples. */ - sum = 0; - for (i = 0; i < extra_bytes_read; i++) { - int8_t value = transfer->buffer[bytes_read + i]; - sum += value * value; - } bytes_read += extra_bytes_read; transfer->valid_length += extra_bytes_read; - - /* Update running totals together. */ - submitted_byte_count += extra_bytes_read; - stream_power += sum; } /* Then return normally. */ return 0; } +static void tx_complete_callback(hackrf_transfer* transfer, int success) +{ + // If a transfer failed to complete, stop the main loop. + if (!success) { + stop_main_loop(); + return; + } + + /* Accumulate power (magnitude squared). */ + uint32_t i; + uint64_t sum = 0; + for (i = 0; i < transfer->valid_length; i++) { + int8_t value = transfer->buffer[i]; + sum += value * value; + } + + /* Update all running totals at approximately the same time. */ + completed_byte_count += transfer->valid_length; + stream_power += sum; +} + static void flush_callback(void* flush_ctx) { - flush_complete = true; stop_main_loop(); } @@ -1296,9 +1281,11 @@ int main(int argc, char** argv) result |= hackrf_set_lna_gain(device, lna_gain); result |= hackrf_start_rx(device, rx_callback, NULL); } else { - preload_transfers = hackrf_get_transfer_queue_depth(device); result = hackrf_set_txvga_gain(device, txvga_gain); result |= hackrf_enable_tx_flush(device, flush_callback, NULL); + result |= hackrf_set_tx_block_complete_callback( + device, + tx_complete_callback); result |= hackrf_start_tx(device, tx_callback, NULL); } @@ -1360,7 +1347,6 @@ int main(int argc, char** argv) } #endif } else { - uint64_t submitted_count_now; uint64_t completed_count_now; uint64_t stream_power_now; #ifdef _WIN32 @@ -1374,25 +1360,18 @@ int main(int argc, char** argv) gettimeofday(&time_now, NULL); /* Read and reset all totals at approximately the same time. */ - submitted_count_now = submitted_byte_count; completed_count_now = completed_byte_count; stream_power_now = stream_power; - - submitted_byte_count = 0; completed_byte_count = 0; stream_power = 0; - if (flush_complete) { - completed_count_now = submitted_count_now; - } - time_difference = TimevalDiff(&time_now, &time_start); rate = (float) completed_count_now / time_difference; if ((completed_count_now == 0) && (hw_sync)) { fprintf(stderr, "Waiting for trigger...\n"); } else { double full_scale_ratio = (double) stream_power_now / - (submitted_count_now * 127 * 127); + (completed_count_now * 127 * 127); double dB_full_scale = 10 * log10(full_scale_ratio) + 3.0; fprintf(stderr, "%4.1f MiB / %5.3f sec = %4.1f MiB/second, average power %3.1f dBfs", diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index d088f376..cc2dd88b 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -148,6 +148,7 @@ struct hackrf_device { bool flush; struct libusb_transfer* flush_transfer; hackrf_flush_cb_fn flush_callback; + hackrf_tx_block_complete_cb_fn tx_completion_callback; void* flush_ctx; }; @@ -728,6 +729,7 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d lib_device->flush_transfer = NULL; lib_device->flush_callback = NULL; lib_device->flush_ctx = NULL; + lib_device->tx_completion_callback = NULL; result = pthread_mutex_init(&lib_device->transfer_lock, NULL); if (result != 0) { @@ -1800,18 +1802,24 @@ static void LIBUSB_CALL hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer) { hackrf_device* device = (hackrf_device*) usb_transfer->user_data; - bool resubmit; + bool success, resubmit; int result; - if (usb_transfer->status == LIBUSB_TRANSFER_COMPLETED) { - hackrf_transfer transfer = { - .device = device, - .buffer = usb_transfer->buffer, - .buffer_length = TRANSFER_BUFFER_SIZE, - .valid_length = usb_transfer->actual_length, - .rx_ctx = device->rx_ctx, - .tx_ctx = device->tx_ctx}; + hackrf_transfer transfer = { + .device = device, + .buffer = usb_transfer->buffer, + .buffer_length = TRANSFER_BUFFER_SIZE, + .valid_length = usb_transfer->actual_length, + .rx_ctx = device->rx_ctx, + .tx_ctx = device->tx_ctx}; + success = usb_transfer->status == LIBUSB_TRANSFER_COMPLETED; + + if (device->tx_completion_callback != NULL) { + device->tx_completion_callback(&transfer, success); + } + + if (success) { if (device->streaming && device->callback(&transfer) == 0) { // Take lock to make sure that we don't restart a // transfer whilst cancel_transfers() is in the middle @@ -2010,6 +2018,14 @@ int ADDCALL hackrf_start_tx( return result; } +ADDAPI int ADDCALL hackrf_set_tx_block_complete_callback( + hackrf_device* device, + hackrf_tx_block_complete_cb_fn callback) +{ + device->tx_completion_callback = callback; + return HACKRF_SUCCESS; +} + ADDAPI int ADDCALL hackrf_enable_tx_flush( hackrf_device* device, hackrf_flush_cb_fn callback, diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index f9e4dde0..73d3bcff 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -228,6 +228,7 @@ struct hackrf_device_list { typedef struct hackrf_device_list hackrf_device_list_t; typedef int (*hackrf_sample_block_cb_fn)(hackrf_transfer* transfer); +typedef void (*hackrf_tx_block_complete_cb_fn)(hackrf_transfer* transfer, int); typedef void (*hackrf_flush_cb_fn)(void* flush_ctx); #ifdef __cplusplus @@ -271,6 +272,10 @@ extern ADDAPI int ADDCALL hackrf_start_tx( hackrf_sample_block_cb_fn callback, void* tx_ctx); +extern ADDAPI int ADDCALL hackrf_set_tx_block_complete_callback( + hackrf_device* device, + hackrf_tx_block_complete_cb_fn callback); + extern ADDAPI int ADDCALL hackrf_enable_tx_flush( hackrf_device* device, hackrf_flush_cb_fn callback,