Skip to content

Commit 2f9a642

Browse files
committed
Add 'hackrf_radio_set_mode()'
1 parent d87b190 commit 2f9a642

9 files changed

Lines changed: 205 additions & 0 deletions

File tree

firmware/common/fpga.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626

2727
#include "ice40_spi.h"
2828

29+
/* Supported Bitstreams. */
30+
typedef enum {
31+
FPGA_BITSTREAM_STANDARD = 0,
32+
FPGA_BITSTREAM_HALFPREC = 1,
33+
FPGA_BITSTREAM_EXTPREC_RX = 2,
34+
FPGA_BITSTREAM_EXTPREC_TX = 3,
35+
} fpga_bitstream_index_t;
36+
2937
/* Up to 7 registers, each containing up to 8 bits of data */
3038
#define FPGA_NUM_REGS 7
3139
#define FPGA_DATA_REGS_MAX_VALUE 255

firmware/common/radio.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,3 +952,66 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode)
952952
nvic_enable_irq(NVIC_USB0_IRQ);
953953
radio_update(radio);
954954
}
955+
956+
bool radio_set_config_mode(radio_t* const radio, const radio_config_mode_t mode)
957+
{
958+
// Check if the requested mode is supported.
959+
switch (mode) {
960+
case RADIO_CONFIG_LEGACY:
961+
case RADIO_CONFIG_STANDARD:
962+
// supported on all boards
963+
break;
964+
#ifdef IS_PRALINE
965+
case RADIO_CONFIG_HALF_PRECISION:
966+
case RADIO_CONFIG_EXT_PRECISION_RX:
967+
case RADIO_CONFIG_EXT_PRECISION_TX:
968+
// only supported on praline
969+
if (!IS_PRALINE) {
970+
return false;
971+
}
972+
break;
973+
#endif
974+
default:
975+
return false;
976+
}
977+
978+
// If we're on praline, load the appropriate bitstream.
979+
#if defined(IS_PRALINE) && !(defined(DFU_MODE) || defined(RAM_MODE))
980+
if (IS_PRALINE) {
981+
fpga_bitstream_index_t bitstream_index;
982+
switch (mode) {
983+
case RADIO_CONFIG_LEGACY:
984+
case RADIO_CONFIG_STANDARD:
985+
bitstream_index = FPGA_BITSTREAM_STANDARD;
986+
break;
987+
case RADIO_CONFIG_HALF_PRECISION:
988+
bitstream_index = FPGA_BITSTREAM_HALFPREC;
989+
break;
990+
case RADIO_CONFIG_EXT_PRECISION_RX:
991+
bitstream_index = FPGA_BITSTREAM_EXTPREC_RX;
992+
break;
993+
case RADIO_CONFIG_EXT_PRECISION_TX:
994+
bitstream_index = FPGA_BITSTREAM_EXTPREC_TX;
995+
break;
996+
default:
997+
return false;
998+
}
999+
1000+
// Load bitstream if needed.
1001+
if (mode != radio->config_mode) {
1002+
extern struct fpga_loader_t fpga_loader;
1003+
if (!fpga_image_load(&fpga_loader, bitstream_index)) {
1004+
return false;
1005+
}
1006+
}
1007+
}
1008+
#endif
1009+
1010+
// Update radio config mode.
1011+
radio->config_mode = mode;
1012+
1013+
// Clear radio registers - TODO temporary workaround for zero-valued samples when switching bitstreams.
1014+
radio_init(radio);
1015+
1016+
return true;
1017+
}

firmware/common/radio.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,15 @@ typedef enum {
4141
} radio_error_t;
4242

4343
/* radio configuration modes */
44+
// TODO are we sure we need a legacy mode?
4445
typedef enum {
4546
RADIO_CONFIG_LEGACY = 0,
4647
RADIO_CONFIG_STANDARD = 1,
48+
#ifdef IS_PRALINE
4749
RADIO_CONFIG_EXT_PRECISION_RX = 2,
4850
RADIO_CONFIG_EXT_PRECISION_TX = 3,
4951
RADIO_CONFIG_HALF_PRECISION = 4,
52+
#endif
5053
} radio_config_mode_t;
5154

5255
typedef struct {
@@ -271,6 +274,12 @@ bool radio_update(radio_t* const radio);
271274
*/
272275
void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode);
273276

277+
/**
278+
* Switch to a new configuration mode.
279+
* Return true if the mode was successfully switched.
280+
*/
281+
bool radio_set_config_mode(radio_t* const radio, const radio_config_mode_t mode);
282+
274283
/**
275284
* Driver instance.
276285
*/

firmware/hackrf_usb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ set(SRC_M4
6060
usb_api_spiflash.c
6161
usb_api_transceiver.c
6262
usb_api_operacake.c
63+
usb_api_radio.c
6364
usb_api_sweep.c
6465
usb_api_selftest.c
6566
usb_api_ui.c

firmware/hackrf_usb/hackrf_usb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#include "usb_api_board_info.h"
7676
#include "usb_api_m0_state.h"
7777
#include "usb_api_operacake.h"
78+
#include "usb_api_radio.h"
7879
#include "usb_api_register.h"
7980
#include "usb_api_selftest.h"
8081
#include "usb_api_spiflash.h"
@@ -185,6 +186,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
185186
usb_vendor_request_lock_radio_reg,
186187
usb_vendor_request_open,
187188
usb_vendor_request_close,
189+
usb_vendor_request_set_radio_mode,
188190
};
189191

190192
static const uint32_t vendor_request_handler_count =
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2026 Great Scott Gadgets <info@greatscottgadgets.com>
3+
*
4+
* This file is part of HackRF.
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2, or (at your option)
9+
* any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; see the file COPYING. If not, write to
18+
* the Free Software Foundation, Inc., 51 Franklin Street,
19+
* Boston, MA 02110-1301, USA.
20+
*/
21+
22+
#include <radio.h>
23+
#include <usb_request.h>
24+
#include <usb_type.h>
25+
26+
#include "usb_queue.h"
27+
28+
usb_request_status_t usb_vendor_request_set_radio_mode(
29+
usb_endpoint_t* const endpoint,
30+
const usb_transfer_stage_t stage)
31+
{
32+
if (stage == USB_TRANSFER_STAGE_SETUP) {
33+
radio_config_mode_t mode = endpoint->setup.value;
34+
if (!radio_set_config_mode(&radio, mode)) {
35+
return USB_REQUEST_STATUS_STALL;
36+
}
37+
usb_transfer_schedule_ack(endpoint->in);
38+
}
39+
40+
return USB_REQUEST_STATUS_OK;
41+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2026 Great Scott Gadgets <info@greatscottgadgets.com>
3+
*
4+
* This file is part of HackRF.
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2, or (at your option)
9+
* any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; see the file COPYING. If not, write to
18+
* the Free Software Foundation, Inc., 51 Franklin Street,
19+
* Boston, MA 02110-1301, USA.
20+
*/
21+
22+
#pragma once
23+
24+
#include <usb_request.h>
25+
#include <usb_type.h>
26+
27+
usb_request_status_t usb_vendor_request_set_radio_mode(
28+
usb_endpoint_t* const endpoint,
29+
const usb_transfer_stage_t stage);

host/libhackrf/src/hackrf.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ typedef enum {
123123
HACKRF_VENDOR_REQUEST_RADIO_LOCK_REG = 62,
124124
HACKRF_VENDOR_REQUEST_OPEN = 63,
125125
HACKRF_VENDOR_REQUEST_CLOSE = 64,
126+
HACKRF_VENDOR_REQUEST_RADIO_SET_MODE = 65,
126127
} hackrf_vendor_request;
127128

128129
#define USB_CONFIG_STANDARD 0x1
@@ -3748,6 +3749,32 @@ int ADDCALL hackrf_radio_lock_register(
37483749
return HACKRF_SUCCESS;
37493750
}
37503751

3752+
int ADDCALL hackrf_radio_set_config_mode(
3753+
hackrf_device* device,
3754+
const enum radio_config_mode mode)
3755+
{
3756+
USB_API_REQUIRED(device, 0x0113);
3757+
int result;
3758+
3759+
result = libusb_control_transfer(
3760+
device->usb_device,
3761+
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
3762+
LIBUSB_RECIPIENT_DEVICE,
3763+
HACKRF_VENDOR_REQUEST_RADIO_SET_MODE,
3764+
mode,
3765+
0,
3766+
NULL,
3767+
0,
3768+
DEFAULT_REQUEST_TIMEOUT);
3769+
3770+
if (result != 0) {
3771+
last_libusb_error = result;
3772+
return HACKRF_ERROR_LIBUSB;
3773+
}
3774+
3775+
return HACKRF_SUCCESS;
3776+
}
3777+
37513778
#ifdef __cplusplus
37523779
} // __cplusplus defined.
37533780
#endif

host/libhackrf/src/hackrf.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,19 @@ enum clkin_ctrl_signal {
946946
CLKIN_SIGNAL_P22 = 1,
947947
};
948948

949+
/**
950+
* HackRF Pro Radio Configuration Mode.
951+
*
952+
* Used by @ref hackrf_radio_set_config_mode, to set the active configuration mode.
953+
*/
954+
enum radio_config_mode {
955+
RADIO_CONFIG_LEGACY = 0,
956+
RADIO_CONFIG_STANDARD = 1,
957+
RADIO_CONFIG_EXT_PRECISION_RX = 2,
958+
RADIO_CONFIG_EXT_PRECISION_TX = 3,
959+
RADIO_CONFIG_HALF_PRECISION = 4,
960+
};
961+
949962
/**
950963
* Opaque struct for hackrf device info. Object can be created via @ref hackrf_open, @ref hackrf_device_list_open or @ref hackrf_open_by_serial and be destroyed via @ref hackrf_close
951964
* @ingroup device
@@ -2477,6 +2490,18 @@ extern ADDAPI int ADDCALL hackrf_radio_lock_register(
24772490
const uint8_t register_number,
24782491
const bool register_locked);
24792492

2493+
/**
2494+
* Switches the radio configuration mode.
2495+
*
2496+
* @param[in] device device to configure
2497+
* @param[in] mode configuration mode. Defaults to RADIO_CONFIG_LEGACY. Available modes are defined in @ref radio_config_mode.
2498+
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
2499+
* @ingroup configuration
2500+
*/
2501+
extern ADDAPI int ADDCALL hackrf_radio_set_config_mode(
2502+
hackrf_device* device,
2503+
const enum radio_config_mode mode);
2504+
24802505
#ifdef __cplusplus
24812506
} // __cplusplus defined.
24822507
#endif

0 commit comments

Comments
 (0)