/************************************************************************** * * Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ConductivityTeensy.c * * @author (last) Arpita Srivastava * @date (last) 3-Nov-2025 * * @author (original) Arpita Srivastava * @date (original) 3-Nov-2025 * ***************************************************************************/ #include // Used for calculating the polynomial calibration equation. #include // For memcpy #include "sci.h" #include "sys_dma.h" #include "ConductivityTeensy.h" #define SCI_RECEIVE_DMA_REQUEST 38 ///< Serial port receive DMA request line. #define SCI_TRANSMIT_DMA_REQUEST 39 ///< Serial port transmit DMA request line. #define COND_WRITE_CMD_BUFFER_LEN 256 ///< Conductivity write command buffer byte length. #define COND_WRITE_RSP_BUFFER_LEN 8 ///< Conductivity write command response buffer byte length. #define COND_READ_CMD_BUFFER_LEN 8 ///< Conductivity read command buffer byte length. #define COND_READ_RSP_BUFFER_LEN 256 ///< Conductivity read command response buffer byte length. // ********** private data ********** static CONDUCTIVITY_COMM_STATE_T conductivityCommState = COND_COMM_STATE_START; static U32 condReceiptCounter = 0; ///< Conductivity response receipt counter. static U32 condTransmitCounter = 0; ///< Conductivity command transmit counter. static BOOL condWriteCommandInProgress = FALSE; ///< Flag indicating an Conductivity write command is in progress. static BOOL condReadCommandInProgress = FALSE; ///< Flag indicating an Conductivity read command is in progress. static BOOL condBulkWriteAndReadInProgress = FALSE; ///< Flag indicating an Conductivity bulk write and read command are in progress. static BOOL condWriteCommandResponseReceived = FALSE; ///< Flag indicating a response to an Conductivity write command has been received. static BOOL condReadCommandResponseReceived = FALSE; ///< Flag indicating a response to an Conductivity read command has been received. // Conductivity comm buffers static U08 condWriteCmdBuffer[ COND_WRITE_CMD_BUFFER_LEN ]; ///< Conductivity write command buffer. Holds the next Conductivity write command to be transmitted. static U08 condWriteResponseBuffer[ COND_WRITE_RSP_BUFFER_LEN ]; ///< Conductivity write command response buffer. Memory reserved to capture the response to the last Conductivity write command. static U08 condReadCmdBuffer[ COND_READ_CMD_BUFFER_LEN ]; ///< Conductivity read command buffer. Holds the next Conductivity read command to be transmitted. static U08 condReadResponseBuffer[ COND_READ_RSP_BUFFER_LEN ]; ///< Conductivity read command response buffer. Memory reserved to capture the response to the last Conductivity read command. // Conductivity DMA control records static g_dmaCTRL condDMAWriteControlRecord; ///< DMA record for controlling a DMA write command transmission from buffer. static g_dmaCTRL condDMAWriteRespControlRecord; ///< DMA record for controlling a DMA write command reception to buffer. static g_dmaCTRL condDMAReadControlRecord; ///< DMA record for controlling a DMA read command transmission from buffer. static g_dmaCTRL condDMAReadRespControlRecord; ///< DMA record for controlling a DMA read command reception to buffer. static CONDUCTIVITY_INIT_STATUS_T conductivityInitStatus; static CONDUCTIVITY_EEPROM_DATA_T conductivityEEPROMdata; static CONDUCTIVITY_MEASUREMENT_SETTINGS_T conductivityMeasurementSettings; static CONDUCTIVITY_SENSOR_DATA_T rawConductivityValues[ MAX_TEENSY_SENSOR ]; static CONDUCTIVITY_CALCULATED_MEASUREMENTS_T calculatedMeasurement[ MAX_TEENSY_SENSOR ]; static CONDUCTIVITY_COEFFICIENTS_T conductivityCoeff[MAX_TEENSY_SENSOR]; static const U08* teensyCmd[] = { "a", ///< COND_COMM_STATE_SEND_CMD_INIT_SENSOR "l", ///< COND_COMM_STATE_SEND_CMD_GET_INIT_STATUS "save", ///< COND_COMM_STATE_SEND_CMD_UPDATE_EEPROM_DATA, "e", ///< COND_COMM_STATE_SEND_CMD_GET_EEPROM_DATA, "cfg", ///< COND_COMM_STATE_SEND_CMD_UPDATE_MEASUREMENT_SETTINGS, "k", ///< COND_COMM_STATE_SEND_CMD_GET_MEASUREMENT_SETTINGS, "m", ///< COND_COMM_STATE_SEND_CMD_GET_MEASUREMENT, "n", ///< Stop getting measurements "g", ///< Get measurements of all the sensors "j", ///< Select a sensor. ex : "j 1" selects sensor number 1 "h" ///< Get that of selected sensor. (First Execute command "j".) }; // ********** private function prototypes ********** static void initConductivityDMAchannels( void ); static void handleConductivitySendCmd( void ); static void handleConductivityReceiveResponse( void ); static void consumeUnexpectedConductivityData( void ); static void setupConductivityDMAForWriteCmd( U32 bytes2Transmit ); static void startConductivityDMAWriteCmd( void ); static void setupConductivityDMAForWriteResp( U32 bytes2Receive ); static void startConductivityDMAReceiptOfWriteResp( void ); static void setupConductivityDMAForReadCmd( U32 bytes2Transmit ); static void startConductivityDMAReadCmd( void ); static void setupConductivityDMAForReadResp( U32 bytes2Receive ); static void startConductivityDMAReceiptOfReadResp( void ); static CONDUCTIVITY_PARSE_STATUS parseMeasurementSettings(const U32 *buffer, U32 len ); static CONDUCTIVITY_PARSE_STATUS parseEEPROMdata( const U32 *buffer, U32 len ); static CONDUCTIVITY_PARSE_STATUS parseConductivityMeasurements( const U32 *buffer, U32 len ); static BOOL sendTeensyWriteCmd( TEENSY_CMD_INDEX_T cmdIndex, const U08* param ); static BOOL sendTeensyReadCmd( TEENSY_CMD_INDEX_T cmdIndex ); static CONDUCTIVITY_COMM_STATE_T sendCmd_initSensor( void ); static CONDUCTIVITY_COMM_STATE_T rcvRspns_initSensor( void ); static CONDUCTIVITY_COMM_STATE_T sendCmd_getInitStatus( void ); static CONDUCTIVITY_COMM_STATE_T rcvRspns_getInitStatus( void ); static CONDUCTIVITY_COMM_STATE_T sendCmd_updateEEPROMdata( CONDUCTIVITY_EEPROM_DATA_T eepromData); static CONDUCTIVITY_COMM_STATE_T rcvRspns_updateEEPROMdata( void ); static CONDUCTIVITY_COMM_STATE_T sendCmd_getEEPROMdata( void ); static CONDUCTIVITY_COMM_STATE_T rcvRspns_getEEPROMdata( void ); static CONDUCTIVITY_COMM_STATE_T sendCmd_updateMeasurementSettings( CONDUCTIVITY_MEASUREMENT_SETTINGS_T measurementSettings ); static CONDUCTIVITY_COMM_STATE_T rcvRspns_updateMeasurementSettings( void ); static CONDUCTIVITY_COMM_STATE_T sendCmd_getMeasurementSettings( void ); static CONDUCTIVITY_COMM_STATE_T rcvRspns_getMeasurementSettings( void ); static CONDUCTIVITY_COMM_STATE_T sendCmd_getMeasurements( void ); static CONDUCTIVITY_COMM_STATE_T rcvRspns_getMeasurements( void ); static void sendCmd_stopMeasurement( void ); static void rcvRspns_stopMeasurement( void ); static void sendCmd_getAllMeasurements( void ); static void rcvRspns_getAllMeasurements( void ); static void sendCmd_selectSensor( TEENSY_SENSOR_INDEX_T sensorNum ); static void rcvRspns_selectSensor( TEENSY_SENSOR_INDEX_T sensorNum ); static void sendCmd_getSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ); static void rcvRspns_getSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ); static CONDUCTIVITY_INIT_STATUS_T getInitStatus( void ); static const CONDUCTIVITY_EEPROM_DATA_T* getEEPROMdata( void ); static const CONDUCTIVITY_MEASUREMENT_SETTINGS_T* getMeasurementSettings( void ); static const CONDUCTIVITY_SENSOR_DATA_T* getSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ); static const CONDUCTIVITY_SENSOR_DATA_T* getAllMeasurements( void ); static void calculateConductivity( TEENSY_SENSOR_INDEX_T sensorNum ); static void calculateTemperature( TEENSY_SENSOR_INDEX_T sensorNum ); void initCondTeensy( void ) { conductivityCommState = COND_COMM_STATE_START; condReceiptCounter = 0; condTransmitCounter = 0; // initialize Conductivity comm buffers memset( &condWriteCmdBuffer, 0, COND_WRITE_CMD_BUFFER_LEN ); memset( &condReadCmdBuffer, 0, COND_READ_CMD_BUFFER_LEN ); memset( &condWriteResponseBuffer, 0, COND_WRITE_RSP_BUFFER_LEN ); memset( &condReadResponseBuffer, 0, COND_READ_RSP_BUFFER_LEN ); initConductivityDMAchannels(); } void execConductivityCommunication( void ) { switch ( conductivityCommState ) { case COND_COMM_STATE_START: break; case COND_COMM_STATE_SEND_CMD: break; case COND_COMM_STATE_RCV_RSPNS: break; case COND_COMM_STATE_SEND_CMD_GET_INIT_STATUS: conductivityCommState = sendCmd_getInitStatus(); break; case COND_COMM_STATE_RCV_RSPNS_GET_INIT_STATUS: conductivityCommState = rcvRspns_getInitStatus(); break; case COND_COMM_STATE_SEND_CMD_UPDATE_EEPROM_DATA: { CONDUCTIVITY_EEPROM_DATA_T eepromData = {0}; conductivityCommState = sendCmd_updateEEPROMdata( eepromData ); break; } case COND_COMM_STATE_RCV_RSPNS_UPDATE_EEPROM_DATA: conductivityCommState = rcvRspns_updateEEPROMdata(); break; case COND_COMM_STATE_SEND_CMD_GET_EEPROM_DATA: conductivityCommState = sendCmd_getEEPROMdata(); break; case COND_COMM_STATE_RCV_RSPNS_GET_EEPROM_DATA: conductivityCommState = rcvRspns_getEEPROMdata(); break; case COND_COMM_STATE_SEND_CMD_UPDATE_MEASUREMENT_SETTINGS: { CONDUCTIVITY_MEASUREMENT_SETTINGS_T measurementSettings = {0}; conductivityCommState = sendCmd_updateMeasurementSettings( measurementSettings ); break; } case COND_COMM_STATE_RCV_RSPNS_UPDATE_MEASUREMENT_SETTINGS: conductivityCommState = rcvRspns_updateMeasurementSettings(); break; case COND_COMM_STATE_SEND_CMD_GET_MEASUREMENT_SETTINGS: conductivityCommState = sendCmd_getMeasurementSettings(); break; case COND_COMM_STATE_RCV_RSPNS_GET_MEASUREMENT_SETTINGS: conductivityCommState = rcvRspns_getMeasurementSettings(); break; case COND_COMM_STATE_SEND_CMD_GET_MEASUREMENT: conductivityCommState = sendCmd_getMeasurements(); break; case COND_COMM_STATE_RCV_RSPNS_GET_MEASUREMENT: conductivityCommState = rcvRspns_getMeasurements(); break; case COND_COMM_STATE_FAILED: break; default: break; } } static void initConductivityDMAchannels( void ) { // Assign DMA channels to h/w DMA requests dmaReqAssign( DMA_CH1, SCI_RECEIVE_DMA_REQUEST ); dmaReqAssign( DMA_CH3, SCI_TRANSMIT_DMA_REQUEST ); // Set DMA channel priorities dmaSetPriority( DMA_CH1, HIGHPRIORITY ); dmaSetPriority( DMA_CH3, LOWPRIORITY ); // Enable DMA block transfer complete interrupts dmaEnableInterrupt( DMA_CH1, BTC ); dmaEnableInterrupt( DMA_CH3, BTC ); // Initialize Conductivity DMA Write Control Record condDMAWriteControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) condDMAWriteControlRecord.SADD = (U32)condWriteCmdBuffer; // Transfer source address condDMAWriteControlRecord.DADD = (U32)(&(sciREG->TD)); // Dest. is SCI xmit register condDMAWriteControlRecord.CHCTRL = 0; // No chaining condDMAWriteControlRecord.ELCNT = 1; // Frame is 1 element condDMAWriteControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known condDMAWriteControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte for read condDMAWriteControlRecord.WRSIZE = ACCESS_8_BIT; // Element size is 1 byte for write condDMAWriteControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer condDMAWriteControlRecord.ADDMODERD = ADDR_INC1; // Source addressing mode is post-increment condDMAWriteControlRecord.ADDMODEWR = ADDR_FIXED; // Dest. addressing mode is fixed condDMAWriteControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off condDMAWriteControlRecord.ELSOFFSET = 0; // Not used condDMAWriteControlRecord.ELDOFFSET = 0; // Not used condDMAWriteControlRecord.FRSOFFSET = 0; // Not used condDMAWriteControlRecord.FRDOFFSET = 0; // Not used // Initialize Conductivity DMA Write Response Control Record condDMAWriteRespControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) condDMAWriteRespControlRecord.SADD = (U32)(&(sciREG->RD)); // Source is SCI recv register condDMAWriteRespControlRecord.DADD = (U32)condWriteResponseBuffer; // Transfer destination address condDMAWriteRespControlRecord.CHCTRL = 0; // No chaining condDMAWriteRespControlRecord.ELCNT = 1; // Frame is 1 element condDMAWriteRespControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known condDMAWriteRespControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte condDMAWriteRespControlRecord.WRSIZE = ACCESS_8_BIT; // condDMAWriteRespControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer condDMAWriteRespControlRecord.ADDMODERD = ADDR_FIXED; // Source addressing mode is fixed condDMAWriteRespControlRecord.ADDMODEWR = ADDR_INC1; // Dest. addressing mode is post-increment condDMAWriteRespControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off condDMAWriteRespControlRecord.ELDOFFSET = 0; // Not used condDMAWriteRespControlRecord.ELSOFFSET = 0; // Not used condDMAWriteRespControlRecord.FRDOFFSET = 0; // Not used condDMAWriteRespControlRecord.FRSOFFSET = 0; // Not used // Initialize Conductivity DMA Read Control Record condDMAReadControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) condDMAReadControlRecord.SADD = (U32)condReadCmdBuffer; // Transfer source address condDMAReadControlRecord.DADD = (U32)(&(sciREG->TD)); // Dest. is SCI xmit register condDMAReadControlRecord.CHCTRL = 0; // No chaining condDMAReadControlRecord.ELCNT = 1; // Frame is 1 element condDMAReadControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known condDMAReadControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte condDMAReadControlRecord.WRSIZE = ACCESS_8_BIT; // condDMAReadControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer condDMAReadControlRecord.ADDMODERD = ADDR_INC1; // Source addressing mode is post-increment condDMAReadControlRecord.ADDMODEWR = ADDR_FIXED; // Dest. addressing mode is fixed condDMAReadControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off condDMAReadControlRecord.ELSOFFSET = 0; // Not used condDMAReadControlRecord.ELDOFFSET = 0; // Not used condDMAReadControlRecord.FRSOFFSET = 0; // Not used condDMAReadControlRecord.FRDOFFSET = 0; // Not used // Initialize Conductivity DMA Read Response Control Record condDMAReadRespControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) condDMAReadRespControlRecord.SADD = (U32)(&(sciREG->RD)); // Source is SCI recv register condDMAReadRespControlRecord.DADD = (U32)condReadResponseBuffer; // Transfer destination address condDMAReadRespControlRecord.CHCTRL = 0; // No chaining condDMAReadRespControlRecord.ELCNT = 1; // Frame is 1 element condDMAReadRespControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known condDMAReadRespControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte condDMAReadRespControlRecord.WRSIZE = ACCESS_8_BIT; // condDMAReadRespControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer condDMAReadRespControlRecord.ADDMODERD = ADDR_FIXED; // Source addressing mode is fixed condDMAReadRespControlRecord.ADDMODEWR = ADDR_INC1; // Dest. addressing mode is post-increment condDMAReadRespControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off condDMAReadRespControlRecord.ELDOFFSET = 0; // Not used condDMAReadRespControlRecord.ELSOFFSET = 0; // Not used condDMAReadRespControlRecord.FRDOFFSET = 0; // Not used condDMAReadRespControlRecord.FRSOFFSET = 0; // Not used // There should not be any data pending yet consumeUnexpectedConductivityData(); } /*********************************************************************//** * @brief * The signalConductivityReceiptCompleted function increments a counter to indicate * that another DMA receipt from the Conductivity has completed and sets comm flags * indicating pending response from Conductivity is completed. * @details \b Inputs: none * @details \b Outputs: condReceiptCounter, condWriteCommandInProgress, * condWriteCommandResponseReceived, condReadCommandInProgress, * condReadCommandResponseReceived, condBulkWriteAndReadInProgress * @return none *************************************************************************/ void signalConductivityReceiptCompleted( void ) { condReceiptCounter++; // Did Conductivity Ack last command? if ( TRUE == condWriteCommandInProgress ) { condWriteCommandInProgress = FALSE; condWriteCommandResponseReceived = TRUE; } else if ( TRUE == condReadCommandInProgress ) { condReadCommandInProgress = FALSE; condReadCommandResponseReceived = TRUE; } // See if we want to follow up with a bulk read command if ( TRUE == condBulkWriteAndReadInProgress ) { condBulkWriteAndReadInProgress = FALSE; condReadCommandInProgress = TRUE; // Initiate bulk read command startConductivityDMAReceiptOfReadResp(); startConductivityDMAReadCmd(); } } /*********************************************************************//** * @brief * The signalConductivityTransmitCompleted function increments a counter to indicate * that another DMA transmit to the Conductivity has completed. * @details \b Inputs: none * @details \b Outputs: condTransmitCounter * @return none *************************************************************************/ void signalConductivityTransmitCompleted( void ) { condTransmitCounter++; } /*********************************************************************//** * @brief * The getImpedanceValue function gets the current calculated conductivity / impedance value. * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @details \b Inputs: lastConductivityErrorCounter * @details \b Outputs: none * @param sensor ID of conductivity sensor to get error count for. * @return The current conductivity sensor error count of a given conductivity sensor. *************************************************************************/ F64 getImpedanceValue( U32 sensorNum ) { return calculatedMeasurement[sensorNum].Conductivity; } /*********************************************************************//** * @brief * The getRTDValue function gets the current conductivity sensor * error count for a given conductivity sensor. * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @details \b Inputs: lastConductivityErrorCounter * @details \b Outputs: none * @param sensor ID of conductivity sensor to get error count for. * @return The current conductivity sensor error count of a given conductivity sensor. *************************************************************************/ F64 getRTDValue( U32 sensorNum ) { return calculatedMeasurement[sensorNum].Temperature; } static void handleConductivitySendCmd( void ) { } static void handleConductivityReceiveResponse( void ) { } static void consumeUnexpectedConductivityData( void ) { // Clear any errors sciRxError( sciREG ); // If a byte is pending read, read it if ( sciIsRxReady( sciREG ) != 0 ) { sciReceiveByte( sciREG ); } } static void setupConductivityDMAForWriteCmd( U32 bytes2Transmit ) { // Verify # of bytes does not exceed buffer length if ( bytes2Transmit <= COND_WRITE_CMD_BUFFER_LEN ) { condDMAWriteControlRecord.FRCNT = bytes2Transmit; } } static void startConductivityDMAWriteCmd( void ) { dmaSetCtrlPacket( DMA_CH3, condDMAWriteControlRecord ); dmaSetChEnable( DMA_CH3, DMA_HW ); setSCIDMATransmitInterrupt(); } static void setupConductivityDMAForWriteResp( U32 bytes2Receive ) { // Verify # of bytes does not exceed buffer length if ( bytes2Receive <= COND_WRITE_RSP_BUFFER_LEN ) { condDMAWriteRespControlRecord.FRCNT = bytes2Receive; } } static void startConductivityDMAReceiptOfWriteResp( void ) { dmaSetCtrlPacket( DMA_CH1, condDMAWriteRespControlRecord ); dmaSetChEnable( DMA_CH1, DMA_HW ); setSCIDMAReceiveInterrupt(); } static void setupConductivityDMAForReadCmd( U32 bytes2Transmit ) { // Verify # of bytes does not exceed buffer length if ( bytes2Transmit <= COND_READ_CMD_BUFFER_LEN ) { condDMAReadControlRecord.FRCNT = bytes2Transmit; } } static void startConductivityDMAReadCmd( void ) { dmaSetCtrlPacket( DMA_CH3, condDMAReadControlRecord ); dmaSetChEnable( DMA_CH3, DMA_HW ); setSCIDMATransmitInterrupt(); } static void setupConductivityDMAForReadResp( U32 bytes2Receive ) { // Verify # of bytes does not exceed buffer length if ( bytes2Receive <= COND_READ_RSP_BUFFER_LEN ) { condDMAReadRespControlRecord.FRCNT = bytes2Receive; } } static void startConductivityDMAReceiptOfReadResp( void ) { dmaSetCtrlPacket( DMA_CH1, condDMAReadRespControlRecord ); dmaSetChEnable( DMA_CH1, DMA_HW ); setSCIDMAReceiveInterrupt(); } /*********************************************************************//** * @brief * The parseMeasurementSettings Reads measurement settings from buffer and * stores in conductivityMeasurementSettings. * @details \b Inputs : none * @details \b Outputs: conductivityMeasurementSettings - Measurement Settings * @param buffer - Data to be parsed and stored. * len - Length of the input data. * @return CONDUCTIVITY_PARSE_STATUS to tell if parsing was successful or not. *************************************************************************/ static CONDUCTIVITY_PARSE_STATUS parseMeasurementSettings( const U32 *buffer, U32 len ) { CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_SUCCESS; U32 expectedDataLength = sizeof( CONDUCTIVITY_MEASUREMENT_SETTINGS_T ); // Validate buffer if ( buffer == NULL ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_NULL_BUFFER; } // Validate buffer length else if ( len != expectedDataLength ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_INVALID_LENGTH; } else { // Parse and Store the data memcpy( &conductivityMeasurementSettings, buffer, expectedDataLength ); } return parseStatus; } /*********************************************************************//** * @brief * The parseEEPROMdata Reads EEPROM data from buffer and * stores in conductivityEEPROMdata. * @details \b Inputs : none * @details \b Outputs: conductivityEEPROMdata - EEPROM data * @param buffer - Data to be parsed and stored. * len - Length of the input data. * @return CONDUCTIVITY_PARSE_STATUS to tell if parsing was successful or not. *************************************************************************/ static CONDUCTIVITY_PARSE_STATUS parseEEPROMdata( const U32 *buffer, U32 len ) { CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_SUCCESS; U32 expectedDataLength = sizeof( CONDUCTIVITY_EEPROM_DATA_T ); // Validate buffer if ( buffer == NULL ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_NULL_BUFFER; } // Validate buffer length else if ( len != expectedDataLength ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_INVALID_LENGTH; } else { // Parse and Store the data memcpy( &conductivityEEPROMdata, buffer, expectedDataLength ); } return parseStatus; } /*********************************************************************//** * @brief * The parseConductivityMeasurements Reads Conductivity Measurements / Sensor readings * from buffer and stores in rawConductivityValues. * @details \b Inputs : none * @details \b Outputs: rawConductivityValues - Raw Conductivity Measurements / Sensor readings * @param buffer - Data to be parsed and stored. * len - Length of the input data. * @return CONDUCTIVITY_PARSE_STATUS to tell if parsing was successful or not. *************************************************************************/ static CONDUCTIVITY_PARSE_STATUS parseConductivityMeasurements( const U32 *buffer, U32 len ) { CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_SUCCESS; U32 expectedDataLength = sizeof( CONDUCTIVITY_SENSOR_DATA_T ); U32 sensorCount = 0; U16 sensorIdx = 0; // // Validate buffer if ( NULL == buffer ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_NULL_BUFFER; } // Validate buffer length else if ( ( len % expectedDataLength ) != 0 ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_INVALID_LENGTH; } else { // Calculate the number of sensors for which we have received the data sensorCount = len / expectedDataLength; // Parse the data and store in conductivityMeasurements[] for ( sensorIdx = 0; sensorIdx < sensorCount; sensorIdx++ ) { // Read the sensor data temporarily CONDUCTIVITY_SENSOR_DATA_T tempSensor; memcpy(&tempSensor, ( buffer + ( sensorIdx * expectedDataLength ) ), expectedDataLength ); // And check if the received sensor number id valid if ( (tempSensor.sensorNum < 1 ) || ( tempSensor.sensorNum > MAX_TEENSY_SENSOR ) ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_INVALID_SENSOR_NUM; break; } else { // The received data value contains sensor values from 1 to 6. // So store value in array index for position (sensorNum - 1) i.e. 0 to 5. rawConductivityValues[tempSensor.sensorNum - 1] = tempSensor; } } } return parseStatus; } /** * @brief Writes a command (with optional parameters) to the write buffer. * * @param cmdIndex Index of the command in teensyCmd[]. * @param param Optional parameter string to append after the command. * @return TRUE if the command was successfully written to the write buffer, FALSE otherwise. */ static BOOL sendTeensyWriteCmd( TEENSY_CMD_INDEX_T cmdIndex, const U08* param ) { BOOL success = FALSE; // Validate command index and ensure command string exists if ( ( cmdIndex >= MAX_NUM_OF_TEENSY_CMDS ) || ( NULL == teensyCmd[ cmdIndex ] ) ) { success = FALSE; } else { const U08* baseCmd = teensyCmd[ cmdIndex ]; // Clear the write buffer before writing memset( condWriteCmdBuffer, 0, COND_WRITE_CMD_BUFFER_LEN ); // Format command with optional parameter if ( ( NULL != param ) && ( strlen( param ) > 0 ) ) { U16 written = snprintf( (U08*)condWriteCmdBuffer, COND_WRITE_CMD_BUFFER_LEN, "%s %s", baseCmd, param ); // Check if snprintf succeeded and did not overflow success = ( written > 0 ) && ( written < COND_WRITE_CMD_BUFFER_LEN ); } else { // No parameter: write only the command U16 written = snprintf( (U08*)condWriteCmdBuffer, COND_WRITE_CMD_BUFFER_LEN, "%s", baseCmd ); success = ( written > 0 ) && ( written < COND_WRITE_CMD_BUFFER_LEN ); } } return success; } /** * @brief Writes a command (without parameters) to the read buffer. * * @param cmdIndex Index of the command in teensyCmd[]. * @return TRUE if the command was successfully written to the read buffer, FALSE otherwise. */ static BOOL sendTeensyReadCmd( TEENSY_CMD_INDEX_T cmdIndex ) { BOOL success = FALSE; // Validate command index and ensure command string exists if ( ( cmdIndex >= MAX_NUM_OF_TEENSY_CMDS ) || ( NULL == teensyCmd[ cmdIndex ] ) ) { success = FALSE; } else { const U08* baseCmd = teensyCmd[ cmdIndex ]; // Clear the read buffer before writing memset( condReadCmdBuffer, 0, COND_READ_CMD_BUFFER_LEN ); // Write only the command string (no parameters allowed) U16 written = snprintf( (U08*)condReadCmdBuffer, COND_READ_CMD_BUFFER_LEN, "%s", baseCmd ); // Check if snprintf succeeded and did not overflow success = ( written > 0 ) && ( written < COND_READ_CMD_BUFFER_LEN ); } return success; } static CONDUCTIVITY_COMM_STATE_T sendCmd_initSensor( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_SEND_CMD_INIT_SENSOR; if ( FALSE == sendTeensyWriteCmd( TEENSY_CMD_INIT_SENSOR, NULL ) ) { // Handle error: log or set error flag } return state; } static CONDUCTIVITY_COMM_STATE_T rcvRspns_initSensor( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RCV_RSPNS_INIT_SENSOR; // condWriteResponseBuffer return state; } static CONDUCTIVITY_COMM_STATE_T sendCmd_getInitStatus( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_SEND_CMD_GET_INIT_STATUS; if ( FALSE == sendTeensyReadCmd( TEENSY_CMD_GET_INIT_STATUS ) ) { // Handle error } return state; } static CONDUCTIVITY_COMM_STATE_T rcvRspns_getInitStatus( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RCV_RSPNS_GET_INIT_STATUS; // condReadResponseBuffer return state; } static CONDUCTIVITY_COMM_STATE_T sendCmd_updateEEPROMdata(CONDUCTIVITY_EEPROM_DATA_T eepromData) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_SEND_CMD_UPDATE_EEPROM_DATA; // Format EEPROM data into a string U08 paramStr[256]; U16 offset = 0; U16 i = 0; for ( i = 0; i < DOUBLE_COUNT; ++i ) { offset += snprintf( paramStr + offset, sizeof(paramStr) - offset, "%.6f,", eepromData.doubleValue[i] ); } for ( i = 0; i < FLOAT_COUNT; ++i ) { offset += snprintf( paramStr + offset, sizeof(paramStr) - offset, "%.6f,", eepromData.floatValue[i] ); } // Remove trailing comma if needed if ( offset > 0 && paramStr[offset - 1] == ',' ) { paramStr[offset - 1] = '\0'; } if ( FALSE == sendTeensyWriteCmd( TEENSY_CMD_UPDATE_EEPROM_DATA, paramStr ) ) { // Handle error } return state; } static CONDUCTIVITY_COMM_STATE_T rcvRspns_updateEEPROMdata( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RCV_RSPNS_UPDATE_EEPROM_DATA; // condWriteResponseBuffer return state; } static CONDUCTIVITY_COMM_STATE_T sendCmd_getEEPROMdata( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_SEND_CMD_GET_EEPROM_DATA; if ( FALSE == sendTeensyReadCmd( TEENSY_CMD_GET_EEPROM_DATA ) ) { // Handle error } return state; } static CONDUCTIVITY_COMM_STATE_T rcvRspns_getEEPROMdata( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RCV_RSPNS_GET_EEPROM_DATA; // condReadResponseBuffer return state; } static CONDUCTIVITY_COMM_STATE_T sendCmd_updateMeasurementSettings( CONDUCTIVITY_MEASUREMENT_SETTINGS_T measurementSettings ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_SEND_CMD_UPDATE_MEASUREMENT_SETTINGS; // Format measurement settings into a string U08 paramStr[128]; snprintf( paramStr, sizeof(paramStr), "%.3f,%.3f,%.3f,%u,%u,%u,%u", measurementSettings.SinFreq, measurementSettings.DacVoltPP, measurementSettings.BiasVolt, measurementSettings.HstiaRtiaSel, measurementSettings.AdcPgaGain, measurementSettings.DftNum, measurementSettings.ADCAvgNum ); if ( FALSE == sendTeensyWriteCmd( TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS, paramStr ) ) { // Handle error } return state; } static CONDUCTIVITY_COMM_STATE_T rcvRspns_updateMeasurementSettings( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RCV_RSPNS_UPDATE_MEASUREMENT_SETTINGS; // condWriteResponseBuffer return state; } static CONDUCTIVITY_COMM_STATE_T sendCmd_getMeasurementSettings( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_SEND_CMD_GET_MEASUREMENT_SETTINGS; if ( FALSE == sendTeensyReadCmd( TEENSY_CMD_GET_MEASUREMENT_SETTINGS ) ) { // Handle error } return state; } static CONDUCTIVITY_COMM_STATE_T rcvRspns_getMeasurementSettings( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RCV_RSPNS_GET_MEASUREMENT_SETTINGS; // condReadResponseBuffer return state; } static CONDUCTIVITY_COMM_STATE_T sendCmd_getMeasurements( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_SEND_CMD_GET_MEASUREMENT; if ( FALSE == sendTeensyReadCmd( TEENSY_CMD_GET_MEASUREMENT ) ) { // Handle error } return state; } static CONDUCTIVITY_COMM_STATE_T rcvRspns_getMeasurements( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RCV_RSPNS_GET_MEASUREMENT; // condReadResponseBuffer return state; } static void sendCmd_stopMeasurement( void ) { if ( FALSE == sendTeensyReadCmd( TEENSY_CMD_STOP_MEASUREMENT ) ) { // Handle error } } static void rcvRspns_stopMeasurement( void ) { // condReadResponseBuffer } static void sendCmd_getAllMeasurements( void ) { if ( FALSE == sendTeensyReadCmd( TEENSY_CMD_GET_ALL_MEASUREMENTS ) ) { // Handle error } } static void rcvRspns_getAllMeasurements( void ) { // condReadResponseBuffer } static void sendCmd_selectSensor( TEENSY_SENSOR_INDEX_T sensorNum ) { U08 paramStr[8]; snprintf( paramStr, sizeof(paramStr), "%d", sensorNum ); if ( FALSE == sendTeensyWriteCmd( TEENSY_CMD_SELECT_SENSOR, paramStr ) ) { // Handle error } } static void rcvRspns_selectSensor( TEENSY_SENSOR_INDEX_T sensorNum ) { // condWriteResponseBuffer } static void sendCmd_getSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ) { // Assumes sensor has already been selected if ( FALSE == sendTeensyReadCmd( TEENSY_CMD_GET_SINGLE_MEASUREMENT ) ) { // Handle error } } static void rcvRspns_getSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ) { // condReadResponseBuffer } static CONDUCTIVITY_INIT_STATUS_T getInitStatus( void ) { sendInitStatusCommand(); receiveInitStatusResponse(); return conductivityInitStatus; } static const CONDUCTIVITY_EEPROM_DATA_T* getEEPROMdata(void) { return &conductivityEEPROMdata; } static const CONDUCTIVITY_MEASUREMENT_SETTINGS_T* getMeasurementSettings(void) { return &conductivityMeasurementSettings; } static const CONDUCTIVITY_SENSOR_DATA_T* getSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ) { const CONDUCTIVITY_SENSOR_DATA_T* result = NULL; if (sensorNum < MAX_TEENSY_SENSOR) { result = &rawConductivityValues[ sensorNum ]; } return result; } static const CONDUCTIVITY_SENSOR_DATA_T* getAllMeasurements( void ) { return rawConductivityValues; } static void calculateConductivity( TEENSY_SENSOR_INDEX_T sensorNum ) { F64 calculatedConductivity = 0.0; F64 B3 = conductivityCoeff[ sensorNum ].B3; F64 B2 = conductivityCoeff[ sensorNum ].B2; F64 B1 = conductivityCoeff[ sensorNum ].B1; F64 B0 = conductivityCoeff[ sensorNum ].B0; F64 R = rawConductivityValues[ sensorNum ].impRzMag; F64 Z = rawConductivityValues[ sensorNum ].rtdRzMag; calculatedConductivity = ( ( B3 * ( 1000.0 / R ) ) + ( B2 * ( Z / R ) ) + ( B1 * ( ( 100 * log( Z ) ) / R ) ) + B0 ); calculatedMeasurement[sensorNum].Conductivity = calculatedConductivity; } static void calculateTemperature( TEENSY_SENSOR_INDEX_T sensorNum ) { F64 calculatedTemperature = 0.0; F64 A1 = conductivityCoeff[ sensorNum ].A1; F64 A0 = conductivityCoeff[ sensorNum ].A0; F64 Z = rawConductivityValues[ sensorNum ].rtdRzMag; calculatedTemperature = ( ( A1 * Z ) + A0 ); calculatedMeasurement[sensorNum].Temperature = calculatedTemperature; }