eive-obsw/linux/devices/Max31865RtdReader.cpp

313 lines
8.7 KiB
C++
Raw Normal View History

#include <fsfw/tasks/TaskFactory.h>
#include <linux/devices/Max31865RtdReader.h>
Max31865RtdReader::Max31865RtdReader(object_id_t objectId, SpiComIF* comIF)
2022-05-12 09:48:41 +02:00
: SystemObject(objectId), rtds(EiveMax31855::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();
}
2022-05-12 09:48:41 +02:00
bool Max31865RtdReader::rtdIsActive(uint8_t idx) {
if (rtds[idx]->on and 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;
}
2022-05-12 09:48:41 +02:00
bool someRtdOn = false;
for (auto& rtd : rtds) {
if (rtd == nullptr) {
continue;
}
2022-05-12 09:48:41 +02:00
if (rtd->on and not rtd->configured) {
if (rtd->cd.hasTimedOut()) {
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
}
someRtdOn = true;
rtd->configured = true;
}
}
}
2022-05-12 09:48:41 +02:00
if (not someRtdOn) {
return false;
}
bool someRtdUsable = false;
for (auto& rtd : rtds) {
if (rtd == nullptr) {
continue;
}
2022-05-12 09:48:41 +02:00
if (rtdIsActive(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;
}
2022-05-12 09:48:41 +02:00
if (rtdIsActive(rtd->idx)) {
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;
}
2022-05-12 09:48:41 +02:00
if (rtdIsActive(rtd->idx)) {
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;
}
2022-05-12 09:48:41 +02:00
// Even if a device was made inactive, turn off the bias here. If it was turned off, not
// necessary anymore..
if (rtd->on) {
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;
}
2022-05-12 09:48:41 +02:00
if (rtdCookie->idx > EiveMax31855::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;
}
2022-05-12 09:48:41 +02:00
auto cmd = static_cast<EiveMax31855::RtdCommands>(sendData[0]);
switch (cmd) {
2022-05-12 09:48:41 +02:00
case (EiveMax31855::RtdCommands::ON): {
if (not rtdCookie->on) {
rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS);
rtdCookie->cd.resetTimer();
rtdCookie->on = true;
rtdCookie->active = false;
rtdCookie->configured = false;
}
break;
}
case (EiveMax31855::RtdCommands::ACTIVE): {
if (not rtdCookie->on) {
rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS);
rtdCookie->cd.resetTimer();
rtdCookie->on = true;
rtdCookie->active = true;
rtdCookie->configured = false;
2022-05-12 09:48:41 +02:00
} else {
rtdCookie->active = true;
}
break;
}
2022-05-12 09:48:41 +02:00
case (EiveMax31855::RtdCommands::OFF): {
rtdCookie->on = false;
rtdCookie->active = false;
rtdCookie->configured = false;
break;
}
2022-05-12 09:48:41 +02:00
case (EiveMax31855::RtdCommands::HIGH_TRESHOLD):
case (EiveMax31855::RtdCommands::LOW_THRESHOLD):
case (EiveMax31855::RtdCommands::CFG):
default: {
// 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;
}