1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
//
// Copyright 2010-2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include "x300_adc_ctrl.hpp"
#include "ads62p48_regs.hpp"
#include <uhd/exception.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/utils/safe_call.hpp>
using namespace uhd;
x300_adc_ctrl::~x300_adc_ctrl(void)
{
/* NOP */
}
/*!
* A X300 codec control specific to the ads62p48 ic.
*/
class x300_adc_ctrl_impl : public x300_adc_ctrl
{
public:
x300_adc_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno)
: _iface(iface), _slaveno(slaveno)
{
init();
}
void init()
{
// power-up adc
_ads62p48_regs.reset = 1;
this->send_ads62p48_reg(0x00); // issue a reset to the ADC
_ads62p48_regs.reset = 0;
_ads62p48_regs.enable_low_speed_mode = 0;
_ads62p48_regs.ref = ads62p48_regs_t::REF_INTERNAL;
_ads62p48_regs.standby = ads62p48_regs_t::STANDBY_NORMAL;
_ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_NORMAL;
_ads62p48_regs.lvds_cmos = ads62p48_regs_t::LVDS_CMOS_DDR_LVDS;
_ads62p48_regs.channel_control = ads62p48_regs_t::CHANNEL_CONTROL_INDEPENDENT;
_ads62p48_regs.data_format = ads62p48_regs_t::DATA_FORMAT_2S_COMPLIMENT;
_ads62p48_regs.clk_out_pos_edge = ads62p48_regs_t::CLK_OUT_POS_EDGE_MINUS4_26;
_ads62p48_regs.clk_out_neg_edge = ads62p48_regs_t::CLK_OUT_NEG_EDGE_MINUS4_26;
this->send_ads62p48_reg(0);
this->send_ads62p48_reg(0x20);
this->send_ads62p48_reg(0x3f);
this->send_ads62p48_reg(0x40);
this->send_ads62p48_reg(0x41);
this->send_ads62p48_reg(0x44);
this->send_ads62p48_reg(0x50);
this->send_ads62p48_reg(0x51);
this->send_ads62p48_reg(0x52);
this->send_ads62p48_reg(0x53);
this->send_ads62p48_reg(0x55);
this->send_ads62p48_reg(0x57);
this->send_ads62p48_reg(0x62);
this->send_ads62p48_reg(0x63);
this->send_ads62p48_reg(0x66);
this->send_ads62p48_reg(0x68);
this->send_ads62p48_reg(0x6a);
this->send_ads62p48_reg(0x75);
this->send_ads62p48_reg(0x76);
}
void reset() override
{
init();
}
double set_gain(const double& gain) override
{
const meta_range_t gain_range = meta_range_t(0, 6.0, 0.5);
const int gain_bits = int((gain_range.clip(gain) * 2.0) + 0.5);
_ads62p48_regs.gain_chA = gain_bits;
_ads62p48_regs.gain_chB = gain_bits;
this->send_ads62p48_reg(0x55);
this->send_ads62p48_reg(0x68);
return gain_bits / 2;
}
void set_test_word(const std::string& patterna,
const std::string& patternb,
const uint32_t num) override
{
_ads62p48_regs.custom_pattern_low = num & 0xff;
_ads62p48_regs.custom_pattern_high = num >> 8;
if (patterna == "ones")
_ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ONES;
if (patterna == "zeros")
_ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ZEROS;
if (patterna == "custom")
_ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_CUSTOM;
if (patterna == "ramp")
_ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_RAMP;
if (patterna == "normal")
_ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_NORMAL;
if (patternb == "ones")
_ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ONES;
if (patternb == "zeros")
_ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ZEROS;
if (patternb == "custom")
_ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_CUSTOM;
if (patterna == "ramp")
_ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_RAMP;
if (patterna == "normal")
_ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_NORMAL;
this->send_ads62p48_reg(0x51);
this->send_ads62p48_reg(0x52);
this->send_ads62p48_reg(0x62);
this->send_ads62p48_reg(0x75);
}
~x300_adc_ctrl_impl(void) override
{
_ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_GLOBAL;
UHD_SAFE_CALL(this->send_ads62p48_reg(0x40);)
}
private:
ads62p48_regs_t _ads62p48_regs;
uhd::spi_iface::sptr _iface;
const size_t _slaveno;
void send_ads62p48_reg(uint8_t addr)
{
uint16_t reg = _ads62p48_regs.get_write_reg(addr);
_iface->write_spi(_slaveno, spi_config_t::EDGE_FALL, reg, 16);
}
};
/***********************************************************************
* Public make function for the ADC control
**********************************************************************/
x300_adc_ctrl::sptr x300_adc_ctrl::make(uhd::spi_iface::sptr iface, const size_t slaveno)
{
return sptr(new x300_adc_ctrl_impl(iface, slaveno));
}
|