Add support for multiple operacake boards connected to one HackRF
This commit is contained in:
@ -57,31 +57,50 @@
|
|||||||
| OPERACAKE_EN_LEDS)
|
| OPERACAKE_EN_LEDS)
|
||||||
#define OPERACAKE_CONFIG_ALL_OUTPUT (0x00)
|
#define OPERACAKE_CONFIG_ALL_OUTPUT (0x00)
|
||||||
|
|
||||||
typedef struct {
|
#define OPERACAKE_DEFAULT_ADDRESS 0x18
|
||||||
i2c_bus_t* const bus;
|
|
||||||
uint8_t i2c_address;
|
|
||||||
} operacake_driver_t;
|
|
||||||
|
|
||||||
operacake_driver_t operacake_driver = {
|
i2c_bus_t* const oc_bus = &i2c0;
|
||||||
.bus = &i2c0,
|
uint8_t operacake_boards[8] = {0,0,0,0,0,0,0,0};
|
||||||
.i2c_address = 0x18,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint8_t operacake_read_single(operacake_driver_t* drv, uint8_t reg);
|
/* read single register */
|
||||||
void operacake_write(operacake_driver_t* drv, const uint8_t* const data, const size_t data_count);
|
uint8_t operacake_read_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg) {
|
||||||
|
const uint8_t data_tx[] = { reg };
|
||||||
|
uint8_t data_rx[] = { 0x00 };
|
||||||
|
i2c_bus_transfer(bus, address, data_tx, 1, data_rx, 1);
|
||||||
|
return data_rx[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write to one of the PCA9557 registers */
|
||||||
|
void operacake_write_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg, uint8_t value) {
|
||||||
|
const uint8_t data[] = {reg, value};
|
||||||
|
i2c_bus_transfer(bus, address, data, 2, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t operacake_init(void) {
|
uint8_t operacake_init(void) {
|
||||||
/* TODO: detect Operacake */
|
int reg, addr, i, j = 0;
|
||||||
uint8_t output_data[] = {OPERACAKE_REG_OUTPUT,
|
/* Find connected operacakes */
|
||||||
OPERACAKE_DEFAULT_OUTPUT};
|
for(i=0; i<8; i++) {
|
||||||
operacake_write(&operacake_driver, output_data, 2);
|
addr = OPERACAKE_DEFAULT_ADDRESS | i;
|
||||||
const uint8_t config_data[] = {OPERACAKE_REG_CONFIG,
|
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_OUTPUT,
|
||||||
OPERACAKE_CONFIG_ALL_OUTPUT};
|
OPERACAKE_DEFAULT_OUTPUT);
|
||||||
operacake_write(&operacake_driver, config_data, 2);
|
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_CONFIG,
|
||||||
|
OPERACAKE_CONFIG_ALL_OUTPUT);
|
||||||
|
reg = operacake_read_reg(oc_bus, addr, OPERACAKE_REG_CONFIG);
|
||||||
|
if(reg==OPERACAKE_CONFIG_ALL_OUTPUT)
|
||||||
|
operacake_boards[j++] = addr;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uint8_t operacake_get_boards(uint8_t *boards) {
|
||||||
|
// int i, j = 0;
|
||||||
|
// for(i=0; i<8; i++) {
|
||||||
|
// if(operacake_boards & (1<<i)) {
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
uint8_t port_to_pins(uint8_t port) {
|
uint8_t port_to_pins(uint8_t port) {
|
||||||
switch(port) {
|
switch(port) {
|
||||||
case OPERACAKE_PA1:
|
case OPERACAKE_PA1:
|
||||||
@ -106,8 +125,7 @@ uint8_t port_to_pins(uint8_t port) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t operacake_set_ports(uint8_t PA, uint8_t PB) {
|
uint8_t operacake_set_ports(uint8_t PA, uint8_t PB) {
|
||||||
uint8_t side, pa, pb;
|
uint8_t side, pa, pb, reg;
|
||||||
uint8_t output_data[2];
|
|
||||||
/* Start with some error checking,
|
/* Start with some error checking,
|
||||||
* which should have been done either
|
* which should have been done either
|
||||||
* on the host or elsewhere in firmware
|
* on the host or elsewhere in firmware
|
||||||
@ -129,14 +147,9 @@ uint8_t operacake_set_ports(uint8_t PA, uint8_t PB) {
|
|||||||
pa = port_to_pins(PA);
|
pa = port_to_pins(PA);
|
||||||
pb = port_to_pins(PB);
|
pb = port_to_pins(PB);
|
||||||
|
|
||||||
output_data[0] = OPERACAKE_REG_OUTPUT;
|
reg = (OPERACAKE_GPIO_DISABLE | side
|
||||||
output_data[1] = (OPERACAKE_GPIO_DISABLE | side
|
|
||||||
| pa | pb | OPERACAKE_EN_LEDS);
|
| pa | pb | OPERACAKE_EN_LEDS);
|
||||||
operacake_write(&operacake_driver, output_data, 2);
|
operacake_write_reg(oc_bus, 0x00, OPERACAKE_REG_OUTPUT, reg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write to one of the PCA9557 registers */
|
|
||||||
void operacake_write(operacake_driver_t* drv, const uint8_t* const data, const size_t data_count) {
|
|
||||||
i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0);
|
|
||||||
}
|
|
||||||
|
@ -40,6 +40,9 @@ extern "C"
|
|||||||
#define OPERACAKE_PB3 6
|
#define OPERACAKE_PB3 6
|
||||||
#define OPERACAKE_PB4 7
|
#define OPERACAKE_PB4 7
|
||||||
|
|
||||||
|
/* Up to 8 Operacake boards can be used with one HackRF */
|
||||||
|
extern uint8_t operacake_boards[8];
|
||||||
|
|
||||||
uint8_t operacake_init(void);
|
uint8_t operacake_init(void);
|
||||||
uint8_t operacake_set_ports(uint8_t PA, uint8_t PB);
|
uint8_t operacake_set_ports(uint8_t PA, uint8_t PB);
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ static const usb_request_handler_fn vendor_request_handler[] = {
|
|||||||
#endif
|
#endif
|
||||||
usb_vendor_request_set_freq_explicit,
|
usb_vendor_request_set_freq_explicit,
|
||||||
usb_vendor_request_read_wcid, // USB_WCID_VENDOR_REQ
|
usb_vendor_request_read_wcid, // USB_WCID_VENDOR_REQ
|
||||||
|
usb_vendor_request_operacake_get_boards,
|
||||||
usb_vendor_request_operacake_set_ports
|
usb_vendor_request_operacake_set_ports
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,8 +24,18 @@
|
|||||||
|
|
||||||
#include <operacake.h>
|
#include <operacake.h>
|
||||||
|
|
||||||
|
usb_request_status_t usb_vendor_request_operacake_get_boards(
|
||||||
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||||
|
{
|
||||||
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
|
usb_transfer_schedule_block(endpoint->in, operacake_boards, 8, NULL, NULL);
|
||||||
|
usb_transfer_schedule_ack(endpoint->out);
|
||||||
|
}
|
||||||
|
return USB_REQUEST_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
usb_request_status_t usb_vendor_request_operacake_set_ports(
|
usb_request_status_t usb_vendor_request_operacake_set_ports(
|
||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||||
{
|
{
|
||||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
operacake_set_ports(endpoint->setup.index, endpoint->setup.value);
|
operacake_set_ports(endpoint->setup.index, endpoint->setup.value);
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
#include <usb_type.h>
|
#include <usb_type.h>
|
||||||
#include <usb_request.h>
|
#include <usb_request.h>
|
||||||
|
|
||||||
|
usb_request_status_t usb_vendor_request_operacake_get_boards(
|
||||||
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||||
|
|
||||||
usb_request_status_t usb_vendor_request_operacake_set_ports(
|
usb_request_status_t usb_vendor_request_operacake_set_ports(
|
||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||||
|
|
||||||
|
@ -32,9 +32,10 @@ int main(void)
|
|||||||
uint8_t board_id = BOARD_ID_INVALID;
|
uint8_t board_id = BOARD_ID_INVALID;
|
||||||
char version[255 + 1];
|
char version[255 + 1];
|
||||||
read_partid_serialno_t read_partid_serialno;
|
read_partid_serialno_t read_partid_serialno;
|
||||||
|
uint8_t operacakes[8];
|
||||||
hackrf_device_list_t *list;
|
hackrf_device_list_t *list;
|
||||||
hackrf_device* device;
|
hackrf_device* device;
|
||||||
int i;
|
int i, j;
|
||||||
|
|
||||||
result = hackrf_init();
|
result = hackrf_init();
|
||||||
if (result != HACKRF_SUCCESS) {
|
if (result != HACKRF_SUCCESS) {
|
||||||
@ -98,7 +99,20 @@ int main(void)
|
|||||||
read_partid_serialno.serial_no[1],
|
read_partid_serialno.serial_no[1],
|
||||||
read_partid_serialno.serial_no[2],
|
read_partid_serialno.serial_no[2],
|
||||||
read_partid_serialno.serial_no[3]);
|
read_partid_serialno.serial_no[3]);
|
||||||
|
|
||||||
|
result = hackrf_get_operacake_boards(device, &operacakes[0]);
|
||||||
|
if (result != HACKRF_SUCCESS) {
|
||||||
|
fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n",
|
||||||
|
hackrf_error_name(result), result);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
for(j=0; j<8; j++) {
|
||||||
|
if(operacakes[j] == 0)
|
||||||
|
break;
|
||||||
|
printf("Operacake found, address: 0x%02x\n", operacakes[j]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
result = hackrf_close(device);
|
result = hackrf_close(device);
|
||||||
if (result != HACKRF_SUCCESS) {
|
if (result != HACKRF_SUCCESS) {
|
||||||
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
|
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
|
||||||
|
@ -68,8 +68,8 @@ typedef enum {
|
|||||||
HACKRF_VENDOR_REQUEST_ANTENNA_ENABLE = 23,
|
HACKRF_VENDOR_REQUEST_ANTENNA_ENABLE = 23,
|
||||||
HACKRF_VENDOR_REQUEST_SET_FREQ_EXPLICIT = 24,
|
HACKRF_VENDOR_REQUEST_SET_FREQ_EXPLICIT = 24,
|
||||||
HACKRF_VENDOR_REQUEST_READ_WCID = 25,
|
HACKRF_VENDOR_REQUEST_READ_WCID = 25,
|
||||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS = 26,
|
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_BOARDS = 26,
|
||||||
HACKRF_VENDOR_REQUEST_GET_OPERACAKES = 27,
|
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS = 27,
|
||||||
} hackrf_vendor_request;
|
} hackrf_vendor_request;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -1698,6 +1698,31 @@ uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz)
|
|||||||
return p->bandwidth_hz;
|
return p->bandwidth_hz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Retrieve list of Operacake board addresses
|
||||||
|
* boards must be *uint8_t[8]
|
||||||
|
*/
|
||||||
|
int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
result = libusb_control_transfer(
|
||||||
|
device->usb_device,
|
||||||
|
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||||
|
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_BOARDS,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
boards,
|
||||||
|
8,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result < 8)
|
||||||
|
{
|
||||||
|
return HACKRF_ERROR_LIBUSB;
|
||||||
|
} else {
|
||||||
|
return HACKRF_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Set Operacake ports */
|
/* Set Operacake ports */
|
||||||
int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
||||||
const uint8_t port_a,
|
const uint8_t port_a,
|
||||||
|
@ -208,6 +208,12 @@ extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(c
|
|||||||
/* Compute best default value depending on sample rate (auto filter) */
|
/* Compute best default value depending on sample rate (auto filter) */
|
||||||
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz);
|
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz);
|
||||||
|
|
||||||
|
/* Operacake functions */
|
||||||
|
int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards);
|
||||||
|
int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
||||||
|
const uint8_t port_a,
|
||||||
|
const uint8_t port_b);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // __cplusplus defined.
|
} // __cplusplus defined.
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user