AVED Sensor Control (ASC) Proxy Driver

Overview

The ASC proxy driver allocates memory and copies all provided sensor data from the appropriate profile (see Profiles and CMake build process#Profiles) in the initialization. ASC uses this to read associated sensor functions, store current values, current statuses and calculates averages for all provided sensors.

Internally, it creates a mutex for protection and a task to handle interaction with the associated sensor functions.

The Task will:

  • Call the associated read sensor function and store its value.

  • Signal an event with the EVL core library.

The Proxy API consists of a number of functions to set and get the sensor data that is updated by the proxy task.

API

Defines

Defines

#define ASC_SENSOR_NAME_MAX  ( 20 )

Enums

ASC_PROXY_DRIVER_EVENTS

/*
 * @enum    ASC_PROXY_DRIVER_EVENTS
 * @brief   Events raised by this proxy driver
 */
typedef enum ASC_PROXY_DRIVER_EVENTS
{
    ASC_PROXY_DRIVER_E_SENSOR_UPDATE_COMPLETE = 0,
    ASC_PROXY_DRIVER_E_SENSOR_UNAVAILABLE,
    ASC_PROXY_DRIVER_E_SENSOR_COMMS_FAILURE,
    ASC_PROXY_DRIVER_E_SENSOR_WARNING,
    ASC_PROXY_DRIVER_E_SENSOR_CRITICAL,
    ASC_PROXY_DRIVER_E_SENSOR_FATAL,
    ASC_PROXY_DRIVER_E_SENSOR_LOWER_WARNING,
    ASC_PROXY_DRIVER_E_SENSOR_LOWER_CRITICAL,
    ASC_PROXY_DRIVER_E_SENSOR_LOWER_FATAL,
    ASC_PROXY_DRIVER_E_SENSOR_UPPER_WARNING,
    ASC_PROXY_DRIVER_E_SENSOR_UPPER_CRITICAL,
    ASC_PROXY_DRIVER_E_SENSOR_UPPER_FATAL,

    MAX_ASC_PROXY_DRIVER_EVENTS

} ASC_PROXY_DRIVER_EVENTS;

ASC_PROXY_DRIVER_SENSOR_STATUS

/*
 * @enum    ASC_PROXY_DRIVER_SENSOR_STATUS
 * @brief   Status of sensor
 */
typedef enum ASC_PROXY_DRIVER_SENSOR_STATUS
{
    ASC_PROXY_DRIVER_SENSOR_STATUS_NOT_PRESENT = 0,
    ASC_PROXY_DRIVER_SENSOR_STATUS_PRESENT_AND_VALID,
    ASC_PROXY_DRIVER_SENSOR_STATUS_DATA_NOT_AVAILABLE,
    ASC_PROXY_DRIVER_SENSOR_STATUS_NOT_AVAILABLE,

    MAX_ASC_PROXY_DRIVER_SENSOR_STATUS

} ASC_PROXY_DRIVER_SENSOR_STATUS;

ASC_PROXY_DRIVER_SENSOR_UNIT_MOD

/*
 * @enum   ASC_PROXY_DRIVER_SENSOR_UNIT_MOD
 * @brief  Base unit modifiers for sensor readings
 */
typedef enum ASC_PROXY_DRIVER_SENSOR_UNIT_MOD
{
    ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_MEGA  = 0,
    ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_KILO,
    ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_NONE,
    ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_MILLI,
    ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_MICRO,

    MAX_ASC_PROXY_DRIVER_SENSOR_UNIT_MOD

} ASC_PROXY_DRIVER_SENSOR_UNIT_MOD;

ASC_PROXY_DRIVER_SENSOR_TYPE

/*
 * @enum    ASC_PROXY_DRIVER_SENSOR_TYPE
 * @brief   Type of sensor
 */
typedef enum ASC_PROXY_DRIVER_SENSOR_TYPE
{
    ASC_PROXY_DRIVER_SENSOR_TYPE_TEMPERATURE = 0,
    ASC_PROXY_DRIVER_SENSOR_TYPE_VOLTAGE,
    ASC_PROXY_DRIVER_SENSOR_TYPE_CURRENT,
    ASC_PROXY_DRIVER_SENSOR_TYPE_POWER,

    MAX_ASC_PROXY_DRIVER_SENSOR_TYPE

} ASC_PROXY_DRIVER_SENSOR_TYPE;

ASC_PROXY_DRIVER_SENSOR_BITFIELD

/*
 * @enum    ASC_PROXY_DRIVER_SENSOR_BITFIELD
 * @brief   Bitfield of sensor types
 */
typedef enum ASC_PROXY_DRIVER_SENSOR_BITFIELD
{
    ASC_PROXY_DRIVER_SENSOR_BITFIELD_TEMPERATURE = ( 1 << 0 ),
    ASC_PROXY_DRIVER_SENSOR_BITFIELD_VOLTAGE     = ( 1 << 1 ),
    ASC_PROXY_DRIVER_SENSOR_BITFIELD_CURRENT     = ( 1 << 2 ),
    ASC_PROXY_DRIVER_SENSOR_BITFIELD_POWER       = ( 1 << 3 ),

    MAX_ASC_PROXY_DRIVER_SENSOR_BITFIELD

} ASC_PROXY_DRIVER_SENSOR_BITFIELD;

Structs

ASC_PROXY_DRIVER_SENSOR_READINGS

/*
 * @struct  ASC_PROXY_DRIVER_SENSOR_READINGS
 * @brief   Sensor data readings
 */
typedef struct ASC_PROXY_DRIVER_SENSOR_READINGS
{
    uint32_t                          ulSensorValue;

    const uint32_t                    ulLowerWarningLimit;
    const uint32_t                    ulLowerCriticalLimit;
    const uint32_t                    ulLowerFatalLimit;
    const uint32_t                    ulUpperWarningLimit;
    const uint32_t                    ulUpperCriticalLimit;
    const uint32_t                    ulUpperFatalLimit;
    uint32_t                          ulAverageSensorValue;
    uint32_t                          ulMaxSensorValue;

    ASC_PROXY_DRIVER_SENSOR_STATUS    xSensorStatus;
    ASC_PROXY_DRIVER_SENSOR_UNIT_MOD  xSensorUnitModifier;

} ASC_PROXY_DRIVER_SENSOR_READINGS;

ASC_PROXY_DRIVER_SENSOR_DATA

/*
 * @struct  ASC_PROXY_DRIVER_SENSOR_DATA
 * @brief   Sensor data
 */
typedef struct ASC_PROXY_DRIVER_SENSOR_DATA
{
    const char                        pcSensorName[ ASC_SENSOR_NAME_MAX ];

    const uint8_t                     ucSensorId;
    const uint8_t                     ucSensorType;
    const uint8_t                     ucSensorAddress;

    ASC_PROXY_DRIVER_SENSOR_READINGS  xReadings[ MAX_ASC_PROXY_DRIVER_SENSOR_TYPE ];

} ASC_PROXY_DRIVER_SENSOR_DATA;

Proxy Driver External APIs

Initialise the ASC

iASC_Initialise

/*
 * @brief   Main initialisation point for the ASC Proxy Driver
 *
 * @param   ucProxyId      Unique ID for this Proxy driver
 * @param   pxFwIf         Handle to the Firmware Interface to use
 * @param   ulFwIfPort     Port to use on the Firmware Interface
 * @param   ulTaskPrio     Priority of the Proxy driver task (if RR disabled)
 * @param   ulTaskStack    Stack size of the Proxy driver task
 * @param   pxSensorData   Array of sensor data
 * @param   ucNumSensors   Number of sensors to monitor
 *
 * @return  OK          Proxy driver initialised correctly
 *          ERROR       Proxy driver not initialised, or was already initialised
 *
 * @notes   Proxy drivers can have 0 or more firmware interfaces
 */
int iASC_Initialise( uint8_t ucProxyId,
                     FW_IF_CFG *pxFwIf,
                     uint32_t ulFwIfPort,
                     uint32_t ulTaskPrio,
                     uint32_t ulTaskStack,
                     ASC_PROXY_DRIVER_SENSOR_DATA *pxSensorData,
                     uint8_t ucNumSensors );

Bind callback

iASC_BindCallback

/*
 * @brief   Bind into this proxy driver
 *
 * @param   pxCallback  Callback to bind into the proxy driver
 *
 * @return  OK          Callback successfully bound
 *          ERROR       Callback not bound
 *
 * @notes   None
 */
int iASC_BindCallback( AEL_CALLBACK *pxCallback );

Reset all of the transient sensor data

iASC_ResetAllSensorData

/*
 * @brief   Reset current, average, max and status values for all sensors
 *
 * @param   None
 *
 * @return  OK          Data reset successfully
 *          ERROR       Data not reset successfully
 *
 * @notes   None
 */
int iASC_ResetAllSensorData( void );

Reset a single sensor’s transient data by ID

iASC_ResetSingleSensorDatabyId

/*
 * @brief   Reset current, average, max and status values for a single sensor by ID
 *
 * @param   ucId        Sensor ID
 *
 * @return  OK          Data reset successfully
 *          ERROR       Data not reset successfully
 *
 * @notes   None
 */
int iASC_ResetSingleSensorDatabyId( uint8_t ucId );

Reset a single sensor’s transient data by name

iASC_ResetSingleSensorDatabyName

/*
 * @brief   Reset current, average, max and status values for a single sensor by name
 *
 * @param   pcName      Sensor Name
 *
 * @return  OK          Data reset successfully
 *          ERROR       Data not reset successfully
 *
 * @notes   None
 */
int iASC_ResetSingleSensorDatabyName( const char *pcName );

Get all of the sensor’s data

iASC_GetAllSensorData

/*
 * @brief   Get all sensor data
 *
 * @param   pxData         Pointer to data to get
 * @param   pucNumSensors  Pointer to the number of sensors monitored
 *                         Orignally passed in as the maximum number of sensors that can be monitored but will then be
 *                         updated to the actual number of sensors that are monitored
 *
 * @return  OK             Data retrieved successfully
 *          ERROR          Data not retrieved successfully
 *
 * @notes   None
 */
int iASC_GetAllSensorData( ASC_PROXY_DRIVER_SENSOR_DATA *pxData, uint8_t *pucNumSensors );

Get a single sensor’s data by ID

iASC_GetSingleSensorDataById

/*
 * @brief   Get single sensor data by ID
 *
 * @param   ucId        Sensor ID
 * @param   pxData      Pointer to data to get
 *
 * @return  OK          Data retrieved successfully
 *          ERROR       Data not retrieved successfully
 *
 * @notes   None
 */
int iASC_GetSingleSensorDataById( uint8_t ucId, ASC_PROXY_DRIVER_SENSOR_DATA *pxData );

Get a single sensor’s data by name

iASC_GetSingleSensorDataByName

/*
 * @brief   Get single sensor data by name
 *
 * @param   pcName      Sensor Name
 * @param   pxData      Pointer to data to get
 *
 * @return  OK          Data retrieved successfully
 *          ERROR       Data not retrieved successfully
 *
 * @notes   None
 */
int iASC_GetSingleSensorDataByName( const char *pcName, ASC_PROXY_DRIVER_SENSOR_DATA *pxData );

Display the statistic counters and errors.

iASC_PrintStatistics

/**
 * @brief   Print all of the stats gathered by the application
 *
 * @return  OK          Stats retrieved from proxy driver successfully
 *          ERROR       Stats not retrieved successfully
 *
 */
int iASC_PrintStatistics( void );

Clear the all statistics counters back to zero.

iASC_ClearStatistics

/**
 * @brief   Clear all of the stats in the application
 *
 * @return  OK          Stats cleared successfully
 *          ERROR       Stats not cleared successfully
 *
 */
int iASC_ClearStatistics( void );

Sequence Diagrams

ASC Proxy Initialization

Two ASC API functions are called from the AMC main task (iASC_Initialise and iASC_BindCallback), in order to initialise the proxy.

iASC_Initialise will call into the FAL to open with the provided handle, create a shared proxy mutex, create the proxy task, allocate memory and copy the provided sensor data.

iASC_BindCallback will bind the appropriate top-level callback function.

image1

ASC Proxy Task

The task within ASC proxy has 2 main responsibilities:

  • For each sensor, and for each sensor type (temperature, voltage, current, power, etc), call the associated read sensor function, store its value, calculate average value, and set its status.

  • Signal an event with EVL core library, if a sensor value exceeds thresholds and when sensor updates have completed.

image2

Examples

Initialize Driver

This function should only be called once. It requires an unique ID for the proxy, used for signaling new events from the proxy, along with a handle to a FW_IF (already created and initialized), FW_IF port number, proxy driver task priority, stack size, pointer to sensor data array and total number of sensors to be monitored (should match the number of entries in the sensor array).

iASC_Initialise Example

if( OK == iASC_Initialise( AMC_EVENT_UNIQUE_ID_ASC, &xI2cIf, 0, AMC_TASK_PRIO_DEFAULT, AMC_TASK_DEFAULT_STACK, PROFILE_SENSORS_SENSOR_DATA, PROFILE_SENSORS_NUM_SENSORS ) )
{
    AMC_PRINTF( "ASC Proxy Driver initialised\r\n" );
}
else
{
    AMC_PRINTF( "Error initialising ASC Proxy Driver\r\n" );
}

Register For Callback

Define a function based on the function pointer prototype and bind in using the API.

iASC_BindCallback Example

/* Define a callback to handle the events */
static int iAscCallback( EVL_SIGNAL *pxSignal )
{
    int iStatus = ERROR;

    if( ( NULL != pxSignal ) && ( AMC_EVENT_UNIQUE_ID_ASC == pxSignal->ucModule ) )
    {
        switch( pxSignal->ucEventType )
        {
        case ASC_PROXY_DRIVER_E_SENSOR_UPDATE_COMPLETE:
        case ASC_PROXY_DRIVER_E_SENSOR_UNAVAILABLE:
        case ASC_PROXY_DRIVER_E_SENSOR_COMMS_FAILURE:
        case ASC_PROXY_DRIVER_E_SENSOR_WARNING:
        case ASC_PROXY_DRIVER_E_SENSOR_CRITICAL:
        case ASC_PROXY_DRIVER_E_SENSOR_FATAL:
        case ASC_PROXY_DRIVER_E_SENSOR_LOWER_WARNING:
        case ASC_PROXY_DRIVER_E_SENSOR_LOWER_CRITICAL:
        case ASC_PROXY_DRIVER_E_SENSOR_LOWER_FATAL:
        case ASC_PROXY_DRIVER_E_SENSOR_UPPER_WARNING:
        case ASC_PROXY_DRIVER_E_SENSOR_UPPER_CRITICAL:
        case ASC_PROXY_DRIVER_E_SENSOR_UPPER_FATAL:
            /* TODO: handle events */
            iStatus = OK;
            break;
        default:
            break;
        }
    }

    return iStatus;
}

/* Bind into the callback during the application initialisation */
if( OK == iASC_BindCallback( &iAscCallback ) )
{
    AMC_PRINTF( "ASC Proxy Driver initialised and bound\r\n" );
}
else
{
    AMC_PRINTF( "Error binding to ASC Proxy Driver\r\n" );
}

Sets

Reset all sensor data

Example of re-setting all sensor data. No parameters required, simply call the API.

iASC_ResetAllSensorData Example

if( OK != iASC_ResetAllSensorData() )
{
    ASC_DBG_PRINTF( "Error resetting sensors data\r\n" );
}
else
{
    ASC_DBG_PRINTF( "All sensor data reset\r\n" );
}

Reset single sensor data (by ID)

Example of re-setting single sensor by ID.

iASC_ResetSingleSensorDataById Example

uint8_t iId = 0;    /* set to required ID */

if( OK != iASC_ResetSingleSensorDataById( iId )
{
    ASC_DBG_PRINTF( "Error resetting sensor %d data\r\n", iId );
}
else
{
    ASC_DBG_PRINTF( "Sensor %d data reset\r\n", iId );
}

Reset single sensor data (by name)

Example of re-setting single sensor by name.

iASC_ResetSingleSensorDataByName Example

char pcName[ ASC_SENSOR_NAME_MAX ] = { 0 };     /* set to required name */

if( OK != iASC_ResetSingleSensorDataByName( pcName ) )
{
    ASC_DBG_PRINTF( "Error resetting sensor %s data\r\n", pcName );
}
else
{
    ASC_DBG_PRINTF( "Sensor %s data reset\r\n", pcName );
}

Gets

Get all sensor data

Example of reading all sensor data, from max number of sensors required.

iASC_GetAllSensorData Example

int iMaxSensors = 15; /* Set to max num of sensors required */
ASC_PROXY_DRIVER_SENSOR_DATA *pxSensors = pvOSAL_MemAlloc( iMaxSensors * sizeof( ASC_PROXY_DRIVER_SENSOR_DATA ) );

if( NULL == pxSensors )
{
    ASC_DBG_PRINTF( "Unable to allocate data for %d sensors\r\n", iMaxSensors );
}
else
{
    uint8_t uNumSensors = ( uint8_t )iMaxSensors;
    if( OK != iASC_GetAllSensorData( pxSensors, &uNumSensors ) )
    {
        ASC_DBG_PRINTF( "Error retrieving sensor data\r\n" );
    }
    else
    {
        ASC_DBG_PRINTF( "Retrieved %d sensors\r\n", uNumSensors );

        int i = 0;
        for( i = 0; i < uNumSensors; i++ )
        {
            ASC_DBG_PRINTF( "Sensor %d:\r\n", i );
            ASC_DBG_PRINTF( "****************************************************\r\n" );
            vPrintSensorData( &pxSensors[ i ] );
        }
    }

    vOSAL_MemFree( ( void** )&pxSensors ); /* free allocated memory */
}

Get single sensor data (by ID)

Example of reading sensor data by ID. Also included, an example of printing full data from a single sensor.

iASC_GetSingleSensorDataById Example

int iId = 0;    /* set to required ID */
ASC_PROXY_DRIVER_SENSOR_DATA xSensor = { { 0 } };

if( OK != iASC_GetSingleSensorDataById( ( uint8_t )iId, &xSensor ) )
{
    ASC_DBG_PRINTF( "Error retrieving sensor %d data\r\n", iId );
}
else
{
    vPrintSensorData( &xSensor );
}


/**
 * @brief   Display the full data of a single sensor
 */
static void vPrintSensorData( ASC_PROXY_DRIVER_SENSOR_DATA *pxSensor )
{
    if( NULL != pxSensor )
    {
        int i = 0;

        ASC_DBG_PRINTF( "====================================================\r\n" );
        ASC_DBG_PRINTF( "Sensor . . . . . . . . . . . . . . %s\r\n", pxSensor->pcSensorName );
        ASC_DBG_PRINTF( "- ID . . . . . . . . . . . . . . . %d\r\n", pxSensor->ucSensorId );
        ASC_DBG_PRINTF( "- Type . . . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorType );
        ASC_DBG_PRINTF( "- Address. . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorAddress );
        for( i = 0; i < MAX_ASC_PROXY_DRIVER_SENSOR_TYPE; i++ )
        {
            ASC_DBG_PRINTF( "----------------------------------------------------\r\n" );
            ASC_DBG_PRINTF( "Type: %s\r\n", pcTypeStrings[ i ] );
            ASC_DBG_PRINTF( "- Channel number . . . . . . . . . %d\r\n", pxSensor->ucChannelNumber[ i ] );
            ASC_DBG_PRINTF( "- Driver callback. . . . . . . . . %s\r\n",
                          ( NULL != pxSensor->pxReadSensorFunc[ i ] ) ? ( "Valid" ):( "NULL" ) );
            ASC_DBG_PRINTF( "- reading: value . . . . . . . . . %d\r\n", pxSensor->xReadings[ i ].ulSensorValue );
            ASC_DBG_PRINTF( "- reading: lower Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulLowerWarningLimit );
            ASC_DBG_PRINTF( "- reading: lower critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulLowerCriticalLimit );
            ASC_DBG_PRINTF( "- reading: lower fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulLowerFatalLimit );
            ASC_DBG_PRINTF( "- reading: upper Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulUpperWarningLimit );
            ASC_DBG_PRINTF( "- reading: upper critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulUpperCriticalLimit );
            ASC_DBG_PRINTF( "- reading: upper fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulUpperFatalLimit );
            ASC_DBG_PRINTF( "- reading: average sensor value. . %d\r\n", pxSensor->xReadings[ i ].ulAverageSensorValue );
            ASC_DBG_PRINTF( "- reading: max sensor value. . . . %d\r\n", pxSensor->xReadings[ i ].ulMaxSensorValue );
            ASC_DBG_PRINTF( "- reading: sensor status . . . . . %s\r\n",
                            pcStatusStrings[ pxSensor->xReadings[ i ].xSensorStatus ] );
            ASC_DBG_PRINTF( "- reading: sensor unit modifier. . %s\r\n",
                            pcModStrings[  pxSensor->xReadings[ i ].xSensorUnitModifier ] );
        }
    }
    else
    {
        ASC_DBG_PRINTF( "Error - invalid sensor data\r\n" );
    }
}

Get single sensor data (by name)

Example of reading sensor data by name. Also included, an example of printing full data from a single sensor.

iASC_GetSingleSensorDataByName Example

char pcName[ ASC_SENSOR_NAME_MAX ] = { 0 }; /* set to required name */
ASC_PROXY_DRIVER_SENSOR_DATA xSensor = { { 0 } };

if( OK != iASC_GetSingleSensorDataByName( pcName, &xSensor ) )
{
    ASC_DBG_PRINTF( "Error retrieving sensor %s data\r\n", pcName );
}
else
{
    vPrintSensorData( &xSensor );
}

/**
 * @brief   Display the full data of a single sensor
 */
static void vPrintSensorData( ASC_PROXY_DRIVER_SENSOR_DATA *pxSensor )
{
    if( NULL != pxSensor )
    {
        int i = 0;

        ASC_DBG_PRINTF( "====================================================\r\n" );
        ASC_DBG_PRINTF( "Sensor . . . . . . . . . . . . . . %s\r\n", pxSensor->pcSensorName );
        ASC_DBG_PRINTF( "- ID . . . . . . . . . . . . . . . %d\r\n", pxSensor->ucSensorId );
        ASC_DBG_PRINTF( "- Type . . . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorType );
        ASC_DBG_PRINTF( "- Address. . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorAddress );
        for( i = 0; i < MAX_ASC_PROXY_DRIVER_SENSOR_TYPE; i++ )
        {
            ASC_DBG_PRINTF( "----------------------------------------------------\r\n" );
            ASC_DBG_PRINTF( "Type: %s\r\n", pcTypeStrings[ i ] );
            ASC_DBG_PRINTF( "- Channel number . . . . . . . . . %d\r\n", pxSensor->ucChannelNumber[ i ] );
            ASC_DBG_PRINTF( "- Driver callback. . . . . . . . . %s\r\n",
                          ( NULL != pxSensor->pxReadSensorFunc[ i ] ) ? ( "Valid" ):( "NULL" ) );
            ASC_DBG_PRINTF( "- reading: value . . . . . . . . . %d\r\n", pxSensor->xReadings[ i ].ulSensorValue );
            ASC_DBG_PRINTF( "- reading: lower Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulLowerWarningLimit );
            ASC_DBG_PRINTF( "- reading: lower critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulLowerCriticalLimit );
            ASC_DBG_PRINTF( "- reading: lower fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulLowerFatalLimit );
            ASC_DBG_PRINTF( "- reading: upper Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulUpperWarningLimit );
            ASC_DBG_PRINTF( "- reading: upper critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulUpperCriticalLimit );
            ASC_DBG_PRINTF( "- reading: upper fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulUpperFatalLimit );
            ASC_DBG_PRINTF( "- reading: average sensor value. . %d\r\n", pxSensor->xReadings[ i ].ulAverageSensorValue );
            ASC_DBG_PRINTF( "- reading: max sensor value. . . . %d\r\n", pxSensor->xReadings[ i ].ulMaxSensorValue );
            ASC_DBG_PRINTF( "- reading: sensor status . . . . . %s\r\n",
                            pcStatusStrings[ pxSensor->xReadings[ i ].xSensorStatus ] );
            ASC_DBG_PRINTF( "- reading: sensor unit modifier. . %s\r\n",
                            pcModStrings[  pxSensor->xReadings[ i ].xSensorUnitModifier ] );
        }
    }
    else
    {
        ASC_DBG_PRINTF( "Error - invalid sensor data\r\n" );
    }
}

Page Revision: v. 62