Add USB requests and host support to set TX/RX shortfall limits.
This adds `-T` and `-R` options to `hackrf_debug`, which set the TX underrun and RX overrun limits in bytes.
This commit is contained in:
@ -116,6 +116,8 @@ static usb_request_handler_fn vendor_request_handler[] = {
|
||||
usb_vendor_request_operacake_get_mode,
|
||||
usb_vendor_request_operacake_set_dwell_times,
|
||||
usb_vendor_request_get_m0_state,
|
||||
usb_vendor_request_set_tx_underrun_limit,
|
||||
usb_vendor_request_set_rx_overrun_limit,
|
||||
};
|
||||
|
||||
static const uint32_t vendor_request_handler_count =
|
||||
|
@ -238,6 +238,8 @@ usb_request_status_t usb_vendor_request_set_freq_explicit(
|
||||
}
|
||||
|
||||
static volatile hw_sync_mode_t _hw_sync_mode = HW_SYNC_MODE_OFF;
|
||||
static volatile uint32_t _tx_underrun_limit;
|
||||
static volatile uint32_t _rx_overrun_limit;
|
||||
|
||||
void set_hw_sync_mode(const hw_sync_mode_t new_hw_sync_mode) {
|
||||
_hw_sync_mode = new_hw_sync_mode;
|
||||
@ -288,12 +290,14 @@ void transceiver_startup(const transceiver_mode_t mode) {
|
||||
led_on(LED2);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX);
|
||||
m0_state.mode = M0_MODE_RX;
|
||||
m0_state.shortfall_limit = _rx_overrun_limit;
|
||||
break;
|
||||
case TRANSCEIVER_MODE_TX:
|
||||
led_off(LED2);
|
||||
led_on(LED3);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX);
|
||||
m0_state.mode = M0_MODE_TX;
|
||||
m0_state.shortfall_limit = _tx_underrun_limit;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -338,6 +342,30 @@ usb_request_status_t usb_vendor_request_set_hw_sync_mode(
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_tx_underrun_limit(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value;
|
||||
_tx_underrun_limit = value;
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_rx_overrun_limit(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value;
|
||||
_rx_overrun_limit = value;
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
void transceiver_bulk_transfer_complete(void *user_data, unsigned int bytes_transferred)
|
||||
{
|
||||
(void) user_data;
|
||||
|
@ -62,6 +62,10 @@ usb_request_status_t usb_vendor_request_set_freq_explicit(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_hw_sync_mode(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_tx_underrun_limit(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_rx_overrun_limit(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
void request_transceiver_mode(transceiver_mode_t mode);
|
||||
void transceiver_startup(transceiver_mode_t mode);
|
||||
|
@ -405,6 +405,8 @@ static void usage() {
|
||||
printf("\t-s, --si5351c: target SI5351C\n");
|
||||
printf("\t-f, --rffc5072: target RFFC5072\n");
|
||||
printf("\t-S, --state: display M0 state\n");
|
||||
printf("\t-T, --tx-underrun-limit <n>: set TX underrun limit in bytes (0 for no limit)\n");
|
||||
printf("\t-R, --rx-overrun-limit <n>: set RX overrun limit in bytes (0 for no limit)\n");
|
||||
printf("\t-u, --ui <1/0>: enable/disable UI\n");
|
||||
printf("\nExamples:\n");
|
||||
printf("\thackrf_debug --si5351c -n 0 -r # reads from si5351c register 0\n");
|
||||
@ -425,6 +427,8 @@ static struct option long_options[] = {
|
||||
{ "si5351c", no_argument, 0, 's' },
|
||||
{ "rffc5072", no_argument, 0, 'f' },
|
||||
{ "state", no_argument, 0, 'S' },
|
||||
{ "tx-underrun-limit", required_argument, 0, 'T' },
|
||||
{ "rx-overrun-limit", required_argument, 0, 'R' },
|
||||
{ "ui", required_argument, 0, 'u' },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
@ -443,6 +447,10 @@ int main(int argc, char** argv) {
|
||||
const char* serial_number = NULL;
|
||||
bool set_ui = false;
|
||||
uint32_t ui_enable;
|
||||
uint32_t tx_limit;
|
||||
uint32_t rx_limit;
|
||||
bool set_tx_limit = false;
|
||||
bool set_rx_limit = false;
|
||||
|
||||
int result = hackrf_init();
|
||||
if(result) {
|
||||
@ -450,7 +458,7 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfSh?u:", long_options, &option_index)) != EOF ) {
|
||||
while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfST:R:h?u:", long_options, &option_index)) != EOF ) {
|
||||
switch( opt ) {
|
||||
case 'n':
|
||||
result = parse_int(optarg, ®ister_number);
|
||||
@ -473,6 +481,15 @@ int main(int argc, char** argv) {
|
||||
dump_state = true;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
set_tx_limit = true;
|
||||
result = parse_int(optarg, &tx_limit);
|
||||
break;
|
||||
case 'R':
|
||||
set_rx_limit = true;
|
||||
result = parse_int(optarg, &rx_limit);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
serial_number = optarg;
|
||||
break;
|
||||
@ -541,13 +558,13 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(!(write || read || dump_config || dump_state || set_ui)) {
|
||||
if(!(write || read || dump_config || dump_state || set_tx_limit || set_rx_limit || set_ui)) {
|
||||
fprintf(stderr, "Specify read, write, or config option.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(part == PART_NONE && !set_ui && !dump_state) {
|
||||
if(part == PART_NONE && !set_ui && !dump_state && !set_tx_limit && !set_rx_limit) {
|
||||
fprintf(stderr, "Specify a part to read, write, or print config from.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
@ -575,6 +592,22 @@ int main(int argc, char** argv) {
|
||||
si5351c_read_configuration(device);
|
||||
}
|
||||
|
||||
if (set_tx_limit) {
|
||||
result = hackrf_set_tx_underrun_limit(device, tx_limit);
|
||||
if(result != HACKRF_SUCCESS) {
|
||||
printf("hackrf_set_tx_underrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (set_rx_limit) {
|
||||
result = hackrf_set_rx_overrun_limit(device, rx_limit);
|
||||
if(result != HACKRF_SUCCESS) {
|
||||
printf("hackrf_set_rx_overrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if(dump_state) {
|
||||
hackrf_m0_state state;
|
||||
result = hackrf_get_m0_state(device, &state);
|
||||
|
@ -93,6 +93,8 @@ typedef enum {
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE = 39,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_DWELL_TIMES = 40,
|
||||
HACKRF_VENDOR_REQUEST_GET_M0_STATE = 41,
|
||||
HACKRF_VENDOR_REQUEST_SET_TX_UNDERRUN_LIMIT = 42,
|
||||
HACKRF_VENDOR_REQUEST_SET_RX_OVERRUN_LIMIT = 43,
|
||||
} hackrf_vendor_request;
|
||||
|
||||
#define USB_CONFIG_STANDARD 0x1
|
||||
@ -1033,6 +1035,56 @@ int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* state)
|
||||
}
|
||||
}
|
||||
|
||||
int ADDCALL hackrf_set_tx_underrun_limit(hackrf_device* device, uint32_t value)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0106)
|
||||
int result;
|
||||
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_SET_TX_UNDERRUN_LIMIT,
|
||||
value & 0xffff,
|
||||
value >> 16,
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
if( result != 0 )
|
||||
{
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int ADDCALL hackrf_set_rx_overrun_limit(hackrf_device* device, uint32_t value)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0106)
|
||||
int result;
|
||||
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_SET_RX_OVERRUN_LIMIT,
|
||||
value & 0xffff,
|
||||
value >> 16,
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
if( result != 0 )
|
||||
{
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int ADDCALL hackrf_spiflash_erase(hackrf_device* device)
|
||||
{
|
||||
int result;
|
||||
|
@ -210,6 +210,8 @@ extern ADDAPI int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_b
|
||||
extern ADDAPI int ADDCALL hackrf_stop_tx(hackrf_device* device);
|
||||
|
||||
extern ADDAPI int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* value);
|
||||
extern ADDAPI int ADDCALL hackrf_set_tx_underrun_limit(hackrf_device* device, uint32_t value);
|
||||
extern ADDAPI int ADDCALL hackrf_set_rx_overrun_limit(hackrf_device* device, uint32_t value);
|
||||
|
||||
/* return HACKRF_TRUE if success */
|
||||
extern ADDAPI int ADDCALL hackrf_is_streaming(hackrf_device* device);
|
||||
|
Reference in New Issue
Block a user