From 5dcc6e2003d95ab29ba2fafec8a3c691c3f650e6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 22 Feb 2022 16:51:26 +0100 Subject: [PATCH] finished ext conv callback --- bsp_q7s/core/ObjectFactory.cpp | 3 +- linux/boardtest/SpiTestClass.cpp | 51 ++++-- linux/boardtest/SpiTestClass.h | 1 + linux/devices/CMakeLists.txt | 1 + .../devices/PayloadPcduHandler.cpp | 148 +++++++++++++++++- .../devices/PayloadPcduHandler.h | 12 +- mission/devices/CMakeLists.txt | 1 - .../payloadPcduDefinitions.h | 4 +- 8 files changed, 200 insertions(+), 21 deletions(-) rename {mission => linux}/devices/PayloadPcduHandler.cpp (65%) rename {mission => linux}/devices/PayloadPcduHandler.h (88%) diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index dd48858f..5f184f8e 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -44,6 +44,7 @@ #include "linux/csp/CspComIF.h" #include "linux/csp/CspCookie.h" #include "linux/devices/GPSHyperionLinuxController.h" +#include "linux/devices/PayloadPcduHandler.h" #include "linux/devices/SolarArrayDeploymentHandler.h" #include "linux/devices/SusHandler.h" #include "linux/devices/devicedefinitions/SusDefinitions.h" @@ -58,7 +59,6 @@ #include "mission/devices/PCDUHandler.h" #include "mission/devices/PDU1Handler.h" #include "mission/devices/PDU2Handler.h" -#include "mission/devices/PayloadPcduHandler.h" #include "mission/devices/PlocMPSoCHandler.h" #include "mission/devices/RadiationSensorHandler.h" #include "mission/devices/RwHandler.h" @@ -1209,6 +1209,7 @@ void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* // Create device handler components auto plPcduHandler = new PayloadPcduHandler(objects::PLPCDU_HANDLER, objects::SPI_COM_IF, spiCookie, gpioComIF, false); + spiCookie->setCallbackMode(PayloadPcduHandler::extConvAsTwoCallback, plPcduHandler); static_cast(plPcduHandler); #if OBSW_TEST_PL_PCDU == 1 plPcduHandler->setStartUpImmediately(); diff --git a/linux/boardtest/SpiTestClass.cpp b/linux/boardtest/SpiTestClass.cpp index 53a0466f..32ca8b85 100644 --- a/linux/boardtest/SpiTestClass.cpp +++ b/linux/boardtest/SpiTestClass.cpp @@ -322,6 +322,7 @@ void SpiTestClass::performOneShotMax1227Test() { adcCfg.plPcduAdcExtConv = true; adcCfg.plPcduAdcIntConv = false; + adcCfg.plPcduAdcExtConvAsOne = false; performMax1227Test(); } @@ -344,7 +345,7 @@ void SpiTestClass::performMax1227Test() { return; } uint32_t spiSpeed = 976'000; - spi::SpiModes spiMode = spi::SpiModes::MODE_0; + spi::SpiModes spiMode = spi::SpiModes::MODE_3; setSpiSpeedAndMode(fd, spiMode, spiSpeed); max1227RadSensorTest(fd); @@ -522,7 +523,8 @@ void SpiTestClass::max1227SusTest(int fd, SusTestCfg &cfg) { void SpiTestClass::max1227PlPcduTest(int fd) { using namespace max1227; - if ((adcCfg.plPcduAdcExtConv or adcCfg.plPcduAdcIntConv) and adcCfg.vbatSwitch) { + if ((adcCfg.plPcduAdcExtConv or adcCfg.plPcduAdcIntConv or adcCfg.plPcduAdcExtConvAsOne) and + adcCfg.vbatSwitch) { // This enables the ADC ReturnValue_t result = gpioIF->pullHigh(gpioIds::PLPCDU_ENB_VBAT0); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -538,7 +540,6 @@ void SpiTestClass::max1227PlPcduTest(int fd) { sendBuffer[0] = max1227::buildResetByte(false); spiTransferStruct[0].len = 1; transfer(fd, gpioIds::PLPCDU_ADC_CS); - } if (adcCfg.plPcduAdcExtConv) { sendBuffer[0] = max1227::buildSetupByte(ClkSel::EXT_CONV_EXT_TIMED, RefSel::INT_REF_NO_WAKEUP, @@ -547,20 +548,52 @@ void SpiTestClass::max1227PlPcduTest(int fd) { transfer(fd, gpioIds::PLPCDU_ADC_CS); uint8_t n = 11; max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), n, spiTransferStruct[0].len); + size_t dummy = 0; + max1227::prepareExternallyClockedTemperatureRead(sendBuffer.data() + spiTransferStruct[0].len, + dummy); + // + 1 to account for temp conversion byte + spiTransferStruct[0].len += 1; transfer(fd, gpioIds::PLPCDU_ADC_CS); uint16_t adcRaw[n + 1] = {}; for (uint8_t idx = 0; idx < n + 1; idx++) { adcRaw[idx] = (recvBuffer[idx * 2 + 1] << 8) | recvBuffer[idx * 2 + 2]; } - usleep(10); - spiTransferStruct[0].len = 0; - max1227::prepareExternallyClockedTemperatureRead(sendBuffer.data(), spiTransferStruct[0].len); + spiTransferStruct[0].len = 24; + // Shift out zeros + shiftOutZeros(); transfer(fd, gpioIds::PLPCDU_ADC_CS); - int16_t tempRaw = ((recvBuffer[23] & 0x0f) << 8) | recvBuffer[24]; + setSendBuffer(); + int16_t tempRaw = ((recvBuffer[22] & 0x0f) << 8) | recvBuffer[23]; sif::info << "PL PCDU ADC ext conv [" << std::hex << std::setfill('0'); for (int idx = 0; idx < n + 1; idx++) { sif::info << std::setw(3) << adcRaw[idx]; - if(idx < n) { + if (idx < n) { + sif::info << ","; + } + } + sif::info << "]" << std::endl; + sif::info << "Temperature: " << max1227::getTemperature(tempRaw) << " C" << std::endl; + } + if (adcCfg.plPcduAdcExtConvAsOne) { + sendBuffer[0] = max1227::buildSetupByte(ClkSel::EXT_CONV_EXT_TIMED, RefSel::INT_REF_NO_WAKEUP, + DiffSel::NONE_0); + spiTransferStruct[0].len = 1; + transfer(fd, gpioIds::PLPCDU_ADC_CS); + uint8_t n = 11; + max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), n, spiTransferStruct[0].len); + max1227::prepareExternallyClockedTemperatureRead(sendBuffer.data() + spiTransferStruct[0].len, + spiTransferStruct[0].len); + transfer(fd, gpioIds::PLPCDU_ADC_CS); + uint16_t adcRaw[n + 1] = {}; + for (uint8_t idx = 0; idx < n + 1; idx++) { + adcRaw[idx] = (recvBuffer[idx * 2 + 1] << 8) | recvBuffer[idx * 2 + 2]; + } + int16_t tempRaw = ((recvBuffer[spiTransferStruct[0].len - 2] & 0x0f) << 8) | + recvBuffer[spiTransferStruct[0].len - 1]; + sif::info << "PL PCDU ADC ext conv [" << std::hex << std::setfill('0'); + for (int idx = 0; idx < n + 1; idx++) { + sif::info << std::setw(3) << adcRaw[idx]; + if (idx < n) { sif::info << ","; } } @@ -594,7 +627,7 @@ void SpiTestClass::max1227PlPcduTest(int fd) { for (int idx = 0; idx < n + 1; idx++) { adcRaw[idx] = (recvBuffer[idx * 2 + 2] << 8) | recvBuffer[idx * 2 + 3]; sif::info << std::setw(3) << adcRaw[idx]; - if(idx < n) { + if (idx < n) { sif::info << ","; } } diff --git a/linux/boardtest/SpiTestClass.h b/linux/boardtest/SpiTestClass.h index d48d6655..15675f1a 100644 --- a/linux/boardtest/SpiTestClass.h +++ b/linux/boardtest/SpiTestClass.h @@ -26,6 +26,7 @@ struct Max1227TestCfg { bool testRadSensorExtConvWithDelay = false; bool testRadSensorIntConv = false; bool plPcduAdcExtConv = false; + bool plPcduAdcExtConvAsOne = false; bool plPcduAdcIntConv = false; bool vbatSwitch = true; diff --git a/linux/devices/CMakeLists.txt b/linux/devices/CMakeLists.txt index 5a367b28..6e525800 100644 --- a/linux/devices/CMakeLists.txt +++ b/linux/devices/CMakeLists.txt @@ -1,6 +1,7 @@ target_sources(${OBSW_NAME} PRIVATE SolarArrayDeploymentHandler.cpp SusHandler.cpp + PayloadPcduHandler.cpp ) if(EIVE_BUILD_GPSD_GPS_HANDLER) diff --git a/mission/devices/PayloadPcduHandler.cpp b/linux/devices/PayloadPcduHandler.cpp similarity index 65% rename from mission/devices/PayloadPcduHandler.cpp rename to linux/devices/PayloadPcduHandler.cpp index a581b2ef..63b83f05 100644 --- a/mission/devices/PayloadPcduHandler.cpp +++ b/linux/devices/PayloadPcduHandler.cpp @@ -1,6 +1,11 @@ #include "PayloadPcduHandler.h" #include +#include +#include +#include +#include +#include #include "devices/gpioIds.h" @@ -52,7 +57,7 @@ ReturnValue_t PayloadPcduHandler::buildNormalDeviceCommand(DeviceCommandId_t* id return buildCommandFromCommand(*id, nullptr, 0); } case (AdcStates::NORMAL): { - *id = plpcdu::READ_WITH_TEMP; + *id = plpcdu::READ_WITH_TEMP_EXT; return buildCommandFromCommand(*id, nullptr, 0); } default: { @@ -72,8 +77,8 @@ ReturnValue_t PayloadPcduHandler::buildTransitionDeviceCommand(DeviceCommandId_t void PayloadPcduHandler::fillCommandAndReplyMap() { insertInCommandAndReplyMap(plpcdu::READ_CMD, 2, &adcSet); - insertInCommandAndReplyMap(plpcdu::READ_TEMP, 1, &adcSet); - insertInCommandAndReplyMap(plpcdu::READ_WITH_TEMP, 1, &adcSet); + insertInCommandAndReplyMap(plpcdu::READ_TEMP_EXT, 1, &adcSet); + insertInCommandAndReplyMap(plpcdu::READ_WITH_TEMP_EXT, 1, &adcSet); insertInCommandAndReplyMap(plpcdu::SETUP_CMD, 1); } @@ -92,12 +97,12 @@ ReturnValue_t PayloadPcduHandler::buildCommandFromCommand(DeviceCommandId_t devi rawPacket = cmdBuf.data(); break; } - case (plpcdu::READ_TEMP): { + case (plpcdu::READ_TEMP_EXT): { max1227::prepareExternallyClockedTemperatureRead(cmdBuf.data(), rawPacketLen); rawPacket = cmdBuf.data(); break; } - case (plpcdu::READ_WITH_TEMP): { + case (plpcdu::READ_WITH_TEMP_EXT): { size_t sz = 0; max1227::prepareExternallyClockedRead0ToN(cmdBuf.data(), plpcdu::CHANNEL_N, sz); max1227::prepareExternallyClockedTemperatureRead(cmdBuf.data() + sz, sz); @@ -130,7 +135,7 @@ ReturnValue_t PayloadPcduHandler::interpretDeviceReply(DeviceCommandId_t id, } break; } - case (READ_TEMP): { + case (READ_TEMP_EXT): { uint8_t tempStartIdx = TEMP_REPLY_SIZE - 2; adcSet.tempC.value = max1227::getTemperature(packet[tempStartIdx] << 8 | packet[tempStartIdx + 1]); @@ -145,7 +150,7 @@ ReturnValue_t PayloadPcduHandler::interpretDeviceReply(DeviceCommandId_t id, handlePrintout(); break; } - case (READ_WITH_TEMP): { + case (READ_WITH_TEMP_EXT): { PoolReadGuard pg(&adcSet); if (pg.getReadResult() != HasReturnvaluesIF::RETURN_OK) { return pg.getReadResult(); @@ -309,3 +314,132 @@ void PayloadPcduHandler::stateMachineToNormal() { } } } + +ReturnValue_t PayloadPcduHandler::extConvAsTwoCallback(SpiComIF* comIf, SpiCookie* cookie, + const uint8_t* sendData, size_t sendLen, + void* args) { + auto handler = reinterpret_cast(args); + if (handler == nullptr) { + sif::error << "GyroADIS16507Handler::spiSendCallback: Passed handler pointer is invalid!" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + DeviceCommandId_t currentCommand = handler->getPendingCommand(); + switch (currentCommand) { + case (plpcdu::READ_WITH_TEMP_EXT): { + return transferAsTwo(comIf, cookie, sendData, sendLen, false); + } + case (plpcdu::READ_TEMP_EXT): { + return transferAsTwo(comIf, cookie, sendData, sendLen, true); + } + default: { + return comIf->performRegularSendOperation(cookie, sendData, sendLen); + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PayloadPcduHandler::transferAsTwo(SpiComIF* comIf, SpiCookie* cookie, + const uint8_t* sendData, size_t sendLen, + bool tempOnly) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + int retval = 0; + // Prepare transfer + int fileDescriptor = 0; + std::string device = cookie->getSpiDevice(); + UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); + if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) { + return SpiComIF::OPENING_FILE_FAILED; + } + spi::SpiModes spiMode = spi::SpiModes::MODE_0; + uint32_t spiSpeed = 0; + cookie->getSpiParameters(spiMode, spiSpeed, nullptr); + comIf->setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed); + cookie->assignWriteBuffer(sendData); + size_t transferLen = plpcdu::TEMP_REPLY_SIZE; + if (not tempOnly) { + transferLen += plpcdu::ADC_REPLY_SIZE; + } + cookie->setTransferSize(transferLen); + + gpioId_t gpioId = cookie->getChipSelectPin(); + GpioIF* gpioIF = comIf->getGpioInterface(); + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 0; + MutexIF* mutex = comIf->getMutex(&timeoutType, &timeoutMs); + if (mutex == nullptr or gpioIF == nullptr) { +#if OBSW_VERBOSE_LEVEL >= 1 + sif::warning << "GyroADIS16507Handler::spiSendCallback: " + "Mutex or GPIO interface invalid" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +#endif + } + + if (gpioId != gpio::NO_GPIO) { + result = mutex->lockMutex(timeoutType, timeoutMs); + if (result != RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "SpiComIF::sendMessage: Failed to lock mutex" << std::endl; +#endif + return result; + } + } + spi_ioc_transfer* transferStruct = cookie->getTransferStructHandle(); + uint64_t origTx = transferStruct->tx_buf; + uint64_t origRx = transferStruct->rx_buf; + if (tempOnly) { + transferLen = 1; + } else { + transferLen = plpcdu::ADC_REPLY_SIZE + 1; + } + transferStruct->len = transferLen; + // Pull SPI CS low. For now, no support for active high given + if (gpioId != gpio::NO_GPIO) { + gpioIF->pullLow(gpioId); + } + + // Execute transfer + // Initiate a full duplex SPI transfer. + retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie->getTransferStructHandle()); + if (retval < 0) { + utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); + result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; + } +#if FSFW_HAL_SPI_WIRETAPPING == 1 + comIf->performSpiWiretapping(cookie); +#endif /* FSFW_LINUX_SPI_WIRETAPPING == 1 */ + + if (gpioId != gpio::NO_GPIO) { + gpioIF->pullHigh(gpioId); + } + + transferStruct->tx_buf += transferLen; + transferStruct->rx_buf += transferLen; + transferStruct->len = plpcdu::TEMP_REPLY_SIZE - 1; + if (gpioId != gpio::NO_GPIO) { + gpioIF->pullLow(gpioId); + } + + // Execute transfer + // Initiate a full duplex SPI transfer. + retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie->getTransferStructHandle()); + if (retval < 0) { + utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); + result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; + } +#if FSFW_HAL_SPI_WIRETAPPING == 1 + comIf->performSpiWiretapping(cookie); +#endif /* FSFW_LINUX_SPI_WIRETAPPING == 1 */ + + if (gpioId != gpio::NO_GPIO) { + gpioIF->pullHigh(gpioId); + } + + transferStruct->tx_buf = origTx; + transferStruct->rx_buf = origRx; + if (gpioId != gpio::NO_GPIO) { + mutex->unlockMutex(); + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/mission/devices/PayloadPcduHandler.h b/linux/devices/PayloadPcduHandler.h similarity index 88% rename from mission/devices/PayloadPcduHandler.h rename to linux/devices/PayloadPcduHandler.h index 31579154..105e4cfe 100644 --- a/mission/devices/PayloadPcduHandler.h +++ b/linux/devices/PayloadPcduHandler.h @@ -5,8 +5,11 @@ #include #include -#include "devicedefinitions/payloadPcduDefinitions.h" #include "fsfw_hal/common/gpio/GpioIF.h" +#include "mission/devices/devicedefinitions/payloadPcduDefinitions.h" + +class SpiComIF; +class SpiCookie; /** * @brief Device handler for the EIVE Payload PCDU @@ -30,6 +33,11 @@ class PayloadPcduHandler : public DeviceHandlerBase { void setToGoToNormalModeImmediately(bool enable); void enablePeriodicPrintout(bool enable, uint8_t divider); + static ReturnValue_t extConvAsTwoCallback(SpiComIF* comIf, SpiCookie* cookie, + const uint8_t* sendData, size_t sendLen, void* args); + static ReturnValue_t transferAsTwo(SpiComIF* comIf, SpiCookie* cookie, const uint8_t* sendData, + size_t sendLen, bool tempOnly); + private: enum class States { PCDU_OFF, @@ -52,6 +60,8 @@ class PayloadPcduHandler : public DeviceHandlerBase { PCDU_ON, } state = States::PCDU_OFF; + enum class AdcMode { EXT_CONV, INT_CONV } adcMode = AdcMode::INT_CONV; + enum class MonitoringMode { NONE, CLOSE_TO_ZERO, NEGATIVE } monMode = MonitoringMode::NONE; enum class AdcStates { OFF, BOOT_DELAY, SEND_SETUP, NORMAL } adcState = AdcStates::OFF; diff --git a/mission/devices/CMakeLists.txt b/mission/devices/CMakeLists.txt index 16defedf..22b64c9e 100644 --- a/mission/devices/CMakeLists.txt +++ b/mission/devices/CMakeLists.txt @@ -16,5 +16,4 @@ target_sources(${LIB_EIVE_MISSION} PRIVATE GyroADIS1650XHandler.cpp RwHandler.cpp max1227.cpp - PayloadPcduHandler.cpp ) diff --git a/mission/devices/devicedefinitions/payloadPcduDefinitions.h b/mission/devices/devicedefinitions/payloadPcduDefinitions.h index 3ac8ce1b..b40e34e6 100644 --- a/mission/devices/devicedefinitions/payloadPcduDefinitions.h +++ b/mission/devices/devicedefinitions/payloadPcduDefinitions.h @@ -18,8 +18,8 @@ static constexpr size_t MAX_ADC_REPLY_SIZE = 64; static constexpr DeviceCommandId_t READ_CMD = 0; static constexpr DeviceCommandId_t SETUP_CMD = 1; -static constexpr DeviceCommandId_t READ_TEMP = 2; -static constexpr DeviceCommandId_t READ_WITH_TEMP = 3; +static constexpr DeviceCommandId_t READ_TEMP_EXT = 2; +static constexpr DeviceCommandId_t READ_WITH_TEMP_EXT = 3; static constexpr Submode_t NORMAL_ADC_ONLY = 0; static constexpr Submode_t NORMAL_ALL_ON = 1;