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 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
Generated on Tue Jul 12 2022 15:36:13 by
