Files
hackrf/host/libhackrf/src/hackrf.h
Martin Ling f3633e285f Replace direct setting of M0 mode with a request/ack mechanism.
This change avoids various possible races in which an autonomous mode
change by the M0 might clobber a mode change made from the M4, as well
as related races on other state fields that can be written by the M4.

The previous mode field is replaced by two separate ones:

- active_mode, which is written only by the M0, and indicates the
  current operating mode.

- requested_mode, which is written by the M4 to request a change.
  This field includes both the requested mode, and a flag bit. The M4
  writes the field with the flag bit set, and must then wait for the
  M0 to signal completion of the request by clearing the flag bit.

Whilst the M4 is blocked waiting for the flag bit to be cleared, the
M0 can safely make all the required changes to the state that are
needed for the transition to the requested mode. Once the transition
is complete, the M0 clears the flag bit and the M4 continues execution.

Request handling is implemented in the idle loop. To handle requests,
mode-specific loops simply need to check the request flag and branch to
idle if it is set.

A request from the M4 to change modes will always require passing
through the idle loop, and is not subject to timing guarantees. Only
transitions made autonomously by the M0 have guaranteed timing
constraints.

The work previously done in reset_counts is now implemented as part of
the request handling, so the tx_start, rx_start and wait_start labels
are no longer required.

An extra two cycles are required in the TX shortfall path because we
must now load the active mode to check whether we are in TX_START.

Two cycles are saved in the normal TX path because updating the active
mode to TX_RUN can now be done without checking the previous value.
2022-02-13 17:53:34 +00:00

336 lines
13 KiB
C

/*
Copyright (c) 2012, Jared Boone <jared@sharebrained.com>
Copyright (c) 2013, Benjamin Vernoux <titanmkd@gmail.com>
Copyright (c) 2013, Michael Ossmann <mike@ossmann.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of Great Scott Gadgets nor the names of its contributors may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __HACKRF_H__
#define __HACKRF_H__
#include <stdint.h>
#ifdef _WIN32
#define ADD_EXPORTS
/* You should define ADD_EXPORTS *only* when building the DLL. */
#ifdef ADD_EXPORTS
#define ADDAPI __declspec(dllexport)
#else
#define ADDAPI __declspec(dllimport)
#endif
/* Define calling convention in one place, for convenience. */
#define ADDCALL __cdecl
#else /* _WIN32 not defined. */
/* Define with no value on non-Windows OSes. */
#define ADDAPI
#define ADDCALL
#endif
#define SAMPLES_PER_BLOCK 8192
#define BYTES_PER_BLOCK 16384
#define MAX_SWEEP_RANGES 10
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
#define HACKRF_OPERACAKE_MAX_BOARDS 8
#define HACKRF_OPERACAKE_MAX_DWELL_TIMES 16
#define HACKRF_OPERACAKE_MAX_FREQ_RANGES 8
enum hackrf_error {
HACKRF_SUCCESS = 0,
HACKRF_TRUE = 1,
HACKRF_ERROR_INVALID_PARAM = -2,
HACKRF_ERROR_NOT_FOUND = -5,
HACKRF_ERROR_BUSY = -6,
HACKRF_ERROR_NO_MEM = -11,
HACKRF_ERROR_LIBUSB = -1000,
HACKRF_ERROR_THREAD = -1001,
HACKRF_ERROR_STREAMING_THREAD_ERR = -1002,
HACKRF_ERROR_STREAMING_STOPPED = -1003,
HACKRF_ERROR_STREAMING_EXIT_CALLED = -1004,
HACKRF_ERROR_USB_API_VERSION = -1005,
HACKRF_ERROR_NOT_LAST_DEVICE = -2000,
HACKRF_ERROR_OTHER = -9999,
};
enum hackrf_board_id {
BOARD_ID_JELLYBEAN = 0,
BOARD_ID_JAWBREAKER = 1,
BOARD_ID_HACKRF_ONE = 2,
BOARD_ID_RAD1O = 3,
BOARD_ID_INVALID = 0xFF,
};
enum hackrf_usb_board_id {
USB_BOARD_ID_JAWBREAKER = 0x604B,
USB_BOARD_ID_HACKRF_ONE = 0x6089,
USB_BOARD_ID_RAD1O = 0xCC15,
USB_BOARD_ID_INVALID = 0xFFFF,
};
enum rf_path_filter {
RF_PATH_FILTER_BYPASS = 0,
RF_PATH_FILTER_LOW_PASS = 1,
RF_PATH_FILTER_HIGH_PASS = 2,
};
enum operacake_ports {
OPERACAKE_PA1 = 0,
OPERACAKE_PA2 = 1,
OPERACAKE_PA3 = 2,
OPERACAKE_PA4 = 3,
OPERACAKE_PB1 = 4,
OPERACAKE_PB2 = 5,
OPERACAKE_PB3 = 6,
OPERACAKE_PB4 = 7,
};
enum operacake_switching_mode {
/**
* Port connections are set manually using @ref hackrf_set_operacake_ports.
*/
OPERACAKE_MODE_MANUAL,
/**
* Port connections are switched automatically when the frequency is changed. Frequency ranges can be set using @ref hackrf_set_operacake_freq_ranges.
*/
OPERACAKE_MODE_FREQUENCY,
/**
* Port connections are switched automatically over time.
*/
OPERACAKE_MODE_TIME,
};
enum sweep_style {
LINEAR = 0,
INTERLEAVED = 1,
};
typedef struct hackrf_device hackrf_device;
/**
* USB transfer information passed to RX or TX callback.
* A callback should treat all these fields as read-only except that a TX callback should write to the data buffer.
*/
typedef struct {
hackrf_device* device; /**< HackRF USB device for this transfer */
uint8_t* buffer; /**< transfer data buffer */
int buffer_length; /**< length of data buffer in bytes */
int valid_length; /**< number of buffer bytes that were transferred */
void* rx_ctx; /**< RX libusb context */
void* tx_ctx; /**< TX libusb context */
} hackrf_transfer;
typedef struct {
uint32_t part_id[2];
uint32_t serial_no[4];
} read_partid_serialno_t;
typedef struct {
uint32_t dwell;
uint8_t port;
} hackrf_operacake_dwell_time;
typedef struct {
uint16_t freq_min;
uint16_t freq_max;
uint8_t port;
} hackrf_operacake_freq_range;
/** State of the SGPIO loop running on the M0 core. */
typedef struct {
/** Request flag. */
uint16_t request_flag;
/** Requested mode. */
uint16_t requested_mode;
/** Active mode. */
uint32_t active_mode;
/** Number of bytes transferred by the M0. */
uint32_t m0_count;
/** Number of bytes transferred by the M4. */
uint32_t m4_count;
/** Number of shortfalls. */
uint32_t num_shortfalls;
/** Longest shortfall. */
uint32_t longest_shortfall;
/** Shortfall limit in bytes. */
uint32_t shortfall_limit;
/** Threshold m0_count value for next mode change. */
uint32_t threshold;
/** Mode which will be switched to when threshold is reached. */
uint32_t next_mode;
/** Error, if any, that caused the M0 to revert to IDLE mode. */
uint32_t error;
} hackrf_m0_state;
struct hackrf_device_list {
char **serial_numbers;
enum hackrf_usb_board_id *usb_board_ids;
int *usb_device_index;
int devicecount;
void **usb_devices;
int usb_devicecount;
};
typedef struct hackrf_device_list hackrf_device_list_t;
typedef int (*hackrf_sample_block_cb_fn)(hackrf_transfer* transfer);
#ifdef __cplusplus
extern "C"
{
#endif
extern ADDAPI int ADDCALL hackrf_init();
extern ADDAPI int ADDCALL hackrf_exit();
extern ADDAPI const char* ADDCALL hackrf_library_version();
extern ADDAPI const char* ADDCALL hackrf_library_release();
extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list();
extern ADDAPI int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device);
extern ADDAPI void ADDCALL hackrf_device_list_free(hackrf_device_list_t *list);
extern ADDAPI int ADDCALL hackrf_open(hackrf_device** device);
extern ADDAPI int ADDCALL hackrf_open_by_serial(const char* const desired_serial_number, hackrf_device** device);
extern ADDAPI int ADDCALL hackrf_close(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* rx_ctx);
extern ADDAPI int ADDCALL hackrf_stop_rx(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* tx_ctx);
extern ADDAPI int ADDCALL hackrf_stop_tx(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* value);
extern ADDAPI int ADDCALL hackrf_set_tx_underrun_limit(hackrf_device* device, uint32_t value);
extern ADDAPI int ADDCALL hackrf_set_rx_overrun_limit(hackrf_device* device, uint32_t value);
/* return HACKRF_TRUE if success */
extern ADDAPI int ADDCALL hackrf_is_streaming(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_max2837_read(hackrf_device* device, uint8_t register_number, uint16_t* value);
extern ADDAPI int ADDCALL hackrf_max2837_write(hackrf_device* device, uint8_t register_number, uint16_t value);
extern ADDAPI int ADDCALL hackrf_si5351c_read(hackrf_device* device, uint16_t register_number, uint16_t* value);
extern ADDAPI int ADDCALL hackrf_si5351c_write(hackrf_device* device, uint16_t register_number, uint16_t value);
extern ADDAPI int ADDCALL hackrf_set_baseband_filter_bandwidth(hackrf_device* device, const uint32_t bandwidth_hz);
extern ADDAPI int ADDCALL hackrf_rffc5071_read(hackrf_device* device, uint8_t register_number, uint16_t* value);
extern ADDAPI int ADDCALL hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number, uint16_t value);
extern ADDAPI int ADDCALL hackrf_spiflash_erase(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* const data);
extern ADDAPI int ADDCALL hackrf_spiflash_read(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* data);
extern ADDAPI int ADDCALL hackrf_spiflash_status(hackrf_device* device, uint8_t* data);
extern ADDAPI int ADDCALL hackrf_spiflash_clear_status(hackrf_device* device);
/* device will need to be reset after hackrf_cpld_write */
extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device,
unsigned char* const data, const unsigned int total_length);
extern ADDAPI int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value);
extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length);
extern ADDAPI int ADDCALL hackrf_usb_api_version_read(hackrf_device* device, uint16_t* version);
extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz);
extern ADDAPI int ADDCALL hackrf_set_freq_explicit(hackrf_device* device,
const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
const enum rf_path_filter path);
/* 2-20Mhz - either as a fraction, i.e. freq 20000000hz divider 2 -> 10Mhz or as plain old 10000000hz (double) */
extern ADDAPI int ADDCALL hackrf_set_sample_rate_manual(hackrf_device* device, const uint32_t freq_hz, const uint32_t divider);
extern ADDAPI int ADDCALL hackrf_set_sample_rate(hackrf_device* device, const double freq_hz);
/* external amp, bool on/off */
extern ADDAPI int ADDCALL hackrf_set_amp_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI int ADDCALL hackrf_board_partid_serialno_read(hackrf_device* device, read_partid_serialno_t* read_partid_serialno);
/* range 0-40 step 8d, IF gain in osmosdr */
extern ADDAPI int ADDCALL hackrf_set_lna_gain(hackrf_device* device, uint32_t value);
/* range 0-62 step 2db, BB gain in osmosdr */
extern ADDAPI int ADDCALL hackrf_set_vga_gain(hackrf_device* device, uint32_t value);
/* range 0-47 step 1db */
extern ADDAPI int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t value);
/* antenna port power control */
extern ADDAPI int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI const char* ADDCALL hackrf_error_name(enum hackrf_error errcode);
extern ADDAPI const char* ADDCALL hackrf_board_id_name(enum hackrf_board_id board_id);
extern ADDAPI const char* ADDCALL hackrf_usb_board_id_name(enum hackrf_usb_board_id usb_board_id);
extern ADDAPI const char* ADDCALL hackrf_filter_path_name(const enum rf_path_filter path);
/* Compute nearest freq for bw filter (manual filter) */
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(const uint32_t bandwidth_hz);
/* 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);
/* All features below require USB API version 0x1002 or higher) */
/* set hardware sync mode */
extern ADDAPI int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value);
/* Start sweep mode */
extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device,
const uint16_t* frequency_list, const int num_ranges,
const uint32_t num_bytes, const uint32_t step_width,
const uint32_t offset, const enum sweep_style style);
/* Operacake functions */
extern ADDAPI int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards);
extern ADDAPI int ADDCALL hackrf_set_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode mode);
extern ADDAPI int ADDCALL hackrf_get_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode *mode);
extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
uint8_t address,
uint8_t port_a,
uint8_t port_b);
extern ADDAPI int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count);
extern ADDAPI int ADDCALL hackrf_set_operacake_freq_ranges(hackrf_device* device, hackrf_operacake_freq_range *freq_ranges, uint8_t count);
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);
extern ADDAPI int ADDCALL hackrf_set_clkout_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI int ADDCALL hackrf_operacake_gpio_test(hackrf_device* device,
uint8_t address,
uint16_t* test_result);
#ifdef HACKRF_ISSUE_609_IS_FIXED
extern ADDAPI int ADDCALL hackrf_cpld_checksum(hackrf_device* device,
uint32_t* crc);
#endif /* HACKRF_ISSUE_609_IS_FIXED */
extern ADDAPI int ADDCALL hackrf_set_ui_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI int ADDCALL hackrf_start_rx_sweep(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* rx_ctx);
#ifdef __cplusplus
} // __cplusplus defined.
#endif
#endif /*__HACKRF_H__*/