Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions firmware/hackrf_usb/hackrf_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
usb_vendor_request_read_supported_platform,
usb_vendor_request_set_leds,
usb_vendor_request_user_config_set_bias_t_opts,
usb_vendor_request_set_freq_when,
};

static const uint32_t vendor_request_handler_count =
Expand Down
60 changes: 58 additions & 2 deletions firmware/hackrf_usb/usb_api_transceiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,23 @@

#define USB_TRANSFER_SIZE 0x4000

static int frequency_switch_scheduled = 0;

typedef struct {
uint32_t freq_mhz;
uint32_t freq_hz;
} set_freq_params_t;

set_freq_params_t set_freq_params;

typedef struct {
uint32_t freq_mhz;
uint32_t freq_hz;
uint32_t when;
} set_freq_when_params_t;

set_freq_when_params_t set_freq_when_params;

struct set_freq_explicit_params {
uint64_t if_freq_hz; /* intermediate frequency */
uint64_t lo_freq_hz; /* front-end local oscillator frequency */
Expand Down Expand Up @@ -113,6 +123,29 @@ usb_request_status_t usb_vendor_request_set_freq(
}
}

usb_request_status_t usb_vendor_request_set_freq_when(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(
endpoint->out,
&set_freq_when_params,
sizeof(set_freq_when_params_t),
NULL,
NULL);
return USB_REQUEST_STATUS_OK;
} else if (stage == USB_TRANSFER_STAGE_DATA) {
if (frequency_switch_scheduled)
return USB_REQUEST_STATUS_STALL;
frequency_switch_scheduled = 1;
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
} else {
return USB_REQUEST_STATUS_OK;
}
}

usb_request_status_t usb_vendor_request_set_sample_rate_frac(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
Expand Down Expand Up @@ -415,9 +448,20 @@ void rx_mode(uint32_t seq)
transceiver_startup(TRANSCEIVER_MODE_RX);

baseband_streaming_enable(&sgpio_config);
frequency_switch_scheduled = 0;

while (transceiver_request.seq == seq) {
if ((m0_state.m0_count - usb_count) >= USB_TRANSFER_SIZE) {
uint32_t local_m0_count = m0_state.m0_count;

/* Check if scheduled frequency change is due, handles integer wrap-around */
if (frequency_switch_scheduled &&
!((local_m0_count - set_freq_when_params.when) & 0x80000000)) {
const uint64_t freq = set_freq_when_params.freq_mhz * 1000000ULL +
set_freq_when_params.freq_hz;
set_freq(freq);
frequency_switch_scheduled = 0;
}
if ((local_m0_count - usb_count) >= USB_TRANSFER_SIZE) {
usb_transfer_schedule_block(
&usb_endpoint_bulk_in,
&usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK],
Expand Down Expand Up @@ -447,13 +491,25 @@ void tx_mode(uint32_t seq)
NULL);
usb_count += USB_TRANSFER_SIZE;

frequency_switch_scheduled = 0;

while (transceiver_request.seq == seq) {
uint32_t local_m0_count = m0_state.m0_count;
if (!started && (m0_state.m4_count == USB_BULK_BUFFER_SIZE)) {
// Buffer is now full, start streaming.
baseband_streaming_enable(&sgpio_config);
started = true;
}
if ((usb_count - m0_state.m0_count) <= USB_TRANSFER_SIZE) {

/* Check if scheduled frequency change is due, handles integer wrap-around */
if (frequency_switch_scheduled &&
!((local_m0_count - set_freq_when_params.when) & 0x80000000)) {
const uint64_t freq = set_freq_when_params.freq_mhz * 1000000ULL +
set_freq_when_params.freq_hz;
set_freq(freq);
frequency_switch_scheduled = 0;
}
if ((usb_count - local_m0_count) <= USB_TRANSFER_SIZE) {
usb_transfer_schedule_block(
&usb_endpoint_bulk_out,
&usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK],
Expand Down
3 changes: 3 additions & 0 deletions firmware/hackrf_usb/usb_api_transceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth(
usb_request_status_t usb_vendor_request_set_freq(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_freq_when(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_sample_rate_frac(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
Expand Down
46 changes: 46 additions & 0 deletions host/libhackrf/src/hackrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ typedef enum {
HACKRF_VENDOR_REQUEST_SUPPORTED_PLATFORM_READ = 46,
HACKRF_VENDOR_REQUEST_SET_LEDS = 47,
HACKRF_VENDOR_REQUEST_SET_USER_BIAS_T_OPTS = 48,
HACKRF_VENDOR_REQUEST_SET_FREQ_WHEN = 49,
} hackrf_vendor_request;

#define USB_CONFIG_STANDARD 0x1
Expand Down Expand Up @@ -1443,6 +1444,51 @@ int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz)
}
}

typedef struct {
uint32_t freq_mhz; /* From 0 to 6000+MHz */
uint32_t freq_hz; /* From 0 to 999999Hz */
/* Final Freq = freq_mhz+freq_hz */
uint32_t when;
} set_freq_when_params_t;

int ADDCALL hackrf_set_freq_when(
hackrf_device* device,
const uint64_t freq_hz,
const uint32_t when)
{
uint32_t l_freq_mhz;
uint32_t l_freq_hz;
set_freq_when_params_t set_freq_when_params;
uint8_t length;
int result;

/* Convert Freq Hz 64bits to Freq MHz (32bits) & Freq Hz (32bits) */
l_freq_mhz = (uint32_t) (freq_hz / FREQ_ONE_MHZ);
l_freq_hz = (uint32_t) (freq_hz - (((uint64_t) l_freq_mhz) * FREQ_ONE_MHZ));
set_freq_when_params.freq_mhz = TO_LE(l_freq_mhz);
set_freq_when_params.freq_hz = TO_LE(l_freq_hz);
set_freq_when_params.when = TO_LE(when);
length = sizeof(set_freq_when_params_t);

result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_SET_FREQ_WHEN,
0,
0,
(unsigned char*) &set_freq_when_params,
length,
0);

if (result < length) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
} else {
return HACKRF_SUCCESS;
}
}

struct set_freq_explicit_params {
uint64_t if_freq_hz; /* intermediate frequency */
uint64_t lo_freq_hz; /* front-end local oscillator frequency */
Expand Down
20 changes: 20 additions & 0 deletions host/libhackrf/src/hackrf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,26 @@ extern ADDAPI int ADDCALL hackrf_usb_api_version_read(
*/
extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz);

/**
* Schedule a center frequency change at a specific point in the RX/TX stream. The "when" argument specifices this point in the stream, and its value corresponds to the number of bytes sent (resp. received) to (resp. from) since the beginning of the stream, modulo 2^32 (this corresponds to the m0_counter value of the firmware).
*
* NOTE: A maximum of one scheduled frequency change is supported at a time. Trying to schedule a frequency change when one is still pending will result in an usb stall.
*
* Simple (auto) tuning via specifying a center frequency in Hz
*
* This setting is not exact and depends on the PLL settings. Exact resolution is not determined, but the actual tuned frequency will be queryable in the future.
*
* @param device device to tune
* @param freq_hz center frequency in Hz. Defaults to 900MHz. Should be in range 1-6000MHz, but 0-7250MHz is possible. The resolution is ~50Hz, I could not find the exact number.
* @param when sets the frequency when the m0 counter matches this value
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
* @ingroup configuration
*/
extern ADDAPI int ADDCALL hackrf_set_freq_when(
hackrf_device* device,
const uint64_t freq_hz,
const uint32_t when);

/**
* Set the center frequency via explicit tuning
*
Expand Down