/************************************************************************** * * 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 "Comm.h" #include "ConductivityTeensy.h" #include "Timers.h" #define SCI_RECEIVE_DMA_REQUEST 30 ///< Serial port receive DMA request line. #define SCI_TRANSMIT_DMA_REQUEST 31 ///< Serial port transmit DMA request line. #define COND_CMD_Q_LEN 8 ///< Maximum number of cmds that can be queue'd. #define QUEUE_START_INDEX 0U ///< Queue start index. #define COND_WRITE_CMD_BUFFER_LEN 256 ///< Conductivity transmit buffer length in bytes. #define COND_WRITE_RSP_BUFFER_LEN 256 ///< Conductivity receive buffer length in bytes. #define COND_TX_BUFFER_LEN 256 ///< Conductivity transmit buffer length in bytes. #define COND_RX_BUFFER_LEN 256 ///< Conductivity receive buffer length in bytes. #define RX_SIZE_INIT_SENSOR 2 #define RX_SIZE_GET_INIT_STATUS 1 #define RX_SIZE_UPDATE_EEPROM 1 #define RX_SIZE_GET_EEPROM ( sizeof( CONDUCTIVITY_EEPROM_DATA_T ) ) #define RX_SIZE_UPDATE_MEASUREMENT_SETTINGS 1 #define RX_SIZE_GET_MEASUREMENT_SETTNGS ( sizeof( CONDUCTIVITY_MEASUREMENT_SETTINGS_T ) ) #define RX_SIZE_GET_MEASUREMENT ( sizeof( CONDUCTIVITY_SENSOR_DATA_T ) ) #define RX_SIZE_STOP_MEASUREMENT 1 #define RX_SIZE_GET_ALL_MEASUREMENTS ( 6 * RX_SIZE_GET_MEASUREMENT ) #define RX_SIZE_SELECT_SENSOR 1 #define RX_SIZE_GET_SINGLE_MEASUREMENT ( sizeof( CONDUCTIVITY_SENSOR_DATA_T ) ) #define COND_STATUS_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Timeout before which we should receive INIT_STATUS_IN_PROGRESS from teensy #define COND_DATA_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Timeout before which we should receive INIT_STATUS_INITIALIZED or INIT_STATUS_FAILED from teensy // ********** private data ********** static CONDUCTIVITY_COMM_STATE_T conductivityCommState = COND_COMM_STATE_IDLE; static CONDUCTIVITY_COMM_STATE_T currentFailedState = COND_COMM_STATE_IDLE; static U32 condResponseTime = 0; 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 condWriteCmdRspnsRcvd = FALSE; ///< Flag indicating a response to an Conductivity write command has been received. static BOOL condReadCmdRspnsRcvd = 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. static U08 condTxBuffer[ COND_TX_BUFFER_LEN ]; ///< Conductivity transmit buffer. static U08 condRxBuffer[ COND_RX_BUFFER_LEN ]; ///< Conductivity receive buffer // Conductivity queue buffer and supporting variables. static TEENSY_CMD_INDEX_T condCmdQ[ COND_CMD_Q_LEN ]; ///< Conductivity command queue buffer. static U08 queueCount; ///< Queue count. static U08 queueRearIndex; ///< Queue rear index. static U08 queueFrontIndex; ///< Queue front index. static TEENSY_CMD_INDEX_T currentCmd; static CONDUCTIVITY_MST_PARAM_IDX_T currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_SINFREQ; // 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_UPDATE_EEPROM_STATUS_T condUpdateEEPROMstatus; static CONDUCTIVITY_UPDATE_MST_STATUS_T condUpdateSettingStatus[MAX_CONDUCTIVITY_MST_PARAM_IDX]; 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 CONDUCTIVITY_CMD_DATA_T teensyCmdMap[] = { // Command Index / Sub state Command Length of expected response data { TEENSY_CMD_INIT_SENSOR , (U08*)"a" , RX_SIZE_INIT_SENSOR }, { TEENSY_CMD_GET_INIT_STATUS , (U08*)"l" , RX_SIZE_GET_INIT_STATUS }, { TEENSY_CMD_UPDATE_EEPROM_DATA , (U08*)"upe" , RX_SIZE_UPDATE_EEPROM }, { TEENSY_CMD_GET_EEPROM_DATA , (U08*)"e" , RX_SIZE_GET_EEPROM }, { TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS , (U08*)"mst" , RX_SIZE_UPDATE_MEASUREMENT_SETTINGS }, { TEENSY_CMD_GET_MEASUREMENT_SETTINGS , (U08*)"k" , RX_SIZE_GET_MEASUREMENT_SETTNGS }, { TEENSY_CMD_GET_MEASUREMENT , (U08*)"m" , RX_SIZE_GET_MEASUREMENT }, { TEENSY_CMD_STOP_MEASUREMENT , (U08*)"n" , RX_SIZE_STOP_MEASUREMENT }, { TEENSY_CMD_GET_ALL_MEASUREMENTS , (U08*)"g" , RX_SIZE_GET_ALL_MEASUREMENTS }, { TEENSY_CMD_SELECT_SENSOR , (U08*)"j" , RX_SIZE_SELECT_SENSOR }, { TEENSY_CMD_GET_SINGLE_MEASUREMENT , (U08*)"h" , RX_SIZE_GET_SINGLE_MEASUREMENT }, }; static const U08* condSettingsParam = { "sinfreq", "dacpp", "bias", "rtia", "pga", "dftnum", "avgnum" }; // Conductivity cmd data structs TEENSY_SENSOR_INDEX_T currentSelectedSensor; CONDUCTIVITY_EEPROM_DATA_T eePromDataTX; CONDUCTIVITY_EEPROM_DATA_T eePromDataRX; CONDUCTIVITY_MEASUREMENT_SETTINGS_T measurementSettingsTX; CONDUCTIVITY_MEASUREMENT_SETTINGS_T measurementSettingsRX; // ********** private function prototypes ********** static void initConductivityDMAchannels( void ); static CONDUCTIVITY_COMM_STATE_T handleConductivityIdle( void ); static CONDUCTIVITY_COMM_STATE_T handleConductivityTX( void ); static CONDUCTIVITY_COMM_STATE_T handleConductivityRX( void ); static CONDUCTIVITY_COMM_STATE_T handleFailedState( void ); static void consumeUnexpectedConductivityData( void ); static BOOL isQueueFull ( void ); static BOOL isQueueEmpty ( void ); static BOOL enqueue ( TEENSY_CMD_INDEX_T cmd ); static void dequeue( 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 U08 *buffer, U32 len ); static CONDUCTIVITY_PARSE_STATUS parseEEPROMdata( const U08 *buffer, U32 len ); static CONDUCTIVITY_PARSE_STATUS parseConductivityMeasurements( const U08 *buffer, U32 len ); static BOOL txTeensyWriteCmd( TEENSY_CMD_INDEX_T cmdIndex, const U08* param ); static BOOL rxTeensyReadRsp( TEENSY_CMD_INDEX_T cmdIndex ); static CONDUCTIVITY_COMM_STATE_T txInitSensor( void ); static CONDUCTIVITY_COMM_STATE_T rxInitSensor( void ); static CONDUCTIVITY_COMM_STATE_T txGetInitStatus( void ); static CONDUCTIVITY_COMM_STATE_T rxGetInitStatus( void ); static CONDUCTIVITY_COMM_STATE_T txUpdateEEPROMdata( CONDUCTIVITY_EEPROM_DATA_T eepromData); static CONDUCTIVITY_COMM_STATE_T rxUpdateEEPROMdata( void ); static CONDUCTIVITY_COMM_STATE_T txGetEEPROMdata( void ); static CONDUCTIVITY_COMM_STATE_T rxGetEEPROMdata( void ); static CONDUCTIVITY_COMM_STATE_T txUpdateMeasurementSettings( CONDUCTIVITY_MEASUREMENT_SETTINGS_T measurementSettings ); static CONDUCTIVITY_COMM_STATE_T rxUpdateMeasurementSettings( void ); static CONDUCTIVITY_COMM_STATE_T txGetMeasurementSettings( void ); static CONDUCTIVITY_COMM_STATE_T rxGetMeasurementSettings( void ); static CONDUCTIVITY_COMM_STATE_T txGetMeasurements( void ); static CONDUCTIVITY_COMM_STATE_T rxGetMeasurements( void ); static CONDUCTIVITY_COMM_STATE_T txStopMeasurement( void ); static CONDUCTIVITY_COMM_STATE_T rxStopMeasurement( void ); static CONDUCTIVITY_COMM_STATE_T txGetAllMeasurements( void ); static CONDUCTIVITY_COMM_STATE_T rxGetAllMeasurements( void ); static CONDUCTIVITY_COMM_STATE_T txSelectSensor( TEENSY_SENSOR_INDEX_T sensorNum ); static CONDUCTIVITY_COMM_STATE_T rxSelectSensor( TEENSY_SENSOR_INDEX_T sensorNum ); static CONDUCTIVITY_COMM_STATE_T txGetSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ); static CONDUCTIVITY_COMM_STATE_T rxGetSingleMeasurement( 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_IDLE; condReceiptCounter = 0; condTransmitCounter = 0; condResponseTime = 0; // initialize Conductivity comm buffers // memset( &condWriteCmdBuffer, 0, COND_WRITE_CMD_BUFFER_LEN ); // memset( &condReadCmdBuffer, 0, COND_READ_CMD_BUFFER_LEN ); memset( &condTxBuffer, 0, COND_TX_BUFFER_LEN ); memset( &condRxBuffer, 0, COND_RX_BUFFER_LEN ); initConductivityDMAchannels(); // add init conductivity commands enqueue( TEENSY_CMD_INIT_SENSOR ); enqueue( TEENSY_CMD_GET_INIT_STATUS ); currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_SINFREQ; enqueue( TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS ); } static void initConductivityDMAchannels( void ) { memset( &condWriteCmdBuffer, 0, COND_WRITE_CMD_BUFFER_LEN ); memset( &condWriteResponseBuffer, 0, COND_WRITE_RSP_BUFFER_LEN ); // Enable interrupt notifications for FPGA serial port sciEnableNotification( sciREG, SCI_OE_INT | SCI_FE_INT ); // 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 RecordfpgaReadCmdBuffer // condDMAReadControlRecord.PORTASGN = 4; // Port B (only choice per datasheet) // condDMAReadControlRecord.SADD = (U32)condRxBuffer; // 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)condRxBuffer; // 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 execConductivityTeensy function manages incoming data exchanges with * the Teensy board over UART. * @details \b Inputs: conductivityCommState * @details \b Outputs: conductivityCommState * @return none *************************************************************************/ void execConductivityTeensy( void ) { switch ( conductivityCommState ) { case COND_COMM_STATE_IDLE: conductivityCommState = handleConductivityIdle(); break; case COND_COMM_STATE_TX: conductivityCommState = handleConductivityTX(); break; case COND_COMM_STATE_RX: conductivityCommState = handleConductivityRX(); break; case COND_COMM_STATE_FAILED: conductivityCommState = handleFailedState(); break; default: SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, (U32)conductivityCommState ) break; } } /*********************************************************************//** * @brief * The handleConductivityIdle handles the command queue and transitions to the respective * comm state. * @details \b Inputs: TBD * @details \b Outputs: TBD * @return none *************************************************************************/ static CONDUCTIVITY_COMM_STATE_T handleConductivityIdle( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_IDLE; if ( !isQueueEmpty() ) { dequeue(); state = COND_COMM_STATE_TX; } return state; } /*********************************************************************//** * @brief * The handleConductivityTX handles the transmission of data over UART * to the Teensy board. * @details \b Inputs: TBD * @details \b Outputs: TBD * @return none *************************************************************************/ static CONDUCTIVITY_COMM_STATE_T handleConductivityTX( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; switch ( currentCmd ) { case TEENSY_CMD_INIT_SENSOR: state = txInitSensor(); break; case TEENSY_CMD_GET_INIT_STATUS: state = txGetInitStatus(); break; case TEENSY_CMD_UPDATE_EEPROM_DATA: state = txUpdateEEPROMdata( eePromDataTX ); break; case TEENSY_CMD_GET_EEPROM_DATA: state = txGetEEPROMdata(); break; case TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS: state = txUpdateMeasurementSettings( measurementSettingsTX ); break; case TEENSY_CMD_GET_MEASUREMENT_SETTINGS: state = txGetMeasurementSettings(); break; case TEENSY_CMD_GET_MEASUREMENT: state = txGetMeasurements(); break; case TEENSY_CMD_STOP_MEASUREMENT: txStopMeasurement(); break; case TEENSY_CMD_GET_ALL_MEASUREMENTS: txGetAllMeasurements(); break; case TEENSY_CMD_SELECT_SENSOR: txSelectSensor( currentSelectedSensor ); break; case TEENSY_CMD_GET_SINGLE_MEASUREMENT: txGetSingleMeasurement( currentSelectedSensor ); break; default: break; } return state; } /*********************************************************************//** * @brief * The handleConductivityRX handles the receiving of data over UART * to the Teensy board. * @details \b Inputs: TBD * @details \b Outputs: TBD * @return none *************************************************************************/ static CONDUCTIVITY_COMM_STATE_T handleConductivityRX( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; switch ( currentCmd ) { case TEENSY_CMD_INIT_SENSOR: state = rxInitSensor(); break; case TEENSY_CMD_GET_INIT_STATUS: state = rxGetInitStatus(); break; case TEENSY_CMD_UPDATE_EEPROM_DATA: state = rxUpdateEEPROMdata( ); break; case TEENSY_CMD_GET_EEPROM_DATA: state = rxGetEEPROMdata(); break; case TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS: state = rxUpdateMeasurementSettings( ); break; case TEENSY_CMD_GET_MEASUREMENT_SETTINGS: state = rxGetMeasurementSettings(); break; case TEENSY_CMD_GET_MEASUREMENT: state = rxGetMeasurements(); break; case TEENSY_CMD_STOP_MEASUREMENT: rxStopMeasurement(); break; case TEENSY_CMD_GET_ALL_MEASUREMENTS: rxGetAllMeasurements(); break; case TEENSY_CMD_SELECT_SENSOR: rxSelectSensor( currentSelectedSensor ); break; case TEENSY_CMD_GET_SINGLE_MEASUREMENT: rxGetSingleMeasurement( currentSelectedSensor ); break; } return state; } static CONDUCTIVITY_COMM_STATE_T handleFailedState( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_FAILED; switch( state ) { case TEENSY_CMD_INIT_SENSOR: break; case TEENSY_CMD_GET_INIT_STATUS: break; case TEENSY_CMD_UPDATE_EEPROM_DATA: break; case TEENSY_CMD_GET_EEPROM_DATA: break; case TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS: break; case TEENSY_CMD_GET_MEASUREMENT_SETTINGS: break; case TEENSY_CMD_GET_MEASUREMENT: break; case TEENSY_CMD_STOP_MEASUREMENT: break; case TEENSY_CMD_GET_ALL_MEASUREMENTS: break; case TEENSY_CMD_SELECT_SENSOR: break; case TEENSY_CMD_GET_SINGLE_MEASUREMENT: break; default: break; } return state; } /*********************************************************************//** * @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, * condWriteCmdRspnsRcvd, condReadCommandInProgress, * condReadCmdRspnsRcvd, condBulkWriteAndReadInProgress * @return none *************************************************************************/ void signalConductivityReceiptCompleted( void ) { condReceiptCounter++; // Did Conductivity Ack last command? if ( TRUE == condWriteCommandInProgress ) { condWriteCommandInProgress = FALSE; condWriteCmdRspnsRcvd = TRUE; } else if ( TRUE == condReadCommandInProgress ) { condReadCommandInProgress = FALSE; condReadCmdRspnsRcvd = 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; } /*********************************************************************//** * @brief * The isQueueFull checks whether the queue is full and if it is full, * it will return a true. * @details Inputs: queueCount * @details Outputs: none * @return TRUE is queue is full *************************************************************************/ static BOOL isQueueFull ( void ) { BOOL isFull = FALSE; if ( queueCount >= COND_CMD_Q_LEN - 1 ) { isFull = TRUE; } return isFull; } /*********************************************************************//** * @brief * The isQueueEmpty checks whether the queue is empty and if it is empty, * it will return a false. * @details Inputs: queueCount * @details Outputs: none * @return TRUE if queue is not empty *************************************************************************/ static BOOL isQueueEmpty ( void ) { BOOL isEmpty = TRUE; if ( queueCount > 0 ) { isEmpty = FALSE; } return isEmpty; } /*********************************************************************//** * @brief * The dequeue function adds a cmd from the cmd queue if it is not full. * @details Inputs: condCmdQ[], queueRearIndex, queueCount * @details Outputs: condCmdQ[], queueRearIndex, queueCount * @param cmd the Cmd ID to be queue'd * @return none *************************************************************************/ static BOOL enqueue ( TEENSY_CMD_INDEX_T cmd ) { BOOL result = FALSE; _disable_IRQ(); if ( !isQueueFull() ) { queueCount++; condCmdQ[ queueRearIndex ] = cmd; queueRearIndex = INC_WRAP( queueRearIndex, 0, COND_CMD_Q_LEN - 1 ); result = TRUE; } _enable_IRQ(); return result; } /*********************************************************************//** * @brief * The dequeue function removes a job from the job queue if it is not empty. * @details Inputs: condCmdQ[], queueFrontIndex, queueCount * @details Outputs: condCmdQ[], queueFrontIndex, queueCount, currentCmd * @return none *************************************************************************/ static void dequeue( void ) { U32 tempIndex; _disable_IRQ(); tempIndex = queueFrontIndex; if ( !isQueueEmpty() ) { queueFrontIndex = INC_WRAP( queueFrontIndex, 0, COND_CMD_Q_LEN - 1 ); currentCmd = condCmdQ [ tempIndex ]; } if ( queueCount > 0 ) { queueCount--; } _enable_IRQ(); } 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_TX_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_RX_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_RX_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_RX_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 U08 *buffer, U32 len) { CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_NONE; U32 expectedDataLength = sizeof(CONDUCTIVITY_MEASUREMENT_SETTINGS_T); // Validate buffer if (buffer == NULL) { parseStatus = CONDUCTIVITY_PARSE_ERROR_NULL_BUFFER; } else if (len != expectedDataLength) { parseStatus = CONDUCTIVITY_PARSE_ERROR_INVALID_LENGTH; } else { // Parse and store the data memcpy(&conductivityMeasurementSettings, buffer, expectedDataLength); parseStatus = CONDUCTIVITY_PARSE_SUCCESS; } 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 U08 *buffer, U32 len) { CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_NONE; 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); parseStatus = CONDUCTIVITY_PARSE_SUCCESS; } 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 U08 *buffer, U32 len) { CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_NONE; 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 ); // Check if the received sensor number is valid if ( ( tempSensor.sensorNum < 1 ) || ( tempSensor.sensorNum > MAX_TEENSY_SENSOR ) ) { parseStatus = CONDUCTIVITY_PARSE_ERROR_INVALID_SENSOR_NUM; break; } else { // Store value in array index for position (sensorNum - 1) rawConductivityValues[tempSensor.sensorNum - 1] = tempSensor; parseStatus = CONDUCTIVITY_PARSE_SUCCESS; } } } 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 txTeensyWriteCmd( TEENSY_CMD_INDEX_T cmdIndex, const U08* param ) { BOOL success = FALSE; U16 written = 0; // Validate command index and ensure command string exists if ( ( cmdIndex >= MAX_NUM_OF_TEENSY_CMDS ) || ( NULL == teensyCmdMap[ cmdIndex ].teensyCMD ) ) { success = FALSE; } else { const U08* baseCmd = (const U08*)teensyCmdMap[ cmdIndex ].teensyCMD; // Clear the write buffer before writing memset( &condTxBuffer, 0, COND_TX_BUFFER_LEN ); // Format command with optional parameter if ( ( NULL != param ) && ( strlen( (const char*)param ) > 0 ) ) { written = snprintf( (char*)condTxBuffer, COND_TX_BUFFER_LEN, "%s,%s", (const char*)baseCmd, (const char*)param ); } else { written = snprintf( (char*)condTxBuffer, COND_TX_BUFFER_LEN, "%s", (const char*)baseCmd ); } } if ( written > 0 ) { memcpy( &condWriteCmdBuffer, &condTxBuffer, written ); success = TRUE; } condWriteCommandInProgress = TRUE; setupConductivityDMAForWriteCmd( written ); setupConductivityDMAForWriteResp( teensyCmdMap[ cmdIndex ].rxSize ); startConductivityDMAReceiptOfWriteResp(); startConductivityDMAWriteCmd(); 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 rxTeensyReadRsp( TEENSY_CMD_INDEX_T cmdIndex ) { BOOL success = FALSE; if ( TRUE == condWriteCmdRspnsRcvd ) { // Clear the read buffer before writing memset( &condRxBuffer, 0, COND_RX_BUFFER_LEN ); memcpy( &condRxBuffer, &condWriteResponseBuffer, teensyCmdMap[ cmdIndex ].rxSize ); success = TRUE; } // Should not be any data received at this time consumeUnexpectedConductivityData(); return success; } static CONDUCTIVITY_COMM_STATE_T txInitSensor( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; // If the init sensor cmd was sent successfully if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_INIT_SENSOR, NULL ) ) { // Get the current time condResponseTime = getMSTimerCount(); // Go to receive state to receive the init status state = COND_COMM_STATE_RX; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } return state; } static CONDUCTIVITY_COMM_STATE_T rxInitSensor( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; CONDUCTIVITY_INIT_STATUS_T initStatusInProgress = CONDUCTIVITY_INIT_STATUS_FAILED; // set to fail for testing CONDUCTIVITY_INIT_STATUS_T initStatusInitialized = CONDUCTIVITY_INIT_STATUS_FAILED; // if data populates BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_INIT_SENSOR ); if ( TRUE == recvComplete ) { // Reset the timer for next use. condResponseTime = 0; // Read the data from the receive buffer initStatusInProgress = (CONDUCTIVITY_INIT_STATUS_T)condRxBuffer[0]; initStatusInitialized = (CONDUCTIVITY_INIT_STATUS_T)condRxBuffer[1]; // Store the init status conductivityInitStatus = initStatusInitialized; switch(conductivityInitStatus) { case CONDUCTIVITY_INIT_STATUS_UNITIALIZED: break; case CONDUCTIVITY_INIT_STATUS_IN_PROGRESS: state = COND_COMM_STATE_IDLE; break; case CONDUCTIVITY_INIT_STATUS_INITIALIZED: state = COND_COMM_STATE_IDLE; break; case CONDUCTIVITY_INIT_STATUS_FAILED: default: state = COND_COMM_STATE_FAILED; break; } } else if ( TRUE == didTimeout( condResponseTime, COND_STATUS_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txGetInitStatus( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; // If the get init status cmd was sent successfully if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_GET_INIT_STATUS, NULL ) ) { // Get the current time condResponseTime = getMSTimerCount(); // Go to receive state to receive the init status state = COND_COMM_STATE_RX; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } return state; } static CONDUCTIVITY_COMM_STATE_T rxGetInitStatus( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_GET_INIT_STATUS ); if ( TRUE == recvComplete ) { // Reset the timer for next use. condResponseTime = 0; // Read the data from the receive buffer memcpy(&conductivityInitStatus, &condRxBuffer, teensyCmdMap[ TEENSY_CMD_GET_INIT_STATUS ].rxSize); // conductivityInitStatus = (CONDUCTIVITY_INIT_STATUS_T)condRxBuffer[0]; switch(conductivityInitStatus) { case CONDUCTIVITY_INIT_STATUS_UNITIALIZED: break; case CONDUCTIVITY_INIT_STATUS_IN_PROGRESS: state = COND_COMM_STATE_IDLE; break; case CONDUCTIVITY_INIT_STATUS_INITIALIZED: state = COND_COMM_STATE_IDLE; break; case CONDUCTIVITY_INIT_STATUS_FAILED: default: state = COND_COMM_STATE_FAILED; break; } } else if ( TRUE == didTimeout( condResponseTime, COND_STATUS_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txUpdateEEPROMdata( CONDUCTIVITY_EEPROM_DATA_T eepromData ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; // Format EEPROM data into a string U08 paramStr[256]; U16 offset = 0; U16 i = 0; // Pack the command and EEPROM data for ( i = 0; i < DOUBLE_COUNT; ++i ) { offset += snprintf( (char*)(paramStr + offset), sizeof(paramStr) - offset, "%.6f,", eepromData.doubleValue[i] ); } for ( i = 0; i < FLOAT_COUNT; ++i ) { offset += snprintf( (char*)(paramStr + offset), sizeof(paramStr) - offset, "%.6f,", eepromData.floatValue[i] ); } // Remove trailing comma if needed if ( ( offset > 0 ) && ( paramStr[ offset - 1 ] == ',' ) ) { paramStr[ offset - 1 ] = '\0'; } // Transmit the command and the EEPROM data and check if it was sent successfully if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_UPDATE_EEPROM_DATA, paramStr ) ) { // Get the current time condResponseTime = getMSTimerCount(); // Go to receive state to receive the EEPROM update status state = COND_COMM_STATE_RX; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } return state; } static CONDUCTIVITY_COMM_STATE_T rxUpdateEEPROMdata( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_UPDATE_EEPROM_DATA ); if ( TRUE == recvComplete ) { // Reset the timer for next use. condResponseTime = 0; // Read the data from the receive buffer memcpy(&condUpdateEEPROMstatus, &condRxBuffer, teensyCmdMap[ TEENSY_CMD_UPDATE_EEPROM_DATA ].rxSize); // condUpdateEEPROMstatus = (CONDUCTIVITY_UPDATE_EEPROM_STATUS_T)condRxBuffer[0]; // Go to the idle state to execute next cmd in the queue state = COND_COMM_STATE_IDLE; } else if ( TRUE == didTimeout( condResponseTime, COND_STATUS_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txGetEEPROMdata( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; // If the get EEPROM data cmd was sent successfully if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_GET_EEPROM_DATA, NULL ) ) { // Get the current time condResponseTime = getMSTimerCount(); // Go to receive state to receive the EEPROM data state = COND_COMM_STATE_RX; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } return state; } static CONDUCTIVITY_COMM_STATE_T rxGetEEPROMdata( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_NONE; state = COND_COMM_STATE_IDLE; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_GET_EEPROM_DATA ); if ( TRUE == recvComplete ) { // Reset the timer for next use. condResponseTime = 0; // Read the data from the receive buffer memcpy(&conductivityEEPROMdata, &condRxBuffer, teensyCmdMap[ TEENSY_CMD_GET_EEPROM_DATA ].rxSize); // parseStatus = parseEEPROMdata( condRxBuffer, COND_RX_BUFFER_LEN ); // Check if parsing was done successfully if(CONDUCTIVITY_PARSE_SUCCESS == parseStatus) { // Go to the idle state to execute next cmd in the queue state = COND_COMM_STATE_IDLE; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } } else if ( TRUE == didTimeout( condResponseTime, COND_DATA_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txUpdateMeasurementSettings( CONDUCTIVITY_MEASUREMENT_SETTINGS_T measurementSettings) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; U08 paramStr[64]; switch (currentSettingParam) { case CONDUCTIVITY_MST_PARAM_IDX_SINFREQ: snprintf(paramStr, sizeof(paramStr), "%s,%.3f", condSettingsParam[currentSettingParam], measurementSettings.SinFreq); break; case CONDUCTIVITY_MST_PARAM_IDX_DACPP: snprintf(paramStr, sizeof(paramStr), "%s,%.3f", condSettingsParam[currentSettingParam], measurementSettings.DacVoltPP); break; case CONDUCTIVITY_MST_PARAM_IDX_BIAS: snprintf(paramStr, sizeof(paramStr), "%s,%.3f", condSettingsParam[currentSettingParam], measurementSettings.BiasVolt); break; case CONDUCTIVITY_MST_PARAM_IDX_RTIA: snprintf(paramStr, sizeof(paramStr), "%s,%u", condSettingsParam[currentSettingParam], measurementSettings.HstiaRtiaSel); break; case CONDUCTIVITY_MST_PARAM_IDX_PGA: snprintf(paramStr, sizeof(paramStr), "%s,%u", condSettingsParam[currentSettingParam], measurementSettings.AdcPgaGain); break; case CONDUCTIVITY_MST_PARAM_IDX_DFTNUM: snprintf(paramStr, sizeof(paramStr), "%s,%u", condSettingsParam[currentSettingParam], measurementSettings.DftNum); break; case CONDUCTIVITY_MST_PARAM_IDX_AVGNUM: snprintf(paramStr, sizeof(paramStr), "%s,%u", condSettingsParam[currentSettingParam], measurementSettings.ADCAvgNum); break; default: // Go to failed state state = COND_COMM_STATE_FAILED; break; } // If update measurement settings cmd was sent successfully if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS, paramStr ) ) { // Get the current time condResponseTime = getMSTimerCount(); // Go to receive state to receive the EEPROM data state = COND_COMM_STATE_RX; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } return state; } static CONDUCTIVITY_COMM_STATE_T rxUpdateMeasurementSettings( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; CONDUCTIVITY_UPDATE_MST_STATUS_T updateSettingStatus = COND_MST_STATUS_ERR_UNRECOGNIZED_PARAM; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS ); if ( TRUE == recvComplete ) { // Get the time stamp for next parameter condResponseTime = getMSTimerCount(); // Read the data from the receive buffer memcpy(&updateSettingStatus, &condRxBuffer, teensyCmdMap[ TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS ].rxSize); // updateSettingStatus = ( CONDUCTIVITY_UPDATE_MST_STATUS_T )condTxBuffer[0]; // Store the status of update measurement settings for the current param condUpdateSettingStatus[currentSettingParam] = updateSettingStatus; // Move to TX state to update the next param. state = COND_COMM_STATE_TX; switch (currentSettingParam) { case CONDUCTIVITY_MST_PARAM_IDX_SINFREQ: currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_DACPP; break; case CONDUCTIVITY_MST_PARAM_IDX_DACPP: currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_BIAS; break; case CONDUCTIVITY_MST_PARAM_IDX_BIAS: currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_RTIA; break; case CONDUCTIVITY_MST_PARAM_IDX_RTIA: currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_PGA; break; case CONDUCTIVITY_MST_PARAM_IDX_PGA: currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_DFTNUM; break; case CONDUCTIVITY_MST_PARAM_IDX_DFTNUM: currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_AVGNUM; break; case CONDUCTIVITY_MST_PARAM_IDX_AVGNUM: { // Reset the timer for next use. condResponseTime = 0; // Update the current setting param to the first param in the list currentSettingParam = CONDUCTIVITY_MST_PARAM_IDX_SINFREQ; // Go to the idle state. All the measurement settings param have been updated. state = COND_COMM_STATE_IDLE; break; } default: // Go to failed state state = COND_COMM_STATE_FAILED; break; } } else if ( TRUE == didTimeout( condResponseTime, COND_STATUS_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txGetMeasurementSettings( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; // If get measurement settings cmd was sent successfully if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_GET_MEASUREMENT_SETTINGS, NULL ) ) { // Get the current time condResponseTime = getMSTimerCount(); // Go to receive state to receive the EEPROM data state = COND_COMM_STATE_RX; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } return state; } static CONDUCTIVITY_COMM_STATE_T rxGetMeasurementSettings( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; CONDUCTIVITY_PARSE_STATUS parseStatus = CONDUCTIVITY_PARSE_NONE; state = COND_COMM_STATE_IDLE; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_GET_MEASUREMENT_SETTINGS ); if ( TRUE == recvComplete ) { // Reset the timer for next use. condResponseTime = 0; // Read the data from the receive buffer memcpy(&conductivityMeasurementSettings, &condRxBuffer, teensyCmdMap[ TEENSY_CMD_GET_MEASUREMENT_SETTINGS ].rxSize); // parseStatus = parseMeasurementSettings( condRxBuffer, COND_RX_BUFFER_LEN ); // Check if parsing was done successfully if(CONDUCTIVITY_PARSE_SUCCESS == parseStatus) { // Go to the idle state to execute next cmd in the queue state = COND_COMM_STATE_IDLE; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } } else if ( TRUE == didTimeout( condResponseTime, COND_DATA_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txGetMeasurements( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; // If get measurement settings cmd was sent successfully if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_GET_MEASUREMENT, NULL ) ) { // Get the current time condResponseTime = getMSTimerCount(); // Go to receive state to receive the measurement data state = COND_COMM_STATE_RX; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } return state; } static CONDUCTIVITY_COMM_STATE_T rxGetMeasurements( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_GET_MEASUREMENT ); if ( TRUE == recvComplete ) { // Get the time stamp for next sensor packet condResponseTime = getMSTimerCount(); // Read the data from the receive buffer CONDUCTIVITY_PARSE_STATUS parseStatus = parseConductivityMeasurements( condRxBuffer, COND_RX_BUFFER_LEN ); // Check if parsing was done successfully if(CONDUCTIVITY_PARSE_SUCCESS == parseStatus) { // Go to the idle state to execute next cmd in the queue state = COND_COMM_STATE_IDLE; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } } else if ( TRUE == didTimeout( condResponseTime, COND_DATA_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txStopMeasurement( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_STOP_MEASUREMENT, NULL ) ) { } return state; } static CONDUCTIVITY_COMM_STATE_T rxStopMeasurement( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; return state; } static CONDUCTIVITY_COMM_STATE_T txGetAllMeasurements( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_GET_ALL_MEASUREMENTS, NULL ) ) { // Get the current time condResponseTime = getMSTimerCount(); } return state; } static CONDUCTIVITY_COMM_STATE_T rxGetAllMeasurements( void ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_GET_ALL_MEASUREMENTS ); if ( TRUE == recvComplete ) { // Reset the timer for next use. condResponseTime = 0; // Read the data from the receive buffer CONDUCTIVITY_PARSE_STATUS parseStatus = parseConductivityMeasurements( condRxBuffer, COND_RX_BUFFER_LEN ); // Check if parsing was done successfully if(CONDUCTIVITY_PARSE_SUCCESS == parseStatus) { // Go to the idle state to execute next cmd in the queue state = COND_COMM_STATE_IDLE; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } } else if ( TRUE == didTimeout( condResponseTime, COND_DATA_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } static CONDUCTIVITY_COMM_STATE_T txSelectSensor( TEENSY_SENSOR_INDEX_T sensorNum ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; U08 paramStr[8]; snprintf( (char*)paramStr, sizeof(paramStr), "%d", sensorNum ); if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_SELECT_SENSOR, paramStr ) ) { } return state; } static CONDUCTIVITY_COMM_STATE_T rxSelectSensor( TEENSY_SENSOR_INDEX_T sensorNum ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; return state; } static CONDUCTIVITY_COMM_STATE_T txGetSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_TX; // Assumes sensor has already been selected if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_GET_SINGLE_MEASUREMENT, NULL ) ) { // Get the current time condResponseTime = getMSTimerCount(); } return state; } static CONDUCTIVITY_COMM_STATE_T rxGetSingleMeasurement( TEENSY_SENSOR_INDEX_T sensorNum ) { CONDUCTIVITY_COMM_STATE_T state = COND_COMM_STATE_RX; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_GET_SINGLE_MEASUREMENT ); if ( TRUE == recvComplete ) { // Reset the timer for next use. condResponseTime = 0; // Read the data from the receive buffer CONDUCTIVITY_PARSE_STATUS parseStatus = parseConductivityMeasurements( condRxBuffer, COND_RX_BUFFER_LEN ); // Check if parsing was done successfully if(CONDUCTIVITY_PARSE_SUCCESS == parseStatus) { // Go to the idle state to execute next cmd in the queue state = COND_COMM_STATE_IDLE; } else { // Go to failed state state = COND_COMM_STATE_FAILED; } } else if ( TRUE == didTimeout( condResponseTime, COND_DATA_TIMEOUT_MS ) ) { // Go to failed state state = COND_COMM_STATE_FAILED; } else { // Do Nothing. Wait until we either receive a response OR timeout happens. } return state; } 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; }