Index: firmware/App/Controllers/Temperatures.c =================================================================== diff -u -r3f26385e0e67b8596b06c26533353c759f3ee996 -r43d0b6c453372488c6bd26ff73e2f48f430d1931 --- firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 3f26385e0e67b8596b06c26533353c759f3ee996) +++ firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 43d0b6c453372488c6bd26ff73e2f48f430d1931) @@ -1,9 +1,25 @@ +/************************************************************************** +* +* Copyright (c) 2019-2022 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 Temperatures.c +* +* @author (last) Sean Nash +* @date (last) 12-Nov-2021 +* +* @author (original) Dara Navaei +* @date (original) 01-Aug-2021 +* +***************************************************************************/ - #include // For temperature calculations #include "FPGA.h" #include "InternalADC.h" +#include "NVDataMgmt.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "Temperatures.h" @@ -16,79 +32,91 @@ // ********** private definitions ********** -#define TEMPERATURES_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Temperatures publish data time interval. -#define TEMPERATURES_ADC_READ_INTERVAL ( MS_PER_SECOND / ( 2 * TASK_GENERAL_INTERVAL ) ) ///< Temperatures ADC read time interval. -#define ADC_FPGA_READ_DELAY_COUNT 1.0 ///< FGPA read delay upon startup. -#define TWELVE_BIT_RESOLUTION 4096U ///< 12 bit resolution conversion. -#define THERMISTOR_REFERENCE_VOLTAGE 3.0 ///< Thermistors source voltage. -#define THERMISTOR_REFERENCE_RESISTOR_AT_25 10000.0 ///< Thermistors reference resistor in ohms. -#define THERMISTOR_REFERENCE_TEMPERATURE 298.0 ///< Thermistors reference temperature in kelvin. -#define ONBOARD_THERMISTOR_BETA_VALUE 3380.0 ///< Onboard thermistor beta value. -#define POWER_SUPPLY_THERMISTOR_BETA_VALUE 3345.0 ///< Power supply beta value. -#define CELSIUS_TO_KELVIN_CONVERSION 273.15 ///< Celsius to Kelvin temperature conversion. -#define MIN_ALLOWED_TEMPERATURE 0.0 ///< Thermistors/sensors minimum allowed temperature reading. -#define MAX_ALLOWED_TEMPERATURE 80.0 ///< Thermistors/sensors maximum allowed temperature reading. -#define MAX_ALLOWED_TEMP_OUT_OF_RANGE_PERIOD ( 5 * MS_PER_SECOND ) ///< Thermistors/sensors maximum allowed temperature out of range period. +#define TEMPERATURES_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Temperatures publish data time interval. +#define TEMPERATURES_ADC_READ_INTERVAL ( MS_PER_SECOND / ( 2 * TASK_GENERAL_INTERVAL ) ) ///< Temperatures ADC read time interval. +#define ADC_FPGA_READ_DELAY_COUNT 1.0 ///< FGPA read delay upon startup. +#define TWELVE_BIT_RESOLUTION 4096U ///< 12 bit resolution conversion. +#define THERMISTOR_REFERENCE_VOLTAGE 3.0 ///< Thermistors source voltage. +#define THERMISTOR_REFERENCE_RESISTOR_AT_25 10000.0 ///< Thermistors reference resistor in ohms. +#define THERMISTOR_REFERENCE_TEMPERATURE 298.0 ///< Thermistors reference temperature in kelvin. +#define THERMISTOR_BETA_VALUE 3380.0 ///< Thermistor beta value. +#define CELSIUS_TO_KELVIN_CONVERSION 273.15 ///< Celsius to Kelvin temperature conversion. +#define ADC_BOARD_TEMP_SENSOR_CONVERSION_CONST_1 272.5 ///< ADC board temperature sensor conversion constant 1. +#define ADC_BOARD_TEMP_SENSOR_CONVERSION_CONST_2 0x800000 ///< ADC board temperature sensor conversion constant 2. +#define MIN_ALLOWED_TEMPERATURE 0.0 ///< Thermistors/sensors minimum allowed temperature reading. +#define MAX_ALLOWED_TEMPERATURE 80.0 ///< Thermistors/sensors maximum allowed temperature reading. +#define MAX_ALLOWED_TEMP_OUT_OF_RANGE_PERIOD ( 5 * MS_PER_SECOND ) ///< Thermistors/sensors maximum allowed temperature out of range period. +#define DATA_PUBLISH_COUNTER_START_COUNT 6 ///< Data publish counter start count. /// Temperatures exec states typedef enum thermistors_Exec_States { - TEMPERATURES_EXEC_STATE_START_STATE = 0, ///< Temperatures exec state start state. - TEMPERATURES_EXEC_STATE_GET_ADC_VALUES_STATE, ///< Temperatures exec state get ADC values state. - NUM_OF_TEMPERATURES_EXEC_STATES, ///< Number of temperatures exec state. + TEMPERATURES_EXEC_STATE_WAIT_FOR_POST_STATE = 0, ///< Temperatures exec state wait for POST state. + TEMPERATURES_EXEC_STATE_GET_ADC_VALUES_STATE, ///< Temperatures exec state get ADC values state. + NUM_OF_TEMPERATURES_EXEC_STATES, ///< Number of temperatures exec state. } TEMPERATURES_EXEC_STATES_T; /// Temperatures structure typedef struct { - U32 rawADCRead; ///< Temperatures raw ADC read. - OVERRIDE_F32_T temperatureValue; ///< Temperatures value. + U32 rawADCRead; ///< Temperatures raw ADC read. + OVERRIDE_F32_T temperatureValue; ///< Temperatures value. } TEMPERATURE_SENSORS_T; // ********** private data ********** static TEMPERATURES_EXEC_STATES_T temperaturesExecState; ///< Temperatures exec state. static TEMPERATURE_SENSORS_T temperaturesStatus[ NUM_OF_TEMPERATURES ]; ///< Temperature sensors status. static OVERRIDE_U32_T temperaturesPublishInterval = { TEMPERATURES_DATA_PUBLISH_INTERVAL, - TEMPERATURES_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Temperatures publish time interval override. + TEMPERATURES_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Temperatures publish time interval override. static U32 dataPublishCounter; ///< Temperatures data publish timer counter. static U32 adcReadCounter; ///< Temperatures ADC read counter. +static HD_TEMP_SENSORS_CAL_RECORD_T temperaturesCalRecord; ///< Temperatures calibration record. +static BOOL isPOSTComplete; ///< Temperatures POST complete flag. -static const F32 THERMISTOR_VOLTAGE_CONV_COEFF = THERMISTOR_REFERENCE_VOLTAGE / - (F32)TWELVE_BIT_RESOLUTION; ///< On board thermistor ADC to voltage conversion coefficient. -static const F32 ON_BOARD_THERMISTOR_REF_TEMP_INV = 1 / THERMISTOR_REFERENCE_TEMPERATURE; ///< On board thermistor reference inverse. +static const F32 THERMISTOR_VOLTAGE_CONV_COEFF = THERMISTOR_REFERENCE_VOLTAGE / + (F32)TWELVE_BIT_RESOLUTION; ///< On board thermistor ADC to voltage conversion coefficient. +static const F32 ON_BOARD_THERMISTOR_REF_TEMP_INV = 1.0 / THERMISTOR_REFERENCE_TEMPERATURE; ///< On board thermistor reference inverse. +static const F32 FGPA_BOARD_TEMP_CONVERSION_COEFF = 503.975 / (F32)TWELVE_BIT_RESOLUTION; ///< FPGA board temperature conversion coefficient. +static const F32 VENOUS_PRESS_SENSOR_TEMP_CONVERSION_COEFF = 200.0 / 2047.0; ///< Venous pressure sensor temperature conversion coefficient. +static const F32 VENOUS_PRESS_SENSOR_TEMP_CONVERSION_CONSTANT = 50.0; ///< Venous pressure sensor temperature conversion constant. +static const F32 ADC_BOARD_TEMP_SENSOR_CONVERSION_COEFF = 1.0 / 13584.0; ///< ADC board temperatures sensor conversion coefficient. +static const F32 ART_PRESS_SENSOR_TEMP_CONVERSION_COEFF = 200.0 / 2047.0; ///< Arterial pressure sensor temperature conversion coefficient. +static const F32 ART_PRESS_SENSOR_TEMP_CONVERSION_CONSTANT = 50.0; ///< Arterial pressure sensor temperature conversion constant. // ********** private function prototypes ********** -static TEMPERATURES_EXEC_STATES_T handleExecStart( void ); +static TEMPERATURES_EXEC_STATES_T handleExecWaitForPOST( void ); static TEMPERATURES_EXEC_STATES_T handleExecGetADCValues( void ); static void monitorTemperatures( void ); static void convertADC2Temperature( void ); -static F32 calculateTemperature( S32 adcValue ); +static F32 calculateThemristorTemperature( S32 adcValue ); static void publishTemperaturesData( void ); -static U32 getPublishTemperaturesDataInterval( void ); +static U32 getPublishTemperaturesDataInterval( void ); /*********************************************************************//** * @brief * The initTemperatures function initializes the temperatures module. * @details Inputs: none - * @details Outputs: temperaturesExecState, dataPublishCounter, temperaturesStatus + * @details Outputs: temperaturesExecState, dataPublishCounter, temperaturesStatus, + * isPOSTComplete * @return none *************************************************************************/ void initTemperatures( void ) { U08 i; - temperaturesExecState = TEMPERATURES_EXEC_STATE_START_STATE; - dataPublishCounter = 0; + temperaturesExecState = TEMPERATURES_EXEC_STATE_WAIT_FOR_POST_STATE; + dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; + isPOSTComplete = FALSE; for ( i = 0; i < NUM_OF_TEMPERATURES; i++ ) { memset( &temperaturesStatus[ i ], 0x0, sizeof( TEMPERATURE_SENSORS_T ) ); } - // Initialize a persistent alarm for temperatures temeprature out of range + // Initialize a persistent alarm for temperatures temperature out of range initPersistentAlarm( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, MAX_ALLOWED_TEMP_OUT_OF_RANGE_PERIOD, MAX_ALLOWED_TEMP_OUT_OF_RANGE_PERIOD ); } @@ -102,14 +130,22 @@ *************************************************************************/ SELF_TEST_STATUS_T execTemperaturesSelfTest( void ) { - SELF_TEST_STATUS_T status = SELF_TEST_STATUS_IN_PROGRESS; + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; - // TODO implement the calibration processing function. - // It returns a pass for now + BOOL calStatus = getNVRecord2Driver( GET_CAL_TEMPERATURE_SESNORS, (U08*)&temperaturesCalRecord, sizeof( HD_TEMP_SENSORS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_HD_TEMP_SENSORS, ALARM_ID_NO_ALARM ); + isPOSTComplete = TRUE; - status = SELF_TEST_STATUS_PASSED; + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } - return status; + return result; } /*********************************************************************//** @@ -121,25 +157,458 @@ *************************************************************************/ void execTemperatures( void ) { + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + getNVRecord2Driver( GET_CAL_TEMPERATURE_SESNORS, (U08*)&temperaturesCalRecord, sizeof( HD_TEMP_SENSORS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_HD_TEMP_SENSORS, ALARM_ID_NO_ALARM ); + } + // Read the sensors all the time switch ( temperaturesExecState ) { - case TEMPERATURES_EXEC_STATE_START_STATE: - temperaturesExecState = handleExecStart(); + case TEMPERATURES_EXEC_STATE_WAIT_FOR_POST_STATE: + temperaturesExecState = handleExecWaitForPOST(); break; case TEMPERATURES_EXEC_STATE_GET_ADC_VALUES_STATE: temperaturesExecState = handleExecGetADCValues(); break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HD_TEMPERATURES_INALID_EXEC_STATE, temperaturesExecState ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_TEMPERATURES_INALID_EXEC_STATE, temperaturesExecState ); temperaturesExecState = TEMPERATURES_EXEC_STATE_GET_ADC_VALUES_STATE; break; } + // Convert the ADC values to temperature + convertADC2Temperature(); + + // Monitor the values for a gross range check + // Monitor is called in this function because this driver is constantly reading + // the temperatures values. Also the internal ADC values are processed with moving average in the internalADC driver + // So the temperatures drivers just gets the latest ADC value and converts it to temperature + monitorTemperatures(); + // Publish the data - getPublishTemperaturesDataInterval(); + publishTemperaturesData(); } +/*********************************************************************//** + * @brief + * The getThermistorTemperatureValue function returns the temperature of + * a requested thermistor or temperature sensor. + * @details Inputs: thermistorsStatus + * @details Outputs: none + * @param sensorID index to get its temperature value + * @return temperature of a thermistor or temperature sensor + *************************************************************************/ +F32 getTemperatureValue( TEMPERATURES_T sensorID ) +{ + F32 temperature = 0.0; + + // Check if the temperature sensor is in range + if ( sensorID < NUM_OF_TEMPERATURES ) + { + if ( OVERRIDE_KEY == temperaturesStatus[ sensorID ].temperatureValue.override ) + { + temperature = temperaturesStatus[ sensorID ].temperatureValue.ovData; + } + else + { + temperature = temperaturesStatus[ sensorID ].temperatureValue.data; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_TEMPERATURE_SENSOR_SELECTED, sensorID ); + } + + return temperature; +} + +/*********************************************************************//** + * @brief + * The handleExecWaitForPOST function handles the wait for POST state of the + * exec state machine. + * @details Inputs: adcReadCounter + * @details Outputs: adcReadCounter + * @return next state of the exec state machine + *************************************************************************/ +static TEMPERATURES_EXEC_STATES_T handleExecWaitForPOST( void ) +{ + TEMPERATURES_EXEC_STATES_T state = TEMPERATURES_EXEC_STATE_WAIT_FOR_POST_STATE; + + // Give a short time for FPGA to boot up and start sending the ADC reads + if ( ( ++adcReadCounter > ADC_FPGA_READ_DELAY_COUNT ) && ( TRUE == isPOSTComplete ) ) + { + state = TEMPERATURES_EXEC_STATE_GET_ADC_VALUES_STATE; + adcReadCounter = 0; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleExecGetADCValues function handles the get ADC values state + * of the exec state machine. + * @details Inputs: adcReadCounter + * @details Outputs: adcReadCounter, thermistorsStatus + * @return next state of the exec machine + *************************************************************************/ +static TEMPERATURES_EXEC_STATES_T handleExecGetADCValues( void ) +{ + TEMPERATURES_EXEC_STATES_T state = TEMPERATURES_EXEC_STATE_GET_ADC_VALUES_STATE; + + // If time has elapsed to read the ADCs, read them all + if ( ++adcReadCounter >= TEMPERATURES_ADC_READ_INTERVAL ) + { + // Get all the raw readings in ADC + temperaturesStatus[ THERMISTOR_ONBOARD_NTC ].rawADCRead = getIntADCReading( INT_ADC_BOARD_THERMISTOR ); + temperaturesStatus[ THERMISTOR_POWER_SUPPLY_1 ].rawADCRead = getIntADCReading( INT_ADC_PS_THERMISTOR ); + temperaturesStatus[ TEMPSENSOR_FPGA_BOARD_SENSOR ].rawADCRead = getFPGABoardTemperature(); + temperaturesStatus[ TEMPSENSOR_VENOUS_PRESSURE_SENSOR ].rawADCRead = getFPGAVenousPressureTemperature(); + temperaturesStatus[ TEMPSENSOR_PBA_ADC_SENSOR ].rawADCRead = getFPGAPBAADCTemperature(); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) ) +#endif + { + temperaturesStatus[ TEMPSENSOR_ARTERIAL_PRESSURE_SENSOR ].rawADCRead = getFPGADVTArterialTemperature(); + } + + // Zero the counter for the next round of reading + adcReadCounter = 0; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The monitorTemperatures function monitors the temperature sensors for + * gross temperature range check. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void monitorTemperatures( void ) +{ + TEMPERATURES_T sensor; + + BOOL isTempOutOfRange = FALSE; + F32 temperature = 0.0; + U32 lastFaultSensor = 0; + F32 faultSensorTemp = 0.0; + + for ( sensor = THERMISTOR_ONBOARD_NTC; sensor < NUM_OF_TEMPERATURES; sensor++ ) + { + temperature = getTemperatureValue( sensor ); + + if ( ( temperature > MAX_ALLOWED_TEMPERATURE ) || ( temperature < MIN_ALLOWED_TEMPERATURE ) ) + { + isTempOutOfRange = TRUE; + lastFaultSensor = sensor; + faultSensorTemp = temperature; + +#ifndef _RELEASE_ + if ( ( TEMPSENSOR_ARTERIAL_PRESSURE_SENSOR == sensor ) && + ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) != SW_CONFIG_ENABLE_VALUE ) ) + { + isTempOutOfRange = FALSE; + } +#endif + } + } + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, isTempOutOfRange ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, lastFaultSensor, faultSensorTemp ); + } +} + +/*********************************************************************//** + * @brief + * The convertADCtoTemperature function converts the ADC values of different + * thermistors and temperature sensors to temperature value. + * @details Inputs: none + * @details Outputs: temperaturesStatus + * @return none + *************************************************************************/ +static void convertADC2Temperature( void ) +{ + TEMPERATURES_T sensor; + F32 temperature; + S32 rawADC; + + // Loop through the list and update the temperatures values + for ( sensor = THERMISTOR_ONBOARD_NTC; sensor < NUM_OF_TEMPERATURES; sensor++ ) + { + rawADC = (S32)( temperaturesStatus[ sensor ].rawADCRead & MASK_OFF_U32_MSB ); + + switch ( sensor ) + { + case THERMISTOR_ONBOARD_NTC: + case THERMISTOR_POWER_SUPPLY_1: + temperature = calculateThemristorTemperature( rawADC ); + break; + + case TEMPSENSOR_FPGA_BOARD_SENSOR: + // Temperature(C) = ((ADC x 503.975) / 4096) - 273.15 + // The value of 503.975/4096 has been calculated and stored in the conversion coefficient variable of the structure + temperature = ( rawADC * FGPA_BOARD_TEMP_CONVERSION_COEFF ) - CELSIUS_TO_KELVIN_CONVERSION; + break; + + case TEMPSENSOR_VENOUS_PRESSURE_SENSOR: + // Temperature (C) = ((ADC / 2047) * 200) - 50 + temperature = ( rawADC * VENOUS_PRESS_SENSOR_TEMP_CONVERSION_COEFF ) - VENOUS_PRESS_SENSOR_TEMP_CONVERSION_CONSTANT; + break; + + case TEMPSENSOR_PBA_ADC_SENSOR: + +#ifndef _RELEASE_ + // If the software configuration is not enable to read the DVT arterial pressure, set the temperature to 30 to make sure + // there is no temperature error because the sensor is not available. The old arterial sensor did not have a temperature sensor + // inside it. NOTE: this line of code should be remove later. + temperature = 30.0; + + if ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + // Temperature (C) = ((ADC - 0x800000) / 13584) - 272.5 + temperature = ( ( rawADC - ADC_BOARD_TEMP_SENSOR_CONVERSION_CONST_2 ) * ADC_BOARD_TEMP_SENSOR_CONVERSION_COEFF ) - + ADC_BOARD_TEMP_SENSOR_CONVERSION_CONST_1; + } + break; + + case TEMPSENSOR_ARTERIAL_PRESSURE_SENSOR: + +#ifndef _RELEASE_ + // If the software configuration is not enable to read the DVT arterial pressure, set the temperature to 30 to make sure + // there is no temperature error because the sensor is not available. The old arterial sensor did not have a temperature sensor + // inside it. NOTE: this line of code should be remove later. + temperature = 30.0; + + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) ) +#endif + { + // Temperature (C) = ((ADC / 2047) * 200) - 50 + temperature = ( rawADC * ART_PRESS_SENSOR_TEMP_CONVERSION_COEFF ) - ART_PRESS_SENSOR_TEMP_CONVERSION_CONSTANT; + } + break; + + default: + // Wrong sensor was called, raise an alarm + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_TEMPERATURE_SENSOR_SELECTED, sensor ); + // Wrong sensor, return temperature to be -1 + temperature = -1.0; + break; + } + + // TODO remove this code and the if statement. This configuration is until the new arterial sensor is implemented everywhere so the temperature calibration + // structure can be updated permanently. This way the PBA sensor will be replaced with the new arterial sensor. This is to make sure the + // calibration structure does not fail in different devices with different sensors + temperaturesStatus[ sensor ].temperatureValue.data = temperature; + if ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) != SW_CONFIG_ENABLE_VALUE ) + { + // Apply the calibration record the temperature values prior to updating the structures + temperaturesStatus[ sensor ].temperatureValue.data = + pow(temperature, 4) * temperaturesCalRecord.hdTemperatureSensors[ (CAL_DATA_HD_TEMEPERATURE_SENSORS_T)sensor ].fourthOrderCoeff + + pow(temperature, 3) * temperaturesCalRecord.hdTemperatureSensors[ (CAL_DATA_HD_TEMEPERATURE_SENSORS_T)sensor ].thirdOrderCoeff + + pow(temperature, 3) * temperaturesCalRecord.hdTemperatureSensors[ (CAL_DATA_HD_TEMEPERATURE_SENSORS_T)sensor ].secondOrderCoeff + + temperature * temperaturesCalRecord.hdTemperatureSensors[ (CAL_DATA_HD_TEMEPERATURE_SENSORS_T)sensor ].gain + + temperaturesCalRecord.hdTemperatureSensors[ (CAL_DATA_HD_TEMEPERATURE_SENSORS_T)sensor ].offset; + } + + } +} + +/*********************************************************************//** + * @brief + * The calculateThemristorTemperature function converts the ADC value + * of thermistors into temperature in C. Below are the calculation + * steps: + * voltage = ADC x 3 / 2^12 + * voltage = 3 x 10000 / ( 10000 + R(T) ) + * R(T) = 10000 x e^(beta x (1/T - 1/298)) + * Solve for T which is temperature in Kelvin + * @details Inputs: none + * @details Outputs: none + * @param adcValue which is the ADC value to be converted into temperature in C + * @return calculated temperature in C + *************************************************************************/ +static F32 calculateThemristorTemperature( S32 adcValue ) +{ + // Voltage = ADC x 3 / 2^12 for 12 bits resolution and a 3V ADC + // The value of 3 / 2^12 has been calculated in a const to prevent the division again + F32 thermistorVoltage = adcValue * THERMISTOR_VOLTAGE_CONV_COEFF; + + // Calculate the thermistor resistor by solving: thermistorVoltage = (3 x 10) / (10 + R(T)) + F32 thermistorResistor = ( ( THERMISTOR_REFERENCE_RESISTOR_AT_25 * THERMISTOR_REFERENCE_VOLTAGE ) - + ( THERMISTOR_REFERENCE_RESISTOR_AT_25 * thermistorVoltage ) ) / thermistorVoltage; + + // 1/T = Ln(thermistorResistor/10000)/3380 + 1/298 + F32 invTemperature = ( logf( thermistorResistor / THERMISTOR_REFERENCE_RESISTOR_AT_25 ) / THERMISTOR_BETA_VALUE ) + + ON_BOARD_THERMISTOR_REF_TEMP_INV; + + // Inverse the value to get the temperature in Kelvin and then convert it to Celsius + F32 temperature = ( 1 / invTemperature ) - CELSIUS_TO_KELVIN_CONVERSION; + + return temperature; +} + +/*********************************************************************//** + * @brief + * The getPublishTemperaturesDataInterval function gets the temperatures + * data publish interval. + * @details Inputs: temperaturesPublishInterval + * @details Outputs: none + * @return data publish time interval in counts + *************************************************************************/ +static U32 getPublishTemperaturesDataInterval( void ) +{ + U32 result = temperaturesPublishInterval.data; + + if ( OVERRIDE_KEY == temperaturesPublishInterval.override ) + { + result = temperaturesPublishInterval.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The publishTemperaturesData function publishes the temperatures sensors + * data at the specified time interval. + * @details Inputs: dataPublishCounter + * @details Outputs: dataPublishCounter + * @return none + *************************************************************************/ +static void publishTemperaturesData( void ) +{ + if ( ++dataPublishCounter > getPublishTemperaturesDataInterval() ) + { + TEMPERATURES_DATA_T sensorsData; + + // Get all the sensors/thermistors temperature values for publication + sensorsData.onboardThermistor = getTemperatureValue( THERMISTOR_ONBOARD_NTC ); + sensorsData.powerSupply1Thermistor = getTemperatureValue( THERMISTOR_POWER_SUPPLY_1 ); + sensorsData.venousPressSensorTemp = getTemperatureValue( TEMPSENSOR_VENOUS_PRESSURE_SENSOR ); + sensorsData.fpgaBoardTempSensor = getTemperatureValue( TEMPSENSOR_FPGA_BOARD_SENSOR ); + sensorsData.pbaADCTempSensor = getTemperatureValue( TEMPSENSOR_PBA_ADC_SENSOR ); + sensorsData.arterialPressSensorTemp = getTemperatureValue( TEMPSENSOR_ARTERIAL_PRESSURE_SENSOR ); + + // Broadcast the temperatures data + broadcastData( MSG_ID_HD_TEMPERATURES_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&sensorsData, sizeof( TEMPERATURES_DATA_T ) ); + + // Reset the counter + dataPublishCounter = 0; + } +} + +/************************************************************************* +* TEST SUPPORT FUNCTIONS +*************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetMeasuredTemperatureOverride function overrides the value of + * a temperature sensor/thermistor. + * @details Inputs: none + * @details Outputs: temperaturesStatus + * @param sensorID the sensor its value is overridden + * @param temperature value to override + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetMeasuredTemperatureOverride( U32 sensorID, F32 temperature ) +{ + BOOL result = FALSE; + + if ( ( sensorID < NUM_OF_TEMPERATURES ) && ( TRUE == isTestingActivated() ) ) + { + result = TRUE; + temperaturesStatus[ sensorID ].temperatureValue.ovData = temperature; + temperaturesStatus[ sensorID ].temperatureValue.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetMeasuredTemperatureOverride function resets the override + * value of a temperature sensors/thermistor. + * @details Inputs: none + * @details Outputs: temperaturesStatus + * @param sensorID which its value is reset + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetMeasuredTemperatureOverride( U32 sensorID ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + if ( sensorID < NUM_OF_TEMPERATURES ) + { + result = TRUE; + temperaturesStatus[ sensorID ].temperatureValue.override = OVERRIDE_RESET; + temperaturesStatus[ sensorID ].temperatureValue.ovData = temperaturesStatus[ sensorID ].temperatureValue.ovInitData; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetTemperturesPublishIntervalOverride function overrides the + * temperatures data publish interval. + * @details Inputs: none + * @details Outputs: temperaturesPublishInterval + * @param value which is override value for the temperatures data publish + * interval + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetTemperaturesPublishIntervalOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = value / TASK_GENERAL_INTERVAL; + + result = TRUE; + temperaturesPublishInterval.ovData = intvl; + temperaturesPublishInterval.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetTemperaturesPublishIntervalOverride function resets the override + * of the temperatures publish interval. + * @details Inputs: none + * @details Outputs: temperaturesPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetTemperaturesPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + temperaturesPublishInterval.override = OVERRIDE_RESET; + temperaturesPublishInterval.ovData = temperaturesPublishInterval.ovInitData; + } + + return result; +} + /**@}*/