mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
verify more assumptions in i2c
add selftest to I2c and readback Dino configuration to verify it was actually set Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
parent
335dd2c0ce
commit
60c65c2880
3 changed files with 56 additions and 6 deletions
|
@ -43,9 +43,10 @@ public:
|
|||
|
||||
class Switch {
|
||||
public:
|
||||
Switch(I2c *i2c, uint8_t address)
|
||||
: i2c(i2c), address(address), channel(0), readOnce(false),
|
||||
switchLock(){};
|
||||
Switch(I2c *i2c, uint8_t address,
|
||||
Logger logger = villas::logging.get("i2c"))
|
||||
: i2c(i2c), address(address), channel(0), readOnce(false), switchLock(),
|
||||
logger(logger){};
|
||||
Switch(const Switch &other) = delete;
|
||||
Switch &operator=(const Switch &other) = delete;
|
||||
void setChannel(uint8_t channel);
|
||||
|
@ -57,6 +58,7 @@ public:
|
|||
uint8_t getChannel();
|
||||
void setAddress(uint8_t address) { this->address = address; }
|
||||
uint8_t getAddress() { return address; }
|
||||
bool selfTest();
|
||||
|
||||
private:
|
||||
I2c *i2c;
|
||||
|
@ -64,10 +66,11 @@ public:
|
|||
uint8_t channel;
|
||||
bool readOnce;
|
||||
std::mutex switchLock;
|
||||
Logger logger;
|
||||
};
|
||||
Switch &getSwitch(uint8_t address = I2C_SWTICH_ADDR) {
|
||||
if (switchInstance == nullptr) {
|
||||
switchInstance = std::make_unique<Switch>(this, address);
|
||||
switchInstance = std::make_unique<Switch>(this, address, logger);
|
||||
} else {
|
||||
switchInstance->setAddress(address);
|
||||
}
|
||||
|
|
|
@ -87,6 +87,12 @@ void DinoAdc::configureHardware() {
|
|||
IoextPorts ioext = {.raw = 0};
|
||||
ioext.fields.sat_detect = true;
|
||||
setIoextDir(ioext);
|
||||
auto readback = getIoextDir();
|
||||
if (readback.raw != ioext.raw) {
|
||||
logger->error("Ioext direction register readback incorrect: {:#x} != {:#x}",
|
||||
readback.raw, ioext.raw);
|
||||
throw RuntimeError("Failed to set IOEXT direction register");
|
||||
}
|
||||
ioext.raw = 0;
|
||||
ioext.fields.data_dir = true;
|
||||
ioext.fields.status_led = true;
|
||||
|
@ -95,6 +101,12 @@ void DinoAdc::configureHardware() {
|
|||
setIoextOut(ioext);
|
||||
ioext.fields.n_we = false;
|
||||
setIoextOut(ioext);
|
||||
readback = getIoextOut();
|
||||
if (readback.raw != ioext.raw) {
|
||||
logger->error("Ioext output register readback incorrect: {:#x} != {:#x}",
|
||||
readback.raw, ioext.raw);
|
||||
throw RuntimeError("Failed to set IOEXT output register");
|
||||
}
|
||||
i2cdev->getSwitch().unlockChannel();
|
||||
}
|
||||
|
||||
|
@ -109,10 +121,24 @@ void DinoDac::configureHardware() {
|
|||
i2cdev->getSwitch().setAndLockChannel(i2c_channel);
|
||||
IoextPorts ioext = {.raw = 0};
|
||||
setIoextDir(ioext);
|
||||
auto readback = getIoextDir();
|
||||
if (readback.raw != ioext.raw) {
|
||||
logger->error("Ioext direction register readback incorrect: {:#x} != {:#x}",
|
||||
readback.raw, ioext.raw);
|
||||
throw RuntimeError("Failed to set IOEXT direction register");
|
||||
}
|
||||
ioext.fields.status_led = true;
|
||||
// Default gain is 1. Although not really necessary, let's be explicit here
|
||||
ioext.fields.gain_lsb = 0x00 & 0x1;
|
||||
ioext.fields.gain_msb = 0x00 & 0x2;
|
||||
setIoextOut(ioext);
|
||||
readback = getIoextOut();
|
||||
if (readback.raw != ioext.raw) {
|
||||
logger->error("Ioext output register readback incorrect: {:#x} != {:#x}",
|
||||
readback.raw, ioext.raw);
|
||||
throw RuntimeError("Failed to set IOEXT output register");
|
||||
}
|
||||
i2cdev->getSwitch().unlockChannel();
|
||||
setGain(GAIN_1);
|
||||
}
|
||||
|
||||
void DinoDac::setGain(Gain gain) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <villas/fpga/ips/i2c.hpp>
|
||||
#include <villas/fpga/ips/intc.hpp>
|
||||
#include <villas/log.hpp>
|
||||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
|
@ -220,7 +221,7 @@ void I2c::Switch::setChannel(uint8_t channel) {
|
|||
}
|
||||
|
||||
uint8_t I2c::Switch::getChannel() {
|
||||
std::vector<u8> data(1);
|
||||
std::vector<u8> data;
|
||||
int retries = 10;
|
||||
do {
|
||||
i2c->read(address, data, 1);
|
||||
|
@ -242,6 +243,26 @@ uint8_t I2c::Switch::getChannel() {
|
|||
return channel;
|
||||
}
|
||||
|
||||
bool I2c::Switch::selfTest() {
|
||||
uint8_t readback;
|
||||
logger->debug("I2c::Switch self test. Testing {} channels of device {:#x}",
|
||||
sizeof(CHANNEL_MAP) / sizeof(CHANNEL_MAP[0]), address);
|
||||
for (size_t i = 0; i < sizeof(CHANNEL_MAP) / sizeof(CHANNEL_MAP[0]); ++i) {
|
||||
logger->debug("Setting switch to channel {}, data byte {:#x}", i,
|
||||
CHANNEL_MAP[i]);
|
||||
setAndLockChannel(i);
|
||||
try {
|
||||
readback = getChannel();
|
||||
logger->debug("Readback channel: {}", readback);
|
||||
} catch (const RuntimeError &e) {
|
||||
logger->debug("Encoutered error on readback: {}", e.what());
|
||||
return false;
|
||||
}
|
||||
unlockChannel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void I2cFactory::parse(Core &ip, json_t *cfg) {
|
||||
NodeFactory::parse(ip, cfg);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue