new RTD reader module handling all RTD SPI Communication
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
This commit is contained in:
@ -4,5 +4,9 @@ if(EIVE_BUILD_GPSD_GPS_HANDLER)
|
||||
)
|
||||
endif()
|
||||
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
Max31865RtdReader.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(ploc)
|
||||
add_subdirectory(startracker)
|
||||
|
289
linux/devices/Max31865RtdReader.cpp
Normal file
289
linux/devices/Max31865RtdReader.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <linux/devices/Max31865RtdReader.h>
|
||||
|
||||
Max31865RtdReader::Max31865RtdReader(object_id_t objectId, SpiComIF* comIF)
|
||||
: SystemObject(objectId), rtds(NUM_RTDS), comIF(comIF) {
|
||||
readerMutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::performOperation(uint8_t operationCode) {
|
||||
using namespace MAX31865;
|
||||
while (true) {
|
||||
rtdMainLoop();
|
||||
// Read all RTDs at once every 500 ms for now
|
||||
TaskFactory::delayTask(500);
|
||||
}
|
||||
}
|
||||
|
||||
void Max31865RtdReader::rtdMainLoop() {
|
||||
using namespace MAX31865;
|
||||
if (periodicInitHandling()) {
|
||||
// 10 ms delay for VBIAS startup
|
||||
TaskFactory::delayTask(10);
|
||||
} else {
|
||||
// No devices usable (e.g. TCS board off)
|
||||
return;
|
||||
}
|
||||
|
||||
periodicReadReqHandling();
|
||||
// After requesting, 65 milliseconds delay required
|
||||
TaskFactory::delayTask(65);
|
||||
|
||||
periodicReadHandling();
|
||||
}
|
||||
|
||||
bool Max31865RtdReader::rtdCanBeUsed(uint8_t idx) {
|
||||
if (rtds[idx]->active and rtds[idx]->configured) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Max31865RtdReader::periodicInitHandling() {
|
||||
using namespace MAX31865;
|
||||
MutexGuard mg(readerMutex);
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
if (mg.getLockResult() != RETURN_OK) {
|
||||
// TODO: Emit warning, return
|
||||
return false;
|
||||
}
|
||||
|
||||
bool someRtdActive = false;
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (rtd->active and not rtd->configured) {
|
||||
someRtdActive = true;
|
||||
uint8_t cfg = (Bias::OFF << CfgBitPos::BIAS_SEL) | (Wires::FOUR_WIRE << CfgBitPos::WIRE_SEL) |
|
||||
(ConvMode::NORM_OFF << CfgBitPos::CONV_MODE) |
|
||||
(1 << CfgBitPos::FAULTY_STATUS_CLEAR);
|
||||
result = writeCfgReg(rtd->spiCookie, cfg);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// TODO: Check retval
|
||||
}
|
||||
rtd->configured = true;
|
||||
}
|
||||
}
|
||||
if (not someRtdActive) {
|
||||
return false;
|
||||
}
|
||||
bool someRtdUsable = false;
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (rtdCanBeUsed(rtd->idx)) {
|
||||
someRtdUsable = true;
|
||||
result = biasSel(Bias::ON, rtd->spiCookie);
|
||||
}
|
||||
}
|
||||
return someRtdUsable;
|
||||
}
|
||||
|
||||
void Max31865RtdReader::periodicReadReqHandling() {
|
||||
using namespace MAX31865;
|
||||
MutexGuard mg(readerMutex);
|
||||
if (mg.getLockResult() != RETURN_OK) {
|
||||
// TODO: Emit warning, return
|
||||
return;
|
||||
}
|
||||
// Now request one shot config for all active RTDs
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (rtd->active) {
|
||||
uint8_t currentCfg = 0;
|
||||
auto result = readCfgReg(rtd->spiCookie, currentCfg);
|
||||
if (result != RETURN_OK) {
|
||||
// TODO: Emit warning, FDIR?
|
||||
continue;
|
||||
}
|
||||
currentCfg |= (1 << CfgBitPos::ONE_SHOT);
|
||||
result = writeCfgReg(rtd->spiCookie, currentCfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Max31865RtdReader::periodicReadHandling() {
|
||||
using namespace MAX31865;
|
||||
auto result = RETURN_OK;
|
||||
MutexGuard mg(readerMutex);
|
||||
if (mg.getLockResult() != RETURN_OK) {
|
||||
// TODO: Emit warning, return
|
||||
return;
|
||||
}
|
||||
// Now read the RTD values
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (rtd->active) {
|
||||
uint16_t rtdVal = 0;
|
||||
bool faultBitSet = false;
|
||||
result = readRtdVal(rtd->spiCookie, rtdVal, faultBitSet);
|
||||
if (result != RETURN_OK) {
|
||||
// TODO: Emit warning, FDIR?
|
||||
continue;
|
||||
}
|
||||
if (faultBitSet) {
|
||||
rtd->db.faultBitSet = faultBitSet;
|
||||
}
|
||||
rtd->db.rtdVal = rtdVal;
|
||||
}
|
||||
}
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (rtd->active) {
|
||||
result = biasSel(Bias::OFF, rtd->spiCookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::initializeInterface(CookieIF* cookie) {
|
||||
if (cookie == nullptr) {
|
||||
throw std::invalid_argument("Invalid MAX31865 Reader Cookie");
|
||||
}
|
||||
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
|
||||
ReturnValue_t result = comIF->initializeInterface(rtdCookie->spiCookie);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (rtdCookie->idx > NUM_RTDS) {
|
||||
throw std::invalid_argument("Invalid RTD index");
|
||||
}
|
||||
rtds[rtdCookie->idx] = rtdCookie;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::sendMessage(CookieIF* cookie, const uint8_t* sendData,
|
||||
size_t sendLen) {
|
||||
if (cookie == nullptr) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
if (sendLen < 1) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
MutexGuard mg(readerMutex);
|
||||
if (mg.getLockResult() != RETURN_OK) {
|
||||
// TODO: Emit warning, return
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
|
||||
uint8_t cmdRaw = sendData[0];
|
||||
if (cmdRaw > 2) {
|
||||
// TODO: Emit warning, invalid command
|
||||
return RETURN_OK;
|
||||
}
|
||||
auto cmd = static_cast<RtdCommands>(sendData[0]);
|
||||
switch (cmd) {
|
||||
case (RtdCommands::ON): {
|
||||
if (not rtdCookie->active) {
|
||||
rtdCookie->active = true;
|
||||
rtdCookie->configured = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (RtdCommands::OFF): {
|
||||
rtdCookie->active = false;
|
||||
rtdCookie->configured = false;
|
||||
break;
|
||||
}
|
||||
case (RtdCommands::CFG): {
|
||||
// TODO: Only implement if needed
|
||||
break;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::getSendSuccess(CookieIF* cookie) { return RETURN_OK; }
|
||||
|
||||
ReturnValue_t Max31865RtdReader::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
|
||||
size_t* size) {
|
||||
MutexGuard mg(readerMutex);
|
||||
if (mg.getLockResult() != RETURN_OK) {
|
||||
// TODO: Emit warning
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
|
||||
uint8_t* exchangePtr = rtdCookie->exchangeBuf.data();
|
||||
size_t serLen = 0;
|
||||
auto result = rtdCookie->db.serialize(&exchangePtr, &serLen, rtdCookie->exchangeBuf.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
if (result != RETURN_OK) {
|
||||
// TODO: Emit warning
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
*buffer = reinterpret_cast<uint8_t*>(rtdCookie->exchangeBuf.data());
|
||||
*size = rtdCookie->db.getSerializedSize();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::writeCfgReg(SpiCookie* cookie, uint8_t cfg) {
|
||||
using namespace MAX31865;
|
||||
uint8_t cmd[2] = {REG_CONFIG | WRITE_BIT, cfg};
|
||||
return comIF->sendMessage(cookie, cmd, 2);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::biasSel(MAX31865::Bias bias, SpiCookie* cookie) {
|
||||
using namespace MAX31865;
|
||||
uint8_t currentCfg = 0;
|
||||
auto result = readCfgReg(cookie, currentCfg);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (bias == MAX31865::Bias::OFF) {
|
||||
currentCfg &= ~(1 << CfgBitPos::BIAS_SEL);
|
||||
} else {
|
||||
currentCfg |= (1 << CfgBitPos::BIAS_SEL);
|
||||
}
|
||||
return writeCfgReg(cookie, currentCfg);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::readCfgReg(SpiCookie* cookie, uint8_t& cfg) {
|
||||
using namespace MAX31865;
|
||||
uint8_t cmd[2] = {REG_CONFIG, 0};
|
||||
ReturnValue_t result = comIF->sendMessage(cookie, cmd, 2);
|
||||
if (result != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
uint8_t reply[2] = {};
|
||||
uint8_t* replyPtr = reply;
|
||||
size_t dummyLen = 0;
|
||||
result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
cfg = reply[1];
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdReader::readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet) {
|
||||
using namespace MAX31865;
|
||||
uint8_t cmd[3] = {REG_RTD, 0, 0};
|
||||
auto result = comIF->sendMessage(cookie, cmd, 3);
|
||||
if (result != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
uint8_t reply[3] = {};
|
||||
uint8_t* replyPtr = reply;
|
||||
size_t dummyLen = 0;
|
||||
result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (reply[2] & 0b0000'0001) {
|
||||
faultBitSet = true;
|
||||
}
|
||||
// Shift 1 to the right to remove fault bit
|
||||
val = ((reply[1] << 8) | reply[2]) >> 1;
|
||||
return result;
|
||||
}
|
92
linux/devices/Max31865RtdReader.h
Normal file
92
linux/devices/Max31865RtdReader.h
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef LINUX_DEVICES_MAX31865RTDREADER_H_
|
||||
#define LINUX_DEVICES_MAX31865RTDREADER_H_
|
||||
|
||||
#include <fsfw/ipc/MutexIF.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||
|
||||
#include "fsfw/devicehandlers/DeviceCommunicationIF.h"
|
||||
#include "mission/devices/devicedefinitions/Max31865Definitions.h"
|
||||
|
||||
static constexpr uint8_t NUM_RTDS = 16;
|
||||
|
||||
enum RtdCommands : uint8_t { ON = 0, OFF = 1, CFG = 2 };
|
||||
|
||||
class ReadOutStruct : public SerialLinkedListAdapter<SerializeIF> {
|
||||
public:
|
||||
ReadOutStruct() { setLinks(); }
|
||||
ReadOutStruct(uint32_t spiErrCnt, bool faultBitSet, uint8_t faultVal, uint16_t rtdVal)
|
||||
: spiErrorCount(spiErrCnt), faultBitSet(faultBitSet), faultValue(faultVal), rtdVal(rtdVal) {
|
||||
setLinks();
|
||||
}
|
||||
|
||||
SerializeElement<uint32_t> spiErrorCount = 0;
|
||||
SerializeElement<bool> faultBitSet = false;
|
||||
SerializeElement<uint8_t> faultValue = 0;
|
||||
SerializeElement<uint16_t> rtdVal = 0;
|
||||
|
||||
private:
|
||||
void setLinks() {
|
||||
setStart(&spiErrorCount);
|
||||
spiErrorCount.setNext(&faultBitSet);
|
||||
faultBitSet.setNext(&faultValue);
|
||||
faultValue.setNext(&rtdVal);
|
||||
};
|
||||
};
|
||||
|
||||
struct Max31865ReaderCookie {
|
||||
Max31865ReaderCookie(){};
|
||||
Max31865ReaderCookie(object_id_t handlerId_, uint8_t idx_, const std::string& locString_,
|
||||
SpiCookie* spiCookie_)
|
||||
: idx(idx_), handlerId(handlerId_), locString(locString_), spiCookie(spiCookie_) {}
|
||||
|
||||
uint8_t idx = 0;
|
||||
object_id_t handlerId = objects::NO_OBJECT;
|
||||
|
||||
std::string locString = "";
|
||||
std::array<uint8_t, 12> exchangeBuf{};
|
||||
bool active = false;
|
||||
|
||||
bool configured = false;
|
||||
|
||||
SpiCookie* spiCookie = nullptr;
|
||||
|
||||
// Exchange data buffer struct
|
||||
ReadOutStruct db;
|
||||
};
|
||||
|
||||
class Max31865RtdReader : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public DeviceCommunicationIF {
|
||||
public:
|
||||
Max31865RtdReader(object_id_t objectId, SpiComIF* comIF);
|
||||
void addRtd(Max31865ReaderCookie rtdCookie);
|
||||
|
||||
[[noreturn]] ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
|
||||
private:
|
||||
std::vector<Max31865ReaderCookie*> rtds;
|
||||
MutexIF* readerMutex;
|
||||
|
||||
void rtdMainLoop();
|
||||
bool periodicInitHandling();
|
||||
void periodicReadReqHandling();
|
||||
void periodicReadHandling();
|
||||
|
||||
bool rtdCanBeUsed(uint8_t idx);
|
||||
ReturnValue_t writeCfgReg(SpiCookie* cookie, uint8_t cfg);
|
||||
ReturnValue_t biasSel(MAX31865::Bias bias, SpiCookie* cookie);
|
||||
ReturnValue_t readCfgReg(SpiCookie* cookie, uint8_t& cfg);
|
||||
ReturnValue_t readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet);
|
||||
|
||||
ReturnValue_t initializeInterface(CookieIF* cookie) override;
|
||||
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
|
||||
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
|
||||
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
|
||||
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
|
||||
|
||||
SpiComIF* comIF;
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_MAX31865RTDREADER_H_ */
|
Reference in New Issue
Block a user