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