Skip to content

Commit

Permalink
soapy: Use std functions in LT7182S
Browse files Browse the repository at this point in the history
soapy: Check DDR3 init and calibration
soapy: Use new ioctl numbers
soapy: Start new DMA buffer management implementation
soapy: Move utility functions
soapy: Misc changes

Signed-off-by: João Silva <jgc3silva@gmail.com>
  • Loading branch information
vankxr committed Jun 1, 2024
1 parent 33e4dd4 commit 6876e03
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 200 deletions.
20 changes: 20 additions & 0 deletions software/soapy/src/DMAMemoryManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "DMAMemoryManager.hpp"

DMAMemoryManager::DMAMemoryManager(int fd, AXIPCIe *axi_pcie)
{
this->fd = fd;
this->axi_pcie = axi_pcie;
}
DMAMemoryManager::~DMAMemoryManager()
{
this->deinit();
}

void DMAMemoryManager::init()
{

}
void DMAMemoryManager::deinit()
{

}
117 changes: 9 additions & 108 deletions software/soapy/src/LT7182S.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,100 +8,6 @@ static const float EAmp_GM_LUT[2][8] = {
{150.f, 300.f, 450.f, 600.f, 750.f, 900.f, 1050.f, 1200.f} // Low VOUT Mode
};

float LT7182S::Pow2(int8_t e)
{
switch(e)
{
case -16:
return 0.0000152587890625f;
case -15:
return 0.000030517578125f;
case -14:
return 0.00006103515625f;
case -13:
return 0.0001220703125f;
case -12:
return 0.000244140625f;
case -11:
return 0.00048828125f;
case -10:
return 0.0009765625f;
case -9:
return 0.001953125f;
case -8:
return 0.00390625f;
case -7:
return 0.0078125f;
case -6:
return 0.015625f;
case -5:
return 0.03125f;
case -4:
return 0.0625f;
case -3:
return 0.125f;
case -2:
return 0.25f;
case -1:
return 0.5f;
case 0:
return 1.f;
case 1:
return 2.f;
case 2:
return 4.f;
case 3:
return 8.f;
case 4:
return 16.f;
case 5:
return 32.f;
case 6:
return 64.f;
case 7:
return 128.f;
case 8:
return 256.f;
case 9:
return 512.f;
case 10:
return 1024.f;
case 11:
return 2048.f;
case 12:
return 4096.f;
case 13:
return 8192.f;
case 14:
return 16384.f;
case 15:
return 32768.f;
}

return 0.f;
}
uint8_t LT7182S::FindClosest(float val, const float *arr, uint8_t size)
{
if(arr == nullptr || size == 0)
throw std::runtime_error("LT7182S: Invalid array");

uint8_t idx = 0;
float diff = ABS(val - arr[0]);

for(uint8_t i = 1; i < size; i++)
{
float _diff = ABS(val - arr[i]);

if(_diff < diff)
{
idx = i;
diff = _diff;
}
}

return idx;
}

void LT7182S::ISR(void *_this)
{
if(_this == nullptr)
Expand Down Expand Up @@ -166,27 +72,22 @@ void LT7182S::writeDWord(uint8_t cmd, uint32_t data)
void LT7182S::writeL11(uint8_t cmd, float data)
{
int8_t exp = -16;
int32_t mant = (int32_t)(data / LT7182S::Pow2(exp));
int32_t mant = (int32_t)(data / std::pow(2.f, exp));

// Search for an exponent that produces valid 11-bit mantissa
do
{
if(mant >= -1024 && mant <= 1023)
break;

mant = (int32_t)(data / LT7182S::Pow2(++exp));
exp++;
mant = (int32_t)(data / (exp >= 0 ? (1 << exp) : std::pow(2.f, exp)));
} while(exp < 15);

if(mant < -1024 || mant > 1023)
throw std::runtime_error("LT7182S: Invalid L11 mantissa");

if(exp < -16 || exp > 15)
throw std::runtime_error("LT7182S: Invalid L11 exponent");

uint16_t exp16 = exp << 11;
uint16_t mant16 = mant & 0x07FF;

this->writeWord(cmd, exp16 | mant16);
this->writeWord(cmd, ((uint16_t)exp << 11) | (mant & 0x07FF));
}
void LT7182S::writeUL16(uint8_t cmd, float data)
{
Expand Down Expand Up @@ -259,7 +160,7 @@ float LT7182S::readL11(uint8_t cmd)
if(data & BIT(10))
mant = -1 * (mant ^ 0x7FF) - 1;

return (float)mant * LT7182S::Pow2(exp);
return (float)mant * (exp >= 0 ? (1 << exp) : std::pow(2.f, exp));
}
float LT7182S::readUL16(uint8_t cmd)
{
Expand Down Expand Up @@ -793,11 +694,11 @@ void LT7182S::setChannelPWMConfig(LT7182S::ChanPWMConfig config, LT7182S::Chan c
if(config.fcm_at_toff)
reg |= BIT(2);

reg |= (LT7182S::FindClosest(config.rith, R_ITH_LUT, 8) << 3) & 0x0038;
reg |= (Utils::FindClosestIndex<float>(R_ITH_LUT, 8, config.rith) << 3) & 0x0038;
reg |= (((uint8_t)(config.cith / 10.f) - 1) << 6) & 0x01C0;
reg |= (LT7182S::FindClosest(config.neg_ilim, Neg_ILim_LUT, 4) << 9) & 0x0600;
reg |= (LT7182S::FindClosest(config.pos_ilim, Pos_ILim_LUT, 4) << 9) & 0x0600;
reg |= (LT7182S::FindClosest(config.ea_gm, EAmp_GM_LUT[config.low_vout_mode ? 1 : 0], 8) << 11) & 0x3800;
reg |= (Utils::FindClosestIndex<float>(Neg_ILim_LUT, 4, config.neg_ilim) << 9) & 0x0600;
reg |= (Utils::FindClosestIndex<float>(Pos_ILim_LUT, 4, config.pos_ilim) << 9) & 0x0600;
reg |= (Utils::FindClosestIndex<float>(EAmp_GM_LUT[config.low_vout_mode ? 1 : 0], 8, config.ea_gm) << 11) & 0x3800;

std::lock_guard<std::recursive_mutex> lock(this->mutex);

Expand Down
64 changes: 39 additions & 25 deletions software/soapy/src/SoapyIcyRadio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,19 +160,23 @@ void SoapyIcyRadio::setupMemoryMaps()
this->axi_ad9361 = new AXIAD9361(this->mm_axi_periph->getVirt(AXI_AD9361_BASE));

// Allocate DMA buffer memory
uint32_t dma_sz = ICYRADIO_DEFAULT_TOTAL_DMA_POOL_SIZE_BYTES; // TODO: make this configurable
icyradio_ioctl_dma_buffer_t arg = {
.ullPhysAddr = 0,
.ulSize = ICYRADIO_DEFAULT_TOTAL_DMA_POOL_SIZE_BYTES // TODO: make this configurable
};

DLOGF(SOAPY_SDR_DEBUG, "Allocating DMA buffer pool of %u bytes", dma_sz);
DLOGF(SOAPY_SDR_DEBUG, "Allocating DMA buffer pool of %u bytes", arg.ulSize);

uint64_t arg = dma_sz;

ioctl(this->fd, ICYRADIO_IOCTL_DMA_FREE); // TODO: Implement getting an existing buffer
ioctl(this->fd, ICYRADIO_IOCTL_DMA_FREE_ALL); // TODO: Implement getting an existing buffer

if(ioctl(this->fd, ICYRADIO_IOCTL_DMA_ALLOC, &arg) < 0)
throw std::runtime_error("Could not allocate DMA buffer memory (" + std::string(std::strerror(errno)) + ")");

if(arg.ulSize != ICYRADIO_DEFAULT_TOTAL_DMA_POOL_SIZE_BYTES)
DLOGF(SOAPY_SDR_WARNING, "Requested DMA buffer of length %u bytes, actually got %u bytes!", ICYRADIO_DEFAULT_TOTAL_DMA_POOL_SIZE_BYTES, arg.ulSize);

// Map DMA buffer memory
this->mm_dma_buffer = new MappedRegion(this->fd, arg | BIT(48), dma_sz);
this->mm_dma_buffer = new MappedRegion(this->fd, arg.ullPhysAddr | BIT(48), arg.ulSize);

DLOGF(SOAPY_SDR_TRACE, "DMA Buffer: Phys = %016llX, Virt = %016llX, Size = %016llX", this->mm_dma_buffer->getPhys() & (BIT(48) - 1), this->mm_dma_buffer->getVirt(), this->mm_dma_buffer->getSize());
}
Expand Down Expand Up @@ -311,7 +315,7 @@ void SoapyIcyRadio::freeMemoryMaps()
this->mm_dma_buffer = nullptr;
}

ioctl(this->fd, ICYRADIO_IOCTL_DMA_FREE);
ioctl(this->fd, ICYRADIO_IOCTL_DMA_FREE_ALL);
}

void SoapyIcyRadio::initPeripheralsPreClocks()
Expand Down Expand Up @@ -1123,7 +1127,7 @@ void SoapyIcyRadio::initPeripheralsPostClocks()
this->mmw_synth->setLockDetectPrecision(IDT8V97003::LDPrecision::LD_PREC_1p0ns);

this->mmw_synth->configReferenceInput(this->clk_mngr->getClockFrequency(Si5351::ClockOutput::CLK_SYNTH_REF_CLK), false);
this->mmw_synth->configPFD(250000000UL, IDT8V97003::PFDPulseWidth::PFD_PW_260ps);
this->mmw_synth->configPFD(250e6, IDT8V97003::PFDPulseWidth::PFD_PW_260ps);

this->mmw_synth->setLoopFilter(
{
Expand All @@ -1143,7 +1147,7 @@ void SoapyIcyRadio::initPeripheralsPostClocks()
this->mmw_synth->setRFOutputPower(IDT8V97003::RFOutput::RFOUT_A, 12);
this->mmw_synth->setRFOutputPower(IDT8V97003::RFOutput::RFOUT_B, 12);

// this->mmw_synth->setFrequency(6000000000ULL); // 8 GHz
this->mmw_synth->setFrequency(8e9); // 8 GHz

{
DLOGF(SOAPY_SDR_DEBUG, "mmWave Synth:");
Expand Down Expand Up @@ -1179,16 +1183,16 @@ void SoapyIcyRadio::initPeripheralsPostClocks()
DLOGF(SOAPY_SDR_TRACE, " Phase Margin: %.3f deg", lfr.phase_margin);
DLOGF(SOAPY_SDR_TRACE, " Target Loop Bandwidth: %.3f kHz", this->mmw_synth->getTargetLoopBandwidth() * 1e-3);

// DLOGF(SOAPY_SDR_DEBUG, " VCO Frequency: %.6f MHz", this->mmw_synth->getVCOFrequency() * 1e-6);
// DLOGF(SOAPY_SDR_DEBUG, " Output Frequency: %.6f MHz", this->mmw_synth->getFrequency() * 1e-6);
DLOGF(SOAPY_SDR_DEBUG, " VCO Frequency: %.6f MHz", this->mmw_synth->getVCOFrequency() * 1e-6);
DLOGF(SOAPY_SDR_DEBUG, " Output Frequency: %.6f MHz", this->mmw_synth->getFrequency() * 1e-6);

// double dist = 0;
// bool frac = this->mmw_synth->isFeedbackDividerFractional(dist);
double dist = 0;
bool frac = this->mmw_synth->isFeedbackDividerFractional(dist);

// if(frac)
// DLOGF(SOAPY_SDR_DEBUG, " Distance to integer boundary: %.6f %%", dist * 100);
// else
// DLOGF(SOAPY_SDR_DEBUG, " PLL in integer mode");
if(frac)
DLOGF(SOAPY_SDR_DEBUG, " Distance to integer boundary: %.6f %%", dist * 100);
else
DLOGF(SOAPY_SDR_DEBUG, " PLL in integer mode");
}

this->mmw_synth->powerDown();
Expand Down Expand Up @@ -1224,7 +1228,7 @@ void SoapyIcyRadio::initClocks()
// Inputs
DLOGF(SOAPY_SDR_DEBUG, "Clock Inputs:");

this->clk_mngr->configXTAL(26000000UL, Si5351::XTALCapacitance::C_10pF);
this->clk_mngr->configXTAL(26e6, Si5351::XTALCapacitance::C_10pF);

uint32_t timeout = 500;
while(--timeout && !this->clk_mngr->isXTALDetected())
Expand Down Expand Up @@ -1270,7 +1274,7 @@ void SoapyIcyRadio::initClocks()
//// PLLA
DLOGF(SOAPY_SDR_DEBUG, " PLL A:");

this->clk_mngr->configPLL(Si5351::PLL::PLLA, 650000000UL, this->config.use_clkin ? Si5351::PLLSource::PLL_SRC_CLKIN : Si5351::PLLSource::PLL_SRC_XTAL, false);
this->clk_mngr->configPLL(Si5351::PLL::PLLA, 650e6, this->config.use_clkin ? Si5351::PLLSource::PLL_SRC_CLKIN : Si5351::PLLSource::PLL_SRC_XTAL, false);

timeout = 500;
while(--timeout && !this->clk_mngr->isPLLLocked(Si5351::PLL::PLLA))
Expand All @@ -1295,7 +1299,7 @@ void SoapyIcyRadio::initClocks()
//// PLLB
DLOGF(SOAPY_SDR_DEBUG, " PLL B:");

this->clk_mngr->configPLL(Si5351::PLL::PLLB, 780000000UL, this->config.use_clkin ? Si5351::PLLSource::PLL_SRC_CLKIN : Si5351::PLLSource::PLL_SRC_XTAL, false);
this->clk_mngr->configPLL(Si5351::PLL::PLLB, 780e6, this->config.use_clkin ? Si5351::PLLSource::PLL_SRC_CLKIN : Si5351::PLLSource::PLL_SRC_XTAL, false);

timeout = 500;
while(--timeout && !this->clk_mngr->isPLLLocked(Si5351::PLL::PLLB))
Expand All @@ -1322,7 +1326,7 @@ void SoapyIcyRadio::initClocks()
//// FPGA Clock #0
DLOGF(SOAPY_SDR_DEBUG, " Clock #%hhu (FPGA_CLK0):", Si5351::ClockOutput::CLK_FPGA_CLK0);

this->clk_mngr->configClock(Si5351::ClockOutput::CLK_FPGA_CLK0, 50000000UL, 0.f, Si5351::PLL::PLLA, false);
this->clk_mngr->configClock(Si5351::ClockOutput::CLK_FPGA_CLK0, 50e6, 0.f, Si5351::PLL::PLLA, false);
this->clk_mngr->setClockDisableState(Si5351::ClockOutput::CLK_FPGA_CLK0, Si5351::ClockOutputDisableState::LOW);
this->clk_mngr->setClockDriveCurrent(Si5351::ClockOutput::CLK_FPGA_CLK0, Si5351::ClockOutputDriveCurrent::I_4mA);
this->clk_mngr->setClockOutputEnableMode(Si5351::ClockOutput::CLK_FPGA_CLK0, true); // Controlled by OE pin
Expand All @@ -1347,7 +1351,7 @@ void SoapyIcyRadio::initClocks()
//// FPGA Clock #1
DLOGF(SOAPY_SDR_DEBUG, " Clock #%hhu (FPGA_CLK1):", Si5351::ClockOutput::CLK_FPGA_CLK1);

this->clk_mngr->configClock(Si5351::ClockOutput::CLK_FPGA_CLK1, 49152000UL, 0.f, Si5351::PLL::PLLA, false);
this->clk_mngr->configClock(Si5351::ClockOutput::CLK_FPGA_CLK1, 49.152e6, 0.f, Si5351::PLL::PLLA, false);
this->clk_mngr->setClockDisableState(Si5351::ClockOutput::CLK_FPGA_CLK1, Si5351::ClockOutputDisableState::LOW);
this->clk_mngr->setClockDriveCurrent(Si5351::ClockOutput::CLK_FPGA_CLK1, Si5351::ClockOutputDriveCurrent::I_4mA);
this->clk_mngr->setClockOutputEnableMode(Si5351::ClockOutput::CLK_FPGA_CLK1, true); // Controlled by OE pin
Expand Down Expand Up @@ -1422,7 +1426,7 @@ void SoapyIcyRadio::initClocks()
//// Transceiver Reference clock
DLOGF(SOAPY_SDR_DEBUG, " Clock #%hhu (TRX_REF_CLK):", Si5351::ClockOutput::CLK_TRX_REF_CLK);

this->clk_mngr->configClock(Si5351::ClockOutput::CLK_TRX_REF_CLK, 39000000UL, 0.f, Si5351::PLL::PLLB, false);
this->clk_mngr->configClock(Si5351::ClockOutput::CLK_TRX_REF_CLK, 39e6, 0.f, Si5351::PLL::PLLB, false);
this->clk_mngr->setClockDisableState(Si5351::ClockOutput::CLK_TRX_REF_CLK, Si5351::ClockOutputDisableState::LOW);
this->clk_mngr->setClockDriveCurrent(Si5351::ClockOutput::CLK_TRX_REF_CLK, Si5351::ClockOutputDriveCurrent::I_4mA);
this->clk_mngr->setClockOutputEnableMode(Si5351::ClockOutput::CLK_TRX_REF_CLK, true); // Controlled by OE pin
Expand All @@ -1447,7 +1451,7 @@ void SoapyIcyRadio::initClocks()
//// mmWave Synthesizer Reference clock
DLOGF(SOAPY_SDR_DEBUG, " Clock #%hhu (SYNTH_REF_CLK):", Si5351::ClockOutput::CLK_SYNTH_REF_CLK);

this->clk_mngr->configClock(Si5351::ClockOutput::CLK_SYNTH_REF_CLK, 25000000UL, 0.f, Si5351::PLL::PLLA, false);
this->clk_mngr->configClock(Si5351::ClockOutput::CLK_SYNTH_REF_CLK, 25e6, 0.f, Si5351::PLL::PLLA, false);
this->clk_mngr->setClockDisableState(Si5351::ClockOutput::CLK_SYNTH_REF_CLK, Si5351::ClockOutputDisableState::LOW);
this->clk_mngr->setClockDriveCurrent(Si5351::ClockOutput::CLK_SYNTH_REF_CLK, Si5351::ClockOutputDriveCurrent::I_8mA);
this->clk_mngr->setClockOutputEnableMode(Si5351::ClockOutput::CLK_SYNTH_REF_CLK, true); // Controlled by OE pin
Expand All @@ -1472,7 +1476,7 @@ void SoapyIcyRadio::initClocks()
//// External clock output (on frontend interface pin 2_3)
// DLOGF(SOAPY_SDR_DEBUG, " Clock #%hhu (EXT_CLK_2_3):", Si5351::ClockOutput::CLK_EXT_CLK_2_3);

// this->clk_mngr->configClock(Si5351::ClockOutput::CLK_EXT_CLK_2_3, 10000000UL, 0.f, Si5351::PLL::PLL_AUTO, false);
// this->clk_mngr->configClock(Si5351::ClockOutput::CLK_EXT_CLK_2_3, 10e6, 0.f, Si5351::PLL::PLL_AUTO, false);
// this->clk_mngr->setClockDisableState(Si5351::ClockOutput::CLK_EXT_CLK_2_3, Si5351::ClockOutputDisableState::LOW);
// this->clk_mngr->setClockDriveCurrent(Si5351::ClockOutput::CLK_EXT_CLK_2_3, Si5351::ClockOutputDriveCurrent::I_8mA);
// this->clk_mngr->setClockOutputEnableMode(Si5351::ClockOutput::CLK_EXT_CLK_2_3, true); // Controlled by OE pin
Expand Down Expand Up @@ -1570,6 +1574,16 @@ void SoapyIcyRadio::initClocks()
else
DLOGF(SOAPY_SDR_DEBUG, "FPGA DDR3 AXI interface reset released!");

// Check DDR3 init & calib done
timeout = 500;
while(--timeout && !this->axi_gpio[AXI_GPIO_SYS_INST]->getValue(AXI_GPIO_MIG_INIT_CALIB_COMPLETE_BIT))
std::this_thread::sleep_for(std::chrono::milliseconds(1));

if(!this->axi_gpio[AXI_GPIO_SYS_INST]->getValue(AXI_GPIO_MIG_INIT_CALIB_COMPLETE_BIT))
throw std::runtime_error("FPGA DDR3 initialization and/or calibration failed, aborting!");
else
DLOGF(SOAPY_SDR_DEBUG, "FPGA DDR3 initialized and calibrated!");

// De-assert I2S Core reset
this->axi_gpio[AXI_GPIO_SYS_INST]->setValue(AXI_GPIO_RST_FPGA_CLK1_49M152_AUX_RESET_IN_BIT, AXIGPIO::Value::LOW);

Expand Down
25 changes: 25 additions & 0 deletions software/soapy/src/include/DMAMemoryManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <cstdint>
#include <string>
#include <vector>
#include <mutex>
#include "ioctl.hpp"
#include "AXIPCIe.hpp"
#include "MappedRegion.hpp"

class DMAMemoryManager
{
public:
DMAMemoryManager(int fd, AXIPCIe *axi_pcie);
~DMAMemoryManager();

void init();
void deinit();

private:
int fd;
AXIPCIe *axi_pcie;

std::mutex mutex;
};
4 changes: 1 addition & 3 deletions software/soapy/src/include/LT7182S.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstdint>
#include <string>
#include <cmath>
#include <sstream>
#include <iomanip>
#include <thread>
Expand Down Expand Up @@ -74,9 +75,6 @@ class LT7182S
};

private:
static float Pow2(int8_t e);
static uint8_t FindClosest(float val, const float *arr, uint8_t size);

static void ISR(void *_this);
void handleIRQ();

Expand Down
Loading

0 comments on commit 6876e03

Please sign in to comment.