Bumped Mbed FW version to 01.20.0080

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers utils.c Source File

utils.c

Go to the documentation of this file.
00001 /*
00002 Copyright 2019 (c) Analog Devices, Inc.
00003 
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions are met:
00008   - Redistributions of source code must retain the above copyright
00009     notice, this list of conditions and the following disclaimer.
00010   - Redistributions in binary form must reproduce the above copyright
00011     notice, this list of conditions and the following disclaimer in
00012     the documentation and/or other materials provided with the
00013     distribution.
00014   - Neither the name of Analog Devices, Inc. nor the names of its
00015     contributors may be used to endorse or promote products derived
00016     from this software without specific prior written permission.
00017   - The use of this software may or may not infringe the patent rights
00018     of one or more patent holders. This license does not release you
00019     from the requirement that you obtain separate licenses from these
00020     patent holders to use this software.
00021   - Use of the software either in source or binary form, must be run
00022     on or directly connected to an Analog Devices Inc. component.
00023 
00024 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
00025 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
00026 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00027 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
00028 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
00030 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 /*!
00037  ******************************************************************************
00038  * @file:  utils.c
00039  * @brief: Interface Utilities for ADMW1001
00040  *-----------------------------------------------------------------------------
00041  */
00042 #include <stdlib.h>
00043 
00044 #include "utils.h"
00045 #include "admw_log.h"
00046 
00047 void utils_printStatus(
00048     ADMW_STATUS  *pStatus)
00049 {
00050     ADMW_LOG_INFO("Status Summary:");
00051 
00052     if (pStatus->deviceStatus  == 0) {
00053         ADMW_LOG_INFO("\tNo errors detected");
00054     } else {
00055         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_BUSY )
00056             ADMW_LOG_INFO("\tCommand running");
00057         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_DATAREADY )
00058             ADMW_LOG_INFO("\tData ready");
00059         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_ERROR )
00060             ADMW_LOG_INFO("\tActive Errors - RESET REQUIRED");
00061         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_FIFO_ERROR )
00062         {
00063             ADMW_LOG_INFO("\tActive FIFO Errors - ATTENTION REQUIRED");
00064             ADMW_LOG_INFO("\tFIFO buffer full");
00065             ADMW_LOG_INFO("\tExceeding measurements per cycle limit of %d",MAXIMUM_MEASUREMENTS_PER_CYCLE);
00066         }
00067         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_CONFIG_ERROR )
00068             ADMW_LOG_INFO("\tActive Configuration Errors - ATTENTION REQUIRED");
00069         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_ALERT ) {
00070             ADMW_LOG_INFO("\tActive Alerts - ATTENTION REQUIRED:");
00071 
00072             for (unsigned i = 0; i < ADMW1001_MAX_CHANNELS ; i++) {
00073                 if (pStatus->channelAlerts [i] == 0)
00074                     continue;
00075 
00076                 ADMW_LOG_INFO("\t\tChannel #%u:", i);
00077                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_ADC_NEAR_OVERRANGE )
00078                     ADMW_LOG_INFO("\t\t\ADC near overrange detected");
00079                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_SENSOR_UNDERRANGE )
00080                     ADMW_LOG_INFO("\t\t\tSensor underrange detected");
00081                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_SENSOR_OVERRANGE )
00082                     ADMW_LOG_INFO("\t\t\tSensor overrange detected");
00083                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_CJ_SOFT_FAULT )
00084                     ADMW_LOG_INFO("\t\t\tCJC soft fault alert detected");
00085                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_CJ_HARD_FAULT )
00086                     ADMW_LOG_INFO("\t\t\tCJC hard fault alert detected");
00087                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_ADC_INPUT_OVERRANGE )
00088                     ADMW_LOG_INFO("\t\t\tADC input overranage alert detected");
00089                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_SENSOR_HARDFAULT )
00090                     ADMW_LOG_INFO("\t\t\tChannel sensor hardfault alert detected");
00091             }
00092         }
00093 
00094         if ((pStatus->deviceStatus  & ADMW_DEVICE_STATUS_ERROR ) ||
00095                 (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_ALERT )) {
00096             ADMW_LOG_INFO("\t\tLast Debug Code: %u-%u",
00097                           (pStatus->debugCode  >> 16) & 0xFFFF,
00098                           (pStatus->debugCode  >> 0) & 0xFFFF);
00099         }
00100     }
00101 }
00102 
00103 void utils_printSamples(
00104     ADMW_DATA_SAMPLE  *pSampleBuffer,
00105     uint32_t nNumSamples,
00106     ADMW_MEASUREMENT_MODE  eMeasurementMode)
00107 {
00108     for (uint32_t i = 0; i < nNumSamples; i++) {
00109         ADMW_LOG_INFO("Sample # %2d Channel_ID # %2d :: Raw_Sample %f :: processedValue %f :: flags: ERROR:%X , ALERT:%X",
00110                       i+1,
00111                       pSampleBuffer[i].Channel_ID,
00112                       pSampleBuffer[i].Raw_Sample,
00113                       pSampleBuffer[i].processedValue,
00114                       pSampleBuffer[i].Ch_Error,
00115                       pSampleBuffer[i].Ch_Alert);
00116     }
00117 }
00118 
00119 static void gpioCallbackFn(ADMW_GPIO_PIN  ePinId, void * pArg)
00120 {
00121     volatile bool *pbFlag = (volatile bool *)pArg;
00122     *pbFlag = true;
00123 }
00124 
00125 ADMW_RESULT  utils_registerCallbacks(
00126     ADMW_DEVICE_HANDLE  hDevice,
00127     volatile bool *pbDataReady,
00128     volatile bool *pbError,
00129     volatile bool *pbAlert)
00130 {
00131     ADMW_RESULT  res;
00132     bool state;
00133 
00134     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_DATAREADY ,
00135                                     gpioCallbackFn, (void *)pbDataReady);
00136     if (res != ADMW_SUCCESS ) {
00137         ADMW_LOG_ERROR("Failed to register DATAREADY callback");
00138         return res;
00139     }
00140 
00141     res = admw_GetGpioState(hDevice, ADMW_GPIO_PIN_ALERT_ERROR , &state);
00142     if (res != ADMW_SUCCESS ) {
00143         ADMW_LOG_ERROR("Failed to get current ERROR state");
00144         return res;
00145     }
00146     if (state) {
00147         ADMW_LOG_ERROR("ERROR signal already asserted");
00148         return ADMW_FAILURE ;
00149     }
00150     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00151                                     gpioCallbackFn, (void *)pbError);
00152     if (res != ADMW_SUCCESS ) {
00153         ADMW_LOG_ERROR("Failed to register ERROR callback");
00154         return res;
00155     }
00156 
00157     /*res = admw_GetGpioState(hDevice, ADMW_GPIO_PIN_ALERT, &state);
00158     if (res != ADMW_SUCCESS)
00159     {
00160         ADMW_LOG_ERROR("Failed to get current ALERT state");
00161         return res;
00162     }
00163     if (state)
00164     {
00165         ADMW_LOG_ERROR("ALERT signal already asserted");
00166         return ADMW_FAILURE;
00167     }*/
00168     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00169                                     gpioCallbackFn, (void *)pbAlert);
00170     if (res != ADMW_SUCCESS ) {
00171         ADMW_LOG_ERROR("Failed to register ALERT callback");
00172         return res;
00173     }
00174 
00175     return ADMW_SUCCESS ;
00176 }
00177 
00178 ADMW_RESULT  utils_deregisterCallbacks(
00179     ADMW_DEVICE_HANDLE  hDevice)
00180 {
00181     ADMW_RESULT  res;
00182 
00183     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_DATAREADY ,
00184                                     NULL, NULL);
00185     if (res != ADMW_SUCCESS ) {
00186         ADMW_LOG_ERROR("Failed to deregister DATAREADY callback");
00187         return res;
00188     }
00189 
00190     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00191                                     NULL, NULL);
00192     if (res != ADMW_SUCCESS ) {
00193         ADMW_LOG_ERROR("Failed to deregister ERROR callback");
00194         return res;
00195     }
00196 
00197     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00198                                     NULL, NULL);
00199     if (res != ADMW_SUCCESS ) {
00200         ADMW_LOG_INFO("Failed to deregister ALERT callback");
00201         return res;
00202     }
00203 
00204     return ADMW_SUCCESS ;
00205 }
00206 
00207 ADMW_RESULT  utils_runMeasurement(
00208     ADMW_DEVICE_HANDLE  hDevice,
00209     ADMW_MEASUREMENT_MODE  eMeasurementMode)
00210 {
00211     ADMW_RESULT  res;
00212     volatile bool bDataReady = false;
00213     volatile bool bError = false;
00214     volatile bool bAlert = false;
00215     res = utils_registerCallbacks(hDevice, &bDataReady, &bError, &bAlert);
00216     if (res != ADMW_SUCCESS )
00217         return res;
00218 
00219     /*
00220      * Retrieve the number of samples per cycle, per DATAREADY pulse, etc. for
00221      * this configuration.
00222      */
00223     ADMW1001_OPERATING_MODE  eOperatingMode;
00224     ADMW1001_DATAREADY_MODE  eDataReadyMode;
00225     uint32_t nSamplesPerDataready;
00226     uint32_t nSamplesPerCycle;
00227     uint8_t nBytesPerSample;
00228     res = admw1001_GetDataReadyModeInfo(hDevice,
00229                                         eMeasurementMode,
00230                                         &eOperatingMode,
00231                                         &eDataReadyMode,
00232                                         &nSamplesPerDataready,
00233                                         &nSamplesPerCycle,
00234                                         &nBytesPerSample);
00235     if (res != ADMW_SUCCESS )
00236         return res;
00237 
00238     /*
00239      * Allocate a buffer to store the samples retrieved on each DATAREADY pulse
00240      */
00241     ADMW_DATA_SAMPLE  *pSampleBuffer;
00242     pSampleBuffer = malloc(sizeof(ADMW_DATA_SAMPLE ) *
00243                            nSamplesPerDataready);
00244     if (pSampleBuffer == NULL) {
00245         ADMW_LOG_ERROR("Failed to allocate sample buffer");
00246         return ADMW_NO_MEM ;
00247     }
00248 
00249     /*
00250      * Kick off the measurement cycle(s) here
00251      */
00252     ADMW_LOG_INFO("Starting measurement");
00253     res = admw_StartMeasurement(hDevice, eMeasurementMode);
00254     if (res != ADMW_SUCCESS ) {
00255         ADMW_LOG_ERROR("Failed to start measurement");
00256         return res;
00257     }
00258 
00259     /*
00260      * Loop continuously unless operating mode is single-cycle
00261      */
00262     uint32_t nSampleCount = 0;
00263     uint32_t nReturned;
00264     while (true) {
00265         ADMW_STATUS  status;
00266 
00267         /*
00268          * Wait until the next batch of 1 or more samples is ready, continuously
00269          * checking DATAREADY until it is asserted
00270          */
00271         res = admw_GetStatus(hDevice, &status);
00272          if (res != ADMW_SUCCESS ) {
00273             ADMW_LOG_ERROR("Failed to retrieve device status");
00274             }
00275          if (status.deviceStatus  & ADMW_DEVICE_STATUS_FIFO_ERROR )
00276          {
00277             utils_printStatus(&status);
00278             break;
00279          }
00280           while (! (bDataReady || bError));
00281             if (!bError) {
00282                 /*
00283                  * Get data samples from the measurement cycle, if no error has occurred
00284                  */
00285                 bDataReady = false;
00286                 res = admw_GetData(hDevice, eMeasurementMode, pSampleBuffer,
00287                                    nBytesPerSample, nSamplesPerDataready,
00288                                    &nReturned);
00289                 if (res != ADMW_SUCCESS ) {
00290                     if (res == ADMW_INCOMPLETE ) {
00291                         /*
00292                          * This is expected in cases where cycleSkipCount may
00293                          * be non-zero for some channels, resulting in
00294                          * variable-length sequences
00295                          */
00296                          
00297                         ADMW_LOG_DEBUG("Retrieved %u of %u requested data samples",
00298                                        nReturned, nSamplesPerDataready);           
00299                         continue;
00300                     } else {
00301                         ADMW_LOG_WARN("Failed to get data samples from device");
00302                         return res;
00303                     }
00304                 }
00305 
00306                 /*
00307                  * Display the data samples.
00308                  *
00309                  * NOTE: this requires a sufficient idle time between subsequent
00310                  * DATAREADY pulses to allow printing to occur.  Otherwise,
00311                  * subsequent samples may be missed if not retrieved promptly when
00312                  * the next DATAREADY assertion occurs.
00313                  */
00314                 utils_printSamples(pSampleBuffer, nReturned, eMeasurementMode);
00315                 nSampleCount += nReturned;
00316             }
00317 
00318         /*
00319          * Check and print device status if errors/alerts have been triggered
00320          */
00321         if (bError || bAlert) {
00322             res = admw_GetStatus(hDevice, &status);
00323             if (res != ADMW_SUCCESS ) {
00324                 ADMW_LOG_ERROR("Failed to retrieve device status");
00325                 return res;
00326             }
00327 
00328             if (status.deviceStatus  &
00329                     (ADMW_DEVICE_STATUS_ERROR  | ADMW_DEVICE_STATUS_ALERT )) {
00330                 utils_printStatus(&status);
00331 
00332                 /* Break out of the loop if any errors are raised */
00333                 if (bError)
00334                     break;
00335             }
00336         }
00337 
00338         if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) {
00339             /*
00340              * In this mode, break out of the loop when the measurement command
00341              * has completed.
00342              *
00343              * One option is to check for the expected number of samples to be
00344              * returned for the cycle.  However, cycles may have variable-length
00345              * sequences if the cycleSkipCount option is non-zero for any of the
00346              * channels.
00347              *
00348              * So, instead, we check for the command-running status, which
00349              * will de-assert in this mode when the measurement command has
00350              * completed a single cycle.
00351              */
00352             bool bCommandRunning;
00353             res = admw_GetCommandRunningState(hDevice, &bCommandRunning);
00354             if (res != ADMW_SUCCESS ) {
00355                 ADMW_LOG_ERROR("Failed to get command-running status");
00356                 return res;
00357             }
00358 
00359             if (!bCommandRunning && !bDataReady)
00360                 break;
00361         }
00362     }
00363 
00364     ADMW_LOG_INFO("Stopping measurement");
00365     res = admw_StopMeasurement(hDevice);
00366     if (res != ADMW_SUCCESS ) {
00367         ADMW_LOG_ERROR("Failed to send stop measurement");
00368         return res;
00369     }
00370 
00371     free(pSampleBuffer);
00372 
00373     res = utils_deregisterCallbacks(hDevice);
00374     if (res != ADMW_SUCCESS )
00375         return res;
00376 
00377     return ADMW_SUCCESS ;
00378 }
00379