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