summaryrefslogtreecommitdiff
path: root/Radio/HW/BladeRF/fpga_common/include
diff options
context:
space:
mode:
authorArturs Artamonovs <arturs.artamonovs@protonmail.com>2024-11-03 15:56:55 +0000
committerArturs Artamonovs <arturs.artamonovs@protonmail.com>2024-11-03 15:56:55 +0000
commitcf4444e7390365df43ecbd3d130015c1e06ef88f (patch)
tree8a6eb114135a04d5efd5af213577b4fac47532ae /Radio/HW/BladeRF/fpga_common/include
parentca50c0f64f1b2fce46b4cb83ed111854bac13852 (diff)
downloadPrySDR-cf4444e7390365df43ecbd3d130015c1e06ef88f.tar.gz
PrySDR-cf4444e7390365df43ecbd3d130015c1e06ef88f.zip
BladeRF library compiles
Diffstat (limited to 'Radio/HW/BladeRF/fpga_common/include')
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/ad936x.h858
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/ad936x_helpers.h127
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/band_select.h50
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/bladerf2_common.h749
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/lms.h838
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_16x64.h218
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_32x32.h208
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x16.h213
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x32.h231
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x64.h206
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x8.h197
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_formats.h37
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_legacy.h231
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune.h334
-rw-r--r--Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune2.h273
15 files changed, 4770 insertions, 0 deletions
diff --git a/Radio/HW/BladeRF/fpga_common/include/ad936x.h b/Radio/HW/BladeRF/fpga_common/include/ad936x.h
new file mode 100644
index 0000000..5fd43e7
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/ad936x.h
@@ -0,0 +1,858 @@
+/**
+ * @file ad936x.h
+ *
+ * @brief Interface to the library for the AD936X RFIC family
+ *
+ * Copyright (c) 2018 Nuand LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef AD936X_H_
+#define AD936X_H_
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+/**
+ * The purpose of this header file is to allow the use of libad9361 without
+ * including all of the unnecessary defines, etc, used during compilation.
+ *
+ * This file is largely copied from the files named in each section. Only
+ * necessary declarations are present.
+ *
+ * In general, defines are prefixed with AD936X_ to avoid conflicts.
+ *
+ * Comments have been removed for brevity. Please see the original header
+ * files from the third-party ADI library for further details.
+ */
+
+/******************************************************************************
+ * From common.h
+ ******************************************************************************/
+
+struct clk_onecell_data {
+ struct clk **clks;
+ uint32_t clk_num;
+};
+
+/******************************************************************************
+ * From ad9361.h
+ ******************************************************************************/
+
+#define AD936X_REG_TX1_OUT_1_PHASE_CORR 0x08E
+#define AD936X_REG_TX1_OUT_1_GAIN_CORR 0x08F
+#define AD936X_REG_TX2_OUT_1_PHASE_CORR 0x090
+#define AD936X_REG_TX2_OUT_1_GAIN_CORR 0x091
+#define AD936X_REG_TX1_OUT_1_OFFSET_I 0x092
+#define AD936X_REG_TX1_OUT_1_OFFSET_Q 0x093
+#define AD936X_REG_TX2_OUT_1_OFFSET_I 0x094
+#define AD936X_REG_TX2_OUT_1_OFFSET_Q 0x095
+#define AD936X_REG_TX1_OUT_2_PHASE_CORR 0x096
+#define AD936X_REG_TX1_OUT_2_GAIN_CORR 0x097
+#define AD936X_REG_TX2_OUT_2_PHASE_CORR 0x098
+#define AD936X_REG_TX2_OUT_2_GAIN_CORR 0x099
+#define AD936X_REG_TX1_OUT_2_OFFSET_I 0x09A
+#define AD936X_REG_TX1_OUT_2_OFFSET_Q 0x09B
+#define AD936X_REG_TX2_OUT_2_OFFSET_I 0x09C
+#define AD936X_REG_TX2_OUT_2_OFFSET_Q 0x09D
+#define AD936X_REG_TX_FORCE_BITS 0x09F
+
+#define AD936X_REG_RX1_INPUT_A_PHASE_CORR 0x170
+#define AD936X_REG_RX1_INPUT_A_GAIN_CORR 0x171
+#define AD936X_REG_RX2_INPUT_A_PHASE_CORR 0x172
+#define AD936X_REG_RX2_INPUT_A_GAIN_CORR 0x173
+#define AD936X_REG_RX1_INPUT_A_Q_OFFSET 0x174
+#define AD936X_REG_RX1_INPUT_A_OFFSETS 0x175
+#define AD936X_REG_INPUT_A_OFFSETS_1 0x176
+#define AD936X_REG_RX2_INPUT_A_OFFSETS 0x177
+#define AD936X_REG_RX2_INPUT_A_I_OFFSET 0x178
+#define AD936X_REG_RX1_INPUT_BC_PHASE_CORR 0x179
+#define AD936X_REG_RX1_INPUT_BC_GAIN_CORR 0x17A
+#define AD936X_REG_RX2_INPUT_BC_PHASE_CORR 0x17B
+#define AD936X_REG_RX2_INPUT_BC_GAIN_CORR 0x17C
+#define AD936X_REG_RX1_INPUT_BC_Q_OFFSET 0x17D
+#define AD936X_REG_RX1_INPUT_BC_OFFSETS 0x17E
+#define AD936X_REG_INPUT_BC_OFFSETS_1 0x17F
+#define AD936X_REG_RX2_INPUT_BC_OFFSETS 0x180
+#define AD936X_REG_RX2_INPUT_BC_I_OFFSET 0x181
+#define AD936X_REG_FORCE_BITS 0x182
+
+#define AD936X_READ (0 << 15)
+#define AD936X_WRITE (1 << 15)
+#define AD936X_CNT(x) ((((x)-1) & 0x7) << 12)
+#define AD936X_ADDR(x) ((x)&0x3FF)
+
+enum dev_id { ID_AD9361, ID_AD9364, ID_AD9363A };
+
+enum ad9361_clocks {
+ BB_REFCLK,
+ RX_REFCLK,
+ TX_REFCLK,
+ BBPLL_CLK,
+ ADC_CLK,
+ R2_CLK,
+ R1_CLK,
+ CLKRF_CLK,
+ RX_SAMPL_CLK,
+ DAC_CLK,
+ T2_CLK,
+ T1_CLK,
+ CLKTF_CLK,
+ TX_SAMPL_CLK,
+ RX_RFPLL_INT,
+ TX_RFPLL_INT,
+ RX_RFPLL_DUMMY,
+ TX_RFPLL_DUMMY,
+ RX_RFPLL,
+ TX_RFPLL,
+ NUM_AD9361_CLKS,
+ EXT_REF_CLK,
+};
+
+enum rx_gain_table_name {
+ TBL_200_1300_MHZ,
+ TBL_1300_4000_MHZ,
+ TBL_4000_6000_MHZ,
+ RXGAIN_TBLS_END,
+};
+
+enum rx_gain_table_type {
+ RXGAIN_FULL_TBL,
+ RXGAIN_SPLIT_TBL,
+};
+
+struct rx_gain_info {
+ enum rx_gain_table_type tbl_type;
+ int32_t starting_gain_db;
+ int32_t max_gain_db;
+ int32_t gain_step_db;
+ int32_t max_idx;
+ int32_t idx_step_offset;
+};
+
+enum ad9361_pdata_rx_freq {
+ BBPLL_FREQ,
+ ADC_FREQ,
+ R2_FREQ,
+ R1_FREQ,
+ CLKRF_FREQ,
+ RX_SAMPL_FREQ,
+ NUM_RX_CLOCKS,
+};
+
+enum ad9361_pdata_tx_freq {
+ IGNORE_FREQ,
+ DAC_FREQ,
+ T2_FREQ,
+ T1_FREQ,
+ CLKTF_FREQ,
+ TX_SAMPL_FREQ,
+ NUM_TX_CLOCKS,
+};
+
+struct ad9361_fastlock_entry {
+ //#define FASTLOOK_INIT 1
+ uint8_t flags;
+ uint8_t alc_orig;
+ uint8_t alc_written;
+};
+
+struct ad9361_fastlock {
+ uint8_t save_profile;
+ uint8_t current_profile[2];
+ struct ad9361_fastlock_entry entry[2][8];
+};
+
+enum ad9361_bist_mode {
+ BIST_DISABLE,
+ BIST_INJ_TX,
+ BIST_INJ_RX,
+};
+
+enum ad9361_clkout {
+ CLKOUT_DISABLE,
+ BUFFERED_XTALN_DCXO,
+ ADC_CLK_DIV_2,
+ ADC_CLK_DIV_3,
+ ADC_CLK_DIV_4,
+ ADC_CLK_DIV_8,
+ ADC_CLK_DIV_16,
+};
+
+enum rf_gain_ctrl_mode {
+ RF_GAIN_MGC,
+ RF_GAIN_FASTATTACK_AGC,
+ RF_GAIN_SLOWATTACK_AGC,
+ RF_GAIN_HYBRID_AGC
+};
+
+enum f_agc_target_gain_index_type {
+ MAX_GAIN,
+ SET_GAIN,
+ OPTIMIZED_GAIN,
+ NO_GAIN_CHANGE,
+};
+
+enum rssi_restart_mode {
+ AGC_IN_FAST_ATTACK_MODE_LOCKS_THE_GAIN,
+ EN_AGC_PIN_IS_PULLED_HIGH,
+ ENTERS_RX_MODE,
+ GAIN_CHANGE_OCCURS,
+ SPI_WRITE_TO_REGISTER,
+ GAIN_CHANGE_OCCURS_OR_EN_AGC_PIN_PULLED_HIGH,
+};
+
+struct rssi_control {
+ enum rssi_restart_mode restart_mode;
+ bool rssi_unit_is_rx_samples;
+ uint32_t rssi_delay;
+ uint32_t rssi_wait;
+ uint32_t rssi_duration;
+};
+
+struct port_control {
+ uint8_t pp_conf[3];
+ uint8_t rx_clk_data_delay;
+ uint8_t tx_clk_data_delay;
+ uint8_t digital_io_ctrl;
+ uint8_t lvds_bias_ctrl;
+ uint8_t lvds_invert[2];
+ uint8_t clk_out_drive;
+ uint8_t dataclk_drive;
+ uint8_t data_port_drive;
+ uint8_t clk_out_slew;
+ uint8_t dataclk_slew;
+ uint8_t data_port_slew;
+};
+
+struct ctrl_outs_control {
+ uint8_t index;
+ uint8_t en_mask;
+};
+
+struct elna_control {
+ uint16_t gain_mdB;
+ uint16_t bypass_loss_mdB;
+ uint32_t settling_delay_ns;
+ bool elna_1_control_en;
+ bool elna_2_control_en;
+ bool elna_in_gaintable_all_index_en;
+};
+
+struct auxadc_control {
+ int8_t offset;
+ uint32_t temp_time_inteval_ms;
+ uint32_t temp_sensor_decimation;
+ bool periodic_temp_measuremnt;
+ uint32_t auxadc_clock_rate;
+ uint32_t auxadc_decimation;
+};
+
+struct auxdac_control {
+ uint16_t dac1_default_value;
+ uint16_t dac2_default_value;
+ bool auxdac_manual_mode_en;
+ bool dac1_in_rx_en;
+ bool dac1_in_tx_en;
+ bool dac1_in_alert_en;
+ bool dac2_in_rx_en;
+ bool dac2_in_tx_en;
+ bool dac2_in_alert_en;
+ uint8_t dac1_rx_delay_us;
+ uint8_t dac1_tx_delay_us;
+ uint8_t dac2_rx_delay_us;
+ uint8_t dac2_tx_delay_us;
+};
+
+struct gpo_control {
+ bool gpo0_inactive_state_high_en;
+ bool gpo1_inactive_state_high_en;
+ bool gpo2_inactive_state_high_en;
+ bool gpo3_inactive_state_high_en;
+ bool gpo0_slave_rx_en;
+ bool gpo0_slave_tx_en;
+ bool gpo1_slave_rx_en;
+ bool gpo1_slave_tx_en;
+ bool gpo2_slave_rx_en;
+ bool gpo2_slave_tx_en;
+ bool gpo3_slave_rx_en;
+ bool gpo3_slave_tx_en;
+ uint8_t gpo0_rx_delay_us;
+ uint8_t gpo0_tx_delay_us;
+ uint8_t gpo1_rx_delay_us;
+ uint8_t gpo1_tx_delay_us;
+ uint8_t gpo2_rx_delay_us;
+ uint8_t gpo2_tx_delay_us;
+ uint8_t gpo3_rx_delay_us;
+ uint8_t gpo3_tx_delay_us;
+};
+
+struct tx_monitor_control {
+ bool tx_mon_track_en;
+ bool one_shot_mode_en;
+ uint32_t low_high_gain_threshold_mdB;
+ uint8_t low_gain_dB;
+ uint8_t high_gain_dB;
+ uint16_t tx_mon_delay;
+ uint16_t tx_mon_duration;
+ uint8_t tx1_mon_front_end_gain;
+ uint8_t tx2_mon_front_end_gain;
+ uint8_t tx1_mon_lo_cm;
+ uint8_t tx2_mon_lo_cm;
+};
+
+struct gain_control {
+ enum rf_gain_ctrl_mode rx1_mode;
+ enum rf_gain_ctrl_mode rx2_mode;
+ uint8_t adc_ovr_sample_size;
+ uint8_t adc_small_overload_thresh;
+ uint8_t adc_large_overload_thresh;
+ uint16_t lmt_overload_high_thresh;
+ uint16_t lmt_overload_low_thresh;
+ uint16_t dec_pow_measuremnt_duration;
+ uint8_t low_power_thresh;
+ bool dig_gain_en;
+ uint8_t max_dig_gain;
+ bool mgc_rx1_ctrl_inp_en;
+ bool mgc_rx2_ctrl_inp_en;
+ uint8_t mgc_inc_gain_step;
+ uint8_t mgc_dec_gain_step;
+ uint8_t mgc_split_table_ctrl_inp_gain_mode;
+ uint8_t agc_attack_delay_extra_margin_us;
+ uint8_t agc_outer_thresh_high;
+ uint8_t agc_outer_thresh_high_dec_steps;
+ uint8_t agc_inner_thresh_high;
+ uint8_t agc_inner_thresh_high_dec_steps;
+ uint8_t agc_inner_thresh_low;
+ uint8_t agc_inner_thresh_low_inc_steps;
+ uint8_t agc_outer_thresh_low;
+ uint8_t agc_outer_thresh_low_inc_steps;
+ uint8_t adc_small_overload_exceed_counter;
+ uint8_t adc_large_overload_exceed_counter;
+ uint8_t adc_large_overload_inc_steps;
+ bool adc_lmt_small_overload_prevent_gain_inc;
+ uint8_t lmt_overload_large_exceed_counter;
+ uint8_t lmt_overload_small_exceed_counter;
+ uint8_t lmt_overload_large_inc_steps;
+ uint8_t dig_saturation_exceed_counter;
+ uint8_t dig_gain_step_size;
+ bool sync_for_gain_counter_en;
+ uint32_t gain_update_interval_us;
+ bool immed_gain_change_if_large_adc_overload;
+ bool immed_gain_change_if_large_lmt_overload;
+ uint32_t f_agc_dec_pow_measuremnt_duration;
+ uint32_t f_agc_state_wait_time_ns;
+ bool f_agc_allow_agc_gain_increase;
+ uint8_t f_agc_lp_thresh_increment_time;
+ uint8_t f_agc_lp_thresh_increment_steps;
+ uint8_t f_agc_lock_level;
+ bool f_agc_lock_level_lmt_gain_increase_en;
+ uint8_t f_agc_lock_level_gain_increase_upper_limit;
+ uint8_t f_agc_lpf_final_settling_steps;
+ uint8_t f_agc_lmt_final_settling_steps;
+ uint8_t f_agc_final_overrange_count;
+ bool f_agc_gain_increase_after_gain_lock_en;
+ enum f_agc_target_gain_index_type f_agc_gain_index_type_after_exit_rx_mode;
+ bool f_agc_use_last_lock_level_for_set_gain_en;
+ uint8_t f_agc_optimized_gain_offset;
+ bool f_agc_rst_gla_stronger_sig_thresh_exceeded_en;
+ uint8_t f_agc_rst_gla_stronger_sig_thresh_above_ll;
+ bool f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en;
+ bool f_agc_rst_gla_engergy_lost_goto_optim_gain_en;
+ uint8_t f_agc_rst_gla_engergy_lost_sig_thresh_below_ll;
+ uint8_t f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt;
+ bool f_agc_rst_gla_large_adc_overload_en;
+ bool f_agc_rst_gla_large_lmt_overload_en;
+ bool f_agc_rst_gla_en_agc_pulled_high_en;
+ enum f_agc_target_gain_index_type f_agc_rst_gla_if_en_agc_pulled_high_mode;
+ uint8_t f_agc_power_measurement_duration_in_state5;
+};
+
+struct ad9361_phy_platform_data {
+ bool rx2tx2;
+ bool fdd;
+ bool fdd_independent_mode;
+ bool split_gt;
+ bool use_extclk;
+ bool ensm_pin_pulse_mode;
+ bool ensm_pin_ctrl;
+ bool debug_mode;
+ bool tdd_use_dual_synth;
+ bool tdd_skip_vco_cal;
+ bool use_ext_rx_lo;
+ bool use_ext_tx_lo;
+ bool rx1rx2_phase_inversion_en;
+ bool qec_tracking_slow_mode_en;
+ uint8_t dc_offset_update_events;
+ uint8_t dc_offset_attenuation_high;
+ uint8_t dc_offset_attenuation_low;
+ uint8_t rf_dc_offset_count_high;
+ uint8_t rf_dc_offset_count_low;
+ uint8_t dig_interface_tune_skipmode;
+ uint8_t dig_interface_tune_fir_disable;
+ uint32_t dcxo_coarse;
+ uint32_t dcxo_fine;
+ uint32_t rf_rx_input_sel;
+ uint32_t rf_tx_output_sel;
+ uint32_t rx1tx1_mode_use_rx_num;
+ uint32_t rx1tx1_mode_use_tx_num;
+ uint32_t rx_path_clks[NUM_RX_CLOCKS];
+ uint32_t tx_path_clks[NUM_TX_CLOCKS];
+ uint32_t trx_synth_max_fref;
+ uint64_t rx_synth_freq;
+ uint64_t tx_synth_freq;
+ uint32_t rf_rx_bandwidth_Hz;
+ uint32_t rf_tx_bandwidth_Hz;
+ int32_t tx_atten;
+ bool update_tx_gain_via_alert;
+ uint32_t rx_fastlock_delay_ns;
+ uint32_t tx_fastlock_delay_ns;
+ bool trx_fastlock_pinctrl_en[2];
+ enum ad9361_clkout ad9361_clkout_mode;
+ struct gain_control gain_ctrl;
+ struct rssi_control rssi_ctrl;
+ struct port_control port_ctrl;
+ struct ctrl_outs_control ctrl_outs_ctrl;
+ struct elna_control elna_ctrl;
+ struct auxadc_control auxadc_ctrl;
+ struct auxdac_control auxdac_ctrl;
+ struct gpo_control gpo_ctrl;
+ struct tx_monitor_control txmon_ctrl;
+ int32_t gpio_resetb;
+ int32_t gpio_sync;
+ int32_t gpio_cal_sw1;
+ int32_t gpio_cal_sw2;
+};
+
+struct ad9361_rf_phy {
+ enum dev_id dev_sel;
+ uint8_t id_no;
+ struct spi_device *spi;
+ struct gpio_device *gpio;
+ struct clk *clk_refin;
+ struct clk *clks[NUM_AD9361_CLKS];
+ struct refclk_scale *ref_clk_scale[NUM_AD9361_CLKS];
+ struct clk_onecell_data clk_data;
+ uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv);
+ int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv,
+ uint32_t rate);
+ int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv,
+ uint32_t rate);
+ struct ad9361_phy_platform_data *pdata;
+ uint8_t prev_ensm_state;
+ uint8_t curr_ensm_state;
+ uint8_t cached_rx_rfpll_div;
+ uint8_t cached_tx_rfpll_div;
+ struct rx_gain_info rx_gain[RXGAIN_TBLS_END];
+ enum rx_gain_table_name current_table;
+ bool ensm_pin_ctl_en;
+ bool auto_cal_en;
+ uint64_t last_tx_quad_cal_freq;
+ uint32_t last_tx_quad_cal_phase;
+ uint64_t current_tx_lo_freq;
+ uint64_t current_rx_lo_freq;
+ bool current_tx_use_tdd_table;
+ bool current_rx_use_tdd_table;
+ uint32_t flags;
+ uint32_t cal_threshold_freq;
+ uint32_t current_rx_bw_Hz;
+ uint32_t current_tx_bw_Hz;
+ uint32_t rxbbf_div;
+ uint32_t rate_governor;
+ bool bypass_rx_fir;
+ bool bypass_tx_fir;
+ bool rx_eq_2tx;
+ bool filt_valid;
+ uint32_t filt_rx_path_clks[NUM_RX_CLOCKS];
+ uint32_t filt_tx_path_clks[NUM_TX_CLOCKS];
+ uint32_t filt_rx_bw_Hz;
+ uint32_t filt_tx_bw_Hz;
+ uint8_t tx_fir_int;
+ uint8_t tx_fir_ntaps;
+ uint8_t rx_fir_dec;
+ uint8_t rx_fir_ntaps;
+ uint8_t agc_mode[2];
+ bool rfdc_track_en;
+ bool bbdc_track_en;
+ bool quad_track_en;
+ bool txmon_tdd_en;
+ uint16_t auxdac1_value;
+ uint16_t auxdac2_value;
+ uint32_t tx1_atten_cached;
+ uint32_t tx2_atten_cached;
+ struct ad9361_fastlock fastlock;
+ struct axiadc_converter *adc_conv;
+ struct axiadc_state *adc_state;
+ int32_t bist_loopback_mode;
+ enum ad9361_bist_mode bist_prbs_mode;
+ enum ad9361_bist_mode bist_tone_mode;
+ uint32_t bist_tone_freq_Hz;
+ uint32_t bist_tone_level_dB;
+ uint32_t bist_tone_mask;
+ bool bbpll_initialized;
+};
+
+struct rf_rx_gain {
+ uint32_t ant;
+ int32_t gain_db;
+ uint32_t fgt_lmt_index;
+ uint32_t lmt_gain;
+ uint32_t lpf_gain;
+ uint32_t digital_gain;
+ uint32_t lna_index;
+ uint32_t tia_index;
+ uint32_t mixer_index;
+};
+
+struct rf_rssi {
+ uint32_t ant;
+ uint32_t symbol;
+ uint32_t preamble;
+ int32_t multiplier;
+ uint8_t duration;
+};
+
+int32_t ad9361_get_rx_gain(struct ad9361_rf_phy *phy,
+ uint32_t rx_id,
+ struct rf_rx_gain *rx_gain);
+int32_t ad9361_spi_read(struct spi_device *spi, uint32_t reg);
+int32_t ad9361_spi_write(struct spi_device *spi, uint32_t reg, uint32_t val);
+void ad9361_get_bist_loopback(struct ad9361_rf_phy *phy, int32_t *mode);
+int32_t ad9361_bist_loopback(struct ad9361_rf_phy *phy, int32_t mode);
+
+/******************************************************************************
+ * From ad9361_api.h
+ ******************************************************************************/
+
+typedef struct {
+ enum dev_id dev_sel;
+ uint8_t id_no;
+ uint32_t reference_clk_rate;
+ uint8_t two_rx_two_tx_mode_enable;
+ uint8_t one_rx_one_tx_mode_use_rx_num;
+ uint8_t one_rx_one_tx_mode_use_tx_num;
+ uint8_t frequency_division_duplex_mode_enable;
+ uint8_t frequency_division_duplex_independent_mode_enable;
+ uint8_t tdd_use_dual_synth_mode_enable;
+ uint8_t tdd_skip_vco_cal_enable;
+ uint32_t tx_fastlock_delay_ns;
+ uint32_t rx_fastlock_delay_ns;
+ uint8_t rx_fastlock_pincontrol_enable;
+ uint8_t tx_fastlock_pincontrol_enable;
+ uint8_t external_rx_lo_enable;
+ uint8_t external_tx_lo_enable;
+ uint8_t dc_offset_tracking_update_event_mask;
+ uint8_t dc_offset_attenuation_high_range;
+ uint8_t dc_offset_attenuation_low_range;
+ uint8_t dc_offset_count_high_range;
+ uint8_t dc_offset_count_low_range;
+ uint8_t split_gain_table_mode_enable;
+ uint32_t trx_synthesizer_target_fref_overwrite_hz;
+ uint8_t qec_tracking_slow_mode_enable;
+ uint8_t ensm_enable_pin_pulse_mode_enable;
+ uint8_t ensm_enable_txnrx_control_enable;
+ uint64_t rx_synthesizer_frequency_hz;
+ uint64_t tx_synthesizer_frequency_hz;
+ uint32_t rx_path_clock_frequencies[6];
+ uint32_t tx_path_clock_frequencies[6];
+ uint32_t rf_rx_bandwidth_hz;
+ uint32_t rf_tx_bandwidth_hz;
+ uint32_t rx_rf_port_input_select;
+ uint32_t tx_rf_port_input_select;
+ int32_t tx_attenuation_mdB;
+ uint8_t update_tx_gain_in_alert_enable;
+ uint8_t xo_disable_use_ext_refclk_enable;
+ uint32_t dcxo_coarse_and_fine_tune[2];
+ uint32_t clk_output_mode_select;
+ uint8_t gc_rx1_mode;
+ uint8_t gc_rx2_mode;
+ uint8_t gc_adc_large_overload_thresh;
+ uint8_t gc_adc_ovr_sample_size;
+ uint8_t gc_adc_small_overload_thresh;
+ uint16_t gc_dec_pow_measurement_duration;
+ uint8_t gc_dig_gain_enable;
+ uint16_t gc_lmt_overload_high_thresh;
+ uint16_t gc_lmt_overload_low_thresh;
+ uint8_t gc_low_power_thresh;
+ uint8_t gc_max_dig_gain;
+ uint8_t mgc_dec_gain_step;
+ uint8_t mgc_inc_gain_step;
+ uint8_t mgc_rx1_ctrl_inp_enable;
+ uint8_t mgc_rx2_ctrl_inp_enable;
+ uint8_t mgc_split_table_ctrl_inp_gain_mode;
+ uint8_t agc_adc_large_overload_exceed_counter;
+ uint8_t agc_adc_large_overload_inc_steps;
+ uint8_t agc_adc_lmt_small_overload_prevent_gain_inc_enable;
+ uint8_t agc_adc_small_overload_exceed_counter;
+ uint8_t agc_dig_gain_step_size;
+ uint8_t agc_dig_saturation_exceed_counter;
+ uint32_t agc_gain_update_interval_us;
+ uint8_t agc_immed_gain_change_if_large_adc_overload_enable;
+ uint8_t agc_immed_gain_change_if_large_lmt_overload_enable;
+ uint8_t agc_inner_thresh_high;
+ uint8_t agc_inner_thresh_high_dec_steps;
+ uint8_t agc_inner_thresh_low;
+ uint8_t agc_inner_thresh_low_inc_steps;
+ uint8_t agc_lmt_overload_large_exceed_counter;
+ uint8_t agc_lmt_overload_large_inc_steps;
+ uint8_t agc_lmt_overload_small_exceed_counter;
+ uint8_t agc_outer_thresh_high;
+ uint8_t agc_outer_thresh_high_dec_steps;
+ uint8_t agc_outer_thresh_low;
+ uint8_t agc_outer_thresh_low_inc_steps;
+ uint32_t agc_attack_delay_extra_margin_us;
+ uint8_t agc_sync_for_gain_counter_enable;
+ uint32_t fagc_dec_pow_measuremnt_duration;
+ uint32_t fagc_state_wait_time_ns;
+ uint8_t fagc_allow_agc_gain_increase;
+ uint32_t fagc_lp_thresh_increment_time;
+ uint32_t fagc_lp_thresh_increment_steps;
+ uint8_t fagc_lock_level_lmt_gain_increase_en;
+ uint32_t fagc_lock_level_gain_increase_upper_limit;
+ uint32_t fagc_lpf_final_settling_steps;
+ uint32_t fagc_lmt_final_settling_steps;
+ uint32_t fagc_final_overrange_count;
+ uint8_t fagc_gain_increase_after_gain_lock_en;
+ uint32_t fagc_gain_index_type_after_exit_rx_mode;
+ uint8_t fagc_use_last_lock_level_for_set_gain_en;
+ uint8_t fagc_rst_gla_stronger_sig_thresh_exceeded_en;
+ uint32_t fagc_optimized_gain_offset;
+ uint32_t fagc_rst_gla_stronger_sig_thresh_above_ll;
+ uint8_t fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en;
+ uint8_t fagc_rst_gla_engergy_lost_goto_optim_gain_en;
+ uint32_t fagc_rst_gla_engergy_lost_sig_thresh_below_ll;
+ uint32_t fagc_energy_lost_stronger_sig_gain_lock_exit_cnt;
+ uint8_t fagc_rst_gla_large_adc_overload_en;
+ uint8_t fagc_rst_gla_large_lmt_overload_en;
+ uint8_t fagc_rst_gla_en_agc_pulled_high_en;
+ uint32_t fagc_rst_gla_if_en_agc_pulled_high_mode;
+ uint32_t fagc_power_measurement_duration_in_state5;
+ uint32_t rssi_delay;
+ uint32_t rssi_duration;
+ uint8_t rssi_restart_mode;
+ uint8_t rssi_unit_is_rx_samples_enable;
+ uint32_t rssi_wait;
+ uint32_t aux_adc_decimation;
+ uint32_t aux_adc_rate;
+ uint8_t aux_dac_manual_mode_enable;
+ uint32_t aux_dac1_default_value_mV;
+ uint8_t aux_dac1_active_in_rx_enable;
+ uint8_t aux_dac1_active_in_tx_enable;
+ uint8_t aux_dac1_active_in_alert_enable;
+ uint32_t aux_dac1_rx_delay_us;
+ uint32_t aux_dac1_tx_delay_us;
+ uint32_t aux_dac2_default_value_mV;
+ uint8_t aux_dac2_active_in_rx_enable;
+ uint8_t aux_dac2_active_in_tx_enable;
+ uint8_t aux_dac2_active_in_alert_enable;
+ uint32_t aux_dac2_rx_delay_us;
+ uint32_t aux_dac2_tx_delay_us;
+ uint32_t temp_sense_decimation;
+ uint16_t temp_sense_measurement_interval_ms;
+ int8_t temp_sense_offset_signed;
+ uint8_t temp_sense_periodic_measurement_enable;
+ uint8_t ctrl_outs_enable_mask;
+ uint8_t ctrl_outs_index;
+ uint32_t elna_settling_delay_ns;
+ uint32_t elna_gain_mdB;
+ uint32_t elna_bypass_loss_mdB;
+ uint8_t elna_rx1_gpo0_control_enable;
+ uint8_t elna_rx2_gpo1_control_enable;
+ uint8_t elna_gaintable_all_index_enable;
+ uint8_t digital_interface_tune_skip_mode;
+ uint8_t digital_interface_tune_fir_disable;
+ uint8_t pp_tx_swap_enable;
+ uint8_t pp_rx_swap_enable;
+ uint8_t tx_channel_swap_enable;
+ uint8_t rx_channel_swap_enable;
+ uint8_t rx_frame_pulse_mode_enable;
+ uint8_t two_t_two_r_timing_enable;
+ uint8_t invert_data_bus_enable;
+ uint8_t invert_data_clk_enable;
+ uint8_t fdd_alt_word_order_enable;
+ uint8_t invert_rx_frame_enable;
+ uint8_t fdd_rx_rate_2tx_enable;
+ uint8_t swap_ports_enable;
+ uint8_t single_data_rate_enable;
+ uint8_t lvds_mode_enable;
+ uint8_t half_duplex_mode_enable;
+ uint8_t single_port_mode_enable;
+ uint8_t full_port_enable;
+ uint8_t full_duplex_swap_bits_enable;
+ uint32_t delay_rx_data;
+ uint32_t rx_data_clock_delay;
+ uint32_t rx_data_delay;
+ uint32_t tx_fb_clock_delay;
+ uint32_t tx_data_delay;
+ uint32_t lvds_bias_mV;
+ uint8_t lvds_rx_onchip_termination_enable;
+ uint8_t rx1rx2_phase_inversion_en;
+ uint8_t lvds_invert1_control;
+ uint8_t lvds_invert2_control;
+ uint8_t clk_out_drive;
+ uint8_t dataclk_drive;
+ uint8_t data_port_drive;
+ uint8_t clk_out_slew;
+ uint8_t dataclk_slew;
+ uint8_t data_port_slew;
+ uint8_t gpo0_inactive_state_high_enable;
+ uint8_t gpo1_inactive_state_high_enable;
+ uint8_t gpo2_inactive_state_high_enable;
+ uint8_t gpo3_inactive_state_high_enable;
+ uint8_t gpo0_slave_rx_enable;
+ uint8_t gpo0_slave_tx_enable;
+ uint8_t gpo1_slave_rx_enable;
+ uint8_t gpo1_slave_tx_enable;
+ uint8_t gpo2_slave_rx_enable;
+ uint8_t gpo2_slave_tx_enable;
+ uint8_t gpo3_slave_rx_enable;
+ uint8_t gpo3_slave_tx_enable;
+ uint8_t gpo0_rx_delay_us;
+ uint8_t gpo0_tx_delay_us;
+ uint8_t gpo1_rx_delay_us;
+ uint8_t gpo1_tx_delay_us;
+ uint8_t gpo2_rx_delay_us;
+ uint8_t gpo2_tx_delay_us;
+ uint8_t gpo3_rx_delay_us;
+ uint8_t gpo3_tx_delay_us;
+ uint32_t low_high_gain_threshold_mdB;
+ uint32_t low_gain_dB;
+ uint32_t high_gain_dB;
+ uint8_t tx_mon_track_en;
+ uint8_t one_shot_mode_en;
+ uint32_t tx_mon_delay;
+ uint32_t tx_mon_duration;
+ uint32_t tx1_mon_front_end_gain;
+ uint32_t tx2_mon_front_end_gain;
+ uint32_t tx1_mon_lo_cm;
+ uint32_t tx2_mon_lo_cm;
+ int32_t gpio_resetb;
+ int32_t gpio_sync;
+ int32_t gpio_cal_sw1;
+ int32_t gpio_cal_sw2;
+ uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv);
+ int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv,
+ uint32_t rate);
+ int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv,
+ uint32_t rate);
+} AD9361_InitParam;
+
+typedef struct {
+ uint32_t rx; /* 1, 2, 3(both) */
+ int32_t rx_gain; /* -12, -6, 0, 6 */
+ uint32_t rx_dec; /* 1, 2, 4 */
+ int16_t rx_coef[128];
+ uint8_t rx_coef_size;
+ uint32_t rx_path_clks[6];
+ uint32_t rx_bandwidth;
+} AD9361_RXFIRConfig;
+
+typedef struct {
+ uint32_t tx; /* 1, 2, 3(both) */
+ int32_t tx_gain; /* -6, 0 */
+ uint32_t tx_int; /* 1, 2, 4 */
+ int16_t tx_coef[128];
+ uint8_t tx_coef_size;
+ uint32_t tx_path_clks[6];
+ uint32_t tx_bandwidth;
+} AD9361_TXFIRConfig;
+
+#define AD936X_A_BALANCED 0
+#define AD936X_B_BALANCED 1
+#define AD936X_C_BALANCED 2
+#define AD936X_A_N 3
+#define AD936X_A_P 4
+#define AD936X_B_N 5
+#define AD936X_B_P 6
+#define AD936X_C_N 7
+#define AD936X_C_P 8
+#define AD936X_TX_MON1 9
+#define AD936X_TX_MON2 10
+#define AD936X_TX_MON1_2 11
+
+#define AD936X_TXA 0
+#define AD936X_TXB 1
+
+int32_t ad9361_init(struct ad9361_rf_phy **ad9361_phy,
+ AD9361_InitParam *init_param,
+ void *userdata);
+int32_t ad9361_deinit(struct ad9361_rf_phy *phy);
+int32_t ad9361_set_rx_rf_gain(struct ad9361_rf_phy *phy,
+ uint8_t ch,
+ int32_t gain_db);
+int32_t ad9361_set_rx_rf_bandwidth(struct ad9361_rf_phy *phy,
+ uint32_t bandwidth_hz);
+int32_t ad9361_get_rx_rf_bandwidth(struct ad9361_rf_phy *phy,
+ uint32_t *bandwidth_hz);
+int32_t ad9361_set_rx_sampling_freq(struct ad9361_rf_phy *phy,
+ uint32_t sampling_freq_hz);
+int32_t ad9361_get_rx_sampling_freq(struct ad9361_rf_phy *phy,
+ uint32_t *sampling_freq_hz);
+int32_t ad9361_set_rx_lo_freq(struct ad9361_rf_phy *phy, uint64_t lo_freq_hz);
+int32_t ad9361_get_rx_lo_freq(struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz);
+int32_t ad9361_get_rx_rssi(struct ad9361_rf_phy *phy,
+ uint8_t ch,
+ struct rf_rssi *rssi);
+int32_t ad9361_set_rx_gain_control_mode(struct ad9361_rf_phy *phy,
+ uint8_t ch,
+ uint8_t gc_mode);
+int32_t ad9361_get_rx_gain_control_mode(struct ad9361_rf_phy *phy,
+ uint8_t ch,
+ uint8_t *gc_mode);
+int32_t ad9361_set_rx_fir_config(struct ad9361_rf_phy *phy,
+ AD9361_RXFIRConfig fir_cfg);
+int32_t ad9361_set_rx_fir_en_dis(struct ad9361_rf_phy *phy, uint8_t en_dis);
+int32_t ad9361_set_rx_rf_port_input(struct ad9361_rf_phy *phy, uint32_t mode);
+int32_t ad9361_get_rx_rf_port_input(struct ad9361_rf_phy *phy, uint32_t *mode);
+int32_t ad9361_set_tx_attenuation(struct ad9361_rf_phy *phy,
+ uint8_t ch,
+ uint32_t attenuation_mdb);
+int32_t ad9361_get_tx_attenuation(struct ad9361_rf_phy *phy,
+ uint8_t ch,
+ uint32_t *attenuation_mdb);
+int32_t ad9361_set_tx_rf_bandwidth(struct ad9361_rf_phy *phy,
+ uint32_t bandwidth_hz);
+int32_t ad9361_get_tx_rf_bandwidth(struct ad9361_rf_phy *phy,
+ uint32_t *bandwidth_hz);
+int32_t ad9361_set_tx_sampling_freq(struct ad9361_rf_phy *phy,
+ uint32_t sampling_freq_hz);
+int32_t ad9361_get_tx_sampling_freq(struct ad9361_rf_phy *phy,
+ uint32_t *sampling_freq_hz);
+int32_t ad9361_set_tx_lo_freq(struct ad9361_rf_phy *phy, uint64_t lo_freq_hz);
+int32_t ad9361_get_tx_lo_freq(struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz);
+int32_t ad9361_set_tx_fir_config(struct ad9361_rf_phy *phy,
+ AD9361_TXFIRConfig fir_cfg);
+int32_t ad9361_set_tx_fir_en_dis(struct ad9361_rf_phy *phy, uint8_t en_dis);
+int32_t ad9361_get_tx_rssi(struct ad9361_rf_phy *phy,
+ uint8_t ch,
+ uint32_t *rssi_db_x_1000);
+int32_t ad9361_set_tx_rf_port_output(struct ad9361_rf_phy *phy, uint32_t mode);
+int32_t ad9361_get_tx_rf_port_output(struct ad9361_rf_phy *phy, uint32_t *mode);
+int32_t ad9361_get_temp(struct ad9361_rf_phy *phy);
+int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile);
+int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy,
+ uint32_t profile,
+ uint8_t *values);
+int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile);
+int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy,
+ uint32_t profile,
+ uint8_t *values);
+int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode);
+
+#endif // AD936X_H_
diff --git a/Radio/HW/BladeRF/fpga_common/include/ad936x_helpers.h b/Radio/HW/BladeRF/fpga_common/include/ad936x_helpers.h
new file mode 100644
index 0000000..bd0037a
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/ad936x_helpers.h
@@ -0,0 +1,127 @@
+/*
+ * This file is part of the bladeRF project:
+ * http://www.github.com/nuand/bladeRF
+ *
+ * Copyright (C) 2018 Nuand LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FPGA_COMMON_AD936X_HELPERS_H_
+#define FPGA_COMMON_AD936X_HELPERS_H_
+
+#ifdef BLADERF_NIOS_BUILD
+#include "devices.h"
+#endif // BLADERF_NIOS_BUILD
+
+#if !defined(BLADERF_NIOS_BUILD) || defined(BLADERF_NIOS_LIBAD936X)
+
+#if !defined(BLADERF_NIOS_BUILD) && !defined(BLADERF_NIOS_PC_SIMULATION)
+#include <libbladeRF.h>
+#else
+#include "libbladeRF_nios_compat.h"
+#endif
+
+#include "ad936x.h"
+
+/**
+ * @brief Retrieve current value in TX attenuation cache.
+ *
+ * @param phy RFIC handle
+ * @param[in] ch Channel
+ *
+ * @return Cached attenuation value
+ */
+uint32_t txmute_get_cached(struct ad9361_rf_phy *phy, bladerf_channel ch);
+
+/**
+ * @brief Save a new value to the TX attenuation cache.
+ *
+ * @param phy RFIC handle
+ * @param[in] ch Channel
+ * @param[in] atten Attenuation
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+int txmute_set_cached(struct ad9361_rf_phy *phy,
+ bladerf_channel ch,
+ uint32_t atten);
+
+/**
+ * @brief Get the transmit mute state
+ *
+ * @param phy RFIC handle
+ * @param[in] ch Channel
+ * @param[out] state Mute state: true for muted, false for unmuted
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+int txmute_get(struct ad9361_rf_phy *phy, bladerf_channel ch, bool *state);
+
+/**
+ * @brief Sets the transmit mute.
+ *
+ * If muted, the TX attenuation will be set to maximum to reduce leakage
+ * as much as possible.
+ *
+ * When unmuted, TX attenuation will be restored to its previous value.
+ *
+ * @param phy RFIC handle
+ * @param[in] ch Channel
+ * @param[in] state Mute state: true for muted, false for unmuted
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+int txmute_set(struct ad9361_rf_phy *phy, bladerf_channel ch, bool state);
+
+/**
+ * @brief Set AD9361 RFIC RF port
+ *
+ * @param phy RFIC handle
+ * @param[in] ch Channel
+ * @param[in] enabled True if the channel is enabled, false otherwise
+ * @param[in] freq Frequency
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+int set_ad9361_port_by_freq(struct ad9361_rf_phy *phy,
+ bladerf_channel ch,
+ bool enabled,
+ bladerf_frequency freq);
+
+/**
+ * @brief Translate bladerf_gain_mode to rf_gain_ctrl_mode
+ *
+ * @param[in] gainmode The libbladeRF gainmode
+ * @param[out] ok True if return value is valid, false otherwise
+ *
+ * @return rf_gain_ctrl_mode
+ */
+enum rf_gain_ctrl_mode gainmode_bladerf_to_ad9361(bladerf_gain_mode gainmode,
+ bool *ok);
+
+/**
+ * @brief Translate rf_gain_ctrl_mode to bladerf_gain_mode
+ *
+ * @param[in] gainmode The RFIC gainmode
+ * @param[out] ok True if return value is valid, false otherwise
+ *
+ * @return bladerf_gain_mode
+ */
+bladerf_gain_mode gainmode_ad9361_to_bladerf(enum rf_gain_ctrl_mode gainmode,
+ bool *ok);
+
+#endif // !defined(BLADERF_NIOS_BUILD) || defined(BLADERF_NIOS_LIBAD936X)
+#endif // FPGA_COMMON_AD936X_HELPERS_H_
diff --git a/Radio/HW/BladeRF/fpga_common/include/band_select.h b/Radio/HW/BladeRF/fpga_common/include/band_select.h
new file mode 100644
index 0000000..bae469d
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/band_select.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the bladeRF project:
+ * http://www.github.com/nuand/bladeRF
+ *
+ * Copyright (C) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef BAND_SELECT_H_
+#define BAND_SELECT_H_
+
+#include <stdbool.h>
+
+#if !defined(BLADERF_NIOS_BUILD) && !defined(BLADERF_NIOS_PC_SIMULATION)
+# include <libbladeRF.h>
+# include "board/board.h"
+# include "log.h"
+#else
+# include "libbladeRF_nios_compat.h"
+# include "devices.h"
+#endif
+
+/**
+ * Select the bladeRF's low or high band
+ *
+ * @param dev Device handle
+ * @param module Module to configure
+ * @param low_band Configure for low band (true) or high band (false)
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int band_select(struct bladerf *dev, bladerf_module module, bool low_band);
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/bladerf2_common.h b/Radio/HW/BladeRF/fpga_common/include/bladerf2_common.h
new file mode 100644
index 0000000..f58e044
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/bladerf2_common.h
@@ -0,0 +1,749 @@
+/* This file is part of the bladeRF project:
+ * http://www.github.com/nuand/bladeRF
+ *
+ * Copyright (c) 2018 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef FPGA_COMMON_BLADERF2_COMMON_H_
+#define FPGA_COMMON_BLADERF2_COMMON_H_
+
+#include <errno.h>
+
+#if !defined(BLADERF_NIOS_BUILD) && !defined(BLADERF_NIOS_PC_SIMULATION)
+#include <libbladeRF.h>
+#else
+#include "libbladeRF_nios_compat.h"
+#endif // !defined(BLADERF_NIOS_BUILD) && !defined(BLADERF_NIOS_PC_SIMULATION)
+
+#include "ad936x.h"
+#include "host_config.h"
+#include "nios_pkt_retune2.h"
+#include "range.h"
+
+/**
+ * Number of modules (directions) present. 1 RX, 1 TX = 2.
+ */
+#define NUM_MODULES 2
+
+/**
+ * Frequency of the system VCTCXO, in Hz.
+ */
+static bladerf_frequency const BLADERF_VCTCXO_FREQUENCY = 38400000;
+
+/**
+ * Default reference input frequency, in Hz.
+ */
+static bladerf_frequency const BLADERF_REFIN_DEFAULT = 10000000;
+
+/**
+ * RFIC reset frequency (arbitrary)
+ */
+static bladerf_frequency const RESET_FREQUENCY = 70000000;
+
+// clang-format off
+// Config GPIO
+#define CFG_GPIO_POWERSOURCE 0
+#define CFG_GPIO_PLL_EN 11
+#define CFG_GPIO_CLOCK_OUTPUT 17
+#define CFG_GPIO_CLOCK_SELECT 18
+
+// RFFE control
+#define RFFE_CONTROL_RESET_N 0
+#define RFFE_CONTROL_ENABLE 1
+#define RFFE_CONTROL_TXNRX 2
+#define RFFE_CONTROL_EN_AGC 3
+#define RFFE_CONTROL_SYNC_IN 4
+#define RFFE_CONTROL_RX_BIAS_EN 5
+#define RFFE_CONTROL_RX_SPDT_1 6 // 6 and 7
+#define RFFE_CONTROL_RX_SPDT_2 8 // 8 and 9
+#define RFFE_CONTROL_TX_BIAS_EN 10
+#define RFFE_CONTROL_TX_SPDT_1 11 // 11 and 12
+#define RFFE_CONTROL_TX_SPDT_2 13 // 13 and 14
+#define RFFE_CONTROL_MIMO_RX_EN_0 15
+#define RFFE_CONTROL_MIMO_TX_EN_0 16
+#define RFFE_CONTROL_MIMO_RX_EN_1 17
+#define RFFE_CONTROL_MIMO_TX_EN_1 18
+#define RFFE_CONTROL_ADF_MUXOUT 19 // input only
+#define RFFE_CONTROL_CTRL_OUT 24 // input only, 24 through 31
+#define RFFE_CONTROL_SPDT_MASK 0x3
+#define RFFE_CONTROL_SPDT_SHUTDOWN 0x0 // no connection
+#define RFFE_CONTROL_SPDT_LOWBAND 0x2 // RF1 <-> RF3
+#define RFFE_CONTROL_SPDT_HIGHBAND 0x1 // RF1 <-> RF2
+
+// Trim DAC control
+#define TRIMDAC_MASK 0x3FFC // 2 through 13
+#define TRIMDAC_EN 14 // 14 and 15
+#define TRIMDAC_EN_MASK 0x3
+#define TRIMDAC_EN_ACTIVE 0x0
+#define TRIMDAC_EN_HIGHZ 0x3
+
+/* Number of fast lock profiles that can be stored in the Nios
+ * Make sure this number matches that of the Nios' devices.h */
+#define NUM_BBP_FASTLOCK_PROFILES 256
+
+/* Number of fast lock profiles that can be stored in the RFFE
+ * Make sure this number matches that of the Nios' devices.h */
+#define NUM_RFFE_FASTLOCK_PROFILES 8
+// clang-format on
+
+/**
+ * RF front end bands
+ */
+enum bladerf2_band {
+ BAND_SHUTDOWN, /**< Inactive */
+ BAND_LOW, /**< Low-band */
+ BAND_HIGH, /**< High-band */
+};
+
+/**
+ * Mapping between libbladeRF gain modes and RFIC gain modes.
+ */
+struct bladerf_rfic_gain_mode_map {
+ bladerf_gain_mode brf_mode; /**< libbladeRF gain mode */
+ enum rf_gain_ctrl_mode rfic_mode; /**< RFIC gain mode */
+};
+
+/**
+ * Mapping between frequency ranges and gain ranges.
+ */
+struct bladerf_gain_range {
+ char const *name; /**< Gain stage name */
+ struct bladerf_range frequency; /**< Frequency range */
+ struct bladerf_range gain; /**< Applicable stage gain range */
+ float offset; /**< Offset in dB, for mapping dB gain to absolute dBm. */
+};
+
+/**
+ * Mapping between string names and RFIC port identifiers.
+ */
+struct bladerf_rfic_port_name_map {
+ char const *name; /**< Port name */
+ uint32_t id; /**< Port ID */
+};
+
+/**
+ * Mapping between RF front end bands, freqencies, and physical hardware
+ * configurations
+ */
+struct band_port_map {
+ struct bladerf_range const frequency; /**< Frequency range */
+ enum bladerf2_band band; /**< RF front end band */
+ uint32_t spdt; /**< RF switch configuration */
+ uint32_t rfic_port; /**< RFIC port configuration */
+};
+
+/**
+ * @brief Round a value into an int
+ *
+ * @param x Value to round
+ *
+ * @return int
+ */
+#define __round_int(x) (x >= 0 ? (int)(x + 0.5) : (int)(x - 0.5))
+
+/**
+ * @brief Round a value into an int64
+ *
+ * @param x Value to round
+ *
+ * @return int64
+ */
+#define __round_int64(x) (x >= 0 ? (int64_t)(x + 0.5) : (int64_t)(x - 0.5))
+
+/**
+ * Subcommands for the BLADERF_RFIC_COMMAND_INIT RFIC command.
+ */
+typedef enum {
+ BLADERF_RFIC_INIT_STATE_OFF = 0, /** Non-initialized state */
+ BLADERF_RFIC_INIT_STATE_ON, /** Initialized ("open") */
+ BLADERF_RFIC_INIT_STATE_STANDBY, /** Standby ("closed") */
+} bladerf_rfic_init_state;
+
+/**
+ * Commands available with the FPGA-based RFIC interface.
+ *
+ * There is an 8-bit address space (0x00 to 0xFF) available. Nuand will not
+ * assign values between 0x80 and 0xFF, so they may be used for custom
+ * applications.
+ */
+typedef enum {
+ /** Query the status register. (Read)
+ *
+ * Pass ::BLADERF_CHANNEL_INVALID as the `ch` parameter.
+ *
+ * Return structure:
+ * +================+========================+
+ * | Bit(s) | Value |
+ * +================+========================+
+ * | 63:16 | Reserved. Set to 0. |
+ * +----------------+------------------------+
+ * | 15:8 | count of items in |
+ * | | write queue |
+ * +----------------+------------------------+
+ * | 0 | 1 if initialized, 0 |
+ * | | otherwise |
+ * +----------------+------------------------+
+ */
+ BLADERF_RFIC_COMMAND_STATUS = 0x00,
+
+ /** Initialize the RFIC. (Read/Write)
+ *
+ * Pass ::BLADERF_CHANNEL_INVALID as the `ch` parameter.
+ *
+ * Pass/expect a ::bladerf_rfic_init_state value as the `data` parameter.
+ */
+ BLADERF_RFIC_COMMAND_INIT = 0x01,
+
+ /** Enable/disable a channel. (Read/Write)
+ *
+ * Set `data` to `true` to enable the channel, or `false` to disable it.
+ */
+ BLADERF_RFIC_COMMAND_ENABLE = 0x02,
+
+ /** Sample rate for a channel. (Read/Write)
+ *
+ * Value in samples per second.
+ */
+ BLADERF_RFIC_COMMAND_SAMPLERATE = 0x03,
+
+ /** Center frequency for a channel. (Read/Write)
+ *
+ * Value in Hz. Read or write.
+ */
+ BLADERF_RFIC_COMMAND_FREQUENCY = 0x04,
+
+ /** Bandwidth for a channel. (Read/Write)
+ *
+ * Value in Hz.
+ */
+ BLADERF_RFIC_COMMAND_BANDWIDTH = 0x05,
+
+ /** Gain mode for a channel. (Read/Write)
+ *
+ * Pass a ::bladerf_gain_mode value as the `data` parameter.
+ */
+ BLADERF_RFIC_COMMAND_GAINMODE = 0x06,
+
+ /** Overall gain for a channel. (Read/Write)
+ *
+ * Value in dB.
+ */
+ BLADERF_RFIC_COMMAND_GAIN = 0x07,
+
+ /** RSSI (received signal strength indication) for a channel. (Read)
+ *
+ * Value in dB.
+ */
+ BLADERF_RFIC_COMMAND_RSSI = 0x08,
+
+ /** FIR filter setting for a channel. (Read/Write)
+ *
+ * RX channels should pass a ::bladerf_rfic_rxfir value, TX channels should
+ * pass a ::bladerf_rfic_txfir value.
+ */
+ BLADERF_RFIC_COMMAND_FILTER = 0x09,
+
+ /** TX Mute setting for a channel. (Read/Write)
+ *
+ * 1 indicates TX mute is enabled, 0 indicates it is not.
+ */
+ BLADERF_RFIC_COMMAND_TXMUTE = 0x0A,
+
+ /** Store Fastlock profile. (Write)
+ *
+ * Stores the current tuning into a fastlock profile, for later recall
+ */
+ BLADERF_RFIC_COMMAND_FASTLOCK = 0x0B,
+
+ /** User-defined functionality (placeholder 1) */
+ BLADERF_RFIC_COMMAND_USER_001 = 0x80,
+
+ /** User-defined functionality (placeholder 128) */
+ BLADERF_RFIC_COMMAND_USER_128 = 0xFF,
+
+ /* Do not add additional commands beyond 0xFF */
+} bladerf_rfic_command;
+
+/** NIOS_PKT_16x64_RFIC_STATUS return structure
+ *
+ * +===============+===================================================+
+ * | Bit(s) | Value |
+ * +===============+===================================================+
+ * | 63:16 | Reserved. Set to 0. |
+ * +---------------+---------------------------------------------------+
+ * | 15:8 | count of items in write queue |
+ * +---------------+---------------------------------------------------+
+ * | 1 | 1 if the last job executed in the write queue was |
+ * | | successful, 0 otherwise |
+ * +---------------+---------------------------------------------------+
+ * | 0 | 1 if initialized, 0 otherwise |
+ * +---------------+---------------------------------------------------+
+ */
+// clang-format off
+#define BLADERF_RFIC_STATUS_INIT_SHIFT 0
+#define BLADERF_RFIC_STATUS_INIT_MASK 0x1
+#define BLADERF_RFIC_STATUS_WQSUCCESS_SHIFT 1
+#define BLADERF_RFIC_STATUS_WQSUCCESS_MASK 0x1
+#define BLADERF_RFIC_STATUS_WQLEN_SHIFT 8
+#define BLADERF_RFIC_STATUS_WQLEN_MASK 0xff
+
+#define BLADERF_RFIC_RSSI_MULT_SHIFT 32
+#define BLADERF_RFIC_RSSI_MULT_MASK 0xFFFF
+#define BLADERF_RFIC_RSSI_PRE_SHIFT 16
+#define BLADERF_RFIC_RSSI_PRE_MASK 0xFFFF
+#define BLADERF_RFIC_RSSI_SYM_SHIFT 0
+#define BLADERF_RFIC_RSSI_SYM_MASK 0xFFFF
+// clang-format on
+
+
+/******************************************************************************/
+/* Constants */
+/******************************************************************************/
+// clang-format off
+
+/* Gain mode mappings */
+static struct bladerf_rfic_gain_mode_map const bladerf2_rx_gain_mode_map[] = {
+ {
+ FIELD_INIT(.brf_mode, BLADERF_GAIN_MGC),
+ FIELD_INIT(.rfic_mode, RF_GAIN_MGC)
+ },
+ {
+ FIELD_INIT(.brf_mode, BLADERF_GAIN_FASTATTACK_AGC),
+ FIELD_INIT(.rfic_mode, RF_GAIN_FASTATTACK_AGC)
+ },
+ {
+ FIELD_INIT(.brf_mode, BLADERF_GAIN_SLOWATTACK_AGC),
+ FIELD_INIT(.rfic_mode, RF_GAIN_SLOWATTACK_AGC)
+ },
+ {
+ FIELD_INIT(.brf_mode, BLADERF_GAIN_HYBRID_AGC),
+ FIELD_INIT(.rfic_mode, RF_GAIN_HYBRID_AGC)
+ },
+};
+
+/* RX gain ranges */
+/* Reference: ad9361.c, ad9361_gt_tableindex and ad9361_init_gain_tables */
+static struct bladerf_gain_range const bladerf2_rx_gain_ranges[] = {
+ {
+ FIELD_INIT(.name, NULL),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 0),
+ FIELD_INIT(.max, 1300000000),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, 1 - 17),
+ FIELD_INIT(.max, 77 - 17),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.offset, -17.0f),
+ },
+ {
+ FIELD_INIT(.name, NULL),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 1300000000UL),
+ FIELD_INIT(.max, 4000000000UL),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, -4 - 11),
+ FIELD_INIT(.max, 71 - 11),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.offset, -11.0f),
+ },
+ {
+ FIELD_INIT(.name, NULL),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 4000000000UL),
+ FIELD_INIT(.max, 6000000000UL),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, -10 - 2),
+ FIELD_INIT(.max, 62 - 2),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.offset, -2.0f),
+ },
+ {
+ FIELD_INIT(.name, "full"),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 0),
+ FIELD_INIT(.max, 1300000000),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, 1),
+ FIELD_INIT(.max, 77),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.offset, 0),
+ },
+ {
+ FIELD_INIT(.name, "full"),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 1300000000UL),
+ FIELD_INIT(.max, 4000000000UL),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, -4),
+ FIELD_INIT(.max, 71),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.offset, 0),
+ },
+ {
+ FIELD_INIT(.name, "full"),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 4000000000UL),
+ FIELD_INIT(.max, 6000000000UL),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, -10),
+ FIELD_INIT(.max, 62),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.offset, 0),
+ },
+};
+
+/* Overall TX gain range */
+static struct bladerf_gain_range const bladerf2_tx_gain_ranges[] = {
+ {
+ /* TX gain offset: 60 dB system gain ~= 0 dBm output */
+ FIELD_INIT(.name, NULL),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 47000000UL),
+ FIELD_INIT(.max, 6000000000UL),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, __round_int64(1000*(-89.750 + 66.0))),
+ FIELD_INIT(.max, __round_int64(1000*(0 + 66.0))),
+ FIELD_INIT(.step, 250),
+ FIELD_INIT(.scale, 0.001F),
+ }),
+ FIELD_INIT(.offset, 66.0f),
+ },
+ {
+ FIELD_INIT(.name, "dsa"),
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 47000000UL),
+ FIELD_INIT(.max, 6000000000UL),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.gain, {
+ FIELD_INIT(.min, -89750),
+ FIELD_INIT(.max, 0),
+ FIELD_INIT(.step, 250),
+ FIELD_INIT(.scale, 0.001F),
+ }),
+ FIELD_INIT(.offset, 0),
+ },
+};
+
+/* RX gain modes */
+static struct bladerf_gain_modes const bladerf2_rx_gain_modes[] = {
+ {
+ FIELD_INIT(.name, "automatic"),
+ FIELD_INIT(.mode, BLADERF_GAIN_DEFAULT)
+ },
+ {
+ FIELD_INIT(.name, "manual"),
+ FIELD_INIT(.mode, BLADERF_GAIN_MGC)
+ },
+ {
+ FIELD_INIT(.name, "fast"),
+ FIELD_INIT(.mode, BLADERF_GAIN_FASTATTACK_AGC)
+ },
+ {
+ FIELD_INIT(.name, "slow"),
+ FIELD_INIT(.mode, BLADERF_GAIN_SLOWATTACK_AGC)
+ },
+ {
+ FIELD_INIT(.name, "hybrid"),
+ FIELD_INIT(.mode, BLADERF_GAIN_HYBRID_AGC)
+ }
+};
+
+/* Default RX gain control modes */
+static enum rf_gain_ctrl_mode const bladerf2_rx_gain_mode_default[2] = {
+ RF_GAIN_SLOWATTACK_AGC, RF_GAIN_SLOWATTACK_AGC
+};
+
+/* Sample Rate Range */
+static struct bladerf_range const bladerf2_sample_rate_range = {
+ FIELD_INIT(.min, 520834),
+ FIELD_INIT(.max, 122880000),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+};
+
+/* Sample Rate Base Range */
+static struct bladerf_range const bladerf2_sample_rate_range_base = {
+ FIELD_INIT(.min, 520834),
+ FIELD_INIT(.max, 61440000),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+};
+
+/* Sample Rate Oversample Range */
+static struct bladerf_range const bladerf2_sample_rate_range_oversample = {
+ FIELD_INIT(.min, 6250000),
+ FIELD_INIT(.max, 122880000),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+};
+
+/* Sample rates requiring a 4x interpolation/decimation */
+static struct bladerf_range const bladerf2_sample_rate_range_4x = {
+ FIELD_INIT(.min, 520834),
+ FIELD_INIT(.max, 2083334),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+};
+
+/* Bandwidth Range */
+static struct bladerf_range const bladerf2_bandwidth_range = {
+ FIELD_INIT(.min, 200000),
+ FIELD_INIT(.max, 56000000),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+};
+
+/* Frequency Ranges */
+static struct bladerf_range const bladerf2_rx_frequency_range = {
+ FIELD_INIT(.min, 70000000),
+ FIELD_INIT(.max, 6000000000),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+};
+
+static struct bladerf_range const bladerf2_tx_frequency_range = {
+ FIELD_INIT(.min, 47000000),
+ FIELD_INIT(.max, 6000000000),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+};
+
+
+/* RF Ports */
+static struct bladerf_rfic_port_name_map const bladerf2_rx_port_map[] = {
+ { FIELD_INIT(.name, "A_BALANCED"), FIELD_INIT(.id, AD936X_A_BALANCED), },
+ { FIELD_INIT(.name, "B_BALANCED"), FIELD_INIT(.id, AD936X_B_BALANCED), },
+ { FIELD_INIT(.name, "C_BALANCED"), FIELD_INIT(.id, AD936X_C_BALANCED), },
+ { FIELD_INIT(.name, "A_N"), FIELD_INIT(.id, AD936X_A_N), },
+ { FIELD_INIT(.name, "A_P"), FIELD_INIT(.id, AD936X_A_P), },
+ { FIELD_INIT(.name, "B_N"), FIELD_INIT(.id, AD936X_B_N), },
+ { FIELD_INIT(.name, "B_P"), FIELD_INIT(.id, AD936X_B_P), },
+ { FIELD_INIT(.name, "C_N"), FIELD_INIT(.id, AD936X_C_N), },
+ { FIELD_INIT(.name, "C_P"), FIELD_INIT(.id, AD936X_C_P), },
+ { FIELD_INIT(.name, "TX_MON1"), FIELD_INIT(.id, AD936X_TX_MON1), },
+ { FIELD_INIT(.name, "TX_MON2"), FIELD_INIT(.id, AD936X_TX_MON2), },
+ { FIELD_INIT(.name, "TX_MON1_2"), FIELD_INIT(.id, AD936X_TX_MON1_2), },
+};
+
+static struct bladerf_rfic_port_name_map const bladerf2_tx_port_map[] = {
+ { FIELD_INIT(.name, "TXA"), FIELD_INIT(.id, AD936X_TXA), },
+ { FIELD_INIT(.name, "TXB"), FIELD_INIT(.id, AD936X_TXB), },
+};
+
+static struct band_port_map const bladerf2_rx_band_port_map[] = {
+ {
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 0),
+ FIELD_INIT(.max, 0),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.band, BAND_SHUTDOWN),
+ FIELD_INIT(.spdt, RFFE_CONTROL_SPDT_SHUTDOWN),
+ FIELD_INIT(.rfic_port, 0),
+ },
+ {
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 70000000UL),
+ FIELD_INIT(.max, 3000000000UL),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.band, BAND_LOW),
+ FIELD_INIT(.spdt, RFFE_CONTROL_SPDT_LOWBAND),
+ FIELD_INIT(.rfic_port, AD936X_B_BALANCED),
+ },
+ {
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 3000000000UL),
+ FIELD_INIT(.max, 6000000000UL),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.band, BAND_HIGH),
+ FIELD_INIT(.spdt, RFFE_CONTROL_SPDT_HIGHBAND),
+ FIELD_INIT(.rfic_port, AD936X_A_BALANCED),
+ },
+};
+
+static struct band_port_map const bladerf2_tx_band_port_map[] = {
+ {
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 0),
+ FIELD_INIT(.max, 0),
+ FIELD_INIT(.step, 1),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.band, BAND_SHUTDOWN),
+ FIELD_INIT(.spdt, RFFE_CONTROL_SPDT_SHUTDOWN),
+ FIELD_INIT(.rfic_port, 0),
+ },
+ {
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 46875000UL),
+ FIELD_INIT(.max, 3000000000UL),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.band, BAND_LOW),
+ FIELD_INIT(.spdt, RFFE_CONTROL_SPDT_LOWBAND),
+ FIELD_INIT(.rfic_port, AD936X_TXB),
+ },
+ {
+ FIELD_INIT(.frequency, {
+ FIELD_INIT(.min, 3000000000UL),
+ FIELD_INIT(.max, 6000000000UL),
+ FIELD_INIT(.step, 2),
+ FIELD_INIT(.scale, 1),
+ }),
+ FIELD_INIT(.band, BAND_HIGH),
+ FIELD_INIT(.spdt, RFFE_CONTROL_SPDT_HIGHBAND),
+ FIELD_INIT(.rfic_port, AD936X_TXA),
+ },
+};
+
+// clang-format on
+
+
+/******************************************************************************/
+/* Helpers */
+/******************************************************************************/
+
+/**
+ * @brief Translate libad936x error codes to libbladeRF error codes
+ *
+ * @param[in] err The error
+ *
+ * @return value from \ref RETCODES list, or 0 if err is >= 0
+ */
+int errno_ad9361_to_bladerf(int err);
+
+/**
+ * @brief Gets the band port map by frequency.
+ *
+ * @param[in] ch Channel
+ * @param[in] freq Frequency. Use 0 for the "disabled" state.
+ *
+ * @return pointer to band_port_map
+ */
+struct band_port_map const *_get_band_port_map_by_freq(bladerf_channel ch,
+ bladerf_frequency freq);
+
+/**
+ * @brief Modifies reg to configure the RF switch SPDT bits
+ *
+ * @param reg RFFE control register ptr
+ * @param[in] ch Channel
+ * @param[in] enabled True if the channel is enabled, False otherwise
+ * @param[in] freq Frequency
+ *
+ * @return 0 on success, value from \ref RETCODES list on failure
+ */
+int _modify_spdt_bits_by_freq(uint32_t *reg,
+ bladerf_channel ch,
+ bool enabled,
+ bladerf_frequency freq);
+
+/**
+ * @brief Look up the RFFE control register bit for a bladerf_direction
+ *
+ * @param[in] dir Direction
+ *
+ * @return Bit index
+ */
+int _get_rffe_control_bit_for_dir(bladerf_direction dir);
+
+/**
+ * @brief Look up the RFFE control register bit for a bladerf_channel
+ *
+ * @param[in] ch Channel
+ *
+ * @return Bit index
+ */
+int _get_rffe_control_bit_for_ch(bladerf_channel ch);
+
+/**
+ * @brief Determine if a channel is active
+ *
+ * @param[in] reg RFFE control register
+ * @param[in] ch Channel
+ *
+ * @return true if active, false otherwise
+ */
+bool _rffe_ch_enabled(uint32_t reg, bladerf_channel ch);
+
+/**
+ * @brief Determine if any channel in a direction is active
+ *
+ * @param[in] reg RFFE control register
+ * @param[in] dir Direction
+ *
+ * @return true if any channel is active, false otherwise
+ */
+bool _rffe_dir_enabled(uint32_t reg, bladerf_direction dir);
+
+/**
+ * @brief Determine if any *other* channel in a direction is active
+ *
+ * @param[in] reg RFFE control register
+ * @param[in] ch Channel
+ *
+ * @return true if any channel in the same direction as ch is active, false
+ * otherwise
+ */
+bool _rffe_dir_otherwise_enabled(uint32_t reg, bladerf_channel ch);
+
+#endif // FPGA_COMMON_BLADERF2_COMMON_H_
diff --git a/Radio/HW/BladeRF/fpga_common/include/lms.h b/Radio/HW/BladeRF/fpga_common/include/lms.h
new file mode 100644
index 0000000..9f67536
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/lms.h
@@ -0,0 +1,838 @@
+/**
+ * @file lms.h
+ *
+ * @brief LMS6002D support
+ *
+ * This file is part of the bladeRF project:
+ * http://www.github.com/nuand/bladeRF
+ *
+ * Copyright (C) 2013-2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef LMS_H_
+#define LMS_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#if !defined(BLADERF_NIOS_BUILD) && !defined(BLADERF_NIOS_PC_SIMULATION)
+# include <libbladeRF.h>
+# include "board/board.h"
+# define LMS_WRITE(dev, addr, value) dev->backend->lms_write(dev, addr, value)
+# define LMS_READ(dev, addr, value) dev->backend->lms_read(dev, addr, value)
+#else
+# include "libbladeRF_nios_compat.h"
+# include "devices.h"
+#endif
+
+/*
+ * lms_freq.flags values
+ */
+
+/**
+ * If this bit is set, configure PLL output buffers for operation in the
+ * bladeRF's "low band." Otherwise, configure the device for operation in the
+ * "high band."
+ */
+#define LMS_FREQ_FLAGS_LOW_BAND (1 << 0)
+
+/**
+ * Use VCOCAP value as-is, rather as using it as a starting point hint
+ * to the tuning algorithm. This offers a faster retune, with a potential
+ * trade-off in phase noise.
+ */
+#define LMS_FREQ_FLAGS_FORCE_VCOCAP (1 << 1)
+
+/**
+ * This bit indicates whether the quicktune needs to set XB-200 parameters
+ */
+#define LMS_FREQ_XB_200_ENABLE (1 << 7)
+
+/*
+ * This bit indicates the quicktune is for the RX module, not setting this bit
+ * indicates the quicktune is for the TX module.
+ */
+#define LMS_FREQ_XB_200_MODULE_RX (1 << 6)
+
+/**
+ * This is the bit mask for the filter switch configuration for the XB-200.
+ */
+#define LMS_FREQ_XB_200_FILTER_SW (3 << 4)
+
+/**
+ * Macro that indicates the number of bitshifts necessary to get to the filter
+ * switch field
+ */
+#define LMS_FREQ_XB_200_FILTER_SW_SHIFT (4)
+
+/**
+ * This is the bit mask for the path configuration for the XB-200.
+ */
+#define LMS_FREQ_XB_200_PATH (3 << 2)
+
+/**
+ * Macro that indicates the number of bitshifts necessary to get to the path
+ * field
+ */
+#define LMS_FREQ_XB_200_PATH_SHIFT (2)
+
+/**
+ * Information about the frequency calculation for the LMS6002D PLL
+ * Calculation taken from the LMS6002D Programming and Calibration Guide
+ * version 1.1r1.
+ */
+struct lms_freq {
+ uint8_t freqsel; /**< Choice of VCO and dision ratio */
+ uint8_t vcocap; /**< VCOCAP hint */
+ uint16_t nint; /**< Integer portion of f_LO given f_REF */
+ uint32_t nfrac; /**< Fractional portion of f_LO given nint and f_REF */
+ uint8_t flags; /**< Additional parameters defining the tuning
+ configuration. See LMFS_FREQ_FLAGS_* values */
+ uint8_t xb_gpio; /**< Store XB-200 switch settings */
+
+#ifndef BLADERF_NIOS_BUILD
+ uint8_t x; /**< VCO division ratio */
+#endif
+
+ uint8_t vcocap_result; /**< Filled in by retune operation to denote
+ which VCOCAP value was used */
+};
+
+/* For >= 1.5 GHz uses the high band should be used. Otherwise, the low
+ * band should be selected */
+#define BLADERF1_BAND_HIGH 1500000000
+
+/**
+ * Internal low-pass filter bandwidth selection
+ */
+typedef enum {
+ BW_28MHz, /**< 28MHz bandwidth, 14MHz LPF */
+ BW_20MHz, /**< 20MHz bandwidth, 10MHz LPF */
+ BW_14MHz, /**< 14MHz bandwidth, 7MHz LPF */
+ BW_12MHz, /**< 12MHz bandwidth, 6MHz LPF */
+ BW_10MHz, /**< 10MHz bandwidth, 5MHz LPF */
+ BW_8p75MHz, /**< 8.75MHz bandwidth, 4.375MHz LPF */
+ BW_7MHz, /**< 7MHz bandwidth, 3.5MHz LPF */
+ BW_6MHz, /**< 6MHz bandwidth, 3MHz LPF */
+ BW_5p5MHz, /**< 5.5MHz bandwidth, 2.75MHz LPF */
+ BW_5MHz, /**< 5MHz bandwidth, 2.5MHz LPF */
+ BW_3p84MHz, /**< 3.84MHz bandwidth, 1.92MHz LPF */
+ BW_3MHz, /**< 3MHz bandwidth, 1.5MHz LPF */
+ BW_2p75MHz, /**< 2.75MHz bandwidth, 1.375MHz LPF */
+ BW_2p5MHz, /**< 2.5MHz bandwidth, 1.25MHz LPF */
+ BW_1p75MHz, /**< 1.75MHz bandwidth, 0.875MHz LPF */
+ BW_1p5MHz, /**< 1.5MHz bandwidth, 0.75MHz LPF */
+} lms_bw;
+
+
+/**
+ * LNA options
+ */
+typedef enum {
+ LNA_NONE, /**< Disable all LNAs */
+ LNA_1, /**< Enable LNA1 (300MHz - 2.8GHz) */
+ LNA_2, /**< Enable LNA2 (1.5GHz - 3.8GHz) */
+ LNA_3 /**< Enable LNA3 (Unused on the bladeRF) */
+} lms_lna;
+
+
+/**
+ * Loopback paths
+ */
+typedef enum {
+ LBP_BB, /**< Baseband loopback path */
+ LBP_RF /**< RF Loopback path */
+} lms_lbp;
+
+/**
+ * PA Selection
+ */
+typedef enum {
+ PA_AUX, /**< AUX PA Enable (for RF Loopback) */
+ PA_1, /**< PA1 Enable (300MHz - 2.8GHz) */
+ PA_2, /**< PA2 Enable (1.5GHz - 3.8GHz) */
+ PA_NONE, /**< All PAs disabled */
+} lms_pa;
+
+/**
+ * LMS6002D Transceiver configuration
+ */
+struct lms_xcvr_config {
+ uint32_t tx_freq_hz; /**< Transmit frequency in Hz */
+ uint32_t rx_freq_hz; /**< Receive frequency in Hz */
+ bladerf_loopback loopback_mode; /**< Loopback Mode */
+ lms_lna lna; /**< LNA Selection */
+ lms_pa pa; /**< PA Selection */
+ lms_bw tx_bw; /**< Transmit Bandwidth */
+ lms_bw rx_bw; /**< Receive Bandwidth */
+};
+
+/**
+ * Convert an integer to a bandwidth selection.
+ * If the actual bandwidth is not available, the closest
+ * bandwidth greater than the requested bandwidth is selected.
+ * If the provided value is greater than the maximum available bandwidth, the
+ * maximum available bandiwidth is returned.
+ *
+ * @param[in] req Requested bandwidth
+ *
+ * @return closest bandwidth
+ */
+lms_bw lms_uint2bw(unsigned int req);
+
+/**
+ * Convert a bandwidth seletion to an unsigned int.
+ *
+ * @param[in] bw Bandwidth enumeration
+ *
+ * @return bandwidth as an unsigned integer
+ */
+unsigned int lms_bw2uint(lms_bw bw);
+
+/**
+ * Wrapper for setting bits in an LMS6002 register via a RMW operation
+ *
+ * @param dev Device to operate on
+ * @param addr Register address
+ * @param mask Bits to set should be '1'
+ *
+ * @return BLADERF_ERR_* value
+ */
+static inline int lms_set(struct bladerf *dev, uint8_t addr, uint8_t mask)
+{
+ int status;
+ uint8_t regval;
+
+ status = LMS_READ(dev, addr, &regval);
+ if (status != 0) {
+ return status;
+ }
+
+ regval |= mask;
+
+ return LMS_WRITE(dev, addr, regval);
+}
+
+/*
+ * Wrapper for clearing bits in an LMS6002 register via a RMW operation
+ *
+ * @param dev Device to operate on
+ * @param addr Register address
+ * @param mask Bits to clear should be '1'
+ *
+ * @return BLADERF_ERR_* value
+ */
+static inline int lms_clear(struct bladerf *dev, uint8_t addr, uint8_t mask)
+{
+ int status;
+ uint8_t regval;
+
+ status = LMS_READ(dev, addr, &regval);
+ if (status != 0) {
+ return status;
+ }
+
+ regval &= ~mask;
+
+ return LMS_WRITE(dev, addr, regval);
+}
+
+/**
+ * Configure charge pump offset currents
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to change
+ */
+int lms_config_charge_pumps(struct bladerf *dev, bladerf_module module);
+
+/**
+ * Enable or disable the low-pass filter on the specified module
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to change
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_lpf_enable(struct bladerf *dev, bladerf_module mod, bool enable);
+
+/**
+ * Set the LPF mode
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to change
+ * @param[in] mode Mode to set to
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_lpf_set_mode(struct bladerf *dev, bladerf_module mod,
+ bladerf_lpf_mode mode);
+
+/**
+ * Get the LPF mode
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to change
+ * @param[out] mode Current LPF mode
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_lpf_get_mode(struct bladerf *dev, bladerf_module mod,
+ bladerf_lpf_mode *mode);
+
+/**
+ * Set the bandwidth for the specified module
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to set bandwidth for
+ * @param[in] bw Desired bandwidth
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_set_bandwidth(struct bladerf *dev, bladerf_module mod, lms_bw bw);
+
+/**
+ * Get the bandwidth for the specified module
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to read
+ * @param[out] bw Current bandwidth
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_get_bandwidth(struct bladerf *dev, bladerf_module mod, lms_bw *bw);
+
+/**
+ * Enable dithering on PLL in the module to help reduce any fractional spurs
+ * which might be occurring.
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to change
+ * @param[in] nbits Number of bits to dither (1 to 8). Ignored when
+ * disabling dithering.
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_dither_enable(struct bladerf *dev, bladerf_module mod,
+ uint8_t nbits, bool enable);
+
+/**
+ * Perform a soft reset of the LMS6002D device
+ *
+ * @param[in] dev Device handle
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_soft_reset(struct bladerf *dev);
+
+/**
+ * Set the gain of the LNA
+ *
+ * The LNA gain can be one of three values: bypassed (0dB gain),
+ * mid (MAX-6dB) and max.
+ *
+ * @param[in] dev Device handle
+ * @param[in] gain Bypass, mid or max gain
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_lna_set_gain(struct bladerf *dev, bladerf_lna_gain gain);
+
+/**
+ * Get the gain of the LNA
+ *
+ * @param[in] dev Device handle
+ * @param[out] gain Bypass, mid or max gain
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_lna_get_gain(struct bladerf *dev, bladerf_lna_gain *gain);
+
+/**
+ * Select which LNA to enable
+ *
+ * LNA1 frequency range is from 300MHz to 2.8GHz
+ * LNA2 frequency range is from 1.5GHz to 3.8GHz
+ * LNA3 frequency range is from 300MHz to 3.0GHz
+ *
+ * @param[in] dev Device handle
+ * @param[in] lna LNA to enable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_select_lna(struct bladerf *dev, lms_lna lna);
+
+/**
+ * Get the currently selected LNA
+ *
+ * @param[in] dev Device handle
+ * @param[out] lna Currently selected LNA, according to device registers
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_get_lna(struct bladerf *dev, lms_lna *lna);
+
+/**
+ * Enable or disable RXVGA1
+ *
+ * @param[in] dev Device handle
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_rxvga1_enable(struct bladerf *dev, bool enable);
+
+/**
+ * Set the gain value of RXVGA1 (in dB)
+ *
+ * @param[in] dev Device handle
+ * @param[in] gain Gain in dB (range: 5 to 30)
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_rxvga1_set_gain(struct bladerf *dev, int gain);
+
+/**
+ * Get the RXVGA1 gain value (in dB)
+ *
+ * @param[in] dev Device handle
+ * @param[out] gain Gain in dB (range: 5 to 30)
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_rxvga1_get_gain(struct bladerf *dev, int *gain);
+
+/**
+ * Enable or disable RXVGA2
+ *
+ * @param[in] dev Device handle
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_rxvga2_enable(struct bladerf *dev, bool enable);
+
+/**
+ * Set the gain value of RXVGA2 (in dB)
+ *
+ * The range of gain values is from 0dB to 60dB.
+ * Anything above 30dB is not recommended as a gain setting and will be clamped.
+ *
+ * @param[in] dev Device handle
+ * @param[in] gain Gain in dB (range: 0 to 30)
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_rxvga2_set_gain(struct bladerf *dev, int gain);
+
+/**
+ * Get the RXVGA2 gain value (in dB)
+ *
+ * @param[in] dev Device handle
+ * @param[out] gain Gain in dB (range: 0 to 30)
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_rxvga2_get_gain(struct bladerf *dev, int *gain);
+
+/**
+ * Set the gain in dB of TXVGA2.
+ *
+ * The range of gain values is from 0dB to 25dB.
+ * Anything above 25 will be clamped at 25.
+ *
+ * @param[in] dev Device handle
+ * @param[in] gain Gain in dB (range: 0 to 25). Out of range values will
+ * be clamped.
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_txvga2_set_gain(struct bladerf *dev, int gain);
+
+/**
+ * Get the gain in dB of TXVGA2.
+ *
+ * @param[in] dev Device handle
+ * @param[out] gain Gain in dB (range: 0 to 25)
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_txvga2_get_gain(struct bladerf *dev, int *gain);
+
+/**
+ * Set the gain in dB of TXVGA1.
+ *
+ * The range of gain values is from -35dB to -4dB.
+ *
+ * @param[in] dev Device handle
+ * @param[in] gain Gain in dB (range: -4 to -35). Out of range values
+ * will be clamped.
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_txvga1_set_gain(struct bladerf *dev, int gain);
+
+/**
+ * Get the gain in dB of TXVGA1.
+ *
+ * The range of gain values is from -35dB to -4dB.
+ *
+ * @param[in] dev Device handle
+ * @param[out] gain Gain in dB (range: -4 to -35)
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_txvga1_get_gain(struct bladerf *dev, int *gain);
+
+/**
+ * Enable or disable a PA
+ *
+ * @note PA_ALL is NOT valid for enabling, only for disabling.
+ *
+ * @param[in] dev Device handle
+ * @param[in] pa PA to enable
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_pa_enable(struct bladerf *dev, lms_pa pa, bool enable);
+
+/**
+ * Enable or disable the peak detectors.
+ *
+ * This is used as a baseband feedback to the system during transmit for
+ * calibration purposes.
+ *
+ * @note You cannot actively receive RF when the peak detectors are enabled.
+ *
+ * @param[in] dev Device handle
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_peakdetect_enable(struct bladerf *dev, bool enable);
+
+/**
+ * Enable or disable the RF front end.
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to enable or disable
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_enable_rffe(struct bladerf *dev, bladerf_module module, bool enable);
+
+/**
+ * Configure TX -> RX loopback mode
+ *
+ * @param[in] dev Device handle
+ * @param[in] mode Loopback mode. USE BLADERF_LB_NONE to disable
+ * loopback functionality.
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_set_loopback_mode(struct bladerf *dev, bladerf_loopback mode);
+
+/**
+ * Figure out what loopback mode we're in.
+ *
+ * @param[in] dev Device handle
+ * @param[out] mode Current loopback mode, or BLADERF_LB_NONE if
+ * loopback is not enabled.
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_get_loopback_mode(struct bladerf *dev, bladerf_loopback *mode);
+
+/**
+ * Top level power down of the LMS6002D
+ *
+ * @param[in] dev Device handle
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_power_down(struct bladerf *dev);
+
+/**
+ * Enable or disable the PLL of a module.
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module PLL to enable
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_pll_enable(struct bladerf *dev, bladerf_module mod, bool enable);
+
+/**
+ * Enable or disable the RX subsystem
+ *
+ * @param[in] dev Device handle
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_rx_enable(struct bladerf *dev, bool enable);
+
+/**
+ * Enable or disable the TX subsystem
+ *
+ * @param[in] dev Device handle
+ * @param[in] enable Set to `true` to enable, `false` to disable
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_tx_enable(struct bladerf *dev, bool enable);
+
+/**
+ * Converts a frequency structure into the final frequency in Hz
+ *
+ * @param[in] f Frequency structure to convert
+ * @returns The closest frequency in Hz that `f` can be converted to
+ */
+uint32_t lms_frequency_to_hz(struct lms_freq *f);
+
+/**
+ * Pretty print a frequency structure
+ *
+ * @note This is intended only for debug purposes. The log level must
+ * be set to DEBUG for this output to be made visible.
+ *
+ * @param[in] freq Frequency structure to print out
+ */
+void lms_print_frequency(struct lms_freq *freq);
+
+/**
+ * Get the frequency structure of the module
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to change
+ * @param[out] freq LMS frequency structure detailing VCO settings
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_get_frequency(struct bladerf *dev, bladerf_module mod,
+ struct lms_freq *freq);
+
+/**
+ * Fetch "Quick tune" parameters
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to query
+ * @param[out] quick_tune Quick retune parameters
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_get_quick_tune(struct bladerf *dev,
+ bladerf_module module,
+ struct bladerf_quick_tune *quick_tune);
+
+/**
+ * Calculate the parameters to tune to a specified frequency
+ *
+ * @param[in] freq Desired frequency
+ * @param[out] f Computed tuning parameters
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_calculate_tuning_params(unsigned int freq, struct lms_freq *f);
+
+/**
+ * Set the frequency of a module, given the lms_freq structure
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to tune
+ * @param[in] f lms_freq structure contaning desired tuning parameters
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_set_precalculated_frequency(struct bladerf *dev, bladerf_module mod,
+ struct lms_freq *f);
+
+/**
+ * Set the frequency of a module in Hz
+ *
+ * @param[in] dev Device handle
+ * @param[in] mod Module to change
+ * @param[in] freq Frequency in Hz to tune
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+static inline int lms_set_frequency(struct bladerf *dev,
+ bladerf_module mod, uint32_t freq)
+{
+ struct lms_freq f;
+ int status;
+
+ status = lms_calculate_tuning_params(freq, &f);
+ if (status < 0) {
+ return status;
+ }
+
+ return lms_set_precalculated_frequency(dev, mod, &f);
+}
+
+/**
+ * Read back every register from the LMS6002D device.
+ *
+ * @note This is intended only for debug purposes.
+ *
+ * @param[in] dev Device handle
+ *
+ * @return 0 on success, BLADERF_ERR_* value on failure
+ */
+int lms_dump_registers(struct bladerf *dev);
+
+/**
+ * Calibrate the DC offset value for RX and TX modules for the
+ * direct conversion receiver.
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to calibrate
+ *
+ * @return 0 on success, -1 on failure.
+ */
+int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module);
+
+/**
+ * Load DC calibration values directly via device registers instead of
+ * running autocalibration routines.
+ *
+ * @param[in] dev Device handle
+ * @param[in] dc_cals Calibration values to load
+ */
+int lms_set_dc_cals(struct bladerf *dev,
+ const struct bladerf_lms_dc_cals *dc_cals);
+
+/**
+ * Retrieve the DC calibration values currently in use
+ *
+ * @param[in] dev Device handle
+ * @param[out] dc_cals Calibration values to load
+ */
+int lms_get_dc_cals(struct bladerf *dev, struct bladerf_lms_dc_cals *dc_cals);
+
+/**
+ * Initialize and configure the LMS6002D given the transceiver
+ * configuration passed in.
+ *
+ * @param[in] dev Device handle
+ * @param[in] config Transceiver configuration
+ *
+ * @return 0 on success, -1 on failure.
+ */
+int lms_config_init(struct bladerf *dev, struct lms_xcvr_config *config);
+
+/**
+ * Select the appropriate band fore the specified frequency
+ *
+ * @note This is band selection is specific to how the bladeRF is connected
+ * to the LNA and PA blocks.
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to configure
+ * @parma[in] low_band Select the low band
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int lms_select_band(struct bladerf *dev, bladerf_module module, bool low_band);
+
+/**
+ * Select internal or external sampling
+ *
+ * @param[in] dev Device handle
+ * @param[in] sampling Desired sampling mode
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int lms_select_sampling(struct bladerf *dev, bladerf_sampling sampling);
+
+/**
+ * Get the current sampling type
+ *
+ * @param[in] dev Device handle
+ * @param[out] sampling Desired sampling mode
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int lms_get_sampling(struct bladerf *dev, bladerf_sampling *sampling);
+
+/**
+ * Set the DC offset value on the I channel
+ *
+ * For consistency with other bladeRF correction values,
+ * this value is scaled to [-2048, 2048].
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to adjust
+ * @param[in] value DC offset adjustment value to write
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int lms_set_dc_offset_i(struct bladerf *dev,
+ bladerf_module module, uint16_t value);
+
+/**
+ * Get the DC offset value on the I channel
+ *
+ * For consistency with other bladeRF correction values,
+ * this value is scaled to [-2048, 2048].
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to adjust
+ * @param[out] value On success, the DC offset value on the I channel
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int lms_get_dc_offset_i(struct bladerf *dev,
+ bladerf_module module, int16_t *value);
+
+/**
+ * Set the DC offset value on the Q channel.
+ *
+ * For consistency with other bladeRF correction values,
+ * this value is scaled to [-2048, 2048].
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to adjust
+ * @param[in] value DC offset adjustment value to write
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int lms_set_dc_offset_q(struct bladerf *dev,
+ bladerf_module module, int16_t value);
+
+/**
+ * Get the DC offset value on the Q channel
+ *
+ * For consistency with other bladeRF correction values,
+ * this value is scaled to [-2048, 2048].
+ *
+ * @param[in] dev Device handle
+ * @param[in] module Module to adjust
+ * @param[out] value On success, the DC offset value on the I channel
+ *
+ * @return 0 on succes, BLADERF_ERR_* value on failure
+ */
+int lms_get_dc_offset_q(struct bladerf *dev,
+ bladerf_module module, int16_t *value);
+
+#endif /* LMS_H_ */
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_16x64.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_16x64.h
new file mode 100644
index 0000000..9e0b417
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_16x64.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_16x64_H_
+#define BLADERF_NIOS_PKT_16x64_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+/*
+ * This file defines the Host <-> FPGA (NIOS II) packet formats for accesses
+ * to devices/blocks with 16-bit addresses and 64-bit data
+ *
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Target ID (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 2 | Flags (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 3 | Reserved. Set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ * | 5:4 | 16-bit address, little-endian |
+ * +----------------+---------------------------------------------------------+
+ * | 13:6 | 64-bit data, little-endian |
+ * +----------------+---------------------------------------------------------+
+ * | 15:14 | Reserved. Set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ *
+ * Response
+ * ----------------------
+ *
+ * The response packet contains the same information as the request.
+ * A status flag will be set if the operation completed successfully.
+ *
+ * In the case of a read request, the data field will contain the read data, if
+ * the read succeeded.
+ *
+ * (Note 1)
+ * The "Target ID" refers to the peripheral, device, or block to access.
+ * See the NIOS_PKT_16x64_TARGET_* values.
+ *
+ * (Note 2)
+ * The flags are defined as follows:
+ *
+ * +================+========================+
+ * | Bit(s) | Value |
+ * +================+========================+
+ * | 7:2 | Reserved. Set to 0. |
+ * +----------------+------------------------+
+ * | | Status. Only used in |
+ * | | response packet. |
+ * | | Ignored in request. |
+ * | 1 | |
+ * | | 1 = Success |
+ * | | 0 = Failure |
+ * +----------------+------------------------+
+ * | 0 | 0 = Read operation |
+ * | | 1 = Write operation |
+ * +----------------+------------------------+
+ *
+ */
+
+#define NIOS_PKT_16x64_MAGIC ((uint8_t) 'E')
+
+/* Request packet indices */
+#define NIOS_PKT_16x64_IDX_MAGIC 0
+#define NIOS_PKT_16x64_IDX_TARGET_ID 1
+#define NIOS_PKT_16x64_IDX_FLAGS 2
+#define NIOS_PKT_16x64_IDX_RESV1 3
+#define NIOS_PKT_16x64_IDX_ADDR 4
+#define NIOS_PKT_16x64_IDX_DATA 6
+#define NIOS_PKT_16x64_IDX_RESV2 14
+
+/* Target IDs */
+#define NIOS_PKT_16x64_TARGET_AD9361 0x00
+#define NIOS_PKT_16x64_TARGET_RFIC 0x01 /* RFIC control */
+
+/* IDs 0x80 through 0xff will not be assigned by Nuand. These are reserved
+ * for user customizations */
+#define NIOS_PKT_16x64_TARGET_USR1 0x80
+#define NIOS_PKT_16x64_TARGET_USR128 0xff
+
+/* Flag bits */
+#define NIOS_PKT_16x64_FLAG_WRITE (1 << 0)
+#define NIOS_PKT_16x64_FLAG_SUCCESS (1 << 1)
+
+/**
+ * Sub-addresses for rfic target.
+ *
+ * +================+============================================+
+ * | Bit(s) | Value |
+ * +================+============================================+
+ * | 15:12 | Reserved. Set to 0. |
+ * +----------------+--------------------------------------------+
+ * | 11:8 | bladerf_channel & 0xf |
+ * | | 1111 = system-wide |
+ * +----------------+--------------------------------------------+
+ * | 7:0 | Subaddress. See bladerf_rfic_command enum. |
+ * +----------------+--------------------------------------------+
+ */
+
+/* Pack the request buffer */
+static inline void nios_pkt_16x64_pack(uint8_t *buf, uint8_t target, bool write,
+ uint16_t addr, uint64_t data)
+{
+ buf[NIOS_PKT_16x64_IDX_MAGIC] = NIOS_PKT_16x64_MAGIC;
+ buf[NIOS_PKT_16x64_IDX_TARGET_ID] = target;
+
+ if (write) {
+ buf[NIOS_PKT_16x64_IDX_FLAGS] = NIOS_PKT_16x64_FLAG_WRITE;
+ } else {
+ buf[NIOS_PKT_16x64_IDX_FLAGS] = 0x00;
+ }
+
+ buf[NIOS_PKT_16x64_IDX_RESV1] = 0x00;
+
+ buf[NIOS_PKT_16x64_IDX_ADDR + 0] = (addr >> 0);
+ buf[NIOS_PKT_16x64_IDX_ADDR + 1] = (addr >> 8);
+
+ buf[NIOS_PKT_16x64_IDX_DATA + 0] = (data >> 0) & 0xff;
+ buf[NIOS_PKT_16x64_IDX_DATA + 1] = (data >> 8) & 0xff;
+ buf[NIOS_PKT_16x64_IDX_DATA + 2] = (data >> 16) & 0xff;
+ buf[NIOS_PKT_16x64_IDX_DATA + 3] = (data >> 24) & 0xff;
+ buf[NIOS_PKT_16x64_IDX_DATA + 4] = (data >> 32) & 0xff;
+ buf[NIOS_PKT_16x64_IDX_DATA + 5] = (data >> 40) & 0xff;
+ buf[NIOS_PKT_16x64_IDX_DATA + 6] = (data >> 48) & 0xff;
+ buf[NIOS_PKT_16x64_IDX_DATA + 7] = (data >> 56) & 0xff;
+
+ buf[NIOS_PKT_16x64_IDX_RESV2 + 0] = 0x00;
+ buf[NIOS_PKT_16x64_IDX_RESV2 + 1] = 0x00;
+}
+
+/* Unpack the request buffer */
+static inline void nios_pkt_16x64_unpack(const uint8_t *buf, uint8_t *target,
+ bool *write, uint16_t *addr,
+ uint64_t *data)
+{
+ if (target != NULL) {
+ *target = buf[NIOS_PKT_16x64_IDX_TARGET_ID];
+ }
+
+ if (write != NULL) {
+ *write = (buf[NIOS_PKT_16x64_IDX_FLAGS] & NIOS_PKT_16x64_FLAG_WRITE) != 0;
+ }
+
+ if (addr != NULL) {
+ *addr = (buf[NIOS_PKT_16x64_IDX_ADDR + 0] << 0) |
+ (buf[NIOS_PKT_16x64_IDX_ADDR + 1] << 8);
+ }
+
+ if (data != NULL) {
+ *data = ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 0] << 0) |
+ ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 1] << 8) |
+ ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 2] << 16) |
+ ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 3] << 24) |
+ ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 4] << 32) |
+ ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 5] << 40) |
+ ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 6] << 48) |
+ ((uint64_t) buf[NIOS_PKT_16x64_IDX_DATA + 7] << 56);
+ }
+}
+
+/* Pack the response buffer */
+static inline void nios_pkt_16x64_resp_pack(uint8_t *buf, uint8_t target,
+ bool write, uint16_t addr,
+ uint64_t data, bool success)
+{
+ nios_pkt_16x64_pack(buf, target, write, addr, data);
+
+ if (success) {
+ buf[NIOS_PKT_16x64_IDX_FLAGS] |= NIOS_PKT_16x64_FLAG_SUCCESS;
+ }
+}
+
+/* Unpack the response buffer */
+static inline void nios_pkt_16x64_resp_unpack(const uint8_t *buf,
+ uint8_t *target, bool *write,
+ uint16_t *addr, uint64_t *data,
+ bool *success)
+{
+ nios_pkt_16x64_unpack(buf, target, write, addr, data);
+
+ if ((buf[NIOS_PKT_16x64_IDX_FLAGS] & NIOS_PKT_16x64_FLAG_SUCCESS) != 0) {
+ *success = true;
+ } else {
+ *success = false;
+ }
+}
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_32x32.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_32x32.h
new file mode 100644
index 0000000..e77cdee
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_32x32.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_32x32_H_
+#define BLADERF_NIOS_PKT_32x32_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+/*
+ * This file defines the Host <-> FPGA (NIOS II) packet formats for accesses
+ * to devices/blocks with 32-bit addresses and 32-bit data
+ *
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Target ID (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 2 | Flags (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 3 | Reserved. Set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ * | 7:4 | 32-bit address |
+ * +----------------+---------------------------------------------------------+
+ * | 11:8 | 32-bit data, little-endian |
+ * +----------------+---------------------------------------------------------+
+ * | 15:12 | Reserved. Set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ *
+ * Response
+ * ----------------------
+ *
+ * The response packet contains the same information as the request.
+ * A status flag will be set if the operation completed successfully.
+ *
+ * In the case of a read request, the data field will contain the read data, if
+ * the read succeeded.
+ *
+ * (Note 1)
+ * The "Target ID" refers to the peripheral, device, or block to access.
+ * See the NIOS_PKT_32x32_TARGET_* values.
+ *
+ * (Note 2)
+ * The flags are defined as follows:
+ *
+ * +================+========================+
+ * | Bit(s) | Value |
+ * +================+========================+
+ * | 7:2 | Reserved. Set to 0. |
+ * +----------------+------------------------+
+ * | | Status. Only used in |
+ * | | response packet. |
+ * | | Ignored in request. |
+ * | 1 | |
+ * | | 1 = Success |
+ * | | 0 = Failure |
+ * +----------------+------------------------+
+ * | 0 | 0 = Read operation |
+ * | | 1 = Write operation |
+ * +----------------+------------------------+
+ *
+ */
+
+#define NIOS_PKT_32x32_MAGIC ((uint8_t) 'K')
+
+/* Request packet indices */
+#define NIOS_PKT_32x32_IDX_MAGIC 0
+#define NIOS_PKT_32x32_IDX_TARGET_ID 1
+#define NIOS_PKT_32x32_IDX_FLAGS 2
+#define NIOS_PKT_32x32_IDX_RESV1 3
+#define NIOS_PKT_32x32_IDX_ADDR 4
+#define NIOS_PKT_32x32_IDX_DATA 8
+#define NIOS_PKT_32x32_IDX_RESV2 12
+
+/* Target IDs */
+
+/* For the EXP and EXP_DIR targets, the address is a bitmask of values
+ * to read/write */
+#define NIOS_PKT_32x32_TARGET_EXP 0x00 /* Expansion I/O */
+#define NIOS_PKT_32x32_TARGET_EXP_DIR 0x01 /* Expansion I/O Direction reg */
+#define NIOS_PKT_32x32_TARGET_ADI_AXI 0x02 /* ADI AXI Interface */
+#define NIOS_PKT_32x32_TARGET_WB_MSTR 0x03 /* Wishbone Master */
+
+/* IDs 0x80 through 0xff will not be assigned by Nuand. These are reserved
+ * for user customizations */
+#define NIOS_PKT_32x32_TARGET_USR1 0x80
+#define NIOS_PKT_32x32_TARGET_USR128 0xff
+
+/* Flag bits */
+#define NIOS_PKT_32x32_FLAG_WRITE (1 << 0)
+#define NIOS_PKT_32x32_FLAG_SUCCESS (1 << 1)
+
+
+/* Pack the request buffer */
+static inline void nios_pkt_32x32_pack(uint8_t *buf, uint8_t target, bool write,
+ uint32_t addr, uint32_t data)
+{
+ buf[NIOS_PKT_32x32_IDX_MAGIC] = NIOS_PKT_32x32_MAGIC;
+ buf[NIOS_PKT_32x32_IDX_TARGET_ID] = target;
+
+ if (write) {
+ buf[NIOS_PKT_32x32_IDX_FLAGS] = NIOS_PKT_32x32_FLAG_WRITE;
+ } else {
+ buf[NIOS_PKT_32x32_IDX_FLAGS] = 0x00;
+ }
+
+ buf[NIOS_PKT_32x32_IDX_RESV1] = 0x00;
+
+ buf[NIOS_PKT_32x32_IDX_ADDR + 0] = (addr >> 0);
+ buf[NIOS_PKT_32x32_IDX_ADDR + 1] = (addr >> 8);
+ buf[NIOS_PKT_32x32_IDX_ADDR + 2] = (addr >> 16);
+ buf[NIOS_PKT_32x32_IDX_ADDR + 3] = (addr >> 24);
+
+ buf[NIOS_PKT_32x32_IDX_DATA + 0] = (data >> 0);
+ buf[NIOS_PKT_32x32_IDX_DATA + 1] = (data >> 8);
+ buf[NIOS_PKT_32x32_IDX_DATA + 2] = (data >> 16);
+ buf[NIOS_PKT_32x32_IDX_DATA + 3] = (data >> 24);
+
+ buf[NIOS_PKT_32x32_IDX_RESV2 + 0] = 0x00;
+ buf[NIOS_PKT_32x32_IDX_RESV2 + 1] = 0x00;
+ buf[NIOS_PKT_32x32_IDX_RESV2 + 2] = 0x00;
+ buf[NIOS_PKT_32x32_IDX_RESV2 + 3] = 0x00;
+}
+
+/* Unpack the request buffer */
+static inline void nios_pkt_32x32_unpack(const uint8_t *buf, uint8_t *target,
+ bool *write, uint32_t *addr,
+ uint32_t *data)
+{
+ if (target != NULL) {
+ *target = buf[NIOS_PKT_32x32_IDX_TARGET_ID];
+ }
+
+ if (write != NULL) {
+ *write = (buf[NIOS_PKT_32x32_IDX_FLAGS] & NIOS_PKT_32x32_FLAG_WRITE) != 0;
+ }
+
+ if (addr != NULL) {
+ *addr = (buf[NIOS_PKT_32x32_IDX_ADDR + 0] << 0) |
+ (buf[NIOS_PKT_32x32_IDX_ADDR + 1] << 8) |
+ (buf[NIOS_PKT_32x32_IDX_ADDR + 2] << 16) |
+ (buf[NIOS_PKT_32x32_IDX_ADDR + 3] << 24);
+ }
+
+
+ if (data != NULL) {
+ *data = (buf[NIOS_PKT_32x32_IDX_DATA + 0] << 0) |
+ (buf[NIOS_PKT_32x32_IDX_DATA + 1] << 8) |
+ (buf[NIOS_PKT_32x32_IDX_DATA + 2] << 16) |
+ (buf[NIOS_PKT_32x32_IDX_DATA + 3] << 24);
+ }
+}
+
+/* Pack the response buffer */
+static inline void nios_pkt_32x32_resp_pack(uint8_t *buf, uint8_t target,
+ bool write, uint32_t addr,
+ uint32_t data, bool success)
+{
+ nios_pkt_32x32_pack(buf, target, write, addr, data);
+
+ if (success) {
+ buf[NIOS_PKT_32x32_IDX_FLAGS] |= NIOS_PKT_32x32_FLAG_SUCCESS;
+ }
+}
+
+/* Unpack the response buffer */
+static inline void nios_pkt_32x32_resp_unpack(const uint8_t *buf,
+ uint8_t *target, bool *write,
+ uint32_t *addr, uint32_t *data,
+ bool *success)
+{
+ nios_pkt_32x32_unpack(buf, target, write, addr, data);
+
+ if ((buf[NIOS_PKT_32x32_IDX_FLAGS] & NIOS_PKT_32x32_FLAG_SUCCESS) != 0) {
+ *success = true;
+ } else {
+ *success = false;
+ }
+}
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x16.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x16.h
new file mode 100644
index 0000000..9ed1d45
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x16.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_8x16_H_
+#define BLADERF_NIOS_PKT_8x16_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+/*
+ * This file defines the Host <-> FPGA (NIOS II) packet formats for accesses
+ * to devices/blocks with 8-bit addresses and 16-bit data
+ *
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Target ID (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 2 | Flags (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 3 | Reserved. Set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ * | 4 | 8-bit address |
+ * +----------------+---------------------------------------------------------+
+ * | 5:6 | 16-bit data, little-endian |
+ * +----------------+---------------------------------------------------------+
+ * | 7-15 | Reserved. Set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ *
+ * Response
+ * ----------------------
+ *
+ * The response packet contains the same information as the request.
+ * A status flag will be set if the operation completed successfully.
+ *
+ * In the case of a read request, the data field will contain the read data, if
+ * the read succeeded.
+ *
+ * (Note 1)
+ * The "Target ID" refers to the peripheral, device, or block to access.
+ * See the NIOS_PKT_8x16_TARGET_* values.
+ *
+ * (Note 2)
+ * The flags are defined as follows:
+ *
+ * +================+========================+
+ * | Bit(s) | Value |
+ * +================+========================+
+ * | 7:2 | Reserved. Set to 0. |
+ * +----------------+------------------------+
+ * | | Status. Only used in |
+ * | | response packet. |
+ * | | Ignored in request. |
+ * | 1 | |
+ * | | 1 = Success |
+ * | | 0 = Failure |
+ * +----------------+------------------------+
+ * | 0 | 0 = Read operation |
+ * | | 1 = Write operation |
+ * +----------------+------------------------+
+ *
+ */
+
+#define NIOS_PKT_8x16_MAGIC ((uint8_t) 'B')
+
+/* Request packet indices */
+#define NIOS_PKT_8x16_IDX_MAGIC 0
+#define NIOS_PKT_8x16_IDX_TARGET_ID 1
+#define NIOS_PKT_8x16_IDX_FLAGS 2
+#define NIOS_PKT_8x16_IDX_RESV1 3
+#define NIOS_PKT_8x16_IDX_ADDR 4
+#define NIOS_PKT_8x16_IDX_DATA 5
+#define NIOS_PKT_8x16_IDX_RESV2 7
+
+/* Target IDs */
+#define NIOS_PKT_8x16_TARGET_VCTCXO_DAC 0x00
+#define NIOS_PKT_8x16_TARGET_IQ_CORR 0x01
+#define NIOS_PKT_8x16_TARGET_AGC_CORR 0x02
+#define NIOS_PKT_8x16_TARGET_AD56X1_DAC 0x03
+#define NIOS_PKT_8x16_TARGET_INA219 0x04
+
+/* IDs 0x80 through 0xff will not be assigned by Nuand. These are reserved
+ * for user customizations */
+#define NIOS_PKT_8x16_TARGET_USR1 0x80
+#define NIOS_PKT_8x16_TARGET_USR128 0xff
+
+/* Flag bits */
+#define NIOS_PKT_8x16_FLAG_WRITE (1 << 0)
+#define NIOS_PKT_8x16_FLAG_SUCCESS (1 << 1)
+
+/* Sub-addresses for the IQ Correction target block */
+#define NIOS_PKT_8x16_ADDR_IQ_CORR_RX_GAIN 0x00
+#define NIOS_PKT_8x16_ADDR_IQ_CORR_RX_PHASE 0x01
+#define NIOS_PKT_8x16_ADDR_IQ_CORR_TX_GAIN 0x02
+#define NIOS_PKT_8x16_ADDR_IQ_CORR_TX_PHASE 0x03
+
+/* Sub-addresses for the AGC DC Correction target block */
+#define NIOS_PKT_8x16_ADDR_AGC_DC_Q_MAX 0x00
+#define NIOS_PKT_8x16_ADDR_AGC_DC_I_MAX 0x01
+#define NIOS_PKT_8x16_ADDR_AGC_DC_Q_MID 0x02
+#define NIOS_PKT_8x16_ADDR_AGC_DC_I_MID 0x03
+#define NIOS_PKT_8x16_ADDR_AGC_DC_Q_MIN 0x04
+#define NIOS_PKT_8x16_ADDR_AGC_DC_I_MIN 0x05
+
+/* Pack the request buffer */
+static inline void nios_pkt_8x16_pack(uint8_t *buf, uint8_t target, bool write,
+ uint8_t addr, uint16_t data)
+{
+ buf[NIOS_PKT_8x16_IDX_MAGIC] = NIOS_PKT_8x16_MAGIC;
+ buf[NIOS_PKT_8x16_IDX_TARGET_ID] = target;
+
+ if (write) {
+ buf[NIOS_PKT_8x16_IDX_FLAGS] = NIOS_PKT_8x16_FLAG_WRITE;
+ } else {
+ buf[NIOS_PKT_8x16_IDX_FLAGS] = 0x00;
+ }
+
+ buf[NIOS_PKT_8x16_IDX_RESV1] = 0x00;
+
+ buf[NIOS_PKT_8x16_IDX_ADDR] = addr;
+
+ buf[NIOS_PKT_8x16_IDX_DATA] = data & 0xff;
+ buf[NIOS_PKT_8x16_IDX_DATA + 1] = (data >> 8);
+
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 0] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 1] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 2] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 3] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 4] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 5] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 6] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 7] = 0x00;
+ buf[NIOS_PKT_8x16_IDX_RESV2 + 8] = 0x00;
+}
+
+/* Unpack the request buffer */
+static inline void nios_pkt_8x16_unpack(const uint8_t *buf, uint8_t *target,
+ bool *write, uint8_t *addr,
+ uint16_t *data)
+{
+ if (target != NULL) {
+ *target = buf[NIOS_PKT_8x16_IDX_TARGET_ID];
+ }
+
+ if (write != NULL) {
+ *write = (buf[NIOS_PKT_8x16_IDX_FLAGS] & NIOS_PKT_8x16_FLAG_WRITE) != 0;
+ }
+
+ if (addr != NULL) {
+ *addr = buf[NIOS_PKT_8x16_IDX_ADDR];
+ }
+
+ if (data != NULL) {
+ *data = (buf[NIOS_PKT_8x16_IDX_DATA + 0] << 0) |
+ (buf[NIOS_PKT_8x16_IDX_DATA + 1] << 8);
+ }
+}
+
+/* Pack the response buffer */
+static inline void nios_pkt_8x16_resp_pack(uint8_t *buf, uint8_t target,
+ bool write, uint8_t addr,
+ uint16_t data, bool success)
+{
+ nios_pkt_8x16_pack(buf, target, write, addr, data);
+
+ if (success) {
+ buf[NIOS_PKT_8x16_IDX_FLAGS] |= NIOS_PKT_8x16_FLAG_SUCCESS;
+ }
+}
+
+/* Unpack the response buffer */
+static inline void nios_pkt_8x16_resp_unpack(const uint8_t *buf,
+ uint8_t *target, bool *write,
+ uint8_t *addr, uint16_t *data,
+ bool *success)
+{
+ nios_pkt_8x16_unpack(buf, target, write, addr, data);
+
+ if ((buf[NIOS_PKT_8x16_IDX_FLAGS] & NIOS_PKT_8x16_FLAG_SUCCESS) != 0) {
+ *success = true;
+ } else {
+ *success = false;
+ }
+}
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x32.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x32.h
new file mode 100644
index 0000000..27e6373
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x32.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_8x32_H_
+#define BLADERF_NIOS_PKT_8x32_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+/*
+ * This file defines the Host <-> FPGA (NIOS II) packet formats for accesses
+ * to devices/blocks with 8-bit addresses and 32-bit data
+ *
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Target ID (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 2 | Flags (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 3 | Reserved. Set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ * | 4 | 8-bit address |
+ * +----------------+---------------------------------------------------------+
+ * | 8:5 | 32-bit data, little-endian |
+ * +----------------+---------------------------------------------------------+
+ * | 15:9 | Reserved. Set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ *
+ * Response
+ * ----------------------
+ *
+ * The response packet contains the same information as the request.
+ * A status flag will be set if the operation completed successfully.
+ *
+ * In the case of a read request, the data field will contain the read data, if
+ * the read succeeded.
+ *
+ * (Note 1)
+ * The "Target ID" refers to the peripheral, device, or block to access.
+ * See the NIOS_PKT_8x32_TARGET_* values.
+ *
+ * (Note 2)
+ * The flags are defined as follows:
+ *
+ * +================+========================+
+ * | Bit(s) | Value |
+ * +================+========================+
+ * | 7:2 | Reserved. Set to 0. |
+ * +----------------+------------------------+
+ * | | Status. Only used in |
+ * | | response packet. |
+ * | | Ignored in request. |
+ * | 1 | |
+ * | | 1 = Success |
+ * | | 0 = Failure |
+ * +----------------+------------------------+
+ * | 0 | 0 = Read operation |
+ * | | 1 = Write operation |
+ * +----------------+------------------------+
+ *
+ */
+
+#define NIOS_PKT_8x32_MAGIC ((uint8_t) 'C')
+
+/* Request packet indices */
+#define NIOS_PKT_8x32_IDX_MAGIC 0
+#define NIOS_PKT_8x32_IDX_TARGET_ID 1
+#define NIOS_PKT_8x32_IDX_FLAGS 2
+#define NIOS_PKT_8x32_IDX_RESV1 3
+#define NIOS_PKT_8x32_IDX_ADDR 4
+#define NIOS_PKT_8x32_IDX_DATA 5
+#define NIOS_PKT_8x32_IDX_RESV2 9
+
+/* Target IDs */
+#define NIOS_PKT_8x32_TARGET_VERSION 0x00 /* FPGA version (read only) */
+#define NIOS_PKT_8x32_TARGET_CONTROL 0x01 /* FPGA control/config register */
+#define NIOS_PKT_8x32_TARGET_ADF4351 0x02 /* XB-200 ADF4351 register access
+ * (write-only) */
+#define NIOS_PKT_8x32_TARGET_RFFE_CSR 0x03 /* RFFE control & status GPIO */
+#define NIOS_PKT_8x32_TARGET_ADF400X 0x04 /* ADF400x config */
+#define NIOS_PKT_8x32_TARGET_FASTLOCK 0x05 /* Save AD9361 fast lock profile
+ * to Nios */
+
+/* IDs 0x80 through 0xff will not be assigned by Nuand. These are reserved
+ * for user customizations */
+#define NIOS_PKT_8x32_TARGET_USR1 0x80
+#define NIOS_PKT_8x32_TARGET_USR128 0xff
+
+/* Flag bits */
+#define NIOS_PKT_8x32_FLAG_WRITE (1 << 0)
+#define NIOS_PKT_8x32_FLAG_SUCCESS (1 << 1)
+
+/* Function to convert target ID to string */
+static inline const char* target2str(uint8_t target_id) {
+ switch (target_id) {
+ case NIOS_PKT_8x32_TARGET_VERSION:
+ return "FPGA Version";
+ case NIOS_PKT_8x32_TARGET_CONTROL:
+ return "FPGA Control/Config Register";
+ case NIOS_PKT_8x32_TARGET_ADF4351:
+ return "XB-200 ADF4351 Register (Write-Only)";
+ case NIOS_PKT_8x32_TARGET_RFFE_CSR:
+ return "RFFE Control & Status GPIO";
+ case NIOS_PKT_8x32_TARGET_ADF400X:
+ return "ADF400x Config";
+ case NIOS_PKT_8x32_TARGET_FASTLOCK:
+ return "AD9361 Fast Lock Profile";
+
+ /* Reserved for user customizations */
+ case NIOS_PKT_8x32_TARGET_USR1:
+ return "User Defined 1";
+ case NIOS_PKT_8x32_TARGET_USR128:
+ return "User Defined 128";
+
+ default:
+ return "Unknown Target ID";
+ }
+}
+
+/* Pack the request buffer */
+static inline void nios_pkt_8x32_pack(uint8_t *buf, uint8_t target, bool write,
+ uint8_t addr, uint32_t data)
+{
+ buf[NIOS_PKT_8x32_IDX_MAGIC] = NIOS_PKT_8x32_MAGIC;
+ buf[NIOS_PKT_8x32_IDX_TARGET_ID] = target;
+
+ if (write) {
+ buf[NIOS_PKT_8x32_IDX_FLAGS] = NIOS_PKT_8x32_FLAG_WRITE;
+ } else {
+ buf[NIOS_PKT_8x32_IDX_FLAGS] = 0x00;
+ }
+
+ buf[NIOS_PKT_8x32_IDX_RESV1] = 0x00;
+
+ buf[NIOS_PKT_8x32_IDX_ADDR] = addr;
+
+ buf[NIOS_PKT_8x32_IDX_DATA + 0] = data & 0xff;
+ buf[NIOS_PKT_8x32_IDX_DATA + 1] = (data >> 8);
+ buf[NIOS_PKT_8x32_IDX_DATA + 2] = (data >> 16);
+ buf[NIOS_PKT_8x32_IDX_DATA + 3] = (data >> 24);
+
+ buf[NIOS_PKT_8x32_IDX_RESV2 + 0] = 0x00;
+ buf[NIOS_PKT_8x32_IDX_RESV2 + 1] = 0x00;
+ buf[NIOS_PKT_8x32_IDX_RESV2 + 2] = 0x00;
+ buf[NIOS_PKT_8x32_IDX_RESV2 + 3] = 0x00;
+ buf[NIOS_PKT_8x32_IDX_RESV2 + 4] = 0x00;
+ buf[NIOS_PKT_8x32_IDX_RESV2 + 5] = 0x00;
+ buf[NIOS_PKT_8x32_IDX_RESV2 + 6] = 0x00;
+}
+
+/* Unpack the request buffer */
+static inline void nios_pkt_8x32_unpack(const uint8_t *buf, uint8_t *target,
+ bool *write, uint8_t *addr,
+ uint32_t *data)
+{
+ if (target != NULL) {
+ *target = buf[NIOS_PKT_8x32_IDX_TARGET_ID];
+ }
+
+ if (write != NULL) {
+ *write = (buf[NIOS_PKT_8x32_IDX_FLAGS] & NIOS_PKT_8x32_FLAG_WRITE) != 0;
+ }
+
+ if (addr != NULL) {
+ *addr = buf[NIOS_PKT_8x32_IDX_ADDR];
+ }
+
+ if (data != NULL) {
+ *data = (buf[NIOS_PKT_8x32_IDX_DATA + 0] << 0) |
+ (buf[NIOS_PKT_8x32_IDX_DATA + 1] << 8) |
+ (buf[NIOS_PKT_8x32_IDX_DATA + 2] << 16) |
+ (buf[NIOS_PKT_8x32_IDX_DATA + 3] << 24);
+ }
+}
+
+/* Pack the response buffer */
+static inline void nios_pkt_8x32_resp_pack(uint8_t *buf, uint8_t target,
+ bool write, uint8_t addr,
+ uint32_t data, bool success)
+{
+ nios_pkt_8x32_pack(buf, target, write, addr, data);
+
+ if (success) {
+ buf[NIOS_PKT_8x32_IDX_FLAGS] |= NIOS_PKT_8x32_FLAG_SUCCESS;
+ }
+}
+
+/* Unpack the response buffer */
+static inline void nios_pkt_8x32_resp_unpack(const uint8_t *buf,
+ uint8_t *target, bool *write,
+ uint8_t *addr, uint32_t *data,
+ bool *success)
+{
+ nios_pkt_8x32_unpack(buf, target, write, addr, data);
+
+ if ((buf[NIOS_PKT_8x32_IDX_FLAGS] & NIOS_PKT_8x32_FLAG_SUCCESS) != 0) {
+ *success = true;
+ } else {
+ *success = false;
+ }
+}
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x64.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x64.h
new file mode 100644
index 0000000..420307c
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x64.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_8x64_H_
+#define BLADERF_NIOS_PKT_8x64_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+/*
+ * This file defines the Host <-> FPGA (NIOS II) packet formats for accesses
+ * to devices/blocks with 8-bit addresses and 64-bit data
+ *
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Target ID (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 2 | Flags (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 3 | Reserved. Set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ * | 4 | 8-bit address |
+ * +----------------+---------------------------------------------------------+
+ * | 12:5 | 64-bit data, little-endian |
+ * +----------------+---------------------------------------------------------+
+ * | 15:13 | Reserved. Set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ *
+ * Response
+ * ----------------------
+ *
+ * The response packet contains the same information as the request.
+ * A status flag will be set if the operation completed successfully.
+ *
+ * In the case of a read request, the data field will contain the read data, if
+ * the read succeeded.
+ *
+ * (Note 1)
+ * The "Target ID" refers to the peripheral, device, or block to access.
+ * See the NIOS_PKT_8x64_TARGET_* values.
+ *
+ * (Note 2)
+ * The flags are defined as follows:
+ *
+ * +================+========================+
+ * | Bit(s) | Value |
+ * +================+========================+
+ * | 7:2 | Reserved. Set to 0. |
+ * +----------------+------------------------+
+ * | | Status. Only used in |
+ * | | response packet. |
+ * | | Ignored in request. |
+ * | 1 | |
+ * | | 1 = Success |
+ * | | 0 = Failure |
+ * +----------------+------------------------+
+ * | 0 | 0 = Read operation |
+ * | | 1 = Write operation |
+ * +----------------+------------------------+
+ *
+ */
+
+#define NIOS_PKT_8x64_MAGIC ((uint8_t) 'D')
+
+/* Request packet indices */
+#define NIOS_PKT_8x64_IDX_MAGIC 0
+#define NIOS_PKT_8x64_IDX_TARGET_ID 1
+#define NIOS_PKT_8x64_IDX_FLAGS 2
+#define NIOS_PKT_8x64_IDX_RESV1 3
+#define NIOS_PKT_8x64_IDX_ADDR 4
+#define NIOS_PKT_8x64_IDX_DATA 5
+#define NIOS_PKT_8x64_IDX_RESV2 13
+
+/* Target IDs */
+
+#define NIOS_PKT_8x64_TARGET_TIMESTAMP 0x00 /* Timestamp readback (read only) */
+
+/* IDs 0x80 through 0xff will not be assigned by Nuand. These are reserved
+ * for user customizations */
+#define NIOS_PKT_8x64_TARGET_USR1 0x80
+#define NIOS_PKT_8x64_TARGET_USR128 0xff
+
+/* Flag bits */
+#define NIOS_PKT_8x64_FLAG_WRITE (1 << 0)
+#define NIOS_PKT_8x64_FLAG_SUCCESS (1 << 1)
+
+/* Sub-addresses for timestamp target */
+#define NIOS_PKT_8x64_TIMESTAMP_RX 0x00
+#define NIOS_PKT_8x64_TIMESTAMP_TX 0x01
+
+/* Pack the request buffer */
+static inline void nios_pkt_8x64_pack(uint8_t *buf, uint8_t target, bool write,
+ uint8_t addr, uint64_t data)
+{
+ buf[NIOS_PKT_8x64_IDX_MAGIC] = NIOS_PKT_8x64_MAGIC;
+ buf[NIOS_PKT_8x64_IDX_TARGET_ID] = target;
+
+ if (write) {
+ buf[NIOS_PKT_8x64_IDX_FLAGS] = NIOS_PKT_8x64_FLAG_WRITE;
+ } else {
+ buf[NIOS_PKT_8x64_IDX_FLAGS] = 0x00;
+ }
+
+ buf[NIOS_PKT_8x64_IDX_RESV1] = 0x00;
+
+ buf[NIOS_PKT_8x64_IDX_ADDR] = addr;
+
+ buf[NIOS_PKT_8x64_IDX_DATA + 0] = (data >> 0) & 0xff;
+ buf[NIOS_PKT_8x64_IDX_DATA + 1] = (data >> 8) & 0xff;
+ buf[NIOS_PKT_8x64_IDX_DATA + 2] = (data >> 16) & 0xff;
+ buf[NIOS_PKT_8x64_IDX_DATA + 3] = (data >> 24) & 0xff;
+ buf[NIOS_PKT_8x64_IDX_DATA + 4] = (data >> 32) & 0xff;
+ buf[NIOS_PKT_8x64_IDX_DATA + 5] = (data >> 40) & 0xff;
+ buf[NIOS_PKT_8x64_IDX_DATA + 6] = (data >> 48) & 0xff;
+ buf[NIOS_PKT_8x64_IDX_DATA + 7] = (data >> 56) & 0xff;
+
+ buf[NIOS_PKT_8x64_IDX_RESV2 + 0] = 0x00;
+ buf[NIOS_PKT_8x64_IDX_RESV2 + 1] = 0x00;
+ buf[NIOS_PKT_8x64_IDX_RESV2 + 2] = 0x00;
+}
+
+/* Unpack the request buffer */
+static inline void nios_pkt_8x64_unpack(const uint8_t *buf, uint8_t *target,
+ bool *write, uint8_t *addr,
+ uint64_t *data)
+{
+ if (target != NULL) {
+ *target = buf[NIOS_PKT_8x64_IDX_TARGET_ID];
+ }
+
+ if (write != NULL) {
+ *write = (buf[NIOS_PKT_8x64_IDX_FLAGS] & NIOS_PKT_8x64_FLAG_WRITE) != 0;
+ }
+
+ if (addr != NULL) {
+ *addr = buf[NIOS_PKT_8x64_IDX_ADDR];
+ }
+
+ if (data != NULL) {
+ *data = ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 0] << 0) |
+ ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 1] << 8) |
+ ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 2] << 16) |
+ ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 3] << 24) |
+ ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 4] << 32) |
+ ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 5] << 40) |
+ ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 6] << 48) |
+ ((uint64_t) buf[NIOS_PKT_8x64_IDX_DATA + 7] << 56);
+ }
+}
+
+/* Pack the response buffer */
+static inline void nios_pkt_8x64_resp_pack(uint8_t *buf, uint8_t target,
+ bool write, uint8_t addr,
+ uint64_t data, bool success)
+{
+ nios_pkt_8x64_pack(buf, target, write, addr, data);
+
+ if (success) {
+ buf[NIOS_PKT_8x64_IDX_FLAGS] |= NIOS_PKT_8x64_FLAG_SUCCESS;
+ }
+}
+
+/* Unpack the response buffer */
+static inline void nios_pkt_8x64_resp_unpack(const uint8_t *buf,
+ uint8_t *target, bool *write,
+ uint8_t *addr, uint64_t *data,
+ bool *success)
+{
+ nios_pkt_8x64_unpack(buf, target, write, addr, data);
+
+ if ((buf[NIOS_PKT_8x64_IDX_FLAGS] & NIOS_PKT_8x64_FLAG_SUCCESS) != 0) {
+ *success = true;
+ } else {
+ *success = false;
+ }
+}
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x8.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x8.h
new file mode 100644
index 0000000..dd8072c
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x8.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_8x8_H_
+#define BLADERF_NIOS_PKT_8x8_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+/*
+ * This file defines the Host <-> FPGA (NIOS II) packet formats for accesses
+ * to devices/blocks with 8-bit addresses and 8-bit data
+ *
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Target ID (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 2 | Flags (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 3 | Reserved. Set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ * | 4 | 8-bit address |
+ * +----------------+---------------------------------------------------------+
+ * | 5 | 8-bit data |
+ * +----------------+---------------------------------------------------------+
+ * | 15:6 | Reserved. Set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ *
+ * Response
+ * ----------------------
+ *
+ * The response packet contains the same information as the request.
+ * A status flag will be set if the operation completed successfully.
+ *
+ * In the case of a read request, the data field will contain the read data, if
+ * the read succeeded.
+ *
+ * (Note 1)
+ * The "Target ID" refers to the peripheral, device, or block to access.
+ * See the NIOS_PKT_8x8_TARGET_* values.
+ *
+ * (Note 2)
+ * The flags are defined as follows:
+ *
+ * +================+========================+
+ * | Bit(s) | Value |
+ * +================+========================+
+ * | 7:2 | Reserved. Set to 0. |
+ * +----------------+------------------------+
+ * | | Status. Only used in |
+ * | | response packet. |
+ * | | Ignored in request. |
+ * | 1 | |
+ * | | 1 = Success |
+ * | | 0 = Failure |
+ * +----------------+------------------------+
+ * | 0 | 0 = Read operation |
+ * | | 1 = Write operation |
+ * +----------------+------------------------+
+ *
+ */
+
+#define NIOS_PKT_8x8_MAGIC ((uint8_t) 'A')
+
+/* Request packet indices */
+#define NIOS_PKT_8x8_IDX_MAGIC 0
+#define NIOS_PKT_8x8_IDX_TARGET_ID 1
+#define NIOS_PKT_8x8_IDX_FLAGS 2
+#define NIOS_PKT_8x8_IDX_RESV1 3
+#define NIOS_PKT_8x8_IDX_ADDR 4
+#define NIOS_PKT_8x8_IDX_DATA 5
+#define NIOS_PKT_8x8_IDX_RESV2 6
+
+/* Target IDs */
+#define NIOS_PKT_8x8_TARGET_LMS6 0x00 /* LMS6002D register access */
+#define NIOS_PKT_8x8_TARGET_SI5338 0x01 /* Si5338 register access */
+#define NIOS_PKT_8x8_TARGET_VCTCXO_TAMER 0x02 /* VCTCXO Tamer control */
+#define NIOS_PKT_8x8_TX_TRIGGER_CTL 0x03 /* TX trigger control */
+#define NIOS_PKT_8x8_RX_TRIGGER_CTL 0x04 /* RX trigger control */
+
+/* IDs 0x80 through 0xff will not be assigned by Nuand. These are reserved
+ * for user customizations */
+#define NIOS_PKT_8x8_TARGET_USR1 0x80
+#define NIOS_PKT_8x8_TARGET_USR128 0xff
+
+/* Flag bits */
+#define NIOS_PKT_8x8_FLAG_WRITE (1 << 0)
+#define NIOS_PKT_8x8_FLAG_SUCCESS (1 << 1)
+
+
+/* Pack the request buffer */
+static inline void nios_pkt_8x8_pack(uint8_t *buf, uint8_t target, bool write,
+ uint8_t addr, uint8_t data)
+{
+ buf[NIOS_PKT_8x8_IDX_MAGIC] = NIOS_PKT_8x8_MAGIC;
+ buf[NIOS_PKT_8x8_IDX_TARGET_ID] = target;
+
+ if (write) {
+ buf[NIOS_PKT_8x8_IDX_FLAGS] = NIOS_PKT_8x8_FLAG_WRITE;
+ } else {
+ buf[NIOS_PKT_8x8_IDX_FLAGS] = 0x00;
+ }
+
+ buf[NIOS_PKT_8x8_IDX_RESV1] = 0x00;
+
+ buf[NIOS_PKT_8x8_IDX_ADDR] = addr;
+ buf[NIOS_PKT_8x8_IDX_DATA] = data;
+
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 0] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 1] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 2] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 3] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 4] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 5] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 6] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 7] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 8] = 0x00;
+ buf[NIOS_PKT_8x8_IDX_RESV2 + 9] = 0x00;
+}
+
+/* Unpack the request buffer */
+static inline void nios_pkt_8x8_unpack(const uint8_t *buf, uint8_t *target,
+ bool *write, uint8_t *addr,
+ uint8_t *data)
+{
+ if (target != NULL) {
+ *target = buf[NIOS_PKT_8x8_IDX_TARGET_ID];
+ }
+
+ if (write != NULL) {
+ *write = (buf[NIOS_PKT_8x8_IDX_FLAGS] & NIOS_PKT_8x8_FLAG_WRITE) != 0;
+ }
+
+ if (addr != NULL) {
+ *addr = buf[NIOS_PKT_8x8_IDX_ADDR];
+ }
+
+ if (data != NULL) {
+ *data = buf[NIOS_PKT_8x8_IDX_DATA];
+ }
+}
+
+/* Pack the response buffer */
+static inline void nios_pkt_8x8_resp_pack(uint8_t *buf, uint8_t target,
+ bool write, uint8_t addr,
+ uint8_t data, bool success)
+{
+ nios_pkt_8x8_pack(buf, target, write, addr, data);
+
+ if (success) {
+ buf[NIOS_PKT_8x8_IDX_FLAGS] |= NIOS_PKT_8x8_FLAG_SUCCESS;
+ }
+}
+
+/* Unpack the response buffer */
+static inline void nios_pkt_8x8_resp_unpack(const uint8_t *buf, uint8_t *target,
+ bool *write, uint8_t *addr,
+ uint8_t *data, bool *success)
+{
+ nios_pkt_8x8_unpack(buf, target, write, addr, data);
+
+ if ((buf[NIOS_PKT_8x8_IDX_FLAGS] & NIOS_PKT_8x8_FLAG_SUCCESS) != 0) {
+ *success = true;
+ } else {
+ *success = false;
+ }
+}
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_formats.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_formats.h
new file mode 100644
index 0000000..7ab5901
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_formats.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef BLADERF_NIOS_PKT_FORMATS_H_
+#define BLADERF_NIOS_PKT_FORMATS_H_
+
+#include "nios_pkt_legacy.h"
+#include "nios_pkt_retune.h"
+#include "nios_pkt_retune2.h"
+#include "nios_pkt_8x8.h"
+#include "nios_pkt_8x16.h"
+#include "nios_pkt_8x32.h"
+#include "nios_pkt_8x64.h"
+#include "nios_pkt_32x32.h"
+#include "nios_pkt_16x64.h"
+
+#define NIOS_PKT_LEN 16
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_legacy.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_legacy.h
new file mode 100644
index 0000000..9912ce9
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_legacy.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2013-2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_LEGACY_H_
+#define BLADERF_NIOS_PKT_LEGACY_H_
+
+/* This is the original packet format used to issue requests from the
+ * host to the FPGA via the FX3 UART.
+ *
+ * This format remains supported for backwards compatibility, but should no
+ * longer be added to.
+ *
+ * If you're looking to customize the FPGA, consider using
+ * one of the "pkt_AxB" packet formats and handlers, or implementing a new
+ * format and handler.
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Configuration byte (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 2 - 15 | Pairs of 8-bit addr, 8-bit data |
+ * +----------------+---------------------------------------------------------+
+ *
+ *
+ *
+ * Note 1: Configuration byte:
+ *
+ * +================+============================+
+ * | Bit(s) | Value |
+ * +================+============================+
+ * | 7 | 1 = Read operation |
+ * +----------------+----------------------------+
+ * | 6 | 1 = Write operation |
+ * +----------------+----------------------------+
+ * | 5:4 | Device: |
+ * | | 00 - Config PIO (Note 2) |
+ * | | 01 - LMS register |
+ * | | 10 - VCTCXO Trim DAC |
+ * | | 11 - SI5338 register |
+ * +----------------+----------------------------+
+ * | 3 | Unused |
+ * +----------------+----------------------------+
+ * | 2:0 | Addr/Data pair count |
+ * | | (Note 2) |
+ * +----------------+----------------------------+
+ *
+ * Note 2: Config PIO addresses
+ *
+ * The NIOS II core and modules in the FPGA's programmable fabric are connected
+ * via parallel IO (PIO). See the NIOS_PKT_LEGACY_PIO_ADDR_* definitions
+ * in this file contain a virtual "register map" for these modules.
+ *
+ * Note 3: "Count" field
+ *
+ * The original intent of this field was to allow multiple register
+ * accesses to be requested at once.
+ *
+ * However, this feature was not leveraged by the host code for the LMS and
+ * SI5338 accesses, so revised legacy packet handler only processes the
+ * first addr/data pair.
+ *
+ * Readback of the time tamer values is the only case where this field
+ * is set to a count greater than 1.
+ *
+ * Although config PIO values are larger than one byte, the host code
+ * accessed these byte by byte through multiple requests. For example,
+ * 4 accesses would be required to fully read/write the configuration PIO.
+ *
+ * The above inefficiency is the motivation behind adding packet handlers
+ * that can read/write 32 or 64 bits in a single request (e.g., pkt_8x32,
+ * pkt_8x64).
+ *
+ *
+ *
+ * Response
+ * ----------------------
+ *
+ * The response for the legacy packet is essentially just the device
+ * echoing the request.
+ *
+ * On a read request, the number of requested items will be populated
+ * in bytes 2:15.
+ *
+ * The remaining bytes, or all of bytes 2:15 on a write request, should
+ * be regarded as "undefined" values and not used.
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | Configuration byte |
+ * +----------------+---------------------------------------------------------+
+ * | 2 - 15 | Pairs of 8-bit addr, 8-bit data |
+ * +----------------+---------------------------------------------------------+
+ *
+ */
+
+#define NIOS_PKT_LEGACY_MAGIC 'N'
+
+#define NIOS_PKT_LEGACY_DEV_GPIO_ADDR 0
+#define NIOS_PKT_LEGACY_DEV_RX_GAIN_ADDR 4
+#define NIOS_PKT_LEGACY_DEV_RX_PHASE_ADDR 6
+#define NIOS_PKT_LEGACY_DEV_TX_GAIN_ADDR 8
+#define NIOS_PKT_LEGACY_DEV_TX_PHASE_ADDR 10
+#define NIOS_PKT_LEGACY_DEV_FPGA_VERSION_ID 12
+
+#define NIOS_PKT_LEGACY_MODE_CNT_MASK 0x7
+#define NIOS_PKT_LEGACY_MODE_CNT_SHIFT 0
+#define NIOS_PKT_LEGACY_MODE_DEV_MASK 0x30
+#define NIOS_PKT_LEGACY_MODE_DEV_SHIFT 4
+
+#define NIOS_PKT_LEGACY_DEV_CONFIG (0 << NIOS_PKT_LEGACY_MODE_DEV_SHIFT)
+#define NIOS_PKT_LEGACY_DEV_LMS (1 << NIOS_PKT_LEGACY_MODE_DEV_SHIFT)
+#define NIOS_PKT_LEGACY_DEV_VCTCXO (2 << NIOS_PKT_LEGACY_MODE_DEV_SHIFT)
+#define NIOS_PKT_LEGACY_DEV_SI5338 (3 << NIOS_PKT_LEGACY_MODE_DEV_SHIFT)
+
+#define NIOS_PKT_LEGACY_MODE_DIR_MASK 0xC0
+#define NIOS_PKT_LEGACY_MODE_DIR_SHIFT 6
+#define NIOS_PKT_LEGACY_MODE_DIR_READ (2 << NIOS_PKT_LEGACY_MODE_DIR_SHIFT)
+#define NIOS_PKT_LEGACY_MODE_DIR_WRITE (1 << NIOS_PKT_LEGACY_MODE_DIR_SHIFT)
+
+
+/* PIO address space */
+
+/*
+ * 32-bit Device control register.
+ *
+ * This is register accessed via the libbladeRF functions,
+ * bladerf_config_gpio_write() and bladerf_config_gpio_read().
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_CONTROL 0
+#define NIOS_PKT_LEGACY_PIO_LEN_CONTROL 4
+
+/*
+ * IQ Correction: 16-bit RX Gain value
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_IQ_RX_GAIN 4
+#define NIOS_PKT_LEGACY_PIO_LEN_IQ_RX_GAIN 2
+
+/*
+ * IQ Correction: 16-bit RX Phase value
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_IQ_RX_PHASE 6
+#define NIOS_PKT_LEGACY_PIO_LEN_IQ_RX_PHASE 2
+
+/*
+ * IQ Correction: 16-bit TX Gain value
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_IQ_TX_GAIN 8
+#define NIOS_PKT_LEGACY_PIO_LEN_IQ_TX_GAIN 2
+
+/*
+ * IQ Correction: 16-bit TX Phase value
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_IQ_TX_PHASE 10
+#define NIOS_PKT_LEGACY_PIO_LEN_IQ_TX_PHASE 2
+
+/*
+ * 32-bit FPGA Version (read-only)
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_FPGA_VERSION 12
+#define NIOS_PKT_LEGACY_PIO_LEN_FPGA_VERSION 4
+
+/*
+ * 64-bit RX timestamp
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_RX_TIMESTAMP 16
+#define NIOS_PKT_LEGACY_PIO_LEN_RX_TIMESTAMP 8
+
+/*
+ * 64-bit TX timestamp
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_TX_TIMESTAMP 24
+#define NIOS_PKT_LEGACY_PIO_LEN_TX_TIMESTAMP 8
+
+/*
+ * VCTCXO Trim DAC value
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_VCTCXO 34
+#define NIOS_PKT_LEGACY_PIO_LEN_VCTCXO 2
+
+/*
+ * XB-200 ADF4351 Synthesizer
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_XB200_SYNTH 36
+#define NIOS_PKT_LEGACY_PIO_LEN_XB200_SYNTH 4
+
+/*
+ * Expansion IO
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_EXP 40
+#define NIOS_PKT_LEGACY_PIO_LEN_EXP 4
+
+/*
+ * Expansion IO Direction
+ */
+#define NIOS_PKT_LEGACY_PIO_ADDR_EXP_DIR 44
+#define NIOS_PKT_LEGACY_PIO_LEN_EXP_DIR 4
+
+struct uart_cmd {
+ unsigned char addr;
+ unsigned char data;
+};
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune.h
new file mode 100644
index 0000000..9bedcb0
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune.h
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2015 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_RETUNE_H_
+#define BLADERF_NIOS_PKT_RETUNE_H_
+
+#ifndef BLADERF_NIOS_BUILD
+# include <libbladeRF.h>
+#else
+# include "libbladeRF_nios_compat.h"
+#endif
+
+#include <stdint.h>
+
+/* Specify this value instead of a timestamp to clear the retune queue */
+#define NIOS_PKT_RETUNE_CLEAR_QUEUE ((uint64_t) -1)
+
+/* This file defines the Host <-> FPGA (NIOS II) packet formats for
+ * retune messages. This packet is formatted, as follows. All values are
+ * little-endian.
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | 64-bit timestamp denoting when to retune. (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 9 | 32-bit LMS6002D n_int & n_frac register values (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 13 | RX/TX bit, FREQSEL LMS6002D reg value (Note 3) |
+ * +----------------+---------------------------------------------------------+
+ * | 14 | Bit 7: Band-selection (Note 4) |
+ * | | Bit 6: 1=Quick tune, 0=Normal tune |
+ * | | Bits [5:0] VCOCAP[5:0] Hint |
+ * +----------------+---------------------------------------------------------+
+ * | 15 | 8-bit reserved word. Should be set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ *
+ * (Note 1) Special Timestamp Values:
+ *
+ * Tune "Now": 0x0000000000000000
+ * Clear Retune Queue: 0xffffffffffffffff
+ *
+ * When the "Clear Retune Queue" value is used, all of the other tuning
+ * parameters are ignored.
+ *
+ * (Note 2) Packed as follows:
+ *
+ * +================+=======================+
+ * | Byte offset | (MSB) Value (LSB)|
+ * +================+=======================+
+ * | 0 | NINT[8:1] |
+ * +----------------+-----------------------+
+ * | 1 | NINT[0], NFRAC[22:16] |
+ * +----------------+-----------------------+
+ * | 2 | NFRAC[15:8] |
+ * +----------------+-----------------------+
+ * | 3 | NFRAC[7:0] |
+ * +----------------+-----------------------+
+ *
+ * (Note 3) Packed as follows:
+ *
+ * +================+=======================+
+ * | Bit(s) | Value |
+ * +================+=======================+
+ * | 7 | TX |
+ * +----------------+-----------------------+
+ * | 6 | RX |
+ * +----------------+-----------------------+
+ * | [5:0] | FREQSEL |
+ * +----------------+-----------------------+
+ *
+ * (Notes 4) Band-selection bit = 1 implies "Low band". 0 = "High band"
+ */
+
+#define NIOS_PKT_RETUNE_IDX_MAGIC 0
+#define NIOS_PKT_RETUNE_IDX_TIME 1
+#define NIOS_PKT_RETUNE_IDX_INTFRAC 9
+#define NIOS_PKT_RETUNE_IDX_FREQSEL 13
+#define NIOS_PKT_RETUNE_IDX_BANDSEL 14
+#define NIOS_PKT_RETUNE_IDX_RESV 15
+
+#define NIOS_PKT_RETUNE_MAGIC 'T'
+
+
+#define FLAG_QUICK_TUNE (1 << 6)
+#define FLAG_RX (1 << 6)
+#define FLAG_TX (1 << 7)
+#define FLAG_LOW_BAND (1 << 7)
+
+
+/* Denotes no tune word is supplied. */
+#define NIOS_PKT_RETUNE_NO_HINT 0xff
+
+/* Denotes that the retune should not be scheduled - it should occur "now" */
+#define NIOS_PKT_RETUNE_NOW ((uint64_t) 0x00)
+
+#define PACK_TXRX_FREQSEL(module_, freqsel_) \
+ (freqsel_ & 0x3f)
+
+/* Pack the retune request buffer with the provided parameters */
+static inline void nios_pkt_retune_pack(uint8_t *buf,
+ bladerf_module module,
+ uint64_t timestamp,
+ uint16_t nint,
+ uint32_t nfrac,
+ uint8_t freqsel,
+ uint8_t vcocap,
+ bool low_band,
+ uint8_t xb_gpio,
+ bool quick_tune)
+{
+ buf[NIOS_PKT_RETUNE_IDX_MAGIC] = NIOS_PKT_RETUNE_MAGIC;
+
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 0] = timestamp & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 1] = (timestamp >> 8) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 2] = (timestamp >> 16) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 3] = (timestamp >> 24) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 4] = (timestamp >> 32) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 5] = (timestamp >> 40) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 6] = (timestamp >> 48) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_TIME + 7] = (timestamp >> 56) & 0xff;
+
+ buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 0] = (nint >> 1) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 1] = (nint & 0x1) << 7;
+ buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 1] |= ((nfrac >> 16) & 0x7f);
+ buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 2] = (nfrac >> 8) & 0xff;
+ buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 3] = nfrac & 0xff;
+
+ buf[NIOS_PKT_RETUNE_IDX_FREQSEL] = freqsel & 0xff;
+
+ switch (module) {
+ case BLADERF_MODULE_TX:
+ buf[NIOS_PKT_RETUNE_IDX_FREQSEL] |= FLAG_TX;
+ break;
+
+ case BLADERF_MODULE_RX:
+ buf[NIOS_PKT_RETUNE_IDX_FREQSEL] |= FLAG_RX;
+ break;
+
+ default:
+ /* Erroneous case - should not occur */
+ break;
+ }
+
+ if (low_band) {
+ buf[NIOS_PKT_RETUNE_IDX_BANDSEL] = FLAG_LOW_BAND;
+ } else {
+ buf[NIOS_PKT_RETUNE_IDX_BANDSEL] = 0x00;
+ }
+
+ if (quick_tune) {
+ buf[NIOS_PKT_RETUNE_IDX_BANDSEL] |= FLAG_QUICK_TUNE;
+ }
+
+ buf[NIOS_PKT_RETUNE_IDX_BANDSEL] |= vcocap;
+
+ buf[NIOS_PKT_RETUNE_IDX_RESV] = xb_gpio;
+}
+
+/* Unpack a retune request */
+static inline void nios_pkt_retune_unpack(const uint8_t *buf,
+ bladerf_module *module,
+ uint64_t *timestamp,
+ uint16_t *nint,
+ uint32_t *nfrac,
+ uint8_t *freqsel,
+ uint8_t *vcocap,
+ bool *low_band,
+ uint8_t *xb_gpio,
+ bool *quick_tune)
+{
+ *timestamp = ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 0]) << 0);
+ *timestamp |= ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 1]) << 8);
+ *timestamp |= ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 2]) << 16);
+ *timestamp |= ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 3]) << 24);
+ *timestamp |= ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 4]) << 32);
+ *timestamp |= ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 5]) << 40);
+ *timestamp |= ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 6]) << 48);
+ *timestamp |= ( ((uint64_t) buf[NIOS_PKT_RETUNE_IDX_TIME + 7]) << 56);
+
+ *nint = buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 0] << 1;
+ *nint |= buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 1] >> 7;
+
+ *nfrac = (buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 1] & 0x7f) << 16;
+ *nfrac |= buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 2] << 8;
+ *nfrac |= buf[NIOS_PKT_RETUNE_IDX_INTFRAC + 3];
+
+ *freqsel = buf[NIOS_PKT_RETUNE_IDX_FREQSEL] & 0x3f;
+
+ *module = -1;
+
+ if (buf[NIOS_PKT_RETUNE_IDX_FREQSEL] & FLAG_TX) {
+ *module = BLADERF_MODULE_TX;
+ } else if (buf[NIOS_PKT_RETUNE_IDX_FREQSEL] & FLAG_RX) {
+ *module = BLADERF_MODULE_RX;
+ }
+
+ *low_band = (buf[NIOS_PKT_RETUNE_IDX_BANDSEL] & FLAG_LOW_BAND) != 0;
+ *quick_tune = (buf[NIOS_PKT_RETUNE_IDX_BANDSEL] & FLAG_QUICK_TUNE) != 0;
+ *vcocap = buf[NIOS_PKT_RETUNE_IDX_BANDSEL] & 0x3f;
+ *xb_gpio = buf[NIOS_PKT_RETUNE_IDX_RESV];
+}
+
+
+/*
+ * Response
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | 64-bit duration denoting how long the operation took to |
+ * | | complete, in units of timestamp ticks. (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 9 | Bits [7:6] Reserved, set to 0. |
+ * | | Bits [5:0] VCOCAP value used. (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 10 | Status Flags (Note 3) |
+ * +----------------+---------------------------------------------------------+
+ * | 11-15 | Reserved. All bits set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ * (Note 1) This value will be zero if timestamps are not running for the
+ * associated module.
+ *
+ * (Note 2) This field's value should be ignored when reading a response for
+ * a request to clear the retune queue.
+ *
+ * (Note 3) Description of Status Flags:
+ *
+ * flags[0]: 1 = Timestamp and VCOCAP are valid. This is only the case for
+ * "Tune NOW" requests. It is not possible to return this
+ * information for scheduled retunes, as the event generally
+ * does not occur before the response is set.
+ *
+ * 0 = This was a scheduled retune. Timestamp and VCOCAP Fields
+ * should be ignored.
+ *
+ *
+ * flags[1]: 1 = Operation completed successfully.
+ * 0 = Operation failed.
+ *
+ * For "Tune NOW" requests, a failure may occur as the result
+ * of the tuning algorithm failing to occur, and such other
+ * unexpected failurs.
+ *
+ * The scheduled tune request will failure if the retune queue
+ * is full.
+ *
+ * flags[7:2] Reserved. Set to 0.
+ */
+
+#define NIOS_PKT_RETUNERESP_IDX_MAGIC 0
+#define NIOS_PKT_RETUNERESP_IDX_TIME 1
+#define NIOS_PKT_RETUNERESP_IDX_VCOCAP 9
+#define NIOS_PKT_RETUNERESP_IDX_FLAGS 10
+#define NIOS_PKT_RETUNERESP_IDX_RESV 11
+
+#define NIOS_PKT_RETUNERESP_FLAG_TSVTUNE_VALID (1 << 0)
+#define NIOS_PKT_RETUNERESP_FLAG_SUCCESS (1 << 1)
+
+static inline void nios_pkt_retune_resp_pack(uint8_t *buf,
+ uint64_t duration,
+ uint8_t vcocap,
+ uint8_t flags)
+{
+ buf[NIOS_PKT_RETUNERESP_IDX_MAGIC] = NIOS_PKT_RETUNE_MAGIC;
+
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 0] = duration & 0xff;
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 1] = (duration >> 8) & 0xff;
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 2] = (duration >> 16) & 0xff;
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 3] = (duration >> 24) & 0xff;
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 4] = (duration >> 32) & 0xff;
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 5] = (duration >> 40) & 0xff;
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 6] = (duration >> 48) & 0xff;
+ buf[NIOS_PKT_RETUNERESP_IDX_TIME + 7] = (duration >> 56) & 0xff;
+
+ buf[NIOS_PKT_RETUNERESP_IDX_VCOCAP] = vcocap;
+
+ buf[NIOS_PKT_RETUNERESP_IDX_FLAGS] = flags;
+
+ buf[NIOS_PKT_RETUNERESP_IDX_RESV + 0] = 0x00;
+ buf[NIOS_PKT_RETUNERESP_IDX_RESV + 1] = 0x00;
+ buf[NIOS_PKT_RETUNERESP_IDX_RESV + 2] = 0x00;
+ buf[NIOS_PKT_RETUNERESP_IDX_RESV + 3] = 0x00;
+ buf[NIOS_PKT_RETUNERESP_IDX_RESV + 4] = 0x00;
+}
+
+static inline void nios_pkt_retune_resp_unpack(const uint8_t *buf,
+ uint64_t *duration,
+ uint8_t *vcocap,
+ uint8_t *flags)
+{
+ *duration = buf[NIOS_PKT_RETUNERESP_IDX_TIME + 0];
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNERESP_IDX_TIME + 1]) << 8;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNERESP_IDX_TIME + 2]) << 16;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNERESP_IDX_TIME + 3]) << 24;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNERESP_IDX_TIME + 4]) << 32;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNERESP_IDX_TIME + 5]) << 40;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNERESP_IDX_TIME + 6]) << 48;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNERESP_IDX_TIME + 7]) << 56;
+
+ *vcocap = buf[NIOS_PKT_RETUNERESP_IDX_VCOCAP];
+
+ *flags = buf[NIOS_PKT_RETUNERESP_IDX_FLAGS];
+}
+
+#endif
diff --git a/Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune2.h b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune2.h
new file mode 100644
index 0000000..e58b51b
--- /dev/null
+++ b/Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune2.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2018 Nuand LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLADERF_NIOS_PKT_RETUNE2_H_
+#define BLADERF_NIOS_PKT_RETUNE2_H_
+
+#ifndef BLADERF_NIOS_BUILD
+# include <libbladeRF.h>
+#else
+# include "libbladeRF_nios_compat.h"
+#endif
+
+#include <stdint.h>
+
+/* This file defines the Host <-> FPGA (NIOS II) packet formats for
+ * retune2 messages. This packet is formatted, as follows. All values are
+ * little-endian.
+ *
+ * Request
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | 64-bit timestamp denoting when to retune. (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 9 | 16-bit Nios fast lock profile number to load (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 11 | 8-bit RFFE fast lock profile slot to use |
+ * +----------------+---------------------------------------------------------+
+ * | 12 | Bit 7: RX bit (set if this is an RX profile |
+ * | | Bits 6: TX output port selection |
+ * | | Bits [5:0]: RX input port selection |
+ * +----------------+---------------------------------------------------------+
+ * | 13 | Bits [7:6]: External TX2 SPDT switch setting |
+ * | | Bits [5:4]: External TX1 SPDT switch setting |
+ * | | Bits [3:2]: External RX2 SPDT switch setting |
+ * | | Bits [1:0]: External RX1 SPDT switch setting |
+ * +----------------+---------------------------------------------------------+
+ * | 14-15 | 8-bit reserved words. Should be set to 0x00. |
+ * +----------------+---------------------------------------------------------+
+ *
+ * (Note 1) Special Timestamp Values:
+ *
+ * Tune "Now": 0x0000000000000000
+ * Clear Retune Queue: 0xffffffffffffffff
+ *
+ * When the "Clear Retune Queue" value is used, all of the other tuning
+ * parameters are ignored.
+ *
+ * (Note 2) Packed as follows:
+ *
+ * +================+=======================+
+ * | Byte offset | (MSB) Value (LSB)|
+ * +================+=======================+
+ * | 0 | NIOS_PROFILE[7:0] |
+ * +----------------+-----------------------+
+ * | 1 | NIOS_PROFILE[15:8] |
+ * +----------------+-----------------------+
+ *
+ */
+
+#define NIOS_PKT_RETUNE2_IDX_MAGIC 0
+#define NIOS_PKT_RETUNE2_IDX_TIME 1
+#define NIOS_PKT_RETUNE2_IDX_NIOS_PROFILE 9
+#define NIOS_PKT_RETUNE2_IDX_RFFE_PROFILE 11
+#define NIOS_PKT_RETUNE2_IDX_RFFE_PORT 12
+#define NIOS_PKT_RETUNE2_IDX_SPDT 13
+#define NIOS_PKT_RETUNE2_IDX_RESV 14
+
+#define NIOS_PKT_RETUNE2_MAGIC 'U'
+
+/* Specify this value instead of a timestamp to clear the retune2 queue */
+#define NIOS_PKT_RETUNE2_CLEAR_QUEUE ((uint64_t) -1)
+
+/* Denotes that the retune2 should not be scheduled - it should occur "now" */
+#define NIOS_PKT_RETUNE2_NOW ((uint64_t) 0x00)
+
+/* The IS_RX bit embedded in the 'port' parameter of the retune2 packet */
+#define NIOS_PKT_RETUNE2_PORT_IS_RX_MASK (0x1 << 7)
+
+/* Pack the retune2 request buffer with the provided parameters */
+static inline void nios_pkt_retune2_pack(uint8_t *buf,
+ bladerf_module module,
+ uint64_t timestamp,
+ uint16_t nios_profile,
+ uint8_t rffe_profile,
+ uint8_t port,
+ uint8_t spdt)
+{
+ uint8_t pkt_port;
+
+ /* Clear the IS_RX bit of the port parameter */
+ pkt_port = (port & (~NIOS_PKT_RETUNE2_PORT_IS_RX_MASK));
+
+ /* Set the IS_RX bit (if needed) */
+ pkt_port = (pkt_port | (BLADERF_CHANNEL_IS_TX(module) ? 0x0 :
+ NIOS_PKT_RETUNE2_PORT_IS_RX_MASK)) & 0xff;
+
+ buf[NIOS_PKT_RETUNE2_IDX_MAGIC] = NIOS_PKT_RETUNE2_MAGIC;
+
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 0] = (timestamp >> 0) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 1] = (timestamp >> 8) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 2] = (timestamp >> 16) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 3] = (timestamp >> 24) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 4] = (timestamp >> 32) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 5] = (timestamp >> 40) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 6] = (timestamp >> 48) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_TIME + 7] = (timestamp >> 56) & 0xff;
+
+ buf[NIOS_PKT_RETUNE2_IDX_NIOS_PROFILE + 0] = (nios_profile >> 0) & 0xff;
+ buf[NIOS_PKT_RETUNE2_IDX_NIOS_PROFILE + 1] = (nios_profile >> 8) & 0xff;
+
+ buf[NIOS_PKT_RETUNE2_IDX_RFFE_PROFILE] = rffe_profile & 0xff;
+
+ buf[NIOS_PKT_RETUNE2_IDX_RFFE_PORT] = pkt_port;
+
+ buf[NIOS_PKT_RETUNE2_IDX_SPDT] = spdt & 0xff;
+
+ buf[NIOS_PKT_RETUNE2_IDX_RESV + 0] = 0x00;
+ buf[NIOS_PKT_RETUNE2_IDX_RESV + 1] = 0x00;
+}
+
+/* Unpack a retune request */
+static inline void nios_pkt_retune2_unpack(const uint8_t *buf,
+ bladerf_module *module,
+ uint64_t *timestamp,
+ uint16_t *nios_profile,
+ uint8_t *rffe_profile,
+ uint8_t *port,
+ uint8_t *spdt)
+{
+ *timestamp = ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 0]) << 0 );
+ *timestamp |= ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 1]) << 8 );
+ *timestamp |= ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 2]) << 16 );
+ *timestamp |= ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 3]) << 24 );
+ *timestamp |= ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 4]) << 32 );
+ *timestamp |= ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 5]) << 40 );
+ *timestamp |= ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 6]) << 48 );
+ *timestamp |= ( ((uint64_t)buf[NIOS_PKT_RETUNE2_IDX_TIME + 7]) << 56 );
+
+ *nios_profile = ( ((uint16_t)buf[NIOS_PKT_RETUNE2_IDX_NIOS_PROFILE + 0])
+ << 0 );
+ *nios_profile |= ( ((uint16_t)buf[NIOS_PKT_RETUNE2_IDX_NIOS_PROFILE + 1])
+ << 8 );
+
+ *rffe_profile = buf[NIOS_PKT_RETUNE2_IDX_RFFE_PROFILE];
+
+ *port = buf[NIOS_PKT_RETUNE2_IDX_RFFE_PORT];
+
+ *spdt = buf[NIOS_PKT_RETUNE2_IDX_SPDT];
+
+ *module = ( (buf[NIOS_PKT_RETUNE2_IDX_RFFE_PORT] &
+ NIOS_PKT_RETUNE2_PORT_IS_RX_MASK) ? BLADERF_MODULE_RX :
+ BLADERF_MODULE_TX );
+
+}
+
+
+/*
+ * Response
+ * ----------------------
+ *
+ * +================+=========================================================+
+ * | Byte offset | Description |
+ * +================+=========================================================+
+ * | 0 | Magic Value |
+ * +----------------+---------------------------------------------------------+
+ * | 1 | 64-bit duration denoting how long the operation took to |
+ * | | complete, in units of timestamp ticks. (Note 1) |
+ * +----------------+---------------------------------------------------------+
+ * | 9 | Status Flags (Note 2) |
+ * +----------------+---------------------------------------------------------+
+ * | 10-15 | Reserved. All bits set to 0. |
+ * +----------------+---------------------------------------------------------+
+ *
+ * (Note 1) This value will be zero if timestamps are not running for the
+ * associated module.
+ *
+ * (Note 2) Description of Status Flags:
+ *
+ * flags[0]: 1 = Timestamp is valid. This is only the case for "Tune NOW"
+ * requests. It is not possible to return this information
+ * for scheduled retunes, as the event generally does not
+ * occur before the response is set.
+ *
+ * 0 = This was a scheduled retune. Timestamp fields should be
+ * ignored.
+ *
+ * flags[1]: 1 = Operation completed successfully.
+ * 0 = Operation failed.
+ *
+ * For "Tune NOW" requests, a failure may occur as the result
+ * of the tuning algorithm failing to occur, and such other
+ * unexpected failurs.
+ *
+ * The scheduled tune request will failure if the retune queue
+ * is full.
+ *
+ * flags[7:2] Reserved. Set to 0.
+ */
+
+#define NIOS_PKT_RETUNE2_RESP_IDX_MAGIC 0
+#define NIOS_PKT_RETUNE2_RESP_IDX_TIME 1
+#define NIOS_PKT_RETUNE2_RESP_IDX_FLAGS 9
+#define NIOS_PKT_RETUNE2_RESP_IDX_RESV 10
+
+#define NIOS_PKT_RETUNE2_RESP_FLAG_TSVTUNE_VALID (1 << 0)
+#define NIOS_PKT_RETUNE2_RESP_FLAG_SUCCESS (1 << 1)
+
+static inline void nios_pkt_retune2_resp_pack(uint8_t *buf,
+ uint64_t duration,
+ uint8_t flags)
+{
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_MAGIC] = NIOS_PKT_RETUNE2_MAGIC;
+
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 0] = duration & 0xff;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 1] = (duration >> 8) & 0xff;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 2] = (duration >> 16) & 0xff;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 3] = (duration >> 24) & 0xff;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 4] = (duration >> 32) & 0xff;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 5] = (duration >> 40) & 0xff;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 6] = (duration >> 48) & 0xff;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 7] = (duration >> 56) & 0xff;
+
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_FLAGS] = flags;
+
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_RESV + 0] = 0x00;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_RESV + 1] = 0x00;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_RESV + 2] = 0x00;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_RESV + 3] = 0x00;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_RESV + 4] = 0x00;
+ buf[NIOS_PKT_RETUNE2_RESP_IDX_RESV + 5] = 0x00;
+}
+
+static inline void nios_pkt_retune2_resp_unpack(const uint8_t *buf,
+ uint64_t *duration,
+ uint8_t *flags)
+{
+ *duration = buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 0];
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 1]) << 8;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 2]) << 16;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 3]) << 24;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 4]) << 32;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 5]) << 40;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 6]) << 48;
+ *duration |= ((uint64_t) buf[NIOS_PKT_RETUNE2_RESP_IDX_TIME + 7]) << 56;
+
+ *flags = buf[NIOS_PKT_RETUNE2_RESP_IDX_FLAGS];
+}
+
+#endif