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 for (uint32_t i = 0; i < nNumSamples; i++) { 00136 ADMW_LOG_INFO("Sample # %2d Channel # %2d :: Raw %f :: Processed %f :: flags: ERROR:%X , ALERT:%X", 00137 i+1, 00138 pSampleBuffer[i].channelId, 00139 pSampleBuffer[i].rawValue, 00140 pSampleBuffer[i].processedValue, 00141 pSampleBuffer[i].status & ADMW_DEVICE_STATUS_ERROR , 00142 pSampleBuffer[i].status & ADMW_DEVICE_STATUS_ALERT ); 00143 } 00144 } 00145 00146 static void gpioCallbackFn(ADMW_GPIO_PIN ePinId, void * pArg) 00147 { 00148 volatile bool *pbFlag = (volatile bool *)pArg; 00149 *pbFlag = true; 00150 } 00151 00152 ADMW_RESULT utils_registerCallbacks( 00153 ADMW_DEVICE_HANDLE hDevice, 00154 volatile bool *pbDataReady, 00155 volatile bool *pbError, 00156 volatile bool *pbAlert) 00157 { 00158 ADMW_RESULT res; 00159 bool state; 00160 00161 res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_DATAREADY , 00162 gpioCallbackFn, (void *)pbDataReady); 00163 if (res != ADMW_SUCCESS ) { 00164 ADMW_LOG_ERROR("Failed to register DATAREADY callback"); 00165 return res; 00166 } 00167 00168 res = admw_GetGpioState(hDevice, ADMW_GPIO_PIN_ALERT_ERROR , &state); 00169 if (res != ADMW_SUCCESS ) { 00170 ADMW_LOG_ERROR("Failed to get current ERROR state"); 00171 return res; 00172 } 00173 if (state) { 00174 ADMW_LOG_ERROR("ERROR signal already asserted"); 00175 return ADMW_FAILURE ; 00176 } 00177 res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR , 00178 gpioCallbackFn, (void *)pbError); 00179 if (res != ADMW_SUCCESS ) { 00180 ADMW_LOG_ERROR("Failed to register ERROR callback"); 00181 return res; 00182 } 00183 00184 /*res = admw_GetGpioState(hDevice, ADMW_GPIO_PIN_ALERT, &state); 00185 if (res != ADMW_SUCCESS) 00186 { 00187 ADMW_LOG_ERROR("Failed to get current ALERT state"); 00188 return res; 00189 } 00190 if (state) 00191 { 00192 ADMW_LOG_ERROR("ALERT signal already asserted"); 00193 return ADMW_FAILURE; 00194 }*/ 00195 res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR , 00196 gpioCallbackFn, (void *)pbAlert); 00197 if (res != ADMW_SUCCESS ) { 00198 ADMW_LOG_ERROR("Failed to register ALERT callback"); 00199 return res; 00200 } 00201 00202 return ADMW_SUCCESS ; 00203 } 00204 00205 ADMW_RESULT utils_deregisterCallbacks( 00206 ADMW_DEVICE_HANDLE hDevice) 00207 { 00208 ADMW_RESULT res; 00209 00210 res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_DATAREADY , 00211 NULL, NULL); 00212 if (res != ADMW_SUCCESS ) { 00213 ADMW_LOG_ERROR("Failed to deregister DATAREADY callback"); 00214 return res; 00215 } 00216 00217 res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR , 00218 NULL, NULL); 00219 if (res != ADMW_SUCCESS ) { 00220 ADMW_LOG_ERROR("Failed to deregister ERROR callback"); 00221 return res; 00222 } 00223 00224 res = admw_RegisterGpioCallback(hDevice, ADMW_GPIO_PIN_ALERT_ERROR , 00225 NULL, NULL); 00226 if (res != ADMW_SUCCESS ) { 00227 ADMW_LOG_INFO("Failed to deregister ALERT callback"); 00228 return res; 00229 } 00230 00231 return ADMW_SUCCESS ; 00232 } 00233 00234 ADMW_RESULT utils_runMeasurement( 00235 ADMW_DEVICE_HANDLE hDevice, 00236 ADMW_MEASUREMENT_MODE eMeasurementMode) 00237 { 00238 ADMW_RESULT res; 00239 volatile bool bDataReady = false; 00240 volatile bool bError = false; 00241 volatile bool bAlert = false; 00242 res = utils_registerCallbacks(hDevice, &bDataReady, &bError, &bAlert); 00243 if (res != ADMW_SUCCESS ) 00244 return res; 00245 00246 /* 00247 * Retrieve the number of samples per cycle, per DATAREADY pulse, etc. for 00248 * this configuration. 00249 */ 00250 ADMW1001_OPERATING_MODE eOperatingMode; 00251 ADMW1001_DATAREADY_MODE eDataReadyMode; 00252 uint32_t nSamplesPerDataready; 00253 uint32_t nSamplesPerCycle; 00254 uint8_t nBytesPerSample; 00255 res = admw1001_GetDataReadyModeInfo(hDevice, 00256 eMeasurementMode, 00257 &eOperatingMode, 00258 &eDataReadyMode, 00259 &nSamplesPerDataready, 00260 &nSamplesPerCycle, 00261 &nBytesPerSample); 00262 if (res != ADMW_SUCCESS ) 00263 return res; 00264 00265 /* 00266 * Allocate a buffer to store the samples retrieved on each DATAREADY pulse 00267 */ 00268 ADMW_DATA_SAMPLE *pSampleBuffer; 00269 pSampleBuffer = malloc(sizeof(ADMW_DATA_SAMPLE ) * 00270 nSamplesPerDataready); 00271 if (pSampleBuffer == NULL) { 00272 ADMW_LOG_ERROR("Failed to allocate sample buffer"); 00273 return ADMW_NO_MEM ; 00274 } 00275 00276 /* 00277 * Kick off the measurement cycle(s) here 00278 */ 00279 ADMW_LOG_INFO("Starting measurement"); 00280 res = admw_StartMeasurement(hDevice, eMeasurementMode); 00281 if (res != ADMW_SUCCESS ) { 00282 ADMW_LOG_ERROR("Failed to start measurement"); 00283 return res; 00284 } 00285 00286 /* 00287 * Loop continuously unless operating mode is single-cycle 00288 */ 00289 uint32_t nSampleCount = 0; 00290 uint32_t nReturned; 00291 while (true) { 00292 ADMW_STATUS status; 00293 00294 /* 00295 * Wait until the next batch of 1 or more samples is ready, continuously 00296 * checking DATAREADY until it is asserted 00297 */ 00298 while (! (bDataReady || bError)); 00299 00300 if (!bError) { 00301 /* 00302 * Get data samples from the measurement cycle, if no error has occurred 00303 */ 00304 bDataReady = false; 00305 res = admw_GetData(hDevice, eMeasurementMode, pSampleBuffer, 00306 nBytesPerSample, nSamplesPerDataready, 00307 &nReturned); 00308 if (res != ADMW_SUCCESS ) { 00309 if (res == ADMW_INCOMPLETE ) { 00310 /* 00311 * This is expected in cases where cycleSkipCount may 00312 * be non-zero for some channels, resulting in 00313 * variable-length sequences 00314 */ 00315 00316 ADMW_LOG_DEBUG("Retrieved %u of %u requested data samples", 00317 nReturned, nSamplesPerDataready); 00318 continue; 00319 } else { 00320 ADMW_LOG_WARN("Failed to get data samples from device"); 00321 return res; 00322 } 00323 } 00324 00325 /* 00326 * Display the data samples. 00327 * 00328 * NOTE: this requires a sufficient idle time between subsequent 00329 * DATAREADY pulses to allow printing to occur. Otherwise, 00330 * subsequent samples may be missed if not retrieved promptly when 00331 * the next DATAREADY assertion occurs. 00332 */ 00333 utils_printSamples(pSampleBuffer, nReturned, eMeasurementMode); 00334 nSampleCount += nReturned; 00335 } 00336 00337 /* 00338 * Check and print device status if errors/alerts have been triggered 00339 */ 00340 if (bError || bAlert) { 00341 res = admw_GetStatus(hDevice, &status); 00342 if (res != ADMW_SUCCESS ) { 00343 ADMW_LOG_ERROR("Failed to retrieve device status"); 00344 return res; 00345 } 00346 00347 if (status.deviceStatus & 00348 (ADMW_DEVICE_STATUS_ERROR | ADMW_DEVICE_STATUS_ALERT )) { 00349 utils_printStatus(&status); 00350 00351 /* Break out of the loop if any errors are raised */ 00352 if (bError) 00353 break; 00354 } 00355 } 00356 00357 if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) { 00358 /* 00359 * In this mode, break out of the loop when the measurement command 00360 * has completed. 00361 * 00362 * One option is to check for the expected number of samples to be 00363 * returned for the cycle. However, cycles may have variable-length 00364 * sequences if the cycleSkipCount option is non-zero for any of the 00365 * channels. 00366 * 00367 * So, instead, we check for the command-running status, which 00368 * will de-assert in this mode when the measurement command has 00369 * completed a single cycle. 00370 */ 00371 bool bCommandRunning; 00372 res = admw_GetCommandRunningState(hDevice, &bCommandRunning); 00373 if (res != ADMW_SUCCESS ) { 00374 ADMW_LOG_ERROR("Failed to get command-running status"); 00375 return res; 00376 } 00377 00378 if (!bCommandRunning && !bDataReady) 00379 break; 00380 } 00381 } 00382 00383 ADMW_LOG_INFO("Stopping measurement"); 00384 res = admw_StopMeasurement(hDevice); 00385 if (res != ADMW_SUCCESS ) { 00386 ADMW_LOG_ERROR("Failed to send stop measurement"); 00387 return res; 00388 } 00389 00390 free(pSampleBuffer); 00391 00392 res = utils_deregisterCallbacks(hDevice); 00393 if (res != ADMW_SUCCESS ) 00394 return res; 00395 00396 return ADMW_SUCCESS ; 00397 } 00398
Generated on Thu Jul 14 2022 16:18:23 by
