Index: firmware/App/Controllers/Buttons.c =================================================================== diff -u -r3f2bb2c7793f68d26138308c8dc48e69d251f5a2 -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Controllers/Buttons.c (.../Buttons.c) (revision 3f2bb2c7793f68d26138308c8dc48e69d251f5a2) +++ firmware/App/Controllers/Buttons.c (.../Buttons.c) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -7,8 +7,8 @@ * * @file Buttons.c * -* @author (last) Sean Nash -* @date (last) 12-Nov-2021 +* @author (last) Dara Navaei +* @date (last) 21-May-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r19a8bf98a7154e24c35da25225d4b55bf70ddd09 -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 19a8bf98a7154e24c35da25225d4b55bf70ddd09) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -59,11 +59,13 @@ #define ARTERIAL_PRESSURE_SELF_TEST_MAX ( 100.0F ) ///< Maximum self-test value for arterial pressure sensor reading (in mmHg). #define ARTERIAL_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum arterial pressure reading (in mmHg) for range check. #define ARTERIAL_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum arterial pressure reading (in mmHg) for range check. +#define ARTERIAL_PRESSURE_ND_MIN_MMHG ( -250.0F ) ///< Minimum arterial pressure reading (in mmHg) when not dialyzing. #define VENOUS_PRESSURE_SELF_TEST_MIN ( -100.0F ) ///< Minimum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_SELF_TEST_MAX ( 600.0F ) ///< Maximum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum venous pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum venous pressure reading (in mmHg) for range check. +#define VENOUS_PRESSURE_ND_MAX_MMHG ( 300.0F ) ///< Maximum venous pressure reading (in mmHg) when not dialyzing. #define PSI_TO_MMHG ( 51.7149F ) ///< Conversion factor for converting PSI to mmHg. @@ -585,7 +587,8 @@ } // Check arterial pressure during treatment mode - if ( ( MODE_TREA == getCurrentOperationMode() ) && ( getTreatmentState() <= TREATMENT_DIALYSIS_STATE ) ) + if ( MODE_TREA == getCurrentOperationMode() && + TREATMENT_DIALYSIS_STATE == getTreatmentState() && getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); @@ -608,6 +611,14 @@ SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres, artHighLimit ); } } + else if ( MODE_TREA == getCurrentOperationMode() ) // All treatment states not covered by the if above + { + // Check arterial pressure is within non-treatment alarm limits + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < ARTERIAL_PRESSURE_ND_MIN_MMHG ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, ARTERIAL_PRESSURE_ND_MIN_MMHG ); + } + } else { // Reset persistence if alarm is out of scope isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, FALSE ); @@ -640,7 +651,8 @@ } // Check venous pressure during treatment mode - if ( ( MODE_TREA == getCurrentOperationMode() ) && ( getTreatmentState() <= TREATMENT_DIALYSIS_STATE ) ) + if ( MODE_TREA == getCurrentOperationMode() && + TREATMENT_DIALYSIS_STATE == getTreatmentState() && getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) { F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); @@ -670,6 +682,14 @@ SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, venHighLimit ); } } + else if ( MODE_TREA == getCurrentOperationMode() ) // All treatment states not covered by the if statement above + { + // Check venous pressure is less than non-treatment alarm limit + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > VENOUS_PRESSURE_ND_MAX_MMHG ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, VENOUS_PRESSURE_ND_MAX_MMHG ); + } + } else { // Reset persistence if alarm is out of scope isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); Index: firmware/App/Controllers/Switches.c =================================================================== diff -u -r19a8bf98a7154e24c35da25225d4b55bf70ddd09 -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Controllers/Switches.c (.../Switches.c) (revision 19a8bf98a7154e24c35da25225d4b55bf70ddd09) +++ firmware/App/Controllers/Switches.c (.../Switches.c) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -123,8 +123,18 @@ // If the debounce time has been elapsed, update the switch status to the new status else if ( TRUE == didTimeout( switchesStatus[ i ].debounceStartTime, SWITCHES_DEBOUNCE_TIME_MS ) ) { - switchesStatus[ i ].debounceStartTime = 0; + if ( FRONT_DOOR == i ) + { + // Log front door switch change + sendTreatmentLogEventData( FRONT_DOOR_SWITCH_CHANGED_EVENT, (F32)switchesStatus[ i ].status.data, (F32)currentSwitchStatus ); + } + else if ( PUMP_TRACK_SWITCH == i ) + { + // Log pump track switch change + sendTreatmentLogEventData( PUMP_TRACK_SWITCH_CHANGED_EVENT, (F32)switchesStatus[ i ].status.data, (F32)currentSwitchStatus ); + } // If the bit is 0, the door switch is open, because it is normally open switch + switchesStatus[ i ].debounceStartTime = 0; switchesStatus[ i ].status.data = currentSwitchStatus; } } Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r19a8bf98a7154e24c35da25225d4b55bf70ddd09 -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 19a8bf98a7154e24c35da25225d4b55bf70ddd09) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -940,6 +940,11 @@ syringePumpMeasHome.data = ( (F32)getFPGASyringePumpADCChannel2() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; syringePumpMeasSyringeDetectionSwitch.data = ( (F32)getFPGASyringePumpADCChannel1() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; + // Log syringe detect switch changes + if ( prevSyringeDetected != isSyringeDetected() ) + { + sendTreatmentLogEventData( SYRINGE_DETECTION_SWITCH_CHANGED_EVENT, (F32)prevSyringeDetected, (F32)isSyringeDetected() ); + } #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -977,7 +982,7 @@ syringePumpLastPosition = getSyringePumpPosition(); syringePumpPosition.data = encPosition - syringePumpHomePositionOffset; // Calculate volume delivered from position - syringePumpVolumeDelivered.data = (F32)(syringePumpPosition.data - syringePumpVolumeStartPosition) / SYRINGE_ENCODER_COUNTS_PER_ML; + syringePumpVolumeDelivered.data = (F32)( syringePumpPosition.data - syringePumpVolumeStartPosition ) / SYRINGE_ENCODER_COUNTS_PER_ML; calcSafetyVolumeDelivered(); // Calculate measured rate (mL/hr) calcMeasRate(); Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r19a8bf98a7154e24c35da25225d4b55bf70ddd09 -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 19a8bf98a7154e24c35da25225d4b55bf70ddd09) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -653,7 +653,9 @@ U32 rejReason = REQUEST_REJECT_REASON_NONE; if ( ( volumeLevel > 0 ) && ( volumeLevel <= MAX_ALARM_VOLUME_LEVEL ) ) - { // Convert volume level to attenuation level + { + sendTreatmentLogEventData( ALARM_AUDIO_VOLUME_CHANGED_EVENT, (F32)volumeLevel, (F32)getAlarmAudioVolume() ); + // Convert volume level to attenuation level alarmAudioVolumeLevel.data = MAX_ALARM_VOLUME_LEVEL - volumeLevel; accepted = TRUE; } Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r2b996e63fa5310e4d627bb473a208342d9b15930 -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 2b996e63fa5310e4d627bb473a208342d9b15930) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -7,8 +7,8 @@ * * @file SystemComm.c * -* @author (last) Darren Cox -* @date (last) 10-Mar-2022 +* @author (last) Dara Navaei +* @date (last) 26-May-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -784,7 +784,7 @@ { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC ) ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_COMM_TOO_MANY_BAD_CRCS, (U32)ALARM_SOURCE_HD ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_COMM_TOO_MANY_BAD_CRCS, (U32)ALARM_SOURCE_HD ); } } @@ -1154,9 +1154,12 @@ handleTesterLogInRequest( message ); break; +#ifndef _VECTORCAST_ + // The default cannot be reached in VectorCAST since the cases are run in a for loop default: // Un-recognized or un-handled message ID received - ignore - break; + break; +#endif } // Handle any test messages if tester has logged in successfully @@ -1658,9 +1661,12 @@ handleSetBloodLeakEmbeddedModeCommand( message ); break; +#ifndef _VECTORCAST_ + // The default cannot be reached in VectorCAST since the cases are run in a for loop default: // Unrecognized message ID received - ignore - break; + break; +#endif } } } Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r19a8bf98a7154e24c35da25225d4b55bf70ddd09 -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 19a8bf98a7154e24c35da25225d4b55bf70ddd09) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -41,6 +41,7 @@ #include "Utilities.h" #include "Valves.h" #include "WatchdogMgmt.h" +#include "HDDefs.h" /** * @addtogroup SystemCommMessages @@ -2636,105 +2637,127 @@ return result; } - - -/*********************************************************************//** - * @brief - * The handleChangeUFSettingsRequest function handles a ultrafiltration - * change settings request message from the UI. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleChangeUFSettingsRequest( MESSAGE_T *message ) -{ - if ( message->hdr.payloadLen == sizeof(F32) ) - { - F32 uFVolume; - - memcpy( &uFVolume, message->payload, sizeof(F32) ); - - verifyUFSettingsChange( uFVolume ); - } - else - { - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); - } -} - -/*********************************************************************//** - * @brief - * The handleChangeUFSettingsConfirmation function handles a ultrafiltration - * change setting confirmation message from the UI. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleChangeUFSettingsConfirmation( MESSAGE_T *message ) -{ - if ( message->hdr.payloadLen == sizeof(UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T) ) - { - UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T) ); - - verifyUFSettingsConfirmation( payload.volume_mL, payload.adjustType ); - } - else - { - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); - } -} - -/*********************************************************************//** - * @brief - * The handleChangeTreatmentDurationRequest function handles a treatment - * duration setting change message from the UI. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleChangeTreatmentDurationRequest( MESSAGE_T *message ) -{ - if ( message->hdr.payloadLen == sizeof(U32) ) - { +/*********************************************************************//** + * @brief + * The handleChangeUFSettingsRequest function handles a ultrafiltration + * change settings request message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleChangeUFSettingsRequest( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof(F32) ) + { + F32 uFVolume; + + memcpy( &uFVolume, message->payload, sizeof(F32) ); + + verifyUFSettingsChange( uFVolume ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The handleChangeUFSettingsConfirmation function handles a ultrafiltration + * change setting confirmation message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleChangeUFSettingsConfirmation( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof(UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T) ) + { + UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T payload; + + memcpy( &payload, message->payload, sizeof(UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T) ); + + verifyUFSettingsConfirmation( payload.volume_mL, payload.adjustType ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The handleChangeTreatmentDurationRequest function handles a treatment + * duration setting change message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleChangeTreatmentDurationRequest( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof(U32) ) + { U32 timeInMin; + + memcpy( &timeInMin, message->payload, sizeof(U32) ); + verifyTreatmentDurationSettingChange( timeInMin ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} - memcpy( &timeInMin, message->payload, sizeof(U32) ); - - verifyTreatmentDurationSettingChange( timeInMin ); - } - else - { - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); - } +/*********************************************************************//** + * @brief + * The handleChangeBloodDialysateRateChangeRequest function handles a blood + * and dialysate rate settings change message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleChangeBloodDialysateRateChangeRequest( MESSAGE_T *message ) +{ + U32 expPayloadSize = sizeof(U32) + sizeof(U32); + + if ( expPayloadSize == message->hdr.payloadLen ) + { + U32 bloodRate; + U32 dialRate; + + memcpy( &bloodRate, &message->payload[0], sizeof(U32) ); + memcpy( &dialRate, &message->payload[sizeof(U32)], sizeof(U32) ); + + verifyBloodAndDialysateRateSettingsChange( bloodRate, dialRate ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } } /*********************************************************************//** * @brief - * The handleChangeBloodDialysateRateChangeRequest function handles a blood - * and dialysate rate settings change message from the UI. + * The handleChangePressureLimitsRequest function handles a pressure limits + * change message from the UI. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ -void handleChangeBloodDialysateRateChangeRequest( MESSAGE_T *message ) +void handleChangePressureLimitsRequest( MESSAGE_T *message ) { - U32 expPayloadSize = sizeof(U32) + sizeof(U32); - - if ( expPayloadSize == message->hdr.payloadLen ) + if ( sizeof( PRESSURE_LIMIT_CHANGE_REQUEST_T ) == message->hdr.payloadLen ) { - U32 bloodRate; - U32 dialRate; + PRESSURE_LIMIT_CHANGE_REQUEST_T data; - memcpy( &bloodRate, &message->payload[0], sizeof(U32) ); - memcpy( &dialRate, &message->payload[sizeof(U32)], sizeof(U32) ); + memcpy( &data, &message->payload[0], sizeof(PRESSURE_LIMIT_CHANGE_REQUEST_T) ); - verifyBloodAndDialysateRateSettingsChange( bloodRate, dialRate ); + verifyPressureLimitsChange( &data ); } else { @@ -2744,22 +2767,22 @@ /*********************************************************************//** * @brief - * The handleChangePressureLimitsRequest function handles a pressure limits - * change message from the UI. + * The handleHeparinCommandRequest function handles a Heparin command + * request message from the UI. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ -void handleChangePressureLimitsRequest( MESSAGE_T *message ) +void handleHeparinCommandRequest( MESSAGE_T *message ) { - if ( sizeof( PRESSURE_LIMIT_CHANGE_REQUEST_T ) == message->hdr.payloadLen ) + if ( sizeof( U32 ) == message->hdr.payloadLen ) { - PRESSURE_LIMIT_CHANGE_REQUEST_T data; + U32 payload; - memcpy( &data, &message->payload[0], sizeof(PRESSURE_LIMIT_CHANGE_REQUEST_T) ); + memcpy( &payload, &message->payload[0], sizeof( U32 ) ); - verifyPressureLimitsChange( &data ); + userHeparinRequest( (HEPARIN_CMD_T)payload ); } else { @@ -2769,22 +2792,22 @@ /*********************************************************************//** * @brief - * The handleHeparinCommandRequest function handles a Heparin command - * request message from the UI. + * The handleAlarmAudioVolumeSetCmd function handles a alarm audio volume + * set request message from the UI. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ -void handleHeparinCommandRequest( MESSAGE_T *message ) +void handleAlarmAudioVolumeSetCmd( MESSAGE_T *message ) { if ( sizeof( U32 ) == message->hdr.payloadLen ) { U32 payload; memcpy( &payload, &message->payload[0], sizeof( U32 ) ); - userHeparinRequest( (HEPARIN_CMD_T)payload ); + setAlarmAudioVolume( payload ); } else { @@ -2794,22 +2817,21 @@ /*********************************************************************//** * @brief - * The handleAlarmAudioVolumeSetCmd function handles a alarm audio volume - * set request message from the UI. + * The handleUIChangedScreenBrightness function handles a screen brightness change + * message from the UI. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ -void handleAlarmAudioVolumeSetCmd( MESSAGE_T *message ) +void handleUIChangedScreenBrightness( MESSAGE_T *message ) { if ( sizeof( U32 ) == message->hdr.payloadLen ) { U32 payload; memcpy( &payload, &message->payload[0], sizeof( U32 ) ); - - setAlarmAudioVolume( payload ); + sendTreatmentLogEventData( SCREEN_BRIGHTNESS_CHANGED_EVENT, (F32)0.0, (F32)payload ); } else { Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r2ad5befab1030c921a87df8ef8848082b19d10de -r28cd9da453de6282baea3113cf9f787810aae1e5 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 2ad5befab1030c921a87df8ef8848082b19d10de) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 28cd9da453de6282baea3113cf9f787810aae1e5) @@ -7,8 +7,8 @@ * * @file SystemCommMessages.h * -* @author (last) Darren Cox -* @date (last) 10-Mar-2022 +* @author (last) Dara Navaei +* @date (last) 25-May-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -575,10 +575,8 @@ // MSG_ID_HD_VALVES_SET_POSITION void handleSetHDValvePositionOverrideRequest( MESSAGE_T *message ); -#ifdef DEBUG_ENABLED // MSG_ID_HD_VALVES_SET_PWM_OVERRIDE void handleSetHDValvePWMOverrideRequest( MESSAGE_T *message ); -#endif // MSG_ID_HD_SOFTWARE_RESET_REQUEST void handleHDSoftwareResetRequest( MESSAGE_T *message );