operacake: add API function to set port dwell times
This commit is contained in:
@ -113,6 +113,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
|
|||||||
usb_vendor_request_set_ui_enable,
|
usb_vendor_request_set_ui_enable,
|
||||||
usb_vendor_request_operacake_set_mode,
|
usb_vendor_request_operacake_set_mode,
|
||||||
usb_vendor_request_operacake_get_mode,
|
usb_vendor_request_operacake_get_mode,
|
||||||
|
usb_vendor_request_operacake_set_dwell_times,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t vendor_request_handler_count =
|
static const uint32_t vendor_request_handler_count =
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <operacake.h>
|
#include <operacake.h>
|
||||||
|
#include <operacake_sctimer.h>
|
||||||
|
#include <sct.h>
|
||||||
|
|
||||||
usb_request_status_t usb_vendor_request_operacake_get_boards(
|
usb_request_status_t usb_vendor_request_operacake_get_boards(
|
||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
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;
|
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;
|
||||||
|
}
|
||||||
|
@ -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_request_status_t usb_vendor_request_operacake_get_mode(
|
||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
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__ */
|
#endif /* end of include guard: __USB_API_OPERACAKE_H__ */
|
||||||
|
@ -51,6 +51,7 @@ static void usage() {
|
|||||||
printf("\t-a <n>: set port A connection\n");
|
printf("\t-a <n>: set port A connection\n");
|
||||||
printf("\t-b <n>: set port B 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-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-l, --list: list available operacake boards\n");
|
||||||
printf("\t-g, --gpio_test: test GPIO functionality of an opera cake\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) {
|
int parse_port(char* str, uint8_t* port) {
|
||||||
uint16_t tmp_port;
|
uint16_t tmp_port;
|
||||||
int result;
|
int result;
|
||||||
@ -142,6 +154,23 @@ int parse_range(char* s, hackrf_oc_range* range) {
|
|||||||
return result;
|
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 main(int argc, char** argv) {
|
||||||
int opt;
|
int opt;
|
||||||
const char* serial_number = NULL;
|
const char* serial_number = NULL;
|
||||||
@ -159,7 +188,9 @@ int main(int argc, char** argv) {
|
|||||||
hackrf_device* device = NULL;
|
hackrf_device* device = NULL;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
hackrf_oc_range ranges[MAX_FREQ_RANGES];
|
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 range_idx = 0;
|
||||||
|
uint8_t dwell_idx = 0;
|
||||||
|
|
||||||
int result = hackrf_init();
|
int result = hackrf_init();
|
||||||
if( result ) {
|
if( result ) {
|
||||||
@ -167,7 +198,7 @@ int main(int argc, char** argv) {
|
|||||||
return -1;
|
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 ) {
|
switch( opt ) {
|
||||||
case 'd':
|
case 'd':
|
||||||
serial_number = optarg;
|
serial_number = optarg;
|
||||||
@ -224,6 +255,22 @@ int main(int argc, char** argv) {
|
|||||||
range_idx++;
|
range_idx++;
|
||||||
break;
|
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':
|
case 'a':
|
||||||
result = parse_port(optarg, &port_a);
|
result = parse_port(optarg, &port_a);
|
||||||
if (result != HACKRF_SUCCESS) {
|
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);
|
result = hackrf_close(device);
|
||||||
if( result ) {
|
if( result ) {
|
||||||
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
|
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
@ -91,6 +91,7 @@ typedef enum {
|
|||||||
HACKRF_VENDOR_REQUEST_UI_ENABLE = 37,
|
HACKRF_VENDOR_REQUEST_UI_ENABLE = 37,
|
||||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_MODE = 38,
|
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_MODE = 38,
|
||||||
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE = 39,
|
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE = 39,
|
||||||
|
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_DWELL_TIMES = 40,
|
||||||
} hackrf_vendor_request;
|
} hackrf_vendor_request;
|
||||||
|
|
||||||
#define USB_CONFIG_STANDARD 0x1
|
#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)
|
int ADDCALL hackrf_set_clkout_enable(hackrf_device* device, const uint8_t value)
|
||||||
{
|
{
|
||||||
USB_API_REQUIRED(device, 0x0103)
|
USB_API_REQUIRED(device, 0x0103)
|
||||||
|
@ -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 MAX_SWEEP_RANGES 10
|
||||||
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
|
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
|
||||||
#define HACKRF_OPERACAKE_MAX_BOARDS 8
|
#define HACKRF_OPERACAKE_MAX_BOARDS 8
|
||||||
|
#define HACKRF_OPERACAKE_MAX_DWELL_TIMES 16
|
||||||
|
|
||||||
enum hackrf_error {
|
enum hackrf_error {
|
||||||
HACKRF_SUCCESS = 0,
|
HACKRF_SUCCESS = 0,
|
||||||
@ -138,6 +139,11 @@ typedef struct {
|
|||||||
uint32_t serial_no[4];
|
uint32_t serial_no[4];
|
||||||
} read_partid_serialno_t;
|
} read_partid_serialno_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t dwell;
|
||||||
|
uint8_t port;
|
||||||
|
} hackrf_operacake_dwell_time;
|
||||||
|
|
||||||
|
|
||||||
struct hackrf_device_list {
|
struct hackrf_device_list {
|
||||||
char **serial_numbers;
|
char **serial_numbers;
|
||||||
@ -260,6 +266,7 @@ extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
|||||||
uint8_t address,
|
uint8_t address,
|
||||||
uint8_t port_a,
|
uint8_t port_a,
|
||||||
uint8_t port_b);
|
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);
|
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user