diff options
Diffstat (limited to 'host/tests/zbx_cpld_test.cpp')
-rw-r--r-- | host/tests/zbx_cpld_test.cpp | 135 |
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); +} |