Skip to content

Commit

Permalink
Merge pull request #29 from lsst-ts/tickets/DM-40574
Browse files Browse the repository at this point in the history
Better modbus device management
  • Loading branch information
pkubanek authored Sep 15, 2023
2 parents 28c1dc1 + 88d5b93 commit 68d4bf8
Show file tree
Hide file tree
Showing 11 changed files with 73,115 additions and 71,847 deletions.
144,622 changes: 73,005 additions & 71,617 deletions Bitfiles/NiFpga_ts_M1M3ThermalFPGA.lvbitx

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ properties(
)

node {


def SALUSER_HOME = "/home/saluser"
def BRANCH = (env.CHANGE_BRANCH != null) ? env.CHANGE_BRANCH : env.BRANCH_NAME
def SAME_CRIO_BRANCH = ["main", "tickets/DM-37923"]
def SAME_CRIO_BRANCH = ["main", "tickets/DM-40574"]

stage('Cloning sources')
{
Expand Down
5 changes: 5 additions & 0 deletions doc/version-history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Version History
###############

v0.2.0
======

* better flow meter and pump control - simplified FPGA code

v0.1.0
======

Expand Down
4 changes: 1 addition & 3 deletions src/LSST/M1M3/TS/IFPGA.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ class IFPGA : public cRIO::FPGA {
float getMixingValvePosition();
void setMixingValvePosition(float position);

virtual void getVFDError(bool& status, int32_t& code) = 0;
virtual void getFlowMeterError(bool& status, int32_t& code) = 0;
virtual float chassisTemperature() = 0;

uint32_t getSlot4DIs();

Expand All @@ -86,7 +85,6 @@ class IFPGA : public cRIO::FPGA {

void setHeartbeat(bool heartbeat);

virtual void setMPUTimeouts(LSST::cRIO::MPU& mpu, uint16_t write_timeout, uint16_t read_timeout) {}
virtual LSST::cRIO::MPUTelemetry readMPUTelemetry(LSST::cRIO::MPU& mpu) = 0;

std::shared_ptr<VFD> vfd;
Expand Down
2 changes: 2 additions & 0 deletions src/LSST/M1M3/TS/SimulatedFPGA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ void SimulatedFPGA::readU16ResponseFIFO(uint16_t* data, size_t length, uint32_t
}
}

float SimulatedFPGA::chassisTemperature() { return -5 + 5.0f * random() / RAND_MAX; }

void SimulatedFPGA::processServerID(uint8_t address, uint64_t uniqueID, uint8_t ilcAppType,
uint8_t networkNodeType, uint8_t ilcSelectedOptions,
uint8_t networkNodeOptions, uint8_t majorRev, uint8_t minorRev,
Expand Down
10 changes: 1 addition & 9 deletions src/LSST/M1M3/TS/SimulatedFPGA.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,10 @@ class SimulatedFPGA : public IFPGA, public LSST::cRIO::ThermalILC {
void readSGLResponseFIFO(float* data, size_t length, uint32_t timeout) override;
void readU8ResponseFIFO(uint8_t* data, size_t length, uint32_t timeout) override;
void readU16ResponseFIFO(uint16_t* data, size_t length, uint32_t timeout) override;
float chassisTemperature() override;
void waitOnIrqs(uint32_t irqs, uint32_t timeout, uint32_t* triggered = NULL) override {}
void ackIrqs(uint32_t irqs) override {}

void getVFDError(bool& status, int32_t& code) override {
status = false;
code = 0;
}
void getFlowMeterError(bool& status, int32_t& code) override {
status = false;
code = 0;
}

protected:
void processServerID(uint8_t address, uint64_t uniqueID, uint8_t ilcAppType, uint8_t networkNodeType,
uint8_t ilcSelectedOptions, uint8_t networkNodeOptions, uint8_t majorRev,
Expand Down
166 changes: 78 additions & 88 deletions src/LSST/M1M3/TS/ThermalFPGA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,10 @@
#include "NiFpga_ts_M1M3ThermalFPGA.h"

using namespace LSST::cRIO;
using namespace LSST::M1M3::TS;

using namespace std::chrono_literals;

namespace LSST {
namespace M1M3 {
namespace TS {

ThermalFPGA::ThermalFPGA() : IFPGA() {
SPDLOG_DEBUG("ThermalFPGA: ThermalFPGA()");
_session = 0;
Expand Down Expand Up @@ -71,75 +68,89 @@ void ThermalFPGA::finalize() {

void ThermalFPGA::writeMPUFIFO(MPU& mpu) {
auto buf = mpu.getCommandVector();
uint8_t bus = (mpu.getBus() << 4) | 1;
uint8_t bus = mpu.getBus();
uint8_t len = buf.size();
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_MPUCommandsFIFO,
&bus, 1, -1, NULL));
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_MPUCommandsFIFO,
&len, 1, -1, NULL));
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_MPUCommandsFIFO,
buf.data(), len, -1, NULL));
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_SerialMultiplexRequest,
&bus, 1, -1, NULL));
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_SerialMultiplexRequest,
&len, 1, -1, NULL));
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_SerialMultiplexRequest,
buf.data(), len, -1, NULL));
}

void ThermalFPGA::readMPUFIFO(MPU& mpu) {
uint8_t req = (mpu.getBus() << 4) | 8;
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_MPUCommandsFIFO,
&req, 1, -1, NULL));
uint8_t req = mpu.getBus() + 10;
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_SerialMultiplexRequest,
&req, 1, -1, NULL));

uint16_t len;
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_MPUResponseFIFO,
reinterpret_cast<uint8_t*>(&len), 2, 1000, NULL));
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_SerialMultiplexResponse,
reinterpret_cast<uint8_t*>(&len), 2, 1000, NULL));
len = ntohs(len);
uint8_t data[len];

NiThrowError(__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_MPUResponseFIFO,
data, len, -1, NULL));
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_SerialMultiplexResponse,
data, len, -1, NULL));
processMPUResponse(mpu, data, len);
}

void ThermalFPGA::setMPUTimeouts(MPU& mpu, uint16_t write_timeout, uint16_t read_timeout) {
struct {
uint8_t call;
uint16_t write_tmout;
uint16_t read_tmout;
} __attribute__((packed)) req;

req.call = (mpu.getBus() << 4) | 4;
req.write_tmout = htobe16(write_timeout);
req.read_tmout = htobe16(read_timeout);

NiThrowError(__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_MPUCommandsFIFO,
&(req.call), 5, -1, NULL));
}

LSST::cRIO::MPUTelemetry ThermalFPGA::readMPUTelemetry(MPU& mpu) {
uint8_t req = (mpu.getBus() << 4) | 2;
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_MPUCommandsFIFO,
&req, 1, -1, NULL));

uint16_t len;
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_MPUResponseFIFO,
reinterpret_cast<uint8_t*>(&len), 2, 1000, NULL));
len = ntohs(len);
uint8_t data[len];
uint8_t req[3] = {mpu.getBus(), 1, 254};
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_SerialMultiplexRequest,
req, 3, -1, NULL));

std::vector<uint8_t> buffer;
auto start = std::chrono::steady_clock::now();

while (buffer.size() < 16) {
uint8_t res = mpu.getBus() + 10;
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_WriteFifoU8(_session,
NiFpga_ts_M1M3ThermalFPGA_HostToTargetFifoU8_SerialMultiplexRequest,
&res, 1, -1, NULL));

uint16_t len;
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session,
NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_SerialMultiplexResponse,
reinterpret_cast<uint8_t*>(&len), 2, 1, NULL));

len = ntohs(len);
uint8_t data[len];

if (len > 0) {
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session,
NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_SerialMultiplexResponse,
data, len, 1000, NULL));

for (int i = 0; i < len; i++) {
buffer.push_back(data[i]);
}
}
}

NiThrowError(__PRETTY_FUNCTION__,
NiFpga_ReadFifoU8(_session, NiFpga_ts_M1M3ThermalFPGA_TargetToHostFifoU8_MPUResponseFIFO,
data, len, 1000, NULL));
if (len != 45) {
throw std::runtime_error(fmt::format("Invalid telemetry length - expected 45, received {}", len));
if (buffer.size() != 16) {
throw std::runtime_error(
fmt::format("Invalid telemetry length - expected 16, received {}", buffer.size()));
}

return MPUTelemetry(data);
return MPUTelemetry(buffer.data());
}

void ThermalFPGA::writeCommandFIFO(uint16_t* data, size_t length, uint32_t timeout) {
Expand Down Expand Up @@ -172,6 +183,16 @@ void ThermalFPGA::readU16ResponseFIFO(uint16_t* data, size_t length, uint32_t ti
data, length, timeout, NULL));
}

float ThermalFPGA::chassisTemperature() {
uint64_t temperature;
cRIO::NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_ReadU64(_session, NiFpga_ts_M1M3ThermalFPGA_IndicatorFxp_ChassisTemperature_Resource,
&temperature));
return NiFpga_ConvertFromFxpToFloat(NiFpga_ts_M1M3ThermalFPGA_IndicatorFxp_ChassisTemperature_TypeInfo,
temperature);
}

void ThermalFPGA::waitOnIrqs(uint32_t irqs, uint32_t timeout, uint32_t* triggered) {
static std::hash<std::thread::id> hasher;
size_t k = hasher(std::this_thread::get_id());
Expand Down Expand Up @@ -199,34 +220,3 @@ void ThermalFPGA::processMPUResponse(MPU& mpu, uint8_t* data, uint16_t len) {
}
mpu.processResponse(u16_data, len);
}

void ThermalFPGA::getVFDError(bool& status, int32_t& code) {
uint8_t packedData[NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_PackedSizeInBytes];
NiThrowError(__PRETTY_FUNCTION__,
NiFpga_ReadArrayU8(_session, NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_Resource,
packedData,
NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_PackedSizeInBytes));

NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_Type vfdError;
NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_UnpackCluster(packedData, &vfdError);
status = vfdError.status;
code = vfdError.code;
}

void ThermalFPGA::getFlowMeterError(bool& status, int32_t& code) {
uint8_t packedData[NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_PackedSizeInBytes];
NiThrowError(
__PRETTY_FUNCTION__,
NiFpga_ReadArrayU8(_session, NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_Resource,
packedData,
NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_PackedSizeInBytes));

NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_Type flowMeterError;
NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_UnpackCluster(packedData, &flowMeterError);
status = flowMeterError.status;
code = flowMeterError.code;
}

} // namespace TS
} // namespace M1M3
} // namespace LSST
4 changes: 1 addition & 3 deletions src/LSST/M1M3/TS/ThermalFPGA.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,18 @@ class ThermalFPGA : public IFPGA {
void finalize() override;
void writeMPUFIFO(cRIO::MPU& mpu) override;
void readMPUFIFO(cRIO::MPU& mpu) override;
void setMPUTimeouts(LSST::cRIO::MPU& mpu, uint16_t write_timeout, uint16_t read_timeout) override;
LSST::cRIO::MPUTelemetry readMPUTelemetry(LSST::cRIO::MPU& mpu) override;
void writeCommandFIFO(uint16_t* data, size_t length, uint32_t timeout) override;
void writeRequestFIFO(uint16_t* data, size_t length, uint32_t timeout) override;
void readSGLResponseFIFO(float* data, size_t length, uint32_t timeout) override;
void readU8ResponseFIFO(uint8_t* data, size_t length, uint32_t timeout) override;
void readU16ResponseFIFO(uint16_t* data, size_t length, uint32_t timeout) override;
float chassisTemperature() override;
void waitOnIrqs(uint32_t irqs, uint32_t timeout, uint32_t* triggered = NULL) override;
void ackIrqs(uint32_t irqs) override;

protected:
void processMPUResponse(LSST::cRIO::MPU& mpu, uint8_t* data, uint16_t len) override;
void getVFDError(bool& status, int32_t& code) override;
void getFlowMeterError(bool& status, int32_t& code) override;

private:
uint32_t _session;
Expand Down
48 changes: 0 additions & 48 deletions src/NiFpga/NiFpga_ts_M1M3ThermalFPGA.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,4 @@

#if !NiFpga_VxWorks

void NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_UnpackCluster(
const uint8_t* const packedData,
NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_Type* const destination) {
(*destination).status = 0;
(*destination).status |= ((packedData[0] >> 7) & 0x1);
(*destination).code = 0;
(*destination).code |= (packedData[0] & 0x7FULL) << 25;
(*destination).code |= (packedData[1] & 0xFF) << 17;
(*destination).code |= (packedData[2] & 0xFF) << 9;
(*destination).code |= (packedData[3] & 0xFF) << 1;
(*destination).code |= ((packedData[4] >> 7) & 0x1);
}

void NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_PackCluster(
uint8_t* const packedData,
const NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_FlowMeterError_Type* const source) {
packedData[0] = (uint8_t)(((*source).status & 0x1) << 7);
packedData[0] |= (uint8_t)(((*source).code >> 25) & 0x7F);
packedData[1] = (uint8_t)(((*source).code >> 17) & 0xFF);
packedData[2] = (uint8_t)(((*source).code >> 9) & 0xFF);
packedData[3] = (uint8_t)(((*source).code >> 1) & 0xFF);
packedData[4] = (uint8_t)(((*source).code & 0x1) << 7);
}

void NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_UnpackCluster(
const uint8_t* const packedData,
NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_Type* const destination) {
(*destination).status = 0;
(*destination).status |= ((packedData[0] >> 7) & 0x1);
(*destination).code = 0;
(*destination).code |= (packedData[0] & 0x7FULL) << 25;
(*destination).code |= (packedData[1] & 0xFF) << 17;
(*destination).code |= (packedData[2] & 0xFF) << 9;
(*destination).code |= (packedData[3] & 0xFF) << 1;
(*destination).code |= ((packedData[4] >> 7) & 0x1);
}

void NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_PackCluster(
uint8_t* const packedData,
const NiFpga_ts_M1M3ThermalFPGA_IndicatorCluster_VFDError_Type* const source) {
packedData[0] = (uint8_t)(((*source).status & 0x1) << 7);
packedData[0] |= (uint8_t)(((*source).code >> 25) & 0x7F);
packedData[1] = (uint8_t)(((*source).code >> 17) & 0xFF);
packedData[2] = (uint8_t)(((*source).code >> 9) & 0xFF);
packedData[3] = (uint8_t)(((*source).code >> 1) & 0xFF);
packedData[4] = (uint8_t)(((*source).code & 0x1) << 7);
}

#endif /* !NiFpga_VxWorks */
Loading

0 comments on commit 68d4bf8

Please sign in to comment.