mirror of
https://github.com/fairwaves/UHD-Fairwaves.git
synced 2025-11-03 13:33:15 +00:00
Add PA control logic
This commit is contained in:
@@ -227,6 +227,13 @@ NET "AUX_XX" LOC = AA6; // empty awhile
|
||||
NET "AUX_SCL" LOC = AB7;// I2C clock (teperature sensor etc.)
|
||||
NET "AUX_SDA" LOC = AB10;// I2C data (teperature sensor etc.)
|
||||
|
||||
## PA control
|
||||
NET "ENPA2" LOC = AB21;
|
||||
NET "ENPA1" LOC = AA21;
|
||||
NET "LOWPA" LOC = Y12;
|
||||
#NET "DC_SYNC" LOC = AA6;
|
||||
|
||||
|
||||
## LEDS
|
||||
NET "leds[1]" LOC = Y3;
|
||||
NET "leds[2]" LOC = W4;
|
||||
@@ -234,7 +241,7 @@ NET "leds[3]" LOC = AB2;
|
||||
NET "leds[4]" LOC = Y4;
|
||||
NET "leds[5]" LOC = AA2;
|
||||
NET "led_stat" LOC = AB3; // output for clock status (or something else) front panel LED !!!
|
||||
// was stupid "master clock" LED indicator
|
||||
// was stupid "master clock" LED indicator
|
||||
|
||||
### Debug // a lot changes !!!
|
||||
NET "debug[0]" LOC = D22;
|
||||
@@ -314,6 +321,11 @@ NET "TXD[1]" IOSTANDARD = LVCMOS33;// FPGA input <- FTDI input !!! in v1a was o
|
||||
NET "TXD[2]" IOSTANDARD = LVCMOS33;// FPGA input <- GPS input !!! in v1a was output !!!
|
||||
NET "TXD[3]" IOSTANDARD = LVCMOS33;
|
||||
|
||||
NET "enpa2" IOSTANDARD = LVCMOS33;
|
||||
NET "enpa1" IOSTANDARD = LVCMOS33;
|
||||
NET "lowpa" IOSTANDARD = LVCMOS33;
|
||||
#NET "DC_SYNC" IOSTANDARD = LVCMOS33;
|
||||
|
||||
NET "DivSw1_N" IOSTANDARD = LVCMOS25;
|
||||
NET "DivSw1_P" IOSTANDARD = LVCMOS25;
|
||||
NET "DivSw2_N" IOSTANDARD = LVCMOS25;
|
||||
|
||||
@@ -77,6 +77,11 @@ module u2plus_umtrx_v2
|
||||
inout AUX_SCL,
|
||||
inout AUX_SDA,
|
||||
|
||||
//PA control
|
||||
output ENPA2,
|
||||
output ENPA1,
|
||||
output LOWPA,
|
||||
|
||||
// PPS
|
||||
input PPS_IN,
|
||||
output GPS_ON,
|
||||
@@ -305,6 +310,10 @@ wire DivSw1, DivSw2;
|
||||
assign GPS_ON = 1'b1;
|
||||
assign pps = PPS_IN;
|
||||
|
||||
wire enpa2_o, enpa1_o, lowpa_o;
|
||||
OBUF enpa2_pin (.I(enpa2_o),.O(ENPA2));
|
||||
OBUF enpa1_pin (.I(enpa1_o),.O(ENPA1));
|
||||
OBUF lowpa_pin (.I(lowpa_o),.O(LOWPA));
|
||||
|
||||
umtrx_core u2p_c(
|
||||
.sys_clk (dsp_clk),
|
||||
@@ -370,6 +379,10 @@ wire DivSw1, DivSw2;
|
||||
//Diversity switches
|
||||
.DivSw1(DivSw1),
|
||||
.DivSw2(DivSw2),
|
||||
//PA control
|
||||
.enpa2(enpa2_o),
|
||||
.enpa1(enpa1_o),
|
||||
.lowpa(lowpa_o),
|
||||
`ifndef NO_EXT_FIFO
|
||||
.RAM_D_po (RAM_D_po),
|
||||
.RAM_D_pi (RAM_D_pi),
|
||||
|
||||
@@ -107,6 +107,11 @@ module umtrx_core
|
||||
input aux_ld1,
|
||||
input aux_ld2,
|
||||
|
||||
//PA control
|
||||
output enpa2,
|
||||
output enpa1,
|
||||
output lowpa,
|
||||
|
||||
`ifndef NO_EXT_FIFO
|
||||
// External RAM
|
||||
input [35:0] RAM_D_pi,
|
||||
@@ -549,7 +554,7 @@ module umtrx_core
|
||||
assign PHY_RESETn = ~phy_reset;
|
||||
|
||||
setting_reg #(.my_addr(SR_MISC+0),.width(2)) sr_lms_res
|
||||
(.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr),.in(set_data),.out(lms_res),.changed());
|
||||
(.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr),.in(set_data),.out({enpa2, enpa1, lowpa, lms_res}),.changed());
|
||||
|
||||
setting_reg #(.my_addr(SR_MISC+1),.width(1)) sr_clear_sfc
|
||||
(.clk(dsp_clk),.rst(dsp_rst),.strobe(set_stb_dsp),.addr(set_addr_dsp),.in(set_data_dsp),.changed(sfc_clear));
|
||||
|
||||
@@ -55,9 +55,11 @@ static const uhd::dict<std::string, boost::uint8_t> UMTRX_OFFSETS = boost::assig
|
||||
("tcxo-dac", 0xFF-3) // 2 bytes
|
||||
("tx2-vga1-dc-i", 0xFF-4) // 1 byte
|
||||
("tx2-vga1-dc-q", 0xFF-5) // 1 byte
|
||||
("pa_dcdc_r", 0xFF-6) // 1 byte
|
||||
("pa_low", 0xFF-7) // 1 byte
|
||||
;
|
||||
|
||||
#if 0x18 + SERIAL_LEN + NAME_MAX_LEN >= 0xFF-5
|
||||
#if 0x18 + SERIAL_LEN + NAME_MAX_LEN >= 0xFF-7
|
||||
# error EEPROM address overlap! Get a bigger EEPROM.
|
||||
#endif
|
||||
|
||||
@@ -87,6 +89,14 @@ void load_umtrx_eeprom(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
|
||||
mb_eeprom["tcxo-dac"] = uint16_bytes_to_string(
|
||||
iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["tcxo-dac"], 2)
|
||||
);
|
||||
|
||||
mb_eeprom["pa_dcdc_r"] =
|
||||
boost::lexical_cast<std::string>(unsigned(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_dcdc_r"], 1).at(0)));
|
||||
|
||||
{
|
||||
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_low"], 1).at(0));
|
||||
mb_eeprom["pa_low"] = (val==255)?"":boost::lexical_cast<std::string>(int(val));
|
||||
}
|
||||
}
|
||||
|
||||
void store_umtrx_eeprom(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
|
||||
@@ -115,4 +125,14 @@ void store_umtrx_eeprom(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
|
||||
N100_EEPROM_ADDR, UMTRX_OFFSETS["tcxo-dac"],
|
||||
string_to_uint16_bytes(mb_eeprom["tcxo-dac"])
|
||||
);
|
||||
|
||||
if (mb_eeprom.has_key("pa_dcdc_r")) iface.write_eeprom(
|
||||
N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_dcdc_r"],
|
||||
byte_vector_t(1, boost::lexical_cast<unsigned>(mb_eeprom["pa_dcdc_r"]))
|
||||
);
|
||||
|
||||
if (mb_eeprom.has_key("pa_low")) iface.write_eeprom(
|
||||
N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_dcdc_r"],
|
||||
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["pa_low"]))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -558,6 +558,13 @@ umtrx_impl::~umtrx_impl(void)
|
||||
}
|
||||
}
|
||||
|
||||
void umtrx_impl::set_pa_dcdc_r(uint8_t val)
|
||||
{
|
||||
// AD5245 control
|
||||
if (_hw_rev >= UMTRX_VER_2_3_1)
|
||||
_iface->write_i2c(BOOST_BINARY(0101100), boost::assign::list_of(0)(val));
|
||||
}
|
||||
|
||||
void umtrx_impl::set_mb_eeprom(const uhd::i2c_iface::sptr &iface, const uhd::usrp::mboard_eeprom_t &eeprom)
|
||||
{
|
||||
store_umtrx_eeprom(eeprom, *iface);
|
||||
@@ -693,8 +700,60 @@ void umtrx_impl::detect_hw_rev(const fs_path& mb_path)
|
||||
UHD_MSG(status) << this->read_dc_v(dc_sensors[i]).to_pp_string() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
_hw_rev = UMTRX_VER_2_3_1;
|
||||
_tree->create<uint8_t>(mb_path / "pa_dcdc_r")
|
||||
.subscribe(boost::bind(&umtrx_impl::set_pa_dcdc_r, this, _1));
|
||||
|
||||
const std::string pa_dcdc_r = _iface->mb_eeprom.get("pa_low", "");
|
||||
if (pa_dcdc_r.empty())
|
||||
set_pa_dcdc_r(0);
|
||||
else
|
||||
set_pa_dcdc_r(boost::lexical_cast<unsigned>(pa_dcdc_r));
|
||||
|
||||
_pa_en1 = false;
|
||||
_pa_en2 = false;
|
||||
|
||||
const std::string pa_low = _iface->mb_eeprom.get("pa_low", "");
|
||||
if (pa_low.empty())
|
||||
_pa_nlow = false;
|
||||
else
|
||||
_pa_nlow = (boost::lexical_cast<int>(pa_low) == 0);
|
||||
|
||||
_tree->create<bool>(mb_path / "pa_en1")
|
||||
.subscribe(boost::bind(&umtrx_impl::set_enpa1, this, _1));
|
||||
_tree->create<bool>(mb_path / "pa_en2")
|
||||
.subscribe(boost::bind(&umtrx_impl::set_enpa2, this, _1));
|
||||
_tree->create<bool>(mb_path / "pa_nlow")
|
||||
.subscribe(boost::bind(&umtrx_impl::set_nlow, this, _1));
|
||||
|
||||
commit_pa_state();
|
||||
UHD_MSG(status) << "PA low=`" << pa_low.c_str()
|
||||
<< "` PA dcdc_r=`" << pa_dcdc_r.c_str()
|
||||
<< "`" << std::endl;
|
||||
}
|
||||
|
||||
void umtrx_impl::commit_pa_state()
|
||||
{
|
||||
if (_hw_rev >= UMTRX_VER_2_3_1)
|
||||
_iface->poke32(U2_REG_MISC_LMS_RES, LMS1_RESET | LMS2_RESET
|
||||
| ((_pa_nlow) ? PAREG_NLOW_PA : 0)
|
||||
| ((_pa_en1) ? PAREG_ENPA1 : 0)
|
||||
| ((_pa_en2) ? PAREG_ENPA2 : 0));
|
||||
}
|
||||
|
||||
void umtrx_impl::set_enpa1(bool en)
|
||||
{
|
||||
_pa_en1 = en; commit_pa_state();
|
||||
}
|
||||
|
||||
void umtrx_impl::set_enpa2(bool en)
|
||||
{
|
||||
_pa_en2 = en; commit_pa_state();
|
||||
}
|
||||
|
||||
void umtrx_impl::set_nlow(bool en)
|
||||
{
|
||||
_pa_nlow = en; commit_pa_state();
|
||||
}
|
||||
|
||||
const char* umtrx_impl::get_hw_rev() const
|
||||
|
||||
@@ -129,6 +129,11 @@ private:
|
||||
tmp102_ctrl _temp_side_a;
|
||||
tmp102_ctrl _temp_side_b;
|
||||
|
||||
//PA control
|
||||
bool _pa_nlow;
|
||||
bool _pa_en1;
|
||||
bool _pa_en2;
|
||||
|
||||
//controls for perifs
|
||||
uhd::dict<std::string, lms6002d_ctrl::sptr> _lms_ctrl;
|
||||
|
||||
@@ -140,6 +145,7 @@ private:
|
||||
time64_core_200::sptr _time64;
|
||||
|
||||
//helper routines
|
||||
void set_pa_dcdc_r(uint8_t val);
|
||||
void set_mb_eeprom(const uhd::i2c_iface::sptr &, const uhd::usrp::mboard_eeprom_t &);
|
||||
double get_master_clock_rate(void) const { return 26e6; }
|
||||
double get_master_dsp_rate(void) const { return get_master_clock_rate()/2; }
|
||||
@@ -155,6 +161,10 @@ private:
|
||||
void set_tx_fe_corrections(const std::string &mb, const std::string &board, const double);
|
||||
void set_tcxo_dac(const umtrx_iface::sptr &, const uint16_t val);
|
||||
void detect_hw_rev(const uhd::fs_path &mb_path);
|
||||
void commit_pa_state();
|
||||
void set_enpa1(bool en);
|
||||
void set_enpa2(bool en);
|
||||
void set_nlow(bool en);
|
||||
uint16_t get_tcxo_dac(const umtrx_iface::sptr &);
|
||||
uhd::transport::zero_copy_if::sptr make_xport(const size_t which, const uhd::device_addr_t &args);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Setting register offsets
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
localparam SR_MISC = 0; // 7 regs
|
||||
localparam SR_MISC = 0; // 9 regs
|
||||
localparam SR_TIME64 = 10; // 6
|
||||
localparam SR_BUF_POOL = 16; // 4
|
||||
|
||||
@@ -123,4 +123,9 @@ localparam SR_SPI_CORE = 185; // 3
|
||||
#define LMS1_RESET (1<<0)
|
||||
#define LMS2_RESET (1<<1)
|
||||
|
||||
// Defined for the U2_REG_MISC_LMS_RES register
|
||||
#define PAREG_NLOW_PA (1<<2)
|
||||
#define PAREG_ENPA1 (1<<3)
|
||||
#define PAREG_ENPA2 (1<<4)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,3 +13,8 @@ install(TARGETS umtrx_test_chains DESTINATION bin)
|
||||
add_executable(umtrx_cal_tx_dc_offset umtrx_cal_tx_dc_offset.cpp)
|
||||
target_link_libraries(umtrx_cal_tx_dc_offset ${UMTRX_LIBRARIES})
|
||||
install(TARGETS umtrx_cal_tx_dc_offset DESTINATION bin)
|
||||
|
||||
add_executable(umtrx_pa_ctrl umtrx_pa_ctrl.cpp)
|
||||
target_link_libraries(umtrx_pa_ctrl ${UMTRX_LIBRARIES})
|
||||
install(TARGETS umtrx_pa_ctrl DESTINATION bin)
|
||||
|
||||
|
||||
110
host/utils/umtrx_pa_ctrl.cpp
Normal file
110
host/utils/umtrx_pa_ctrl.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// Copyright 2014 Fairwaves LLC
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <uhd/utils/thread_priority.hpp>
|
||||
#include <uhd/utils/safe_main.hpp>
|
||||
#include <uhd/utils/paths.hpp>
|
||||
#include <uhd/utils/algorithm.hpp>
|
||||
#include <uhd/usrp/multi_usrp.hpp>
|
||||
#include <uhd/types/sensors.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/random.hpp>
|
||||
#include <iostream>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Main
|
||||
**********************************************************************/
|
||||
int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
std::string args;
|
||||
unsigned pa_dcdc_r = 0;
|
||||
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
("help,h", "help message")
|
||||
("verbose", "enable some verbose")
|
||||
("debug_raw_data", "save raw captured signals to files")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
|
||||
("dcdc_cal,C", "Calibrate DC/DC")
|
||||
("paen1", "Enable PA1")
|
||||
("paen2", "Enable PA2")
|
||||
("padis1", "Disable PA1")
|
||||
("padis2", "Disable PA2")
|
||||
("palow", "Turn off internal DC/DC")
|
||||
("pa_dcdc_r", po::value<unsigned>(&pa_dcdc_r),"Turn on internal DC/DC")
|
||||
;
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
//print the help message
|
||||
if (vm.count("help")){
|
||||
std::cout << desc << std::endl;
|
||||
return ~0;
|
||||
}
|
||||
|
||||
//create a usrp device
|
||||
std::cout << std::endl;
|
||||
std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
|
||||
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
|
||||
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
|
||||
const uhd::fs_path mb_path = "/mboards/0";
|
||||
|
||||
if (vm.count("paen1")) {
|
||||
tree->access<bool>(mb_path / "pa_en1").set(true);
|
||||
}
|
||||
if (vm.count("paen2")) {
|
||||
tree->access<bool>(mb_path / "pa_en2").set(true);
|
||||
}
|
||||
if (vm.count("palow")) {
|
||||
tree->access<bool>(mb_path / "pa_nlow").set(false);
|
||||
}
|
||||
if (vm.count("padis1")) {
|
||||
tree->access<bool>(mb_path / "pa_en1").set(false);
|
||||
}
|
||||
if (vm.count("padis2")) {
|
||||
tree->access<bool>(mb_path / "pa_en2").set(false);
|
||||
}
|
||||
if (vm.count("pa_dcdc_r")) {
|
||||
tree->access<bool>(mb_path / "pa_nlow").set(true);
|
||||
tree->access<uint8_t>(mb_path / "pa_dcdc_r").set(pa_dcdc_r);
|
||||
}
|
||||
|
||||
if (vm.count("dcdc_cal")) {
|
||||
tree->access<bool>(mb_path / "pa_nlow").set(true);
|
||||
unsigned i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
tree->access<uint8_t>(mb_path / "pa_dcdc_r").set(i);
|
||||
usleep(100 * 1000); // Wait for value to settle
|
||||
|
||||
std::cout << "[" << std::setw(3) << i << "]="
|
||||
<< tree->access<uhd::sensor_value_t>(mb_path / "sensors" / "voltageDCOUT").get().to_pp_string().c_str()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user