Opera glasses: allow user specified ranges for operacake ports
- HackRF switches antenna when tuning - ports specified using hackrf_operacake cmdline tool hackrf_operacake -f 2350:2800:0 -f 0:400:1 -f 400:700:2 -f 700:6000:3
This commit is contained in:
@ -145,3 +145,52 @@ uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t freq_min;
|
||||||
|
uint16_t freq_max;
|
||||||
|
uint8_t portA;
|
||||||
|
uint8_t portB;
|
||||||
|
} operacake_range;
|
||||||
|
|
||||||
|
static operacake_range ranges[MAX_OPERACAKE_RANGES * sizeof(operacake_range)];
|
||||||
|
static uint8_t range_idx = 0;
|
||||||
|
|
||||||
|
uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port) {
|
||||||
|
if(range_idx >= MAX_OPERACAKE_RANGES) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ranges[range_idx].freq_min = freq_min;
|
||||||
|
ranges[range_idx].freq_max = freq_max;
|
||||||
|
ranges[range_idx].portA = port;
|
||||||
|
ranges[range_idx].portB = 7;
|
||||||
|
if(port <= OPERACAKE_PA4) {
|
||||||
|
ranges[range_idx].portB = range_idx+4;
|
||||||
|
} else {
|
||||||
|
ranges[range_idx].portB = OPERACAKE_PA1;
|
||||||
|
}
|
||||||
|
range_idx++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FREQ_ONE_MHZ (1000000ull)
|
||||||
|
static uint8_t current_range = 0xFF;
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i == current_range) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
operacake_set_ports(operacake_boards[0], ranges[i].portA, ranges[i].portB);
|
||||||
|
current_range = i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -40,11 +40,15 @@ extern "C"
|
|||||||
#define OPERACAKE_PB3 6
|
#define OPERACAKE_PB3 6
|
||||||
#define OPERACAKE_PB4 7
|
#define OPERACAKE_PB4 7
|
||||||
|
|
||||||
|
#define MAX_OPERACAKE_RANGES 8
|
||||||
|
|
||||||
/* Up to 8 Operacake boards can be used with one HackRF */
|
/* Up to 8 Operacake boards can be used with one HackRF */
|
||||||
extern uint8_t operacake_boards[8];
|
extern uint8_t operacake_boards[8];
|
||||||
|
|
||||||
uint8_t operacake_init(void);
|
uint8_t operacake_init(void);
|
||||||
uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB);
|
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);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <mixer.h>
|
#include <mixer.h>
|
||||||
#include <max2837.h>
|
#include <max2837.h>
|
||||||
#include <sgpio.h>
|
#include <sgpio.h>
|
||||||
|
#include <operacake.h>
|
||||||
|
|
||||||
#define FREQ_ONE_MHZ (1000*1000)
|
#define FREQ_ONE_MHZ (1000*1000)
|
||||||
|
|
||||||
@ -115,6 +116,7 @@ bool set_freq(const uint64_t freq)
|
|||||||
if( success ) {
|
if( success ) {
|
||||||
freq_cache = freq;
|
freq_cache = freq;
|
||||||
hackrf_ui_setFrequency(freq);
|
hackrf_ui_setFrequency(freq);
|
||||||
|
operacake_set_range(freq_mhz);
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,8 @@ static const usb_request_handler_fn vendor_request_handler[] = {
|
|||||||
usb_vendor_request_operacake_get_boards,
|
usb_vendor_request_operacake_get_boards,
|
||||||
usb_vendor_request_operacake_set_ports,
|
usb_vendor_request_operacake_set_ports,
|
||||||
usb_vendor_request_set_hw_sync_mode,
|
usb_vendor_request_set_hw_sync_mode,
|
||||||
usb_vendor_request_reset
|
usb_vendor_request_reset,
|
||||||
|
usb_vendor_request_operacake_set_ranges
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t vendor_request_handler_count =
|
static const uint32_t vendor_request_handler_count =
|
||||||
|
@ -47,3 +47,30 @@ usb_request_status_t usb_vendor_request_operacake_set_ports(
|
|||||||
}
|
}
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char data[MAX_OPERACAKE_RANGES * 5];
|
||||||
|
usb_request_status_t usb_vendor_request_operacake_set_ranges(
|
||||||
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||||
|
{
|
||||||
|
uint16_t i, freq_min, freq_max, num_ranges = 0;
|
||||||
|
uint8_t port;
|
||||||
|
|
||||||
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
|
num_ranges = endpoint->setup.length / 5;
|
||||||
|
if((num_ranges == 0) || (num_ranges > MAX_OPERACAKE_RANGES)) {
|
||||||
|
return USB_REQUEST_STATUS_STALL;
|
||||||
|
}
|
||||||
|
usb_transfer_schedule_block(endpoint->out, &data,
|
||||||
|
endpoint->setup.length, NULL, NULL);
|
||||||
|
} else if (stage == USB_TRANSFER_STAGE_DATA) {
|
||||||
|
|
||||||
|
for(i=0; i<endpoint->setup.length; i+=5) {
|
||||||
|
freq_min = data[i] << 8 | data[i+1];
|
||||||
|
freq_max = data[i+2] << 8 | data[i+3];
|
||||||
|
port = data[i+4];
|
||||||
|
operacake_add_range(freq_min, freq_max, port);
|
||||||
|
}
|
||||||
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
|
}
|
||||||
|
return USB_REQUEST_STATUS_OK;
|
||||||
|
}
|
||||||
|
@ -31,4 +31,7 @@ usb_request_status_t usb_vendor_request_operacake_get_boards(
|
|||||||
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);
|
||||||
|
|
||||||
|
usb_request_status_t usb_vendor_request_operacake_set_ranges(
|
||||||
|
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__ */
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
#define USB_PRODUCT_ID (0xFFFF)
|
#define USB_PRODUCT_ID (0xFFFF)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define USB_API_VERSION (0x0103)
|
||||||
|
|
||||||
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
|
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
|
||||||
|
|
||||||
#define USB_MAX_PACKET0 (64)
|
#define USB_MAX_PACKET0 (64)
|
||||||
@ -57,7 +59,7 @@ uint8_t usb_descriptor_device[] = {
|
|||||||
USB_MAX_PACKET0, // bMaxPacketSize0
|
USB_MAX_PACKET0, // bMaxPacketSize0
|
||||||
USB_WORD(USB_VENDOR_ID), // idVendor
|
USB_WORD(USB_VENDOR_ID), // idVendor
|
||||||
USB_WORD(USB_PRODUCT_ID), // idProduct
|
USB_WORD(USB_PRODUCT_ID), // idProduct
|
||||||
USB_WORD(0x0102), // bcdDevice
|
USB_WORD(USB_API_VERSION), // bcdDevice
|
||||||
0x01, // iManufacturer
|
0x01, // iManufacturer
|
||||||
0x02, // iProduct
|
0x02, // iProduct
|
||||||
0x04, // iSerialNumber
|
0x04, // iSerialNumber
|
||||||
|
@ -32,6 +32,7 @@ SET(TOOLS
|
|||||||
hackrf_info
|
hackrf_info
|
||||||
hackrf_debug
|
hackrf_debug
|
||||||
hackrf_sweep
|
hackrf_sweep
|
||||||
|
hackrf_operacake
|
||||||
)
|
)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef bool
|
#ifndef bool
|
||||||
typedef int bool;
|
typedef int bool;
|
||||||
@ -31,6 +32,10 @@ typedef int bool;
|
|||||||
#define false 0
|
#define false 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FREQ_MIN_MHZ (0) /* 0 MHz */
|
||||||
|
#define FREQ_MAX_MHZ (7250) /* 7250 MHz */
|
||||||
|
#define MAX_FREQ_RANGES 8
|
||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
printf("\nUsage:\n");
|
printf("\nUsage:\n");
|
||||||
printf("\t-h, --help: this help\n");
|
printf("\t-h, --help: this help\n");
|
||||||
@ -38,6 +43,7 @@ static void usage() {
|
|||||||
printf("\t-o, --address <n>: specify a particular operacake by address [default: 0x00]\n");
|
printf("\t-o, --address <n>: specify a particular operacake by address [default: 0x00]\n");
|
||||||
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-l, --list: list available operacake boards\n");
|
printf("\t-l, --list: list available operacake boards\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +55,13 @@ static struct option long_options[] = {
|
|||||||
{ 0, 0, 0, 0 },
|
{ 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
int parse_int(char* const s, uint16_t* const value) {
|
typedef struct {
|
||||||
|
uint16_t freq_min;
|
||||||
|
uint16_t freq_max;
|
||||||
|
uint8_t port;
|
||||||
|
} hackrf_oc_range;
|
||||||
|
|
||||||
|
int parse_uint16(char* const s, uint16_t* const value) {
|
||||||
char* s_end = s;
|
char* s_end = s;
|
||||||
const long long_value = strtol(s, &s_end, 10);
|
const long long_value = strtol(s, &s_end, 10);
|
||||||
if( (s != s_end) && (*s_end == 0) ) {
|
if( (s != s_end) && (*s_end == 0) ) {
|
||||||
@ -60,6 +72,34 @@ int parse_int(char* const s, uint16_t* const value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_u16_range(char* s, hackrf_oc_range* range) {
|
||||||
|
int result;
|
||||||
|
uint16_t port;
|
||||||
|
|
||||||
|
char *sep = strchr(s, ':');
|
||||||
|
if (!sep)
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
|
*sep = 0;
|
||||||
|
|
||||||
|
char *sep2 = strchr(sep+1, ':');
|
||||||
|
if (!sep2)
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
|
*sep2 = 0;
|
||||||
|
|
||||||
|
result = parse_uint16(s, &range->freq_min);
|
||||||
|
if (result != HACKRF_SUCCESS)
|
||||||
|
return result;
|
||||||
|
result = parse_uint16(sep + 1, &range->freq_max);
|
||||||
|
if (result != HACKRF_SUCCESS)
|
||||||
|
return result;
|
||||||
|
result = parse_uint16(sep2 + 1, &port);
|
||||||
|
if (result != HACKRF_SUCCESS)
|
||||||
|
return result;
|
||||||
|
range->port = port;
|
||||||
|
|
||||||
|
return HACKRF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -73,6 +113,8 @@ int main(int argc, char** argv) {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
hackrf_device* device = NULL;
|
hackrf_device* device = NULL;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
hackrf_oc_range ranges[MAX_FREQ_RANGES];
|
||||||
|
uint8_t range_idx = 0;
|
||||||
|
|
||||||
int result = hackrf_init();
|
int result = hackrf_init();
|
||||||
if( result ) {
|
if( result ) {
|
||||||
@ -80,7 +122,7 @@ int main(int argc, char** argv) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( (opt = getopt_long(argc, argv, "d:o:a:b:lh?", long_options, &option_index)) != EOF ) {
|
while( (opt = getopt_long(argc, argv, "d:o:a:b:lf:h?", long_options, &option_index)) != EOF ) {
|
||||||
switch( opt ) {
|
switch( opt ) {
|
||||||
case 'd':
|
case 'd':
|
||||||
serial_number = optarg;
|
serial_number = optarg;
|
||||||
@ -91,6 +133,31 @@ int main(int argc, char** argv) {
|
|||||||
set_ports = true;
|
set_ports = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
result = parse_u16_range(optarg, &ranges[range_idx]);
|
||||||
|
if(ranges[range_idx].freq_min >= ranges[range_idx].freq_max) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"argument error: freq_max must be greater than freq_min.\n");
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if(FREQ_MAX_MHZ < ranges[range_idx].freq_max) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"argument error: freq_max may not be higher than %u.\n",
|
||||||
|
FREQ_MAX_MHZ);
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
range_idx++;
|
||||||
|
if(MAX_FREQ_RANGES <= range_idx) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"argument error: specify a maximum of %u frequency ranges.\n",
|
||||||
|
MAX_FREQ_RANGES);
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
port_a = atoi(optarg);
|
port_a = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
@ -114,7 +181,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(list || set_ports)) {
|
if(!(list || set_ports || range_idx)) {
|
||||||
fprintf(stderr, "Specify either list or address option.\n");
|
fprintf(stderr, "Specify either list or address option.\n");
|
||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -154,6 +221,25 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(range_idx) {
|
||||||
|
uint8_t range_bytes[MAX_FREQ_RANGES * 5];
|
||||||
|
uint8_t ptr;
|
||||||
|
for(i=0; i<range_idx; i++) {
|
||||||
|
ptr = 5*i;
|
||||||
|
range_bytes[ptr] = ranges[i].freq_min >> 8;
|
||||||
|
range_bytes[ptr+1] = ranges[i].freq_min;
|
||||||
|
range_bytes[ptr+2] = ranges[i].freq_max >> 8;
|
||||||
|
range_bytes[ptr+3] = ranges[i].freq_max;
|
||||||
|
range_bytes[ptr+4] = ranges[i].port;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = hackrf_set_operacake_ranges(device, range_bytes, range_idx*5);
|
||||||
|
if( result ) {
|
||||||
|
printf("hackrf_set_operacake_ranges() 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);
|
||||||
|
@ -78,6 +78,7 @@ typedef enum {
|
|||||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS = 28,
|
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS = 28,
|
||||||
HACKRF_VENDOR_REQUEST_SET_HW_SYNC_MODE = 29,
|
HACKRF_VENDOR_REQUEST_SET_HW_SYNC_MODE = 29,
|
||||||
HACKRF_VENDOR_REQUEST_RESET = 30,
|
HACKRF_VENDOR_REQUEST_RESET = 30,
|
||||||
|
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_RANGES = 31,
|
||||||
} hackrf_vendor_request;
|
} hackrf_vendor_request;
|
||||||
|
|
||||||
#define USB_CONFIG_STANDARD 0x1
|
#define USB_CONFIG_STANDARD 0x1
|
||||||
@ -1967,6 +1968,29 @@ 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;
|
||||||
|
|
||||||
|
result = libusb_control_transfer(
|
||||||
|
device->usb_device,
|
||||||
|
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||||
|
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_RANGES,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
ranges,
|
||||||
|
len_ranges,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result < len_ranges) {
|
||||||
|
last_libusb_error = result;
|
||||||
|
return HACKRF_ERROR_LIBUSB;
|
||||||
|
} else {
|
||||||
|
return HACKRF_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // __cplusplus defined.
|
} // __cplusplus defined.
|
||||||
#endif
|
#endif
|
||||||
|
@ -242,6 +242,10 @@ extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
|||||||
|
|
||||||
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);
|
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);
|
||||||
|
|
||||||
|
extern ADDAPI int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device,
|
||||||
|
uint8_t* ranges,
|
||||||
|
uint8_t num_ranges);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // __cplusplus defined.
|
} // __cplusplus defined.
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user