Add support for multiple operacake boards connected to one HackRF

This commit is contained in:
Dominic Spill
2016-12-23 21:59:45 +00:00
parent 9d7b55ccb1
commit c54e31f397
8 changed files with 106 additions and 31 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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
}; };

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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,

View File

@ -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