Vybhav Kadaba / Mbed OS EV-PRO-MW1001_Development_code_cleanup2
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             ADMW_LOG_INFO("\tActive FIFO Errors - ATTENTION REQUIRED");
00063         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_CONFIG_ERROR )
00064             ADMW_LOG_INFO("\tActive Configuration Errors - ATTENTION REQUIRED");
00065 
00066         if (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_ALERT ) {
00067             ADMW_LOG_INFO("\tActive Alerts - ATTENTION REQUIRED:");
00068             ADMW_LOG_INFO("\t\tLast Alert Code: %u (0x%X)",
00069                           pStatus->alertCode , pStatus->alertCode );
00070 
00071             for (unsigned i = 0; i < ADMW1001_MAX_CHANNELS ; i++) {
00072                 if (pStatus->channelAlerts [i] == 0)
00073                     continue;
00074 
00075                 ADMW_LOG_INFO("\t\tChannel #%u:", i);
00076                 ADMW_LOG_INFO("\t\t\tLast Alert Code: %u (0x%X)",
00077                               pStatus->channelAlertCodes [i],
00078                               pStatus->channelAlertCodes [i]);
00079                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_ADC_NEAR_OVERRANGE )
00080                     ADMW_LOG_INFO("\t\t\ADC near overrange detected");
00081                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_SENSOR_UNDERRANGE )
00082                     ADMW_LOG_INFO("\t\t\tSensor underrange detected");
00083                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_SENSOR_OVERRANGE )
00084                     ADMW_LOG_INFO("\t\t\tSensor overrange detected");
00085                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_CJ_SOFT_FAULT )
00086                     ADMW_LOG_INFO("\t\t\tCJC soft fault alert detected");
00087                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_CJ_HARD_FAULT )
00088                     ADMW_LOG_INFO("\t\t\tCJC hard fault alert detected");
00089                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_ADC_INPUT_OVERRANGE )
00090                     ADMW_LOG_INFO("\t\t\tADC input overranage alert detected");
00091                 if (pStatus->channelAlerts [i] & ADMW_ALERT_DETAIL_CH_SENSOR_HARDFAULT )
00092                     ADMW_LOG_INFO("\t\t\tChannel sensor hardfault alert detected");
00093             }
00094         }
00095 
00096         if ((pStatus->deviceStatus  & ADMW_DEVICE_STATUS_ERROR ) ||
00097                 (pStatus->deviceStatus  & ADMW_DEVICE_STATUS_ALERT )) {
00098             ADMW_LOG_INFO("\t\tLast Debug Code: %u-%u",
00099                           (pStatus->debugCode  >> 16) & 0xFFFF,
00100                           (pStatus->debugCode  >> 0) & 0xFFFF);
00101         }
00102     }
00103 }
00104 
00105 void utils_printSamples(
00106     ADMW_DATA_SAMPLE  *pSampleBuffer,
00107     uint32_t nNumSamples,
00108     ADMW_MEASUREMENT_MODE  eMeasurementMode)
00109 {
00110     for (uint32_t i = 0; i < nNumSamples; i++) {
00111         ADMW_LOG_INFO("Sample # %2d Channel_ID # %2d :: Raw_Sample %f :: processedValue %f :: flags: ERROR:%X , ALERT:%X",
00112                       i+1,
00113                       pSampleBuffer[i].Channel_ID,
00114                       pSampleBuffer[i].Raw_Sample,
00115                       pSampleBuffer[i].processedValue,
00116                       pSampleBuffer[i].Ch_Error,
00117                       pSampleBuffer[i].Ch_Alert);
00118     }
00119 }
00120 
00121 static void gpioCallbackFn(ADMW_GPIO_PIN  ePinId, void * pArg)
00122 {
00123     volatile bool *pbFlag = (volatile bool *)pArg;
00124     *pbFlag = true;
00125 }
00126 
00127 ADMW_RESULT  utils_registerCallbacks(
00128     ADMW_DEVICE_HANDLE  hDevice,
00129     volatile bool *pbDataReady,
00130     volatile bool *pbError,
00131     volatile bool *pbAlert)
00132 {
00133     ADMW_RESULT  res;
00134     bool state;
00135 
00136     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_DATAREADY ,
00137                                     gpioCallbackFn, (void *)pbDataReady);
00138     if (res != ADMW_SUCCESS ) {
00139         ADMW_LOG_ERROR("Failed to register DATAREADY callback");
00140         return res;
00141     }
00142 
00143     res = admw_GetGpioState(hDevice, ADMW_GPIO_PIN_ALERT_ERROR , &state);
00144     if (res != ADMW_SUCCESS ) {
00145         ADMW_LOG_ERROR("Failed to get current ERROR state");
00146         return res;
00147     }
00148     if (state) {
00149         ADMW_LOG_ERROR("ERROR signal already asserted");
00150         return ADMW_FAILURE ;
00151     }
00152     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00153                                     gpioCallbackFn, (void *)pbError);
00154     if (res != ADMW_SUCCESS ) {
00155         ADMW_LOG_ERROR("Failed to register ERROR callback");
00156         return res;
00157     }
00158 
00159     /*res = admw_GetGpioState(hDevice, ADMW_GPIO_PIN_ALERT, &state);
00160     if (res != ADMW_SUCCESS)
00161     {
00162         ADMW_LOG_ERROR("Failed to get current ALERT state");
00163         return res;
00164     }
00165     if (state)
00166     {
00167         ADMW_LOG_ERROR("ALERT signal already asserted");
00168         return ADMW_FAILURE;
00169     }*/
00170     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00171                                     gpioCallbackFn, (void *)pbAlert);
00172     if (res != ADMW_SUCCESS ) {
00173         ADMW_LOG_ERROR("Failed to register ALERT callback");
00174         return res;
00175     }
00176 
00177     return ADMW_SUCCESS ;
00178 }
00179 
00180 ADMW_RESULT  utils_deregisterCallbacks(
00181     ADMW_DEVICE_HANDLE  hDevice)
00182 {
00183     ADMW_RESULT  res;
00184 
00185     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_DATAREADY ,
00186                                     NULL, NULL);
00187     if (res != ADMW_SUCCESS ) {
00188         ADMW_LOG_ERROR("Failed to deregister DATAREADY callback");
00189         return res;
00190     }
00191 
00192     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00193                                     NULL, NULL);
00194     if (res != ADMW_SUCCESS ) {
00195         ADMW_LOG_ERROR("Failed to deregister ERROR callback");
00196         return res;
00197     }
00198 
00199     res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR ,
00200                                     NULL, NULL);
00201     if (res != ADMW_SUCCESS ) {
00202         ADMW_LOG_INFO("Failed to deregister ALERT callback");
00203         return res;
00204     }
00205 
00206     return ADMW_SUCCESS ;
00207 }
00208 
00209 ADMW_RESULT  utils_runMeasurement(
00210     ADMW_DEVICE_HANDLE  hDevice,
00211     ADMW_MEASUREMENT_MODE  eMeasurementMode)
00212 {
00213     ADMW_RESULT  res;
00214     volatile bool bDataReady = false;
00215     volatile bool bError = false;
00216     volatile bool bAlert = false;
00217     res = utils_registerCallbacks(hDevice, &bDataReady, &bError, &bAlert);
00218     if (res != ADMW_SUCCESS )
00219         return res;
00220 
00221     /*
00222      * Retrieve the number of samples per cycle, per DATAREADY pulse, etc. for
00223      * this configuration.
00224      */
00225     ADMW1001_OPERATING_MODE  eOperatingMode;
00226     ADMW1001_DATAREADY_MODE  eDataReadyMode;
00227     uint32_t nSamplesPerDataready;
00228     uint32_t nSamplesPerCycle;
00229     uint8_t nBytesPerSample;
00230     res = admw1001_GetDataReadyModeInfo(hDevice,
00231                                         eMeasurementMode,
00232                                         &eOperatingMode,
00233                                         &eDataReadyMode,
00234                                         &nSamplesPerDataready,
00235                                         &nSamplesPerCycle,
00236                                         &nBytesPerSample);
00237     if (res != ADMW_SUCCESS )
00238         return res;
00239 
00240     /*
00241      * Allocate a buffer to store the samples retrieved on each DATAREADY pulse
00242      */
00243     ADMW_DATA_SAMPLE  *pSampleBuffer;
00244     pSampleBuffer = malloc(sizeof(ADMW_DATA_SAMPLE ) *
00245                            nSamplesPerDataready);
00246     if (pSampleBuffer == NULL) {
00247         ADMW_LOG_ERROR("Failed to allocate sample buffer");
00248         return ADMW_NO_MEM ;
00249     }
00250 
00251     /*
00252      * Kick off the measurement cycle(s) here
00253      */
00254     ADMW_LOG_INFO("Starting measurement");
00255     res = admw_StartMeasurement(hDevice, eMeasurementMode);
00256     if (res != ADMW_SUCCESS ) {
00257         ADMW_LOG_ERROR("Failed to start measurement");
00258         return res;
00259     }
00260 
00261     /*
00262      * Loop continuously unless operating mode is single-cycle
00263      */
00264     uint32_t nSampleCount = 0;
00265     uint32_t nReturned;
00266     while (true) {
00267         ADMW_STATUS  status;
00268 
00269         /*
00270          * Wait until the next batch of 1 or more samples is ready, continuously
00271          * checking DATAREADY until it is asserted
00272          */
00273         while (! (bDataReady || bError));
00274 
00275             if (!bError) {
00276                 /*
00277                  * Get data samples from the measurement cycle, if no error has occurred
00278                  */
00279                 bDataReady = false;
00280                 res = admw_GetData(hDevice, eMeasurementMode, pSampleBuffer,
00281                                    nBytesPerSample, nSamplesPerDataready,
00282                                    &nReturned);
00283                 if (res != ADMW_SUCCESS ) {
00284                     if (res == ADMW_INCOMPLETE ) {
00285                         /*
00286                          * This is expected in cases where cycleSkipCount may
00287                          * be non-zero for some channels, resulting in
00288                          * variable-length sequences
00289                          */
00290                          
00291                         ADMW_LOG_DEBUG("Retrieved %u of %u requested data samples",
00292                                        nReturned, nSamplesPerDataready);           
00293                         continue;
00294                     } else {
00295                         ADMW_LOG_WARN("Failed to get data samples from device");
00296                         return res;
00297                     }
00298                 }
00299 
00300                 /*
00301                  * Display the data samples.
00302                  *
00303                  * NOTE: this requires a sufficient idle time between subsequent
00304                  * DATAREADY pulses to allow printing to occur.  Otherwise,
00305                  * subsequent samples may be missed if not retrieved promptly when
00306                  * the next DATAREADY assertion occurs.
00307                  */
00308                 utils_printSamples(pSampleBuffer, nReturned, eMeasurementMode);
00309                 nSampleCount += nReturned;
00310             }
00311 
00312         /*
00313          * Check and print device status if errors/alerts have been triggered
00314          */
00315         if (bError || bAlert) {
00316             res = admw_GetStatus(hDevice, &status);
00317             if (res != ADMW_SUCCESS ) {
00318                 ADMW_LOG_ERROR("Failed to retrieve device status");
00319                 return res;
00320             }
00321 
00322             if (status.deviceStatus  &
00323                     (ADMW_DEVICE_STATUS_ERROR  | ADMW_DEVICE_STATUS_ALERT )) {
00324                 utils_printStatus(&status);
00325 
00326                 /* Break out of the loop if any errors are raised */
00327                 if (bError)
00328                     break;
00329             }
00330         }
00331 
00332         if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) {
00333             /*
00334              * In this mode, break out of the loop when the measurement command
00335              * has completed.
00336              *
00337              * One option is to check for the expected number of samples to be
00338              * returned for the cycle.  However, cycles may have variable-length
00339              * sequences if the cycleSkipCount option is non-zero for any of the
00340              * channels.
00341              *
00342              * So, instead, we check for the command-running status, which
00343              * will de-assert in this mode when the measurement command has
00344              * completed a single cycle.
00345              */
00346             bool bCommandRunning;
00347             res = admw_GetCommandRunningState(hDevice, &bCommandRunning);
00348             if (res != ADMW_SUCCESS ) {
00349                 ADMW_LOG_ERROR("Failed to get command-running status");
00350                 return res;
00351             }
00352 
00353             if (!bCommandRunning && !bDataReady)
00354                 break;
00355         }
00356     }
00357 
00358     ADMW_LOG_INFO("Stopping measurement");
00359     res = admw_StopMeasurement(hDevice);
00360     if (res != ADMW_SUCCESS ) {
00361         ADMW_LOG_ERROR("Failed to send stop measurement");
00362         return res;
00363     }
00364 
00365     free(pSampleBuffer);
00366 
00367     res = utils_deregisterCallbacks(hDevice);
00368     if (res != ADMW_SUCCESS )
00369         return res;
00370 
00371     return ADMW_SUCCESS ;
00372 }
00373