/************************************************************************** * * Copyright (c) 2019-2020 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 Accel.c * * @author (last) Sean Nash * @date (last) 12-Aug-2020 * * @author (original) Sean Nash * @date (original) 29-Jul-2020 * ***************************************************************************/ #include #include "Accel.h" #include "FPGA.h" #include "NVDataMgmt.h" #include "SystemCommMessages.h" #include "TaskPriority.h" /** * @addtogroup Accel * @{ */ // ********** private definitions ********** #define ACCEL_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the accelerometer data is published on the CAN bus #define SIZE_OF_ROLLING_AVG ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< vector for tilt is filtered w/ moving average #define G_PER_LSB ( 0.00390625 ) ///< conversion from counts (LSB) to gravities #define NO_NEW_ACCEL_SAMPLES_TIMEOUT ( 100 / TASK_PRIORITY_INTERVAL ) ///< maximum time w/o new accelerometer sample from FPGA. #define NOMINAL_ACCEL_VECTOR_LENGTH ( 1.0 ) ///< expect unit vector length when system is stable #define MAX_ACCEL_VECTOR_LENGTH_ERROR ( 0.1 ) ///< POST test looks at vector length at presumably stable moment - should be 1 +/- 0.1 #define MAX_TILT_ANGLE ( 7.0 ) ///< maximum tilt of system before alarm. #define MIN_TILT_ANGLE_TO_CLEAR_ALARM ( 5.0 ) ///< minimum tilt of system before alarm is cleared. #define MAX_TILT_PERSISTENCE ( 1 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< maximum time (in task intervals) that a tilt in excess of limit can persist before alarm #define MAX_SHOCK_ACCELERATION ( 2.0 ) ///< maximum shock (acceleration) measured on any axis before alarm. #define MAX_TILT_G ( 1.0 ) ///< maximum tilt (in g) #define MAX_TILT_ANGLE_DEG ( 90.0 ) ///< maximum tilt angle (in degrees) /// Enumeration of accelerometer monitor states. typedef enum Accelerometer_States { ACCELEROMETER_START_STATE = 0, ///< Accelerometer start state. ACCELEROMETER_MONITOR_STATE, ///< Accelerometer monitor state. NUM_OF_ACCELEROMETER_STATES ///< Number of accelerometer states. } ACCEL_STATE_T; /// Enumeration of accelerometer self test states. typedef enum Accelerometer_Self_Test_States { ACCELEROMETER_SELF_TEST_STATE_START = 0, ///< Accelerometer self test start state. ACCELEROMETER_SELF_TEST_STATE_IN_PROGRESS, ///< Accelerometer self test in progress state. ACCELEROMETER_SELF_TEST_STATE_COMPLETE, ///< Accelerometer self test completed state. NUM_OF_ACCELEROMETER_SELF_TEST_STATES ///< Number of accelerometer self test states. } ACCELEROMETER_SELF_TEST_STATE_T; // ********** private data ********** static ACCEL_STATE_T accelState = ACCELEROMETER_START_STATE; ///< current state of accelerometer monitor state machine static U32 accelDataPublicationTimerCounter = 0; ///< used to schedule accelerometer data publication to CAN bus static F32 accelCalOffsets[ NUM_OF_ACCEL_AXES ] = { 0, 0, 0 }; ///< accelerometer calibration offsets. static OVERRIDE_U32_T accelDataPublishInterval = { ACCEL_DATA_PUB_INTERVAL, ACCEL_DATA_PUB_INTERVAL, 0, 0 }; ///< interval (in ms/task interval) at which to publish accelerometer data to CAN bus. static OVERRIDE_F32_T accelAxes[ NUM_OF_ACCEL_AXES ]; ///< Measured accelerometer axis readings (calibrated, converted to gravities). static OVERRIDE_F32_T accelMaxs[ NUM_OF_ACCEL_AXES ]; ///< Maximum axis readings since last sample (calibrated, converted to gravities). static U16 accelFPGAFaultReg = 0; ///< FPGA accelerometer fault register value indicates whether issues with reading accelerometer. static U16 accelFPGASampleCtr = 0; ///< Sample counter from FPGA indicates when new sample(s) are available. static U32 accelNoNewSampleTimerCounter = 0; ///< used to enforce timeout on no new samples. static F32 accelReadings[ NUM_OF_ACCEL_AXES ][ SIZE_OF_ROLLING_AVG ]; ///< holds flow samples for a rolling average static F32 accelReadingsTotal[ NUM_OF_ACCEL_AXES ]; ///< rolling total - used to calc average static U32 accelReadingsIdx = 0; ///< index for next sample in rolling average array static U32 accelReadingsCount = 0; ///< number of samples in flow rolling average buffer static F32 accelAvgVector[ NUM_OF_ACCEL_AXES ]; ///< Filtered accelerometer vector for tilt. static F32 accelTilt[ NUM_OF_ACCEL_AXES ]; ///< Axis angles for tilt determination (filtered and converted to degrees). static U32 accelTiltErrorTimerCounter = 0; ///< used for persistence requirement on tilt error static ACCELEROMETER_SELF_TEST_STATE_T accelSelfTestState = ACCELEROMETER_SELF_TEST_STATE_START; ///< current accelerometer self test state // ********** private function prototypes ********** static ACCEL_STATE_T handleAccelMonitorState( void ); static void publishAccelData( void ); static void resetAccelMovingAverage( void ); static void filterAccelReadings( void ); static F32 calcVectorLength( F32 x, F32 y, F32 z ); static void checkForTiltError( void ); static void checkForShockError( void ); /*********************************************************************//** * @brief * The initAccel function initializes the Accel module. * @details * Inputs : none * Outputs : Accel module initialized. * @return none *************************************************************************/ void initAccel( void ) { ACCEL_AXIS_T axis; // zero rolling average buffer on accelerometer readings resetAccelMovingAverage(); // zero accel readings for ( axis = ACCEL_AXIS_X; axis < NUM_OF_ACCEL_AXES; axis++ ) { accelAxes[ axis ].data = 0.0; accelAxes[ axis ].ovData = 0.0; accelAxes[ axis ].ovInitData = 0.0; accelAxes[ axis ].override = OVERRIDE_RESET; accelMaxs[ axis ].data = 0.0; accelMaxs[ axis ].ovData = 0.0; accelMaxs[ axis ].ovInitData = 0.0; accelMaxs[ axis ].override = OVERRIDE_RESET; } } /*********************************************************************//** * @brief * The execAccel function executes the accelerometer monitor state machine. * @details * Inputs : accelState * Outputs : accelState * @return none *************************************************************************/ void execAccel( void ) { switch ( accelState ) { case ACCELEROMETER_START_STATE: accelState = ACCELEROMETER_MONITOR_STATE; break; case ACCELEROMETER_MONITOR_STATE: accelState = handleAccelMonitorState(); break; default: #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_INVALID_STATE, accelState ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_INVALID_STATE, accelState ) #endif break; } // publish accelerometer data on interval publishAccelData(); } /*********************************************************************//** * @brief * The handleAccelMonitorState function handles the accelerometer monitor state \n * of the accelerometer monitor state machine. * @details * Inputs : * Outputs : * @return next state *************************************************************************/ static ACCEL_STATE_T handleAccelMonitorState( void ) { ACCEL_STATE_T result = ACCELEROMETER_MONITOR_STATE; S16 x, y, z; // axis readings S16 xm, ym, zm; // max axis readings since last time we read FPGA registers F32 xMax, yMax, zMax; // max axis readings (in gs) U16 cnt; // FPGA read counter // read FPGA accelerometer registers getFPGAAccelAxes( &x, &y, &z ); getFPGAAccelMaxes( &xm, &ym, &zm ); getFPGAAccelStatus( &cnt, &accelFPGAFaultReg ); // check fresh sample if ( cnt != accelFPGASampleCtr ) { accelNoNewSampleTimerCounter = 0; accelFPGASampleCtr = cnt; } else { if ( ++accelNoNewSampleTimerCounter > NO_NEW_ACCEL_SAMPLES_TIMEOUT ) { #ifdef _DG_ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_ACCELEROMETER_FAILURE, 0 ) #else SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ACCELEROMETER_FAILURE, 0 ) #endif } } // check error status if ( accelFPGAFaultReg != 0 ) { #ifdef _DG_ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_ACCELEROMETER_FAILURE, 1 ) #else SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ACCELEROMETER_FAILURE, 1 ) #endif } // convert to gravities and apply calibration (axis offsets) accelAxes[ ACCEL_AXIS_X ].data = (F32)x * G_PER_LSB + accelCalOffsets[ ACCEL_AXIS_X ]; accelAxes[ ACCEL_AXIS_Y ].data = (F32)y * G_PER_LSB + accelCalOffsets[ ACCEL_AXIS_Y ]; accelAxes[ ACCEL_AXIS_Z ].data = (F32)z * G_PER_LSB + accelCalOffsets[ ACCEL_AXIS_Z ]; xMax = (F32)xm * G_PER_LSB; yMax = (F32)ym * G_PER_LSB; zMax = (F32)zm * G_PER_LSB; if ( xMax > accelMaxs[ ACCEL_AXIS_X ].data ) { accelMaxs[ ACCEL_AXIS_X ].data = xMax; } if ( yMax > accelMaxs[ ACCEL_AXIS_Y ].data ) { accelMaxs[ ACCEL_AXIS_Y ].data = yMax; } if ( zMax > accelMaxs[ ACCEL_AXIS_Z ].data ) { accelMaxs[ ACCEL_AXIS_Z ].data = zMax; } // filter readings to get a stable vector for tilt filterAccelReadings(); // check tilt and shock checkForTiltError(); checkForShockError(); return result; } /*********************************************************************//** * @brief * The getPublishAccelDataInterval function gets the accelerometer vector data \n * publication interval. * @details * Inputs : accelDataPublishInterval * Outputs : none * @return the current accelerometer vector data publication interval (in priority task periods). *************************************************************************/ U32 getPublishAccelDataInterval( void ) { U32 result = accelDataPublishInterval.data; if ( OVERRIDE_KEY == accelDataPublishInterval.override ) { result = accelDataPublishInterval.ovData; } return result; } /*********************************************************************//** * @brief * The getMeasuredAccelAxis function gets the current magnitude for the given \n * accelerometer axis. * @details * Inputs : accelAxes[] * Outputs : accelAxes[] * @return the current magnitude for the given accelerometer axis (in g). *************************************************************************/ F32 getMeasuredAccelAxis( U32 axis ) { F32 result = 0.0; if ( axis < NUM_OF_ACCEL_AXES ) { if ( OVERRIDE_KEY == accelAxes[ axis ].override ) { result = accelAxes[ axis ].ovData; } else { result = accelAxes[ axis ].data; } } else { #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_GET_INVALID_AXIS, axis ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_GET_INVALID_AXIS, axis ) #endif } return result; } /*********************************************************************//** * @brief * The getMaxAccelAxis function gets the current max magnitude for the given \n * accelerometer axis. * @details * Inputs : accelMaxs[] * Outputs : accelMaxs[] * @return the current maximum magnitude for the given accelerometer axis (in g). *************************************************************************/ F32 getMaxAccelAxis( U32 axis ) { F32 result = 0.0; if ( axis < NUM_OF_ACCEL_AXES ) { if ( OVERRIDE_KEY == accelMaxs[ axis ].override ) { result = accelMaxs[ axis ].ovData; } else { result = accelMaxs[ axis ].data; } } else { #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_GET_MAX_INVALID_AXIS, axis ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_GET_MAX_INVALID_AXIS, axis ) #endif } return result; } /*********************************************************************//** * @brief * The publishAccelData function publishes accelerometer data at the set \n * interval. * @details * Inputs : accelAxes[] * Outputs : Accelerometer data is published to CAN bus. * @return none *************************************************************************/ static void publishAccelData( void ) { // publish accelerometer data on interval if ( ++accelDataPublicationTimerCounter >= getPublishAccelDataInterval() ) { F32 x = accelAvgVector[ ACCEL_AXIS_X ]; F32 y = accelAvgVector[ ACCEL_AXIS_Y ]; F32 z = accelAvgVector[ ACCEL_AXIS_Z ]; F32 xm = getMaxAccelAxis( ACCEL_AXIS_X ); F32 ym = getMaxAccelAxis( ACCEL_AXIS_Y ); F32 zm = getMaxAccelAxis( ACCEL_AXIS_Z ); F32 xt = accelTilt[ ACCEL_AXIS_X ]; F32 yt = accelTilt[ ACCEL_AXIS_Y ]; F32 zt = accelTilt[ ACCEL_AXIS_Z ]; broadcastAccelData( x, y, z, xm, ym, zm, xt, yt, zt ); // reset publication timer counter accelDataPublicationTimerCounter = 0; // reset max axes accelMaxs[ ACCEL_AXIS_X ].data = 0.0; accelMaxs[ ACCEL_AXIS_Y ].data = 0.0; accelMaxs[ ACCEL_AXIS_Z ].data = 0.0; } } /*********************************************************************//** * @brief * The resetAccelMovingAverage function re-initializes the accelerometer \n * moving average sample buffer. * @details * Inputs : none * Outputs : accelReadingsTotal, accelReadingsIdx, accelReadingsCount all set to zero. * @return none *************************************************************************/ static void resetAccelMovingAverage( void ) { U32 axis, i; for ( axis = ACCEL_AXIS_X; axis < NUM_OF_ACCEL_AXES; axis++ ) { accelReadingsTotal[ axis ] = 0.0; accelAvgVector[ axis ] = 0.0; accelTilt[ axis ] = 0.0; for ( i = 0; i < SIZE_OF_ROLLING_AVG; i++ ) { accelReadings[ axis ][ i ] = 0.0; } } accelReadingsIdx = 0; accelReadingsCount = 0; } /*********************************************************************//** * @brief * The filterAccelReadings function adds a new axis samples to the filter. \n * @details * Inputs : none * Outputs : flowReadings[], flowReadingsIdx, flowReadingsCount * @return none *************************************************************************/ static void filterAccelReadings( void ) { U32 axis; for ( axis = ACCEL_AXIS_X; axis < NUM_OF_ACCEL_AXES; axis++ ) { F32 rdg = getMeasuredAccelAxis( axis ); if ( accelReadingsCount >= SIZE_OF_ROLLING_AVG ) { accelReadingsTotal[ axis ] -= accelReadings[ axis ][ accelReadingsIdx ]; } accelReadings[ axis ][ accelReadingsIdx ] = rdg; accelReadingsTotal[ axis ] += rdg; } accelReadingsIdx = INC_WRAP( accelReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); accelReadingsCount = INC_CAP( accelReadingsCount, SIZE_OF_ROLLING_AVG ); // calculate average vector axes accelAvgVector[ ACCEL_AXIS_X ] = accelReadingsTotal[ ACCEL_AXIS_X ] / (F32)accelReadingsCount; accelAvgVector[ ACCEL_AXIS_Y ] = accelReadingsTotal[ ACCEL_AXIS_Y ] / (F32)accelReadingsCount; accelAvgVector[ ACCEL_AXIS_Z ] = accelReadingsTotal[ ACCEL_AXIS_Z ] / (F32)accelReadingsCount; // calculate axis angles for ( axis = ACCEL_AXIS_X; axis < NUM_OF_ACCEL_AXES; axis++ ) { if ( accelAvgVector[ axis ] > MAX_TILT_G ) { accelTilt[ axis ] = MAX_TILT_ANGLE_DEG; } else if ( accelAvgVector[ axis ] < ( MAX_TILT_G * -1.0 ) ) { accelTilt[ axis ] = MAX_TILT_ANGLE_DEG * -1.0; } else { accelTilt[ axis ] = RAD2DEG( asin( accelAvgVector[ axis ] ) ); } } } /*********************************************************************//** * @brief * The calcVectorLength function calculates the length of a vector with \n * given vector axis magnitudes. * @details * Inputs : none * Outputs : none * @param x X axis magnitude of vector * @param y Y axis magnitude of vector * @param z Z axis magnitude of vector * @return the length of the given vector. *************************************************************************/ static F32 calcVectorLength( F32 x, F32 y, F32 z ) { F32 result = sqrt( x * x + y * y + z * z ); return result; } /*********************************************************************//** * @brief * The checkForTiltError function checks for a tilt error. * @details * Inputs : accelTilt[], accelTiltErrorTimerCounter * Outputs : alarm if persistent excessive tilt detected * @return none *************************************************************************/ static void checkForTiltError( void ) { F32 x = accelTilt[ ACCEL_AXIS_X ]; F32 y = accelTilt[ ACCEL_AXIS_Y ]; // is system tilted too much? if ( ( fabs( x ) > MAX_TILT_ANGLE ) || ( fabs( y ) > MAX_TILT_ANGLE ) ) { // excessive tilt must persist before triggering alarm if ( ++accelTiltErrorTimerCounter > MAX_TILT_PERSISTENCE ) { #ifdef _DG_ SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_EXCESSIVE_TILT, x, y ) #else SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_EXCESSIVE_TILT, x, y ) #endif } } else if ( ( fabs( x ) <= MIN_TILT_ANGLE_TO_CLEAR_ALARM ) && ( fabs( y ) <= MIN_TILT_ANGLE_TO_CLEAR_ALARM ) ) { accelTiltErrorTimerCounter = 0; #ifdef _DG_ clearAlarm( ALARM_ID_DG_EXCESSIVE_TILT ); #else clearAlarm( ALARM_ID_HD_EXCESSIVE_TILT ); #endif } else { accelTiltErrorTimerCounter = ( accelTiltErrorTimerCounter > 0 ? accelTiltErrorTimerCounter - 1 : 0 ); } } /*********************************************************************//** * @brief * The checkForShockError function checks for a shock error. * @details * Inputs : accelMaxs[] * Outputs : alarm if excessive shock detected * @return none *************************************************************************/ static void checkForShockError( void ) { F32 maxX = fabs(getMaxAccelAxis( ACCEL_AXIS_X )); F32 maxY = fabs(getMaxAccelAxis( ACCEL_AXIS_Y )); F32 maxZ = fabs(getMaxAccelAxis( ACCEL_AXIS_Z )); F32 maxAll = maxX; ACCEL_AXIS_T maxAxis = ACCEL_AXIS_X; // determine axis with most acceleration if ( maxY > maxX || maxZ > maxX ) { if ( maxZ > maxY ) { maxAxis = ACCEL_AXIS_Z; maxAll = maxZ; } else { maxAxis = ACCEL_AXIS_Y; maxAll = maxY; } } // has system just experienced an excessive shock? if ( maxAll > MAX_SHOCK_ACCELERATION ) { #ifdef _DG_ SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SHOCK, (F32)maxAxis, maxAll ) #else SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SHOCK, (F32)maxAxis, maxAll ) #endif } } /*********************************************************************//** * @brief * The execAccelTest function executes the state machine for the \n * accelerometer self test. * @details * Inputs : accelSelfTestState * Outputs : accelSelfTestState * @return the current state of the accelerometer self test. *************************************************************************/ SELF_TEST_STATUS_T execAccelTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; switch ( accelSelfTestState ) { case ACCELEROMETER_SELF_TEST_STATE_START: { CALIBRATION_DATA_T cal; // retrieve blood flow sensor calibration data if ( TRUE == getCalibrationData( &cal ) ) { accelCalOffsets[ ACCEL_AXIS_X ] = cal.accelXOffset; accelCalOffsets[ ACCEL_AXIS_Y ] = cal.accelYOffset; accelCalOffsets[ ACCEL_AXIS_Z ] = cal.accelZOffset; accelSelfTestState = ACCELEROMETER_SELF_TEST_STATE_IN_PROGRESS; } else { // shouldn't get here - should have failed NV-Data POST prior result = SELF_TEST_STATUS_FAILED; accelSelfTestState = ACCELEROMETER_SELF_TEST_STATE_COMPLETE; #ifdef _DG_ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_ACCELEROMETER_SELF_TEST_FAILURE, 0 ) #else SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ACCELEROMETER_SELF_TEST_FAILURE, 0 ) #endif } } break; case ACCELEROMETER_SELF_TEST_STATE_IN_PROGRESS: { F32 vectorLen = calcVectorLength( accelAxes[ ACCEL_AXIS_X ].data, accelAxes[ ACCEL_AXIS_Y ].data, accelAxes[ ACCEL_AXIS_Z ].data ); if ( fabs(NOMINAL_ACCEL_VECTOR_LENGTH - vectorLen) < MAX_ACCEL_VECTOR_LENGTH_ERROR ) { result = SELF_TEST_STATUS_PASSED; } else { result = SELF_TEST_STATUS_FAILED; #ifdef _DG_ SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_ACCELEROMETER_SELF_TEST_FAILURE, vectorLen ) #else SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ACCELEROMETER_SELF_TEST_FAILURE, vectorLen ) #endif } accelSelfTestState = ACCELEROMETER_SELF_TEST_STATE_COMPLETE; } break; case ACCELEROMETER_SELF_TEST_STATE_COMPLETE: default: result = SELF_TEST_STATUS_FAILED; #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_INVALID_SELF_TEST_STATE, accelSelfTestState ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ACCEL_INVALID_SELF_TEST_STATE, accelSelfTestState ) #endif break; } return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The setAccelCalibration function sets the accelerometer calibration \n * factors and has them stored in non-volatile memory. * @details * Inputs : none * Outputs : accelCalOffsets[] * @param offsetX offset calibration factor for X axis * @param offsetY offset calibration factor for Y axis * @param offsetZ offset calibration factor for Z axis * @return TRUE if calibration factors successfully set/stored, FALSE if not *************************************************************************/ BOOL setAccelCalibration( F32 offsetX, F32 offsetY, F32 offsetZ ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { CALIBRATION_DATA_T cal; getCalibrationData( &cal ); // keep locally and apply immediately accelCalOffsets[ ACCEL_AXIS_X ] = offsetX; accelCalOffsets[ ACCEL_AXIS_Y ] = offsetY; accelCalOffsets[ ACCEL_AXIS_Z ] = offsetZ; // also update calibration record in non-volatile memory cal.accelXOffset = offsetX; cal.accelYOffset = offsetY; cal.accelZOffset = offsetZ; setCalibrationData( cal ); result = TRUE; } return result; } /*********************************************************************//** * @brief * The getAccelCalibration function retrieves the current accelerometer \n * calibration factors. * @details * Inputs : accelCalOffsets[] * Outputs : none * @param offsetX value to populate with X axis offset calibration factor * @param offsetY value to populate with Y axis offset calibration factor * @param offsetZ value to populate with Z axis offset calibration factor * @return none *************************************************************************/ void getAccelCalibration( F32 *offsetX, F32 *offsetY, F32 *offsetZ ) { *offsetX = accelCalOffsets[ ACCEL_AXIS_X ]; *offsetY = accelCalOffsets[ ACCEL_AXIS_Y ]; *offsetZ = accelCalOffsets[ ACCEL_AXIS_Z ]; } /*********************************************************************//** * @brief * The testSetAccelDataPublishIntervalOverride function overrides the \n * accelerometer data publish interval. * @details * Inputs : none * Outputs : accelDataPublishInterval * @param value override accelerometer data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetAccelDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; result = TRUE; accelDataPublishInterval.ovData = intvl; accelDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetAccelDataPublishIntervalOverride function resets the override \n * of the accelerometer data publish interval. * @details * Inputs : none * Outputs : accelDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetAccelDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; accelDataPublishInterval.override = OVERRIDE_RESET; accelDataPublishInterval.ovData = accelDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetAccelAxisOverride function overrides the value of the \n * specified accelerometer axis with a given value. * Inputs : none * Outputs : accelAxes[] * @param axis ID of sensor axis to override for * @param value override value for the given axis * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetAccelAxisOverride( U32 axis, F32 value ) { BOOL result = FALSE; if ( axis < NUM_OF_ACCEL_AXES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; accelAxes[ axis ].ovData = value; accelAxes[ axis ].override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetAccelAxisOverride function resets the override of the \n * specified accelerometer axis. * @details * Inputs : none * Outputs : accelAxes[] * @param axis ID of accelerometer axis to reset override for * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetAccelAxisOverride( U32 axis ) { BOOL result = FALSE; if ( axis < NUM_OF_ACCEL_AXES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; accelAxes[ axis ].override = OVERRIDE_RESET; accelAxes[ axis ].ovData = accelAxes[ axis ].ovInitData; } } return result; } /*********************************************************************//** * @brief * The testSetAccelMaxOverride function overrides the max. value of the \n * specified accelerometer axis with a given value. * Inputs : none * Outputs : accelMaxs[] * @param axis ID of sensor axis to override for * @param value override value for the given axis maximum * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetAccelMaxOverride( U32 axis, F32 value ) { BOOL result = FALSE; if ( axis < NUM_OF_ACCEL_AXES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; accelMaxs[ axis ].ovData = value; accelMaxs[ axis ].override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetAccelMaxOverride function resets the override of the \n * specified accelerometer axis maximum. * @details * Inputs : none * Outputs : accelMaxs[] * @param axis ID of accelerometer axis to reset override for * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetAccelMaxOverride( U32 axis ) { BOOL result = FALSE; if ( axis < NUM_OF_ACCEL_AXES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; accelMaxs[ axis ].override = OVERRIDE_RESET; accelMaxs[ axis ].ovData = accelMaxs[ axis ].ovInitData; } } return result; } /**@}*/