1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

add i2c configuration logic to dino IP

Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
Niklas Eiling 2024-01-08 10:44:17 +01:00 committed by Niklas Eiling
parent 810b1259f8
commit dbe4e4e472
2 changed files with 172 additions and 14 deletions

View file

@ -1,12 +1,15 @@
/* Driver for wrapper around Dino
*
* Author: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
* Author: Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
* SPDX-FileCopyrightText: 2024 Niklas Eiling
* SPDX-FileCopyrightText: 2020 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <villas/fpga/ips/i2c.hpp>
#include <villas/fpga/node.hpp>
namespace villas {
@ -15,18 +18,65 @@ namespace ip {
class Dino : public Node {
public:
static constexpr const char* masterPort = "m_axis";
static constexpr const char* slavePort = "s_axis";
union IoextPorts {
struct __attribute__((packed)) {
bool clk_dir : 1;
bool data_dir : 1;
bool status_led : 1;
bool n_we : 1; // write enable (active low)
bool input_zero : 1;
bool sat_detect : 1;
bool gain_lsb : 1;
bool gain_msb : 1;
} fields;
uint8_t raw;
};
enum Gain { GAIN_1 = 0, GAIN_2 = 1, GAIN_5 = 2, GAIN_10 = 3 };
const StreamVertex& getDefaultSlavePort() const
{
return getSlavePort(slavePort);
}
Dino();
virtual ~Dino();
void setI2c(std::shared_ptr<I2c> i2cdev, uint8_t i2c_channel) {
this->i2cdev = i2cdev;
this->i2c_channel = i2c_channel;
}
virtual void configureHardware() = 0;
const StreamVertex& getDefaultMasterPort() const
{
return getMasterPort(masterPort);
}
static constexpr const char *masterPort = "M00_AXIS";
static constexpr const char *slavePort = "S00_AXIS";
const StreamVertex &getDefaultSlavePort() const {
return getSlavePort(slavePort);
}
const StreamVertex &getDefaultMasterPort() const {
return getMasterPort(masterPort);
}
IoextPorts getIoextDir();
IoextPorts getIoextOut();
protected:
std::shared_ptr<I2c> i2cdev;
uint8_t i2c_channel;
void setIoextDir(IoextPorts ports);
void setIoextOut(IoextPorts ports);
};
class DinoAdc : public Dino {
public:
DinoAdc();
virtual ~DinoAdc();
virtual void configureHardware() override;
};
class DinoDac : public Dino {
public:
DinoDac();
virtual ~DinoDac();
virtual void configureHardware() override;
void setGain(Gain gain);
Gain getGain();
};
} // namespace ip

View file

@ -13,7 +13,115 @@
using namespace villas::fpga::ip;
static char n[] = "dino";
static char d[] = "Analog and Digital IO";
static char v[] = "xilinx.com:module_ref:dino:";
static NodePlugin<Dino, n, d, v> f;
Dino::Dino() : Node(), i2cdev(nullptr), i2c_channel(0) {}
Dino::~Dino() {}
void Dino::setIoextDir(IoextPorts ports) {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
std::vector<u8> data = {I2C_IOEXT_REG_DIR, ports.raw};
i2cdev->write(I2C_IOEXT_ADDR, data);
}
void Dino::setIoextOut(IoextPorts ports) {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
std::vector<u8> data = {I2C_IOEXT_REG_OUT, ports.raw};
i2cdev->write(I2C_IOEXT_ADDR, data);
}
Dino::IoextPorts Dino::getIoextDir() {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
std::vector<u8> data = {I2C_IOEXT_REG_DIR};
i2cdev->write(I2C_IOEXT_ADDR, data);
i2cdev->read(I2C_IOEXT_ADDR, data, 1);
IoextPorts ports;
ports.raw = data[0];
return ports;
}
Dino::IoextPorts Dino::getIoextOut() {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
std::vector<u8> data = {I2C_IOEXT_REG_OUT};
i2cdev->write(I2C_IOEXT_ADDR, data);
i2cdev->read(I2C_IOEXT_ADDR, data, 1);
IoextPorts ports;
ports.raw = data[0];
return ports;
}
DinoAdc::DinoAdc() : Dino() {}
DinoAdc::~DinoAdc() {}
void DinoAdc::configureHardware() {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
i2cdev->getSwitch().setChannel(i2c_channel);
IoextPorts ioext = {.raw = 0};
ioext.fields.sat_detect = true;
setIoextDir(ioext);
ioext.raw = 0;
ioext.fields.data_dir = true;
ioext.fields.status_led = true;
ioext.fields.n_we = true;
ioext.fields.input_zero = true;
setIoextOut(ioext);
ioext.fields.n_we = false;
setIoextOut(ioext);
}
DinoDac::DinoDac() : Dino() {}
DinoDac::~DinoDac() {}
void DinoDac::configureHardware() {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
i2cdev->getSwitch().setChannel(i2c_channel);
IoextPorts ioext = {.raw = 0};
setIoextDir(ioext);
ioext.fields.status_led = true;
setIoextOut(ioext);
setGain(GAIN_1);
}
void DinoDac::setGain(Gain gain) {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
i2cdev->getSwitch().setChannel(i2c_channel);
IoextPorts ioext = getIoextOut();
ioext.fields.gain_lsb = gain & 0x1;
ioext.fields.gain_msb = gain & 0x2;
setIoextOut(ioext);
}
Dino::Gain DinoDac::getGain() {
if (i2cdev == nullptr) {
throw RuntimeError("I2C device not set");
}
i2cdev->getSwitch().setChannel(i2c_channel);
IoextPorts ioext = getIoextOut();
return static_cast<Gain>((ioext.fields.gain_msb << 1) |
ioext.fields.gain_lsb);
}
static char n_adc[] = "DINO ADC";
static char d_adc[] = "DINO analog to digital converter";
static char v_adc[] = "xilinx.com:module_ref:dinoif_fast:";
static NodePlugin<DinoAdc, n_adc, d_adc, v_adc> f_adc;
static char n_dac[] = "DINO DAC";
static char d_dac[] = "DINO digital to analog converter";
static char v_dac[] = "xilinx.com:module_ref:dinoif_dac:";
static NodePlugin<DinoDac, n_dac, d_dac, v_dac> f_dac;