operacake: add get/set switching mode functions
This commit is contained in:
@ -75,8 +75,14 @@
|
||||
|
||||
i2c_bus_t* const oc_bus = &i2c0;
|
||||
|
||||
enum operacake_switching_mode {
|
||||
MODE_MANUAL = 0,
|
||||
MODE_FREQUENCY = 1,
|
||||
};
|
||||
|
||||
struct operacake_state {
|
||||
bool present;
|
||||
enum operacake_switching_mode mode;
|
||||
};
|
||||
|
||||
struct operacake_state operacake_boards[OPERACAKE_MAX_BOARDS];
|
||||
@ -112,6 +118,7 @@ uint8_t operacake_init(bool allow_gpio) {
|
||||
uint8_t reg = operacake_read_reg(oc_bus, addr, OPERACAKE_REG_CONFIG);
|
||||
|
||||
operacake_boards[addr].present = (reg == OPERACAKE_CONFIG_ALL_OUTPUT);
|
||||
operacake_boards[addr].mode = MODE_MANUAL;
|
||||
}
|
||||
allow_gpio_mode = allow_gpio;
|
||||
return 0;
|
||||
@ -135,6 +142,20 @@ void operacake_get_boards(uint8_t *addresses) {
|
||||
}
|
||||
}
|
||||
|
||||
void operacake_set_mode(uint8_t address, uint8_t mode) {
|
||||
if (address >= OPERACAKE_MAX_BOARDS)
|
||||
return;
|
||||
|
||||
operacake_boards[address].mode = mode;
|
||||
}
|
||||
|
||||
uint8_t operacake_get_mode(uint8_t address) {
|
||||
if (address >= OPERACAKE_MAX_BOARDS)
|
||||
return 0;
|
||||
|
||||
return operacake_boards[address].mode;
|
||||
}
|
||||
|
||||
uint8_t port_to_pins(uint8_t port) {
|
||||
switch(port) {
|
||||
case OPERACAKE_PA1:
|
||||
@ -225,25 +246,26 @@ uint8_t operacake_set_range(uint32_t freq_mhz) {
|
||||
if(range_idx == 0) {
|
||||
return 1;
|
||||
}
|
||||
int i;
|
||||
for(i=0; i<range_idx; i++) {
|
||||
if((freq_mhz >= ranges[i].freq_min)
|
||||
&& (freq_mhz <= ranges[i].freq_max)) {
|
||||
|
||||
int range;
|
||||
for(range=0; range<range_idx; range++) {
|
||||
if((freq_mhz >= ranges[range].freq_min)
|
||||
&& (freq_mhz <= ranges[range].freq_max)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == current_range) {
|
||||
if(range == current_range) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
|
||||
if (operacake_is_board_present(i)) {
|
||||
operacake_set_ports(i, ranges[i].portA, ranges[i].portB);
|
||||
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
|
||||
if (operacake_is_board_present(i) && operacake_get_mode(i) == MODE_FREQUENCY) {
|
||||
operacake_set_ports(i, ranges[range].portA, ranges[range].portB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
current_range = i;
|
||||
current_range = range;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,8 @@ extern "C"
|
||||
uint8_t operacake_init(bool allow_gpio);
|
||||
bool operacake_is_board_present(uint8_t address);
|
||||
void operacake_get_boards(uint8_t *addresses);
|
||||
void operacake_set_mode(uint8_t address, uint8_t mode);
|
||||
uint8_t operacake_get_mode(uint8_t address);
|
||||
uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB);
|
||||
uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port);
|
||||
uint8_t operacake_set_range(uint32_t freq_mhz);
|
||||
|
@ -111,6 +111,8 @@ static usb_request_handler_fn vendor_request_handler[] = {
|
||||
NULL,
|
||||
#endif
|
||||
usb_vendor_request_set_ui_enable,
|
||||
usb_vendor_request_operacake_set_mode,
|
||||
usb_vendor_request_operacake_get_mode,
|
||||
};
|
||||
|
||||
static const uint32_t vendor_request_handler_count =
|
||||
|
@ -92,3 +92,29 @@ usb_request_status_t usb_vendor_request_operacake_gpio_test(
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_set_mode(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint8_t address, mode;
|
||||
address = endpoint->setup.value & 0xFF;
|
||||
mode = endpoint->setup.index & 0xFF;
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
operacake_set_mode(address, mode);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_get_mode(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint8_t address;
|
||||
address = endpoint->setup.value & 0xFF;
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
endpoint->buffer[0] = operacake_get_mode(address);
|
||||
usb_transfer_schedule_block(endpoint->in, endpoint->buffer, 1, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
@ -37,4 +37,10 @@ usb_request_status_t usb_vendor_request_operacake_set_ranges(
|
||||
usb_request_status_t usb_vendor_request_operacake_gpio_test(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_set_mode(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_get_mode(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
#endif /* end of include guard: __USB_API_OPERACAKE_H__ */
|
||||
|
@ -37,6 +37,7 @@ typedef int bool;
|
||||
#define MAX_FREQ_RANGES 8
|
||||
|
||||
#define INVALID_ADDRESS 0xFF
|
||||
#define INVALID_MODE 0xFF
|
||||
#define INVALID_PORT 0xFF
|
||||
|
||||
#define GPIO_TEST_DISABLED 0xFFFF
|
||||
@ -46,6 +47,7 @@ static void usage() {
|
||||
printf("\t-h, --help: this help\n");
|
||||
printf("\t-d, --device <n>: specify a particular device by serial number\n");
|
||||
printf("\t-o, --address <n>: specify a particular operacake by address [default: 0x00]\n");
|
||||
printf("\t-m, --mode <mode>: specify switching mode [options: manual, frequency]\n");
|
||||
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");
|
||||
@ -56,6 +58,7 @@ static void usage() {
|
||||
static struct option long_options[] = {
|
||||
{ "device", no_argument, 0, 'd' },
|
||||
{ "address", no_argument, 0, 'o' },
|
||||
{ "mode", no_argument, 0, 'm' },
|
||||
{ "list", no_argument, 0, 'l' },
|
||||
{ "gpio_test", no_argument, 0, 'g' },
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
@ -143,6 +146,8 @@ int main(int argc, char** argv) {
|
||||
int opt;
|
||||
const char* serial_number = NULL;
|
||||
uint8_t operacake_address = INVALID_ADDRESS;
|
||||
bool set_mode = false;
|
||||
uint8_t mode;
|
||||
uint8_t port_a = INVALID_PORT;
|
||||
uint8_t port_b = INVALID_PORT;
|
||||
bool set_ports = false;
|
||||
@ -162,7 +167,7 @@ int main(int argc, char** argv) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while( (opt = getopt_long(argc, argv, "d:o:a:b:lf:hg?", long_options, &option_index)) != EOF ) {
|
||||
while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:hg?", long_options, &option_index)) != EOF ) {
|
||||
switch( opt ) {
|
||||
case 'd':
|
||||
serial_number = optarg;
|
||||
@ -172,6 +177,21 @@ int main(int argc, char** argv) {
|
||||
operacake_address = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (strcmp(optarg, "manual") == 0) {
|
||||
mode = OPERACAKE_MODE_MANUAL;
|
||||
set_mode = true;
|
||||
} else if (strcmp(optarg, "frequency") == 0) {
|
||||
mode = OPERACAKE_MODE_FREQUENCY;
|
||||
set_mode = true;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"argument error: mode must be one of [manual, frequency].\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if(MAX_FREQ_RANGES == range_idx) {
|
||||
fprintf(stderr,
|
||||
@ -239,13 +259,13 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if(!(list || set_ports || range_idx || gpio_test)) {
|
||||
fprintf(stderr, "Specify either list, address, or GPIO test option.\n");
|
||||
if(!(list || set_mode || set_ports || range_idx || gpio_test)) {
|
||||
fprintf(stderr, "Specify either list, mode, address, or GPIO test option.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if((set_ports || gpio_test) && (operacake_address == INVALID_ADDRESS)) {
|
||||
if((set_mode || set_ports || gpio_test) && (operacake_address == INVALID_ADDRESS)) {
|
||||
fprintf(stderr, "An address is required.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
@ -258,6 +278,15 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (set_mode) {
|
||||
result = hackrf_set_operacake_mode(device, operacake_address, mode);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_set_operacake_mode() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if(list) {
|
||||
result = hackrf_get_operacake_boards(device, operacakes);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
@ -269,6 +298,16 @@ int main(int argc, char** argv) {
|
||||
for(i=0; i<8; i++) {
|
||||
if(operacakes[i] != HACKRF_OPERACAKE_ADDRESS_INVALID) {
|
||||
printf("\n\tAddress: %d", operacakes[i]);
|
||||
enum operacake_switching_mode mode;
|
||||
hackrf_get_operacake_mode(device, i, &mode);
|
||||
printf("\tSwitching mode: ");
|
||||
if (mode == OPERACAKE_MODE_MANUAL) {
|
||||
printf("manual\n");
|
||||
} else if (mode == OPERACAKE_MODE_FREQUENCY) {
|
||||
printf("frequency\n");
|
||||
} else {
|
||||
printf("unknown\n");
|
||||
}
|
||||
operacake_count++;
|
||||
}
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ typedef enum {
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_GPIO_TEST = 35,
|
||||
HACKRF_VENDOR_REQUEST_CPLD_CHECKSUM = 36,
|
||||
HACKRF_VENDOR_REQUEST_UI_ENABLE = 37,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_MODE = 38,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE = 39,
|
||||
} hackrf_vendor_request;
|
||||
|
||||
#define USB_CONFIG_STANDARD 0x1
|
||||
@ -2090,6 +2092,10 @@ int ADDCALL hackrf_init_sweep(hackrf_device* device,
|
||||
}
|
||||
}
|
||||
|
||||
bool hackrf_operacake_valid_address(uint8_t address) {
|
||||
return address < HACKRF_OPERACAKE_MAX_BOARDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve list of Opera Cake board addresses
|
||||
* @param[in] device
|
||||
@ -2121,6 +2127,82 @@ int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Opera Cake switching mode.
|
||||
* @param[in] device
|
||||
* @param[in] address Opera Cake address.
|
||||
* @param[in] mode Switching mode.
|
||||
* @return @ref HACKRF_SUCCESS
|
||||
* @return @ref HACKRF_ERROR_LIBUSB
|
||||
*/
|
||||
int ADDCALL hackrf_set_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode mode)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0105)
|
||||
|
||||
if (!hackrf_operacake_valid_address(address)) {
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
int result;
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_MODE,
|
||||
address,
|
||||
(uint8_t)mode,
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Opera Cake switching mode.
|
||||
* @param[in] device
|
||||
* @param[in] address Opera Cake address.
|
||||
* @param[out] mode Switching mode.
|
||||
* @return @ref HACKRF_SUCCESS
|
||||
* @return @ref HACKRF_ERROR_LIBUSB
|
||||
*/
|
||||
int ADDCALL hackrf_get_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode *mode)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0105)
|
||||
|
||||
if (!hackrf_operacake_valid_address(address)) {
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
int result;
|
||||
uint8_t buf;
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE,
|
||||
address,
|
||||
0,
|
||||
&buf,
|
||||
1,
|
||||
0
|
||||
);
|
||||
|
||||
if (result < 1)
|
||||
{
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
*mode = buf;
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Operacake ports */
|
||||
int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
||||
uint8_t address,
|
||||
@ -2128,6 +2210,11 @@ int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
||||
uint8_t port_b)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0102)
|
||||
|
||||
if (!hackrf_operacake_valid_address(address)) {
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
int result;
|
||||
/* Error checking */
|
||||
if((port_a > OPERACAKE_PB4) || (port_b > OPERACAKE_PB4)) {
|
||||
@ -2181,8 +2268,8 @@ int ADDCALL hackrf_reset(hackrf_device* device) {
|
||||
int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device, uint8_t* ranges, uint8_t len_ranges)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0103)
|
||||
int result;
|
||||
|
||||
int result;
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
@ -2230,6 +2317,11 @@ int ADDCALL hackrf_operacake_gpio_test(hackrf_device* device, const uint8_t addr
|
||||
uint16_t* test_result)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0103)
|
||||
|
||||
if (!hackrf_operacake_valid_address(address)) {
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
int result;
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
|
@ -51,6 +51,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
|
||||
#define BYTES_PER_BLOCK 16384
|
||||
#define MAX_SWEEP_RANGES 10
|
||||
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
|
||||
#define HACKRF_OPERACAKE_MAX_BOARDS 8
|
||||
|
||||
enum hackrf_error {
|
||||
HACKRF_SUCCESS = 0,
|
||||
@ -101,6 +102,17 @@ enum operacake_ports {
|
||||
OPERACAKE_PB4 = 7,
|
||||
};
|
||||
|
||||
enum operacake_switching_mode {
|
||||
/**
|
||||
* Port connections are set manually using @ref hackrf_set_operacake_ports.
|
||||
*/
|
||||
OPERACAKE_MODE_MANUAL,
|
||||
/**
|
||||
* Port connections are switched automatically when the frequency is changed. Frequency ranges can be set using @ref hackrf_set_operacake_ranges.
|
||||
*/
|
||||
OPERACAKE_MODE_FREQUENCY,
|
||||
};
|
||||
|
||||
enum sweep_style {
|
||||
LINEAR = 0,
|
||||
INTERLEAVED = 1,
|
||||
@ -238,6 +250,8 @@ extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device,
|
||||
|
||||
/* Operacake functions */
|
||||
extern ADDAPI int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards);
|
||||
extern ADDAPI int ADDCALL hackrf_set_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode mode);
|
||||
extern ADDAPI int ADDCALL hackrf_get_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode *mode);
|
||||
extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
||||
uint8_t address,
|
||||
uint8_t port_a,
|
||||
|
Reference in New Issue
Block a user