Provide a callback for completion of a TX transfer.
This commit is contained in:

committed by
Michael Ossmann

parent
2448796e35
commit
14093fe73b
@ -324,15 +324,12 @@ char* u64toa(uint64_t val, t_u64toa* str)
|
|||||||
static volatile bool do_exit = false;
|
static volatile bool do_exit = false;
|
||||||
static volatile bool interrupted = false;
|
static volatile bool interrupted = false;
|
||||||
static volatile bool tx_complete = false;
|
static volatile bool tx_complete = false;
|
||||||
static volatile bool flush_complete = false;
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static HANDLE interrupt_handle;
|
static HANDLE interrupt_handle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FILE* file = NULL;
|
FILE* file = NULL;
|
||||||
volatile uint32_t preload_transfers = 0;
|
|
||||||
volatile uint32_t completed_byte_count = 0;
|
volatile uint32_t completed_byte_count = 0;
|
||||||
volatile uint32_t submitted_byte_count = 0;
|
|
||||||
|
|
||||||
bool signalsource = false;
|
bool signalsource = false;
|
||||||
uint32_t amplitude = 0;
|
uint32_t amplitude = 0;
|
||||||
@ -423,7 +420,6 @@ int rx_callback(hackrf_transfer* transfer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update all running totals at approximately the same time. */
|
/* Update all running totals at approximately the same time. */
|
||||||
submitted_byte_count += transfer->valid_length;
|
|
||||||
completed_byte_count += transfer->valid_length;
|
completed_byte_count += transfer->valid_length;
|
||||||
stream_power += sum;
|
stream_power += sum;
|
||||||
|
|
||||||
@ -490,16 +486,8 @@ int tx_callback(hackrf_transfer* transfer)
|
|||||||
return -1;
|
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 the last data was already buffered, stop. */
|
||||||
if (tx_complete) {
|
if (tx_complete) {
|
||||||
completed_byte_count += transfer->valid_length;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,24 +514,11 @@ int tx_callback(hackrf_transfer* transfer)
|
|||||||
|
|
||||||
/* If no more bytes, error or file empty, treat as end. */
|
/* If no more bytes, error or file empty, treat as end. */
|
||||||
if (bytes_read == 0) {
|
if (bytes_read == 0) {
|
||||||
completed_byte_count += transfer->valid_length;
|
|
||||||
tx_complete = true;
|
tx_complete = true;
|
||||||
return 0;
|
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. */
|
/* Now set the valid length to the bytes we put in the buffer. */
|
||||||
transfer->valid_length = bytes_read;
|
transfer->valid_length = bytes_read;
|
||||||
|
|
||||||
@ -582,27 +557,37 @@ int tx_callback(hackrf_transfer* transfer)
|
|||||||
return 0;
|
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;
|
bytes_read += extra_bytes_read;
|
||||||
transfer->valid_length += 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. */
|
/* Then return normally. */
|
||||||
return 0;
|
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)
|
static void flush_callback(void* flush_ctx)
|
||||||
{
|
{
|
||||||
flush_complete = true;
|
|
||||||
stop_main_loop();
|
stop_main_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1296,9 +1281,11 @@ int main(int argc, char** argv)
|
|||||||
result |= hackrf_set_lna_gain(device, lna_gain);
|
result |= hackrf_set_lna_gain(device, lna_gain);
|
||||||
result |= hackrf_start_rx(device, rx_callback, NULL);
|
result |= hackrf_start_rx(device, rx_callback, NULL);
|
||||||
} else {
|
} else {
|
||||||
preload_transfers = hackrf_get_transfer_queue_depth(device);
|
|
||||||
result = hackrf_set_txvga_gain(device, txvga_gain);
|
result = hackrf_set_txvga_gain(device, txvga_gain);
|
||||||
result |= hackrf_enable_tx_flush(device, flush_callback, NULL);
|
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);
|
result |= hackrf_start_tx(device, tx_callback, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1360,7 +1347,6 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
uint64_t submitted_count_now;
|
|
||||||
uint64_t completed_count_now;
|
uint64_t completed_count_now;
|
||||||
uint64_t stream_power_now;
|
uint64_t stream_power_now;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -1374,25 +1360,18 @@ int main(int argc, char** argv)
|
|||||||
gettimeofday(&time_now, NULL);
|
gettimeofday(&time_now, NULL);
|
||||||
|
|
||||||
/* Read and reset all totals at approximately the same time. */
|
/* Read and reset all totals at approximately the same time. */
|
||||||
submitted_count_now = submitted_byte_count;
|
|
||||||
completed_count_now = completed_byte_count;
|
completed_count_now = completed_byte_count;
|
||||||
stream_power_now = stream_power;
|
stream_power_now = stream_power;
|
||||||
|
|
||||||
submitted_byte_count = 0;
|
|
||||||
completed_byte_count = 0;
|
completed_byte_count = 0;
|
||||||
stream_power = 0;
|
stream_power = 0;
|
||||||
|
|
||||||
if (flush_complete) {
|
|
||||||
completed_count_now = submitted_count_now;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_difference = TimevalDiff(&time_now, &time_start);
|
time_difference = TimevalDiff(&time_now, &time_start);
|
||||||
rate = (float) completed_count_now / time_difference;
|
rate = (float) completed_count_now / time_difference;
|
||||||
if ((completed_count_now == 0) && (hw_sync)) {
|
if ((completed_count_now == 0) && (hw_sync)) {
|
||||||
fprintf(stderr, "Waiting for trigger...\n");
|
fprintf(stderr, "Waiting for trigger...\n");
|
||||||
} else {
|
} else {
|
||||||
double full_scale_ratio = (double) stream_power_now /
|
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;
|
double dB_full_scale = 10 * log10(full_scale_ratio) + 3.0;
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%4.1f MiB / %5.3f sec = %4.1f MiB/second, average power %3.1f dBfs",
|
"%4.1f MiB / %5.3f sec = %4.1f MiB/second, average power %3.1f dBfs",
|
||||||
|
@ -148,6 +148,7 @@ struct hackrf_device {
|
|||||||
bool flush;
|
bool flush;
|
||||||
struct libusb_transfer* flush_transfer;
|
struct libusb_transfer* flush_transfer;
|
||||||
hackrf_flush_cb_fn flush_callback;
|
hackrf_flush_cb_fn flush_callback;
|
||||||
|
hackrf_tx_block_complete_cb_fn tx_completion_callback;
|
||||||
void* flush_ctx;
|
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_transfer = NULL;
|
||||||
lib_device->flush_callback = NULL;
|
lib_device->flush_callback = NULL;
|
||||||
lib_device->flush_ctx = NULL;
|
lib_device->flush_ctx = NULL;
|
||||||
|
lib_device->tx_completion_callback = NULL;
|
||||||
|
|
||||||
result = pthread_mutex_init(&lib_device->transfer_lock, NULL);
|
result = pthread_mutex_init(&lib_device->transfer_lock, NULL);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
@ -1800,10 +1802,9 @@ static void LIBUSB_CALL
|
|||||||
hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer)
|
hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer)
|
||||||
{
|
{
|
||||||
hackrf_device* device = (hackrf_device*) usb_transfer->user_data;
|
hackrf_device* device = (hackrf_device*) usb_transfer->user_data;
|
||||||
bool resubmit;
|
bool success, resubmit;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (usb_transfer->status == LIBUSB_TRANSFER_COMPLETED) {
|
|
||||||
hackrf_transfer transfer = {
|
hackrf_transfer transfer = {
|
||||||
.device = device,
|
.device = device,
|
||||||
.buffer = usb_transfer->buffer,
|
.buffer = usb_transfer->buffer,
|
||||||
@ -1812,6 +1813,13 @@ hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer)
|
|||||||
.rx_ctx = device->rx_ctx,
|
.rx_ctx = device->rx_ctx,
|
||||||
.tx_ctx = device->tx_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) {
|
if (device->streaming && device->callback(&transfer) == 0) {
|
||||||
// Take lock to make sure that we don't restart a
|
// Take lock to make sure that we don't restart a
|
||||||
// transfer whilst cancel_transfers() is in the middle
|
// transfer whilst cancel_transfers() is in the middle
|
||||||
@ -2010,6 +2018,14 @@ int ADDCALL hackrf_start_tx(
|
|||||||
return result;
|
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(
|
ADDAPI int ADDCALL hackrf_enable_tx_flush(
|
||||||
hackrf_device* device,
|
hackrf_device* device,
|
||||||
hackrf_flush_cb_fn callback,
|
hackrf_flush_cb_fn callback,
|
||||||
|
@ -228,6 +228,7 @@ struct hackrf_device_list {
|
|||||||
typedef struct hackrf_device_list hackrf_device_list_t;
|
typedef struct hackrf_device_list hackrf_device_list_t;
|
||||||
|
|
||||||
typedef int (*hackrf_sample_block_cb_fn)(hackrf_transfer* transfer);
|
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);
|
typedef void (*hackrf_flush_cb_fn)(void* flush_ctx);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -271,6 +272,10 @@ extern ADDAPI int ADDCALL hackrf_start_tx(
|
|||||||
hackrf_sample_block_cb_fn callback,
|
hackrf_sample_block_cb_fn callback,
|
||||||
void* tx_ctx);
|
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(
|
extern ADDAPI int ADDCALL hackrf_enable_tx_flush(
|
||||||
hackrf_device* device,
|
hackrf_device* device,
|
||||||
hackrf_flush_cb_fn callback,
|
hackrf_flush_cb_fn callback,
|
||||||
|
Reference in New Issue
Block a user