Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rc45f78c0ff3b0a866b7f6233092a2e611e801460 -r1aa06c27877a9054c0655ada917a08016a60f8ef --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision c45f78c0ff3b0a866b7f6233092a2e611e801460) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 1aa06c27877a9054c0655ada917a08016a60f8ef) @@ -7,8 +7,8 @@ * * @file DGInterface.c * -* @author (last) Dong Nguyen -* @date (last) 27-Sep-2022 +* @author (last) Dara Navaei +* @date (last) 19-Oct-2022 * * @author (original) Sean * @date (original) 08-Apr-2020 @@ -24,7 +24,7 @@ #include "ModeInitPOST.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" -#include "OperationModes.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemComm.h" #include "SystemCommMessages.h" @@ -58,13 +58,15 @@ static const U32 DIP_RESERVOIRS_DATA_MESSAGE_ALARM_THRESHOLD = ((2 * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); static const U32 DIP_DG_OP_MODE_DATA_MESSAGE_ALARM_THRESHOLD = ((2 * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); -// DG status -static DG_OP_MODE_T dgCurrentOpMode = DG_MODE_INIT; ///< Current DG operation mode. -static U32 dgSubMode = 0; ///< Current state (sub-mode) of current DG operation mode. -static BOOL dgStartCommandSent = FALSE; ///< Flag indicates command to start DG has been sent. -static BOOL dgStarted = FALSE; ///< Flag indicates whether we have commanded the DG to start or stop. -static BOOL dgTrimmerHeaterOn = FALSE; ///< Flag indicates whether we have commanded the DG to start or stop the trimmer heater. +// ********** private data ********** +// DG status +static DG_OP_MODE_T dgCurrentOpMode; ///< Current DG operation mode. +static U32 dgSubMode; ///< Current state (sub-mode) of current DG operation mode. +static BOOL dgStartCommandSent; ///< Flag indicates command to start DG has been sent. +static BOOL dgStarted; ///< Flag indicates whether we have commanded the DG to start or stop. +static BOOL dgTrimmerHeaterOn; ///< Flag indicates whether we have commanded the DG to start or stop the trimmer heater. + // State machine states static U32 timeStartMS = 0; // TODO is this needed? @@ -108,13 +110,17 @@ static DG_DISINFECT_UI_STATES_T disinfectsStatus; ///< DG disinfects status. static DG_MIXING_RATIOS_T dgMixingRatios; ///< DG mixing ratios. +static HEATERS_DATA_T dgHeatersData; ///< DG heaters data. +static DG_SERVICE_AND_USAGE_DATA_T dgServiceAndUsageData; ///< DG service and usage data. // DG command response static DG_CMD_RESPONSE_T dgCmdResp[ NUM_OF_DG_COMMANDS ]; ///< Keep the latest DG command response for each command. // ********** private function prototypes ********** static void checkDGRestart( void ); +static void checkDGTrimmerHeaterStatus( void ); +static void checkDGDataFreshness( ALARM_ID_T alarmID, BOOL *dgFreshDataFlag ); /*********************************************************************//** * @brief @@ -198,7 +204,7 @@ * @param flag to signal the fresh data processing * @return None *************************************************************************/ -void checkDGDataFreshness( ALARM_ID_T alarmID, BOOL *dgFreshDataFlag ) +static void checkDGDataFreshness( ALARM_ID_T alarmID, BOOL *dgFreshDataFlag ) { if ( TRUE == *dgFreshDataFlag ) { @@ -231,7 +237,7 @@ void execDGInterfaceMonitor( void ) { // Trigger alarm if not receiving new load cell data message in timely manner - checkDGDataFreshness( ALARM_ID_HD_NEW_LOAD_CELL_DATA_MESSAGE_NOT_RECEIVE, &dgLoadCellDataFreshFlag ); + /*checkDGDataFreshness( ALARM_ID_HD_NEW_LOAD_CELL_DATA_MESSAGE_NOT_RECEIVE, &dgLoadCellDataFreshFlag ); // Trigger alarm if not receiving new dialysate temperature data message in timely manner checkDGDataFreshness( ALARM_ID_HD_NEW_DIALYSATE_TEMPERATURE_DATA_MESSAGE_NOT_RECEIVE, &dgDialysateTemperatureDataFreshFlag ); @@ -242,11 +248,16 @@ // Trigger alarm if not receiving new DG op mode message in timely manner checkDGDataFreshness( ALARM_ID_HD_NEW_DG_OPERATION_MODE_MESSAGE_NOT_RECEIVE, &dgOpModeDataFreshFlag ); + // Check to see if DG has restarted*/ + // Trigger alarm if not receiving new DG op mode message in timely manner //checkDGDataFreshness( ALARM_ID_HD_DIAL_IN_FLOW_CHECK_FAILURE, &dgDialysateFlowDataFreshFlag ); // DN-31OCT2022 - TODO: Will remove this line??? // Check to see if DG has restarted checkDGRestart(); + + // Check the status of the trimmer heater + checkDGTrimmerHeaterStatus(); } /*********************************************************************//** @@ -411,6 +422,22 @@ /*********************************************************************//** * @brief + * The getReservoirWeight function gets the load cell weight of a given reservoir. + * @details Inputs: loadCellWeightInGrams[] + * @details Outputs: none + * @param resID ID of reservoir to get weight for + * @return the current weight of the given reservoir in grams + *************************************************************************/ +F32 getReservoirWeight( DG_RESERVOIR_ID_T resID ) +{ + LOAD_CELL_ID_T lc = ( DG_RESERVOIR_1 == resID ? LOAD_CELL_RESERVOIR_1_PRIMARY : LOAD_CELL_RESERVOIR_2_PRIMARY ); + F32 wt = getLoadCellWeight( lc ); + + return wt; +} + +/*********************************************************************//** + * @brief * The getReservoirBackupWeightLargeFilter function gets the backup load cell weight * of the given reservoir after large (32 sample) filter applied. * @details Inputs: lgFilteredReservoirWeightInGrams[] @@ -432,26 +459,26 @@ /*********************************************************************//** * @brief - * The getDialysateTemperature function gets the latest dialysate temperature. - * @details Inputs: dgDialysateTemp + * The getDGDisinfectsStates function returns the DG disinfects readings. + * @details Inputs: none * @details Outputs: none - * @return the current dialysate temperature + * @return the current DG disinfects readings *************************************************************************/ -F32 getDialysateTemperature( void ) +DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) { - return dgDialysateTemp; + return disinfectsStatus; } /*********************************************************************//** * @brief - * The getDGDisinfectsStates function returns the DG disinfects readings. - * @details Inputs: none + * The getDialysateTemperature function gets the latest dialysate temperature. + * @details Inputs: dgDialysateTemp * @details Outputs: none - * @return the current DG disinfects readings + * @return the current dialysate temperature *************************************************************************/ -DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) +F32 getDialysateTemperature( void ) { - return disinfectsStatus; + return dgDialysateTemp; } /*********************************************************************//** @@ -469,26 +496,25 @@ /*********************************************************************//** * @brief - * The getReservoirWeight function gets the load cell weight of a given reservoir. - * @details Inputs: loadCellWeightInGrams[] + * The getHDVersionDGServiceAndUsageData function copies the HD version of + * the DG service and usage data into the provided buffer. + * @details Inputs: dgServiceAndUsageData * @details Outputs: none - * @param resID ID of reservoir to get weight for - * @return the current weight of the given reservoir in grams + * @param data which is a pointer of type DG_SERVICE_AND_USAGE_DATA_T that + * is the provided buffer + * @return none *************************************************************************/ -F32 getReservoirWeight( DG_RESERVOIR_ID_T resID ) +void getHDVersionDGServiceAndUsageData( DG_SERVICE_AND_USAGE_DATA_T* data ) { - LOAD_CELL_ID_T lc = ( DG_RESERVOIR_1 == resID ? LOAD_CELL_RESERVOIR_1_PRIMARY : LOAD_CELL_RESERVOIR_2_PRIMARY ); - F32 wt = getLoadCellWeight( lc ); - - return wt; + memcpy( data, &dgServiceAndUsageData, sizeof( DG_SERVICE_AND_USAGE_DATA_T ) ); } /*********************************************************************//** * @brief * The setDGOpMode function sets the latest DG operating mode reported by * the DG. * @details Inputs: none - * @details Outputs: dgCurrentOpMode, dgSubMode + * @details Outputs: dgCurrentOpMode, dgSubMode, dgOpModeDataFreshFlag * @param opMode operating mode reported by DG * @param subMode sub-mode (current state) of operating mode reported by DG * @return none @@ -513,7 +539,8 @@ * The setDialysateTemperatureReadings function sets the latest dialysate * temperatures reported by the DG. * @details Inputs: none - * @details Outputs: dgDialysateTemp, dgRedundantDialysateTemp + * @details Outputs: dgDialysateTemp, dgRedundantDialysateTemp, + * dgDialysateTemperatureDataFreshFlag * @param temp1 dialysate temperature reported by DG * @param temp2 redundant dialysate temperature reported by DG * @return none @@ -531,7 +558,8 @@ * The setDGReservoirsData function sets the latest reservoir data * reported by the DG. * @details Inputs: none - * @details Outputs: dgActiveReservoir, dgReservoirFillVolumeTarget, dgReservoirDrainVolumeTarget + * @details Outputs: dgActiveReservoir, dgReservoirFillVolumeTarget, + * dgReservoirDrainVolumeTarget, dgReservoirsDataFreshFlag * @param resID ID of active reservoir * @param fillVol Reservoir fill to volume reported by DG * @param drainVol Reservoir drain to volume reported by DG @@ -558,7 +586,7 @@ * The setDialysateFlowData function sets the latest dialysate flow rate * and its freshness status. The dialysate flow data is reported by the DG. * @details Inputs: none - * @details Outputs: dgDialysateFlowRateMlMin + * @details Outputs: dgDialysateFlowRateMlMin, dgDialysateFlowDataFreshFlag * @param flowRate latest dialysate flow rate (mL/min) reported by DG * @return none *************************************************************************/ @@ -581,7 +609,8 @@ * every 100 ms. * @details Inputs: none * @details Outputs: loadCellWeightInGrams[], smFilteredReservoirWeightInGrams[], - * lgFilteredReservoirWeightInGrams[] + * lgFilteredReservoirWeightInGrams[], lgLoadCellReadingsTotal[], + * lgLoadCellBackupReadingsTotal[], lgLoadCellReadingsIdx, dgLoadCellDataFreshFlag * @param res1Primary New weight from primary load cell of reservoir 1 * @param res1Backup New weight from backup load cell of reservoir 1 * @param res2Primary New weight from primary load cell of reservoir 2 @@ -647,11 +676,56 @@ *************************************************************************/ void setDGMixingRatios( DG_MIXING_RATIOS_T ratios ) { - memcpy( &dgMixingRatios, &ratios, sizeof(DG_MIXING_RATIOS_T) ); + memcpy( &dgMixingRatios, &ratios, sizeof( DG_MIXING_RATIOS_T ) ); } /*********************************************************************//** * @brief + * The setDGHeatersData function sets heaters data that has been read from DG. + * @details Inputs: none + * @details Outputs: dgHeatersData + * @param data which is a pointer to the received heaters data + * @return none + *************************************************************************/ +void setDGHeatersData( HEATERS_DATA_T *data ) +{ + memcpy( &dgHeatersData, data, sizeof( HEATERS_DATA_T ) ); +} + +/*********************************************************************//** + * @brief + * The setHDVersionDGServiceRecord function sets the HD version of the DG + * service record. + * @details Inputs: none + * @details Outputs: dgServiceAndUsageData + * @param data which is a pointer to the received HD version of the DG service + * record + * @return none + *************************************************************************/ +void setHDVersionDGServiceRecord( HD_VERSION_DG_SERVICE_RECORD_T* data ) +{ + dgServiceAndUsageData.isDGServiceRecordAvailable = TRUE; + memcpy( &dgServiceAndUsageData.dgServiceRecord, data, sizeof( HD_VERSION_DG_SERVICE_RECORD_T ) ); +} + +/*********************************************************************//** + * @brief + * The setHDVersionDGUsageInfo function sets the HD version of the DG + * usage information. + * @details Inputs: none + * @details Outputs: dgServiceAndUsageData + * @param data which is a pointer to the received HD version of the DG usage + * info + * @return none + *************************************************************************/ +void setHDVersionDGUsageInfo( HD_VERSION_DG_USAGE_INFO_T* data ) +{ + dgServiceAndUsageData.isDGUsageInfoAviable = TRUE; + memcpy( &dgServiceAndUsageData.dgUsageInfo, data, sizeof( HD_VERSION_DG_USAGE_INFO_T ) ); +} + +/*********************************************************************//** + * @brief * The cmdSetDGDialysateHeatingParams function sends the dialysate heating * parameters to DG. * @details Inputs: none @@ -1049,6 +1123,7 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DIALYSATE_TEMP_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { + // Per PRS 377, PRS 124 checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_HIGH_SAFETY_RANGE, isTDiTempAboveHighSafety, dgDialysateTemp, DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C ); checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_LOW_SAFETY_RANGE, isTDiTempAboveLowSafety, dgDialysateTemp, DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C ); @@ -1085,7 +1160,35 @@ } } +/*********************************************************************//** + * @brief + * The checkDGTrimmerHeaterStatus function checks to see the status of the + * trimmer heater and set them according to the status of the trimmer heater flag. + * @details Inputs: dgTrimmerHeaterOn, dgHeatersData + * @details Outputs: none + * @return none + *************************************************************************/ +static void checkDGTrimmerHeaterStatus( void ) +{ + U32 trimmerState = dgHeatersData.trimmerHeaterState; + DG_OP_MODE_T dgOp = getDGOpMode(); + if ( ( DG_MODE_GENE == dgOp ) || ( DG_MODE_FILL == dgOp ) || ( DG_MODE_DRAI == dgOp ) ) + { + // In heat disinfect and chemical disinfect, the trimmer heater is controlled by the DG itself so no commands from HD should be sent + // regarding the trimmer heater. + if ( ( TRUE == dgTrimmerHeaterOn ) && ( HEATER_EXEC_STATE_OFF == trimmerState ) ) + { + cmdStartDGTrimmerHeater(); + } + else if ( ( FALSE == dgTrimmerHeaterOn ) && ( trimmerState != HEATER_EXEC_STATE_OFF ) ) + { + cmdStopDGTrimmerHeater(); + } + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Drivers/Battery.c =================================================================== diff -u -rebe0866d88ffe938d6ff48c9c1e30a83d63145be -r1aa06c27877a9054c0655ada917a08016a60f8ef --- firmware/App/Drivers/Battery.c (.../Battery.c) (revision ebe0866d88ffe938d6ff48c9c1e30a83d63145be) +++ firmware/App/Drivers/Battery.c (.../Battery.c) (revision 1aa06c27877a9054c0655ada917a08016a60f8ef) @@ -8,7 +8,7 @@ * @file Battery.c * * @author (last) Dara Navaei -* @date (last) 22-Sep-2022 +* @date (last) 18-Oct-2022 * * @author (original) Quang Nguyen * @date (original) 24-Feb-2021 @@ -20,8 +20,8 @@ #include "Battery.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" -#include "Timers.h" - +#include "Timers.h" + /** * @addtogroup Battery * @{ @@ -35,132 +35,167 @@ #define BATTERY_CHARGER_STATUS_CMD 0x13 ///< Command to get battery charger status. #define BATTERY_CHARGER_STATUS_AC_PRESENT_MASK 0x8000 ///< Battery charger status AC present bit mask. -#define BATTERY_PACK_REL_STATE_OF_CHARGE_CMD 0x0D ///< Command to get battery pack relative state of charge. -#define BATTERY_PACK_REM_CAPACITY_CMD 0x0F ///< Command to get battery pack remaining capacity (in mAh). -#define BATTERY_PACK_STATUS_CMD 0x16 ///< Command to get battery pack status. - #define BATTERY_PACK_ERROR_BITS 0x0F ///< Error codes are in the first byte. #define BATTERY_PACK_MIN_CHARGE_PCT 50 ///< Minimum battery pack state of charge in percentage. -#define BATTERY_COMM_TIME_OUT_MS 1 ///< Battery communication time out in ms. -#define BATTERY_MONITOR_INTERVAL_MS 750 ///< Battery monitor interval in ms. +#define BATTERY_COMM_TIME_OUT_MS 2 ///< Battery communication time out in ms. +#define BATTERY_MONITOR_INTERVAL_MS 247 ///< Battery monitor interval in ms. #define AC_POWER_LOST_PERSISTENT_COUNT 3 ///< AC power lost persistent count before alarming. #define BATTERY_COMM_FAULT_PERSISTENTCE_COUNT 5 ///< Battery communication fault persistent count before alarming. #define BATTERY_MAH_2_MWH_FACTOR 14.7F ///< Conversion factor for mAh to mWh. #define BATTERY_MIN_CAPACITY_MWH 5000.0F ///< Minimum battery capacity for starting a treatment is 10 minutes (5 Wh @ 30W). - + +// Battery logging +#define BATTERY_PACK_ADDR_REMAINING_CAPACITY_ALARM 0x01 ///< Battery pack address remaining capacity alarm. +#define BATTERY_PACK_ADDR_REMAINING_TIME_ALARM 0x02 ///< Battery pack address remaining time alarm. +#define BATTERY_PACK_ADDR_BATTERY_MODE 0x03 ///< Battery pack address battery mode. +#define BATTERY_PACK_ADDR_AT_RATE 0x04 ///< Battery pack address at rate. +#define BATTERY_PACK_ADDR_AT_RATE_TIME_TO_FULL 0x05 ///< Battery pack address at rate time to full. +#define BATTERY_PACK_ADDR_AT_RATE_TIME_TO_EMPTY 0x06 ///< Battery pack address at rate time to empty. +#define BATTERY_PACK_ADDR_AT_RATE_OK 0x07 ///< Battery pack address at rate ok. +#define BATTERY_PACK_ADDR_TEMPERATURE 0x08 ///< Battery pack address temperature. +#define BATTERY_PACK_ADDR_VOLTAGE 0x09 ///< Battery pack address voltage. +#define BATTERY_PACK_ADDR_CURRENT 0x0a ///< Battery pack address current. +#define BATTERY_PACK_ADDR_AVERAGE_CURRENT 0x0b ///< Battery pack address average current. +#define BATTERY_PACK_ADDR_MAX_ERROR 0x0c ///< Battery pack address max error. +#define BATTERY_PACK_ADDR_RELATIVE_STATE_OF_CHARGE 0x0d ///< Battery pack address relative state of charge. +#define BATTERY_PACK_ADDR_ABSOLUTE_STATE_OF_CHARGE 0x0e ///< Battery pack address absolute state of charge. +#define BATTERY_PACK_ADDR_REMAINING_CAPACITY 0x0f ///< Battery pack address remaining capacity. +#define BATTERY_PACK_ADDR_FULL_CHARGE_CAPACITY 0x10 ///< Battery pack address full charge capacity. +#define BATTERY_PACK_ADDR_RUN_TIME_TO_EMPTY 0x11 ///< Battery pack address run time to empty. +#define BATTERY_PACK_ADDR_AVERAGE_TIME_TO_EMPTY 0x12 ///< Battery pack address average time to empty. +#define BATTERY_PACK_ADDR_AVERAGE_TIME_TO_FULL 0x13 ///< Battery pack address average time full. +#define BATTERY_PACK_ADDR_CHARGING_CURRENT 0x14 ///< Battery pack address charging current. +#define BATTERY_PACK_ADDR_CHARGING_VOLTAGE 0x15 ///< Battery pack address charging voltage. +#define BATTERY_PACK_ADDR_BATTERY_STATUS 0x16 ///< Battery pack address battery status. +#define BATTERY_PACK_ADDR_CYCLE_COUNT 0x17 ///< Battery pack address cycle count. +#define BATTERY_PACK_ADDR_DESIGN_CAPACITY 0x18 ///< Battery pack address design capacity. +#define BATTERY_PACK_ADDR_DESIGN_VOLTAGE 0x19 ///< Battery pack address design voltage. +#define BATTERY_PACK_ADDR_SPECIFICATION_INFO 0x1a ///< Battery pack address specification information. +#define BATTERY_PACK_ADDR_MANUFACTURE_DATE 0x1b ///< Battery pack address manufacture date. +#define BATTERY_PACK_ADDR_SERIAL_NUMBER 0x1c ///< Battery pack address serial number. +#define BATTERY_PACK_ADDR_MANUFACTURER_NAME 0x20 ///< Battery pack address manufacture name. +#define BATTERY_PACK_ADDR_DEVICE_NAME 0x21 ///< Battery pack address device name. +#define BATTERY_PACK_ADDR_DEVICE_CHEMISTRY 0x22 ///< Battery pack address device chemistry. + /// Persist time (in ms) for battery pack status error condition. static const U32 BATT_STATUS_ERROR_PERSIST_MS = ( 5 * MS_PER_SECOND ); +/// Enumeration of battery data to be read from the battery pack or battery charger in a round-robin fashion. +typedef enum BatteryManagementEnum +{ + BEGINNING_OF_LIST = 0, ///< Start of battery data list + BATTERY_PACK_REMAINING_CAPACITY1, ///< Remaining battery capacity (in mWh) (first of 5 to increase frequency of reads) + BATTERY_PACK_BATTERY_STATUS1, ///< Battery pack status (first of 5 to increase frequency of reads) + BATTERY_CHARGER_STATUS1, ///< Battery charger status (first of 5 to increase frequency of reads) + BATTERY_PACK_REMAINING_CAPACITY_ALARM, ///< Remaining battery capacity alarm + BATTERY_PACK_REMAINING_TIME_ALARM, ///< Remaining battery time alarm + BATTERY_PACK_BATTERY_MODE, ///< Battery pack mode + BATTERY_PACK_AT_RATE, ///< Battery pack at rate + BATTERY_PACK_AT_RATE_TIME_TO_FULL, ///< Battery pack at rate time to full + BATTERY_PACK_REMAINING_CAPACITY2, ///< Remaining battery capacity (in mWh) (second of 5 to increase frequency of reads) + BATTERY_PACK_BATTERY_STATUS2, ///< Battery pack status (second of 5 to increase frequency of reads) + BATTERY_CHARGER_STATUS2, ///< Battery charger status (second of 5 to increase frequency of reads) + BATTERY_PACK_AT_RATE_TIME_TO_EMPTY, ///< Battery pack at rate time to empty + BATTERY_PACK_AT_RATE_OK, ///< Battery pack at rate ok (boolean) + BATTERY_PACK_TEMPERATURE, ///< Battery pack temperature (in deg K) + BATTERY_PACK_VOLTAGE, ///< Battery pack terminal voltage (in mV) + BATTERY_PACK_CURRENT, ///< Battery pack terminal current (in mA) + BATTERY_PACK_AVERAGE_CURRENT, ///< Battery pack average terminal current (in mA - 1 minute rolling avg) + BATTERY_PACK_REMAINING_CAPACITY3, ///< Remaining battery capacity (in mWh) (third of 5 to increase frequency of reads) + BATTERY_PACK_BATTERY_STATUS3, ///< Battery pack status (third of 5 to increase frequency of reads) + BATTERY_CHARGER_STATUS3, ///< Battery charger status (third of 5 to increase frequency of reads) + BATTERY_PACK_MAX_ERROR, ///< Battery pack expected margin of error (%) in the state of charge calculation + BATTERY_PACK_RELATIVE_STATE_OF_CHARGE, ///< Battery pack relative state of charge (%) (relative to full charge capacity) + BATTERY_PACK_ABSOLUTE_STATE_OF_CHARGE, ///< Battery pack absolute state of charge (%) (relative to design capacity) + BATTERY_PACK_FULL_CHARGE_CAPACITY, ///< Battery pack full charge capacity (in mWh) + BATTERY_PACK_RUN_TIME_TO_EMPTY, ///< Battery pack run time (in minutes) predicted based on present rate of discharge + BATTERY_PACK_AVERAGE_TIME_TO_EMPTY, ///< Battery pack average time to empty (in minutes - 1 minute rolling avg) + BATTERY_PACK_AVERAGE_TIME_TO_FULL, ///< Battery pack average time to full (in minutes - 1 minute rolling avg) + BATTERY_PACK_REMAINING_CAPACITY4, ///< Remaining battery capacity (in mWh) (fourth of 5 to increase frequency of reads) + BATTERY_PACK_BATTERY_STATUS4, ///< Battery pack status (fourth of 5 to increase frequency of reads) + BATTERY_CHARGER_STATUS4, ///< Battery charger status (fourth of 5 to increase frequency of reads) + BATTERY_PACK_CHARGING_CURRENT, ///< Battery pack desired charging current (in mA) + BATTERY_PACK_CHARGING_VOLTAGE, ///< Battery pack desired charging voltage (in mV) + BATTERY_PACK_CYCLE_COUNT, ///< Battery pack cycle count + BATTERY_PACK_DESIGN_CAPACITY, ///< Battery pack design capacity (in mWh) + BATTERY_PACK_DESIGN_VOLTAGE, ///< Battery pack design voltage (in mV) + BATTERY_PACK_SPECIFICATION_INFO, ///< Version number of the smart battery specification the battery pack supports + BATTERY_PACK_MANUFACTURE_DATE, ///< Battery pack mfg date ( [year - 1980] x 512 + month x 32 + day + BATTERY_PACK_REMAINING_CAPACITY5, ///< Remaining battery capacity (in mWh) (fifth of 5 to increase frequency of reads) + BATTERY_PACK_BATTERY_STATUS5, ///< Battery pack status (fifth of 5 to increase frequency of reads) + BATTERY_CHARGER_STATUS5, ///< Battery charger status (fifth of 5 to increase frequency of reads) + BATTERY_PACK_SERIAL_NUMBER, ///< Battery pack serial number + BATTERY_PACK_MANUFACTURER_NAME, ///< Battery pack mfg name + BATTERY_PACK_DEVICE_NAME, ///< Battery pack device name + BATTERY_PACK_DEVICE_CHEMISTRY, ///< Battery pack device chemistry + END_OF_LIST +} BATTERY_MANAGEMENT_ENUM_T; + // ********** private data ********** -static U16 batteryStatus = 0; ///< Battery current status. -static U32 batteryRelStateOfCharge_pct; ///< Battery pack relative state of charge. static OVERRIDE_F32_T batteryRemCapacity_mAh = { 0.0, 0.0, 0.0, 0 }; ///< Battery pack remaining capacity (in mAh). -static U16 batteryPackStatus = 0; ///< Battery pack current status. -static U32 lastBatteryMonitorTime = 0; ///< Previous battery monitor time. -static U32 lostACPowerPersistentCount = 0; ///< Persistent count for AC power lost alarm. -static BOOL hasBatteryChargerStatus = FALSE; ///< Flag indicates if battery charger status has been obtained. -static U32 commFaultPersistentCount = 0; ///< Persistence count for battery comm fault. +static U32 lastBatteryMonitorTime; ///< Previous battery monitor time. +static U32 commFaultPersistentCount; ///< Persistence count for battery comm fault. -// ********** private function prototypes ********** +static BATTERY_MANAGEMENT_ENUM_T current_BM_value; ///< Index for which battery data to read now. +static BATTERY_MANAGER_PAYLOAD_T BatteryManagerData; ///< Record with latest battery pack data updated at the slower frequency. +static BATTERY_STATUS_PAYLOAD_T BatteryStatusData; ///< Record with latest battery pack/charger status data updated at the faster frequency. +// ********** private function prototypes ********** + static F32 getBatteryRemainingCapacity_mWh( void ); static void setupI2CDriver( void ); static BOOL waitForTxReady( void ); static BOOL waitForRxReady( void ); static BOOL waitForAccessReady( void ); static void generateStopCondition( void ); -static BOOL getBatteryData( U32 slaveAddr, U08 command, U16 * dataPtr ); +static BOOL getBatteryData( U32 slaveAddr, U08 command, U32 * dataPtr ); static BOOL startCommTx( U32 slaveAddr ); static BOOL getData( U08 command, U16 * dataPtr ); - -/*********************************************************************//** - * @brief - * The initBattery function initializes the Battery module. - * @details Inputs: none - * @details Outputs: Battery module is initialized. - * @return none - *************************************************************************/ -void initBattery( void ) + +// For logging +static void getBatteryManagementData( void ); +static void publishBatteryManagementData( void ); +static void publishBatteryStatusData( void ); + +/*********************************************************************//** + * @brief + * The initBattery function initializes the Battery module. + * @details Inputs: none + * @details Outputs: Battery module is initialized. + * @return none + *************************************************************************/ +void initBattery( void ) { - batteryStatus = 0; - batteryRelStateOfCharge_pct = 0; - batteryPackStatus = 0; - lastBatteryMonitorTime = 0; - lostACPowerPersistentCount = 0; - hasBatteryChargerStatus = FALSE; + lastBatteryMonitorTime = 0; commFaultPersistentCount = 0; + current_BM_value = BEGINNING_OF_LIST; + memset( &BatteryStatusData, 0, sizeof( BATTERY_STATUS_PAYLOAD_T ) ); + memset( &BatteryManagerData, 0, sizeof( BATTERY_MANAGER_PAYLOAD_T ) ); + // Initialize persistent alarm for battery pack status error initPersistentAlarm( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, 0, BATT_STATUS_ERROR_PERSIST_MS ); setupI2CDriver(); -} - -/*********************************************************************//** - * @brief - * The execBatteryMonitor function monitors the battery status. - * @details Inputs: lastBatteryMonitorTime, hasBatteryChargerStatus, batteryStatus, - * batteryRelStateOfCharge_pct, batteryPackStatus, lostACPowerPersistentCount - * @details Outputs: lastBatteryMonitorTime, hasBatteryChargerStatus, - * lostACPowerPersistentCount, batteryRelStateOfCharge_pct, batteryRemCapacity_mAh - * @return none +} + +/*********************************************************************//** + * @brief + * The execBatteryMonitor function monitors the battery status. + * @details Inputs: lastBatteryMonitorTime + * @details Outputs: lastBatteryMonitorTime + * @return none *************************************************************************/ -void execBatteryMonitor( void ) +void execBatteryMonitor( void ) { - U16 relStateOfCharge_pct; - U16 remCapacity_mAh; - if ( TRUE == didTimeout( lastBatteryMonitorTime, BATTERY_MONITOR_INTERVAL_MS ) ) { lastBatteryMonitorTime = getMSTimerCount(); - if ( FALSE == hasBatteryChargerStatus ) - { - hasBatteryChargerStatus = TRUE; - - if ( TRUE == getBatteryData( BATTERY_CHARGER_SLAVE_ADDRESS, BATTERY_CHARGER_STATUS_CMD, &batteryStatus ) ) - { - if ( 0 == ( batteryStatus & BATTERY_CHARGER_STATUS_AC_PRESENT_MASK ) ) - { - if ( ++lostACPowerPersistentCount > AC_POWER_LOST_PERSISTENT_COUNT ) - { -#ifndef DISABLE_BATT_COMM - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST, batteryStatus ); -#endif - } - } - else - { - clearAlarmCondition( ALARM_ID_HD_AC_POWER_LOST ); - lostACPowerPersistentCount = 0; - } - } - } - else - { - hasBatteryChargerStatus = FALSE; - - if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REL_STATE_OF_CHARGE_CMD, &relStateOfCharge_pct ) ) - { - batteryRelStateOfCharge_pct = (U32)relStateOfCharge_pct; - } - - if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REM_CAPACITY_CMD, &remCapacity_mAh ) ) - { - batteryRemCapacity_mAh.data = (F32)remCapacity_mAh * BATTERY_MAH_2_MWH_FACTOR; - } - - if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_STATUS_CMD, &batteryPackStatus ) ) - { - if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, ( batteryPackStatus & BATTERY_PACK_ERROR_BITS ) != 0 ) ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, batteryPackStatus ); - } - } - } + getBatteryManagementData(); } } @@ -304,14 +339,17 @@ * @param dataPtr data pointer to store command response data * @return none *************************************************************************/ -static BOOL getBatteryData( U32 slaveAddr, U08 command, U16 * dataPtr ) +static BOOL getBatteryData( U32 slaveAddr, U08 command, U32 * dataPtr ) { BOOL result = FALSE; if ( TRUE == startCommTx( slaveAddr ) ) { - if ( TRUE == getData( command, dataPtr ) ) + U16 data = (U16)( (*dataPtr) & MASK_OFF_MSW ); + + if ( TRUE == getData( command, &data ) ) { + *dataPtr = data; result = TRUE; } } @@ -408,10 +446,245 @@ } } + if ( FALSE == result ) + { + if ( ++commFaultPersistentCount > BATTERY_COMM_FAULT_PERSISTENTCE_COUNT ) + { +#ifndef DISABLE_BATT_COMM + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BATTERY_COMM_FAULT, dataPtr ); +#endif + commFaultPersistentCount = 0; + } + } + return result; } +/*********************************************************************//** + * @brief + * The getBatteryManagementData function accumulates the battery management + * and status data and publishes the two sets of values when complete. Also, + * the battery remaining capacity is stored, the battery status alarm is set + * if necessary, and the loss of AC power alarm is set if necessary. + * @details Inputs: current_BM_value, BatteryStatusData + * @details Outputs: batteryRemCapacity_mAh, BatteryManagerData + * @return none + *************************************************************************/ +static void getBatteryManagementData(void) +{ + HD_OP_MODE_T opMode = getCurrentOperationMode(); + // Increment the position in the enum. Starting value is BEGINNING_OF_LIST (0), so on the first + // cycle through this function it will be set to the first valid position (1) + current_BM_value += 1; + + switch( current_BM_value ) + { + case BATTERY_PACK_REMAINING_CAPACITY1: + case BATTERY_PACK_REMAINING_CAPACITY2: + case BATTERY_PACK_REMAINING_CAPACITY3: + case BATTERY_PACK_REMAINING_CAPACITY4: + case BATTERY_PACK_REMAINING_CAPACITY5: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_REMAINING_CAPACITY, &BatteryStatusData.RemainingCapacity ); + batteryRemCapacity_mAh.data = (F32)BatteryStatusData.RemainingCapacity * BATTERY_MAH_2_MWH_FACTOR; + break; + + case BATTERY_PACK_BATTERY_STATUS1: + case BATTERY_PACK_BATTERY_STATUS2: + case BATTERY_PACK_BATTERY_STATUS3: + case BATTERY_PACK_BATTERY_STATUS4: + case BATTERY_PACK_BATTERY_STATUS5: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_BATTERY_STATUS, &BatteryStatusData.BatteryStatus ); + if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, ( BatteryStatusData.BatteryStatus & BATTERY_PACK_ERROR_BITS ) != 0 ) ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, BatteryStatusData.BatteryStatus ); + } + break; + + case BATTERY_PACK_REMAINING_CAPACITY_ALARM: + getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_REMAINING_CAPACITY_ALARM, &BatteryManagerData.RemainingCapacityAlarm ); + break; + + case BATTERY_PACK_REMAINING_TIME_ALARM: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_REMAINING_TIME_ALARM, &BatteryManagerData.RemainingTimeAlarm ); + break; + + case BATTERY_PACK_BATTERY_MODE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_BATTERY_MODE, &BatteryManagerData.BatteryMode ); + break; + + case BATTERY_PACK_AT_RATE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE, &BatteryManagerData.AtRate ); + break; + + case BATTERY_PACK_AT_RATE_TIME_TO_FULL: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE_TIME_TO_FULL, &BatteryManagerData.AtRateTimeToFull ); + break; + + case BATTERY_PACK_AT_RATE_TIME_TO_EMPTY: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE_TIME_TO_EMPTY, &BatteryManagerData.AtRateTimeToEmpty ); + break; + + case BATTERY_PACK_AT_RATE_OK: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE_OK, &BatteryManagerData.AtRateOK ); + break; + + case BATTERY_PACK_TEMPERATURE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_TEMPERATURE, &BatteryManagerData.Temperature ); + break; + + case BATTERY_PACK_VOLTAGE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_VOLTAGE, &BatteryManagerData.Voltage ); + break; + + case BATTERY_PACK_CURRENT: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CURRENT, &BatteryManagerData.Current ); + break; + + case BATTERY_PACK_AVERAGE_CURRENT: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AVERAGE_CURRENT, &BatteryManagerData.AverageCurrent ); + break; + + case BATTERY_PACK_MAX_ERROR: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_MAX_ERROR, &BatteryManagerData.MaxError ); + break; + + case BATTERY_PACK_RELATIVE_STATE_OF_CHARGE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_RELATIVE_STATE_OF_CHARGE, &BatteryManagerData.RelativeStateOfCharge ); + break; + + case BATTERY_PACK_ABSOLUTE_STATE_OF_CHARGE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_ABSOLUTE_STATE_OF_CHARGE, &BatteryManagerData.AbsoluteStateOfCharge ); + break; + + case BATTERY_PACK_FULL_CHARGE_CAPACITY: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_FULL_CHARGE_CAPACITY, &BatteryManagerData.FullChargeCapacity ); + break; + + case BATTERY_PACK_RUN_TIME_TO_EMPTY: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_RUN_TIME_TO_EMPTY, &BatteryManagerData.RunTimeToEmpty ); + break; + + case BATTERY_PACK_AVERAGE_TIME_TO_EMPTY: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AVERAGE_TIME_TO_EMPTY, &BatteryManagerData.AverageTimeToEmpty ); + break; + + case BATTERY_PACK_AVERAGE_TIME_TO_FULL: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AVERAGE_TIME_TO_FULL, &BatteryManagerData.AverageTimeToFull ); + break; + + case BATTERY_PACK_CHARGING_CURRENT: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CHARGING_CURRENT, &BatteryManagerData.ChargingCurrent ); + break; + + case BATTERY_PACK_CHARGING_VOLTAGE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CHARGING_VOLTAGE, &BatteryManagerData.ChargingVoltage ); + break; + + case BATTERY_PACK_CYCLE_COUNT: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CYCLE_COUNT, &BatteryManagerData.CycleCount ); + break; + + case BATTERY_PACK_DESIGN_CAPACITY: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DESIGN_CAPACITY, &BatteryManagerData.DesignCapacity ); + break; + + case BATTERY_PACK_DESIGN_VOLTAGE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DESIGN_VOLTAGE, &BatteryManagerData.DesignVoltage ); + break; + + case BATTERY_PACK_SPECIFICATION_INFO: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_SPECIFICATION_INFO, &BatteryManagerData.SpecificationInfo ); + break; + + case BATTERY_PACK_MANUFACTURE_DATE: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_MANUFACTURE_DATE, &BatteryManagerData.ManufactureDate ); + break; + + case BATTERY_PACK_SERIAL_NUMBER: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_SERIAL_NUMBER, &BatteryManagerData.SerialNumber ); + break; + + case BATTERY_PACK_MANUFACTURER_NAME: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_MANUFACTURER_NAME, &BatteryManagerData.ManufacturerName ); + break; + + case BATTERY_PACK_DEVICE_NAME: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DEVICE_NAME, &BatteryManagerData.DeviceName ); + break; + + case BATTERY_PACK_DEVICE_CHEMISTRY: + getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DEVICE_CHEMISTRY, &BatteryManagerData.DeviceChemistry ); + break; + + case BATTERY_CHARGER_STATUS1: + case BATTERY_CHARGER_STATUS2: + case BATTERY_CHARGER_STATUS3: + case BATTERY_CHARGER_STATUS4: + case BATTERY_CHARGER_STATUS5: + if ( TRUE == getBatteryData( BATTERY_CHARGER_SLAVE_ADDRESS, BATTERY_CHARGER_STATUS_CMD, &BatteryStatusData.BatteryChargerStatus ) ) + { // If A/C not present, trigger A/C lost alarm + if ( 0 == ( BatteryStatusData.BatteryChargerStatus & BATTERY_CHARGER_STATUS_AC_PRESENT_MASK ) ) + { +#ifndef DISABLE_BATT_COMM + // Pre-Treatment, Treatment, or Post-Treatment mode + if( opMode == MODE_PRET || opMode == MODE_TREA || opMode == MODE_POST ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST_IN_TREATMENT, BatteryStatusData.BatteryChargerStatus ); + } + // Standby, Service, or Treatment Parameters mode + else + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST, BatteryStatusData.BatteryChargerStatus ); + } +#endif + } + else + { + clearAlarmCondition( ALARM_ID_HD_AC_POWER_LOST ); + } + } + // Publish battery status data after reading battery charger status (last status read) + publishBatteryStatusData(); + break; + + case END_OF_LIST: + current_BM_value = BEGINNING_OF_LIST; + publishBatteryManagementData(); + break; + + default: + // TODO s/w fault + break; + } +} + +/*********************************************************************//** + * @brief + * The publishBatteryManagementData function publishes the battery management data + * @details Inputs: BatteryManagerData + * @details Outputs: send battery management data + * @return none + *************************************************************************/ +static void publishBatteryManagementData( void ) +{ + broadcastData( MSG_ID_HD_BATTERY_MANAGEMENT_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&BatteryManagerData, sizeof( BATTERY_MANAGER_PAYLOAD_T ) ); +} + +/*********************************************************************//** + * @brief + * The publishBatteryStatusData function publishes the battery status data + * @details Inputs: BatteryStatusData + * @details Outputs: none + * @return none + *************************************************************************/ +static void publishBatteryStatusData( void ) +{ + BatteryStatusData.RemainingCapacity = (U32)getBatteryRemainingCapacity_mWh(); + broadcastData( MSG_ID_HD_BATTERY_STATUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&BatteryStatusData, sizeof( BATTERY_STATUS_PAYLOAD_T ) ); +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -426,7 +699,7 @@ * @param value override battery remaining percent * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetBatteryRemainingPercentOverride( U32 value ) // TODO - rename to capacity (instead of percent) + messaging + Dialin // TODO - add override of broadcast interval // TODO - broadcast battery data +BOOL testSetBatteryRemainingPercentOverride( F32 value ) // TODO - rename to capacity (instead of percent) + messaging + Dialin // TODO - add override of broadcast interval // TODO - broadcast battery data { BOOL result = FALSE;