diff options
Diffstat (limited to 'Radio/HW/BladeRF/fpga_common/include')
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/ad936x.h | 858 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/ad936x_helpers.h | 127 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/band_select.h | 50 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/bladerf2_common.h | 749 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/lms.h | 838 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_16x64.h | 218 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_32x32.h | 208 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x16.h | 213 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x32.h | 231 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x64.h | 206 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_8x8.h | 197 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_formats.h | 37 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_legacy.h | 231 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune.h | 334 | ||||
-rw-r--r-- | Radio/HW/BladeRF/fpga_common/include/nios_pkt_retune2.h | 273 |
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, ®val); + 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, ®val); + 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 |