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:
parent
810b1259f8
commit
dbe4e4e472
2 changed files with 172 additions and 14 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue