operacake: add API function to set port dwell times

This commit is contained in:
Mike Walters
2021-08-09 22:51:30 +01:00
parent c50ebb1a36
commit e41314f130
6 changed files with 137 additions and 1 deletions

View File

@ -113,6 +113,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
usb_vendor_request_set_ui_enable,
usb_vendor_request_operacake_set_mode,
usb_vendor_request_operacake_get_mode,
usb_vendor_request_operacake_set_dwell_times,
};
static const uint32_t vendor_request_handler_count =

View File

@ -24,6 +24,8 @@
#include <stddef.h>
#include <operacake.h>
#include <operacake_sctimer.h>
#include <sct.h>
usb_request_status_t usb_vendor_request_operacake_get_boards(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
@ -118,3 +120,33 @@ usb_request_status_t usb_vendor_request_operacake_get_mode(
}
return USB_REQUEST_STATUS_OK;
}
static struct operacake_dwell_times dwell_times[SCT_EVENT_COUNT];
usb_request_status_t usb_vendor_request_operacake_set_dwell_times(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
{
uint16_t count;
uint32_t dwell;
uint8_t port;
if (stage == USB_TRANSFER_STAGE_SETUP) {
count = endpoint->setup.length / 5;
if((count == 0) || (count > SCT_EVENT_COUNT)) {
return USB_REQUEST_STATUS_STALL;
}
usb_transfer_schedule_block(endpoint->out, &data,
endpoint->setup.length, NULL, NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
count = endpoint->setup.length / 5;
for(int i = 0; i < count; i++) {
dwell = data[(i*5)+0] | (data[(i*5)+1] << 8) | (data[(i*5)+2] << 16) | (data[(i*5)+3] << 24);
port = data[(i*5)+4];
dwell_times[i].dwell = dwell;
dwell_times[i].port = port;
}
operacake_sctimer_set_dwell_times(dwell_times, count);
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}

View File

@ -43,4 +43,7 @@ usb_request_status_t usb_vendor_request_operacake_set_mode(
usb_request_status_t usb_vendor_request_operacake_get_mode(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_set_dwell_times(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
#endif /* end of include guard: __USB_API_OPERACAKE_H__ */

View File

@ -51,6 +51,7 @@ static void usage() {
printf("\t-a <n>: set port A connection\n");
printf("\t-b <n>: set port B connection\n");
printf("\t-f <min:max:port>: automatically assign <port> for range <min:max> in MHz\n");
printf("\t-t <port:dwell>: in time-switching mode, dwell on <port> for <dwell> samples. This argument can be repeated to specify a list of ports.\n");
printf("\t-l, --list: list available operacake boards\n");
printf("\t-g, --gpio_test: test GPIO functionality of an opera cake\n");
}
@ -82,6 +83,17 @@ int parse_uint16(char* const s, uint16_t* const value) {
}
}
int parse_uint32(char* const s, uint32_t* const value) {
char* s_end = s;
const long long_value = strtol(s, &s_end, 10);
if( (s != s_end) && (*s_end == 0) ) {
*value = (uint32_t)long_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
int parse_port(char* str, uint8_t* port) {
uint16_t tmp_port;
int result;
@ -142,6 +154,23 @@ int parse_range(char* s, hackrf_oc_range* range) {
return result;
}
int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
int result;
char port[16];
float dwell;
// Read dwell as a float here to support scientific notation (e.g: 1e6)
if (sscanf(s, "%15[^:]:%f", port, &dwell) == 2) {
result = parse_port(port, &dwell_time->port);
if (result != HACKRF_SUCCESS)
return result;
dwell_time->dwell = (uint32_t)dwell;
return HACKRF_SUCCESS;
}
return HACKRF_ERROR_INVALID_PARAM;
}
int main(int argc, char** argv) {
int opt;
const char* serial_number = NULL;
@ -159,7 +188,9 @@ int main(int argc, char** argv) {
hackrf_device* device = NULL;
int option_index = 0;
hackrf_oc_range ranges[MAX_FREQ_RANGES];
hackrf_operacake_dwell_time dwell_times[HACKRF_OPERACAKE_MAX_DWELL_TIMES];
uint8_t range_idx = 0;
uint8_t dwell_idx = 0;
int result = hackrf_init();
if( result ) {
@ -167,7 +198,7 @@ int main(int argc, char** argv) {
return -1;
}
while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:hg?", long_options, &option_index)) != EOF ) {
while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:t:hg?", long_options, &option_index)) != EOF ) {
switch( opt ) {
case 'd':
serial_number = optarg;
@ -224,6 +255,22 @@ int main(int argc, char** argv) {
range_idx++;
break;
case 't':
if(HACKRF_OPERACAKE_MAX_DWELL_TIMES == dwell_idx) {
fprintf(stderr,
"argument error: specify a maximum of %u dwell times.\n",
HACKRF_OPERACAKE_MAX_DWELL_TIMES);
usage();
return EXIT_FAILURE;
}
result = parse_dwell(optarg, &dwell_times[dwell_idx]);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "failed to parse dwell time\n");
return EXIT_FAILURE;
}
dwell_idx++;
break;
case 'a':
result = parse_port(optarg, &port_a);
if (result != HACKRF_SUCCESS) {
@ -417,6 +464,14 @@ int main(int argc, char** argv) {
}
}
if(dwell_idx) {
result = hackrf_set_operacake_dwell_times(device, dwell_times, dwell_idx);
if( result ) {
printf("hackrf_set_operacake_dwell_times() failed: %s (%d)\n", hackrf_error_name(result), result);
return -1;
}
}
result = hackrf_close(device);
if( result ) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);

View File

@ -91,6 +91,7 @@ typedef enum {
HACKRF_VENDOR_REQUEST_UI_ENABLE = 37,
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_MODE = 38,
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE = 39,
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_DWELL_TIMES = 40,
} hackrf_vendor_request;
#define USB_CONFIG_STANDARD 0x1
@ -2289,6 +2290,43 @@ int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device, uint8_t* ranges,
}
}
#define DWELL_TIME_SIZE 5
static uint8_t dwell_data[DWELL_TIME_SIZE*HACKRF_OPERACAKE_MAX_DWELL_TIMES];
int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count)
{
USB_API_REQUIRED(device, 0x0105)
if (count > HACKRF_OPERACAKE_MAX_DWELL_TIMES) {
return HACKRF_ERROR_INVALID_PARAM;
}
int i;
for (i = 0; i < count; i++) {
*(uint32_t*)&dwell_data[i*DWELL_TIME_SIZE] = TO_LE(dwell_times[i].dwell);
dwell_data[(i*DWELL_TIME_SIZE)+4] = dwell_times[i].port;
}
int data_len = count * DWELL_TIME_SIZE;
int result;
result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_DWELL_TIMES,
0,
0,
dwell_data,
data_len,
0
);
if (result < data_len) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
} else {
return HACKRF_SUCCESS;
}
}
int ADDCALL hackrf_set_clkout_enable(hackrf_device* device, const uint8_t value)
{
USB_API_REQUIRED(device, 0x0103)

View File

@ -52,6 +52,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
#define MAX_SWEEP_RANGES 10
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
#define HACKRF_OPERACAKE_MAX_BOARDS 8
#define HACKRF_OPERACAKE_MAX_DWELL_TIMES 16
enum hackrf_error {
HACKRF_SUCCESS = 0,
@ -138,6 +139,11 @@ typedef struct {
uint32_t serial_no[4];
} read_partid_serialno_t;
typedef struct {
uint32_t dwell;
uint8_t port;
} hackrf_operacake_dwell_time;
struct hackrf_device_list {
char **serial_numbers;
@ -260,6 +266,7 @@ extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
uint8_t address,
uint8_t port_a,
uint8_t port_b);
extern ADDAPI int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count);
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);