aboutsummaryrefslogtreecommitdiffstats
path: root/host/tests/zbx_cpld_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/tests/zbx_cpld_test.cpp')
-rw-r--r--host/tests/zbx_cpld_test.cpp135
1 files changed, 135 insertions, 0 deletions
diff --git a/host/tests/zbx_cpld_test.cpp b/host/tests/zbx_cpld_test.cpp
new file mode 100644
index 000000000..b125e8435
--- /dev/null
+++ b/host/tests/zbx_cpld_test.cpp
@@ -0,0 +1,135 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/types/time_spec.hpp>
+#include <uhdlib/usrp/dboard/zbx/zbx_cpld_ctrl.hpp>
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+
+using namespace uhd::usrp::zbx;
+
+struct mock_reg_iface_type
+{
+ uint32_t last_addr = 0;
+ zbx_cpld_ctrl::chan_t last_chan;
+ std::map<uint32_t, uint32_t> memory;
+ uhd::time_spec_t sleep_counter = uhd::time_spec_t(0.0);
+};
+
+
+struct zbx_cpld_fixture
+{
+ zbx_cpld_fixture()
+ : cpld(
+ [&](const uint32_t addr,
+ const uint32_t data,
+ const zbx_cpld_ctrl::chan_t chan) {
+ std::cout << "[MOCKREGS] poke32(" << addr << ", " << data << ")"
+ << std::endl;
+ mock_reg_iface.last_addr = addr;
+ mock_reg_iface.last_chan = chan;
+ mock_reg_iface.memory[addr] = data;
+ },
+ [&](const uint32_t addr) -> uint32_t {
+ std::cout << "[MOCKREGS] peek32(" << addr << ") => "
+ << mock_reg_iface.memory.at(addr) << std::endl;
+ return mock_reg_iface.memory.at(addr);
+ },
+ [&](const uhd::time_spec_t& time) { mock_reg_iface.sleep_counter += time; },
+ "TEST::CPLD")
+ {
+ // nop
+ }
+
+ mock_reg_iface_type mock_reg_iface;
+ zbx_cpld_ctrl cpld;
+};
+
+
+BOOST_FIXTURE_TEST_CASE(zbx_cpld_ctrl_test, zbx_cpld_fixture)
+{
+ cpld.set_scratch(23);
+ BOOST_CHECK_EQUAL(cpld.get_scratch(), 23);
+
+ cpld.pulse_lo_sync(0, {zbx_lo_t::TX0_LO1});
+ BOOST_CHECK_EQUAL(mock_reg_iface.memory[0x1024], 1);
+ mock_reg_iface.memory[0x1024] = 0;
+ // Make sure there are no caching issues:
+ cpld.pulse_lo_sync(0, {zbx_lo_t::TX0_LO1});
+ BOOST_CHECK_EQUAL(mock_reg_iface.memory[0x1024], 1);
+ // Now all:
+ cpld.pulse_lo_sync(0,
+ {zbx_lo_t::TX0_LO1,
+ zbx_lo_t::TX0_LO2,
+ zbx_lo_t::TX1_LO1,
+ zbx_lo_t::TX1_LO2,
+ zbx_lo_t::RX0_LO1,
+ zbx_lo_t::RX0_LO2,
+ zbx_lo_t::RX1_LO1,
+ zbx_lo_t::RX1_LO2});
+ BOOST_CHECK_EQUAL(mock_reg_iface.memory[0x1024], 0xFF);
+ mock_reg_iface.memory[0x1024] = 0;
+ cpld.set_lo_sync_bypass(true);
+ BOOST_CHECK_THROW(cpld.pulse_lo_sync(0, {zbx_lo_t::TX0_LO1}), uhd::runtime_error);
+ BOOST_CHECK_EQUAL(mock_reg_iface.memory[0x1024], 0x100);
+}
+
+BOOST_FIXTURE_TEST_CASE(zbx_tx_amp_test, zbx_cpld_fixture)
+{
+ cpld.set_tx_antenna_switches(
+ 0, 0, uhd::usrp::zbx::DEFAULT_TX_ANTENNA, tx_amp::HIGHBAND);
+ BOOST_CHECK(tx_amp::HIGHBAND == cpld.get_tx_amp_settings(0, 0, false));
+ mock_reg_iface.memory[0x2000] = 0;
+ BOOST_CHECK(tx_amp::HIGHBAND == cpld.get_tx_amp_settings(0, 0, false));
+ BOOST_CHECK(tx_amp::HIGHBAND != cpld.get_tx_amp_settings(0, 0, true));
+ BOOST_CHECK(tx_amp::BYPASS == cpld.get_tx_amp_settings(0, 0, false));
+}
+
+BOOST_FIXTURE_TEST_CASE(zbx_get_set_dsa_test, zbx_cpld_fixture)
+{
+ // We only test the first table index
+ constexpr size_t dsa_table_index = 0;
+ for (const size_t chan : {0, 1}) {
+ const uint32_t tx_dsa_table_addr = 0x3000 + chan * 0x400;
+ const uint32_t rx_dsa_table_addr = 0x3800 + chan * 0x400;
+
+ auto& tx_dsa_reg = mock_reg_iface.memory[tx_dsa_table_addr];
+ auto& rx_dsa_reg = mock_reg_iface.memory[rx_dsa_table_addr];
+
+ // We'll skip DSA3A/B, because they work just like the rest and would
+ // make this test much longer and less readable without adding much test
+ // coverage.
+ for (const auto dsa :
+ {zbx_cpld_ctrl::dsa_type::DSA1, zbx_cpld_ctrl::dsa_type::DSA2}) {
+ const size_t tx_shift = (dsa == zbx_cpld_ctrl::dsa_type::DSA1) ? 0 : 8;
+ const size_t rx_shift = (dsa == zbx_cpld_ctrl::dsa_type::DSA1) ? 0 : 4;
+ // 0xB and 0xC are just random attenuation values. They are valid
+ // for both TX and RX.
+ cpld.set_tx_dsa(chan, dsa_table_index, dsa, 0xB);
+ BOOST_CHECK_EQUAL((tx_dsa_reg >> tx_shift) & 0x1F, 0xB);
+ tx_dsa_reg = 0x0C0C;
+ BOOST_CHECK_EQUAL(0xB, cpld.get_tx_dsa(chan, dsa_table_index, dsa, false));
+ BOOST_CHECK_EQUAL(0xC, cpld.get_tx_dsa(chan, dsa_table_index, dsa, true));
+
+ cpld.set_rx_dsa(chan, 0, dsa, 0xB);
+ BOOST_CHECK_EQUAL((rx_dsa_reg >> rx_shift) & 0xF, 0xB);
+ rx_dsa_reg = 0xCC;
+ BOOST_CHECK_EQUAL(0xB, cpld.get_rx_dsa(chan, dsa_table_index, dsa, false));
+ BOOST_CHECK_EQUAL(0xC, cpld.get_rx_dsa(chan, dsa_table_index, dsa, true));
+ }
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(zbx_set_from_table_test, zbx_cpld_fixture)
+{
+ constexpr uint32_t tx_sel_addr = 0x4000;
+ constexpr size_t chan = 0;
+ constexpr uint8_t idx = 2;
+
+ auto& tx_table_select = mock_reg_iface.memory[tx_sel_addr + idx * 4];
+ cpld.set_tx_gain_switches(chan, idx, 23);
+ BOOST_REQUIRE_EQUAL(tx_table_select, 23);
+}