PoC_Team
/
ADMW1001_example_firmware
Host API Example for the ADMW1001
Embed:
(wiki syntax)
Show/hide line numbers
admw_1001.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: 00039 * @brief: API implementation for ADMW1001 00040 *----------------------------------------------------------------------------- 00041 */ 00042 00043 #include <float.h> 00044 #include <math.h> 00045 #include <string.h> 00046 00047 #include "admw_platform.h" 00048 #include "admw_api.h" 00049 #include "admw1001/admw1001_api.h" 00050 00051 #include "admw1001/ADMW1001_REGISTERS_typedefs.h" 00052 #include "admw1001/ADMW1001_REGISTERS.h" 00053 #include "admw1001/admw1001_lut_data.h" 00054 #include "admw1001/admw1001_host_comms.h" 00055 00056 #include "crc16.h" 00057 #define VERSIONID_MAJOR 2 00058 #define VERSIONID_MINOR 0 00059 00060 uint32_t getDataCnt = 0; 00061 00062 /* 00063 * The following macros are used to encapsulate the register access code 00064 * to improve readability in the functions further below in this file 00065 */ 00066 #define STRINGIFY(name) #name 00067 00068 /* Expand the full name of the reset value macro for the specified register */ 00069 #define REG_RESET_VAL(_name) REG_##_name##_RESET 00070 00071 /* Checks if a value is outside the bounds of the specified register field */ 00072 #define CHECK_REG_FIELD_VAL(_field, _val) \ 00073 do { \ 00074 uint32_t _mask = BITM_##_field; \ 00075 uint32_t _shift = BITP_##_field; \ 00076 if ((((_val) << _shift) & ~(_mask)) != 0) { \ 00077 ADMW_LOG_ERROR("Value 0x%08X invalid for register field %s",\ 00078 (uint32_t)(_val), \ 00079 STRINGIFY(ADMW_##_field)); \ 00080 return ADMW_INVALID_PARAM; \ 00081 } \ 00082 } while(false) 00083 00084 /* 00085 * Encapsulates the write to a specified register 00086 * NOTE - this will cause the calling function to return on error 00087 */ 00088 #define WRITE_REG(_hdev, _val, _name, _type) \ 00089 do { \ 00090 ADMW_RESULT _res; \ 00091 _type _regval = _val; \ 00092 _res = admw1001_WriteRegister((_hdev), \ 00093 REG_##_name, \ 00094 &_regval, sizeof(_regval)); \ 00095 if (_res != ADMW_SUCCESS) \ 00096 return _res; \ 00097 } while(false) 00098 00099 /* Wrapper macro to write a value to a uint32_t register */ 00100 #define WRITE_REG_U32(_hdev, _val, _name) \ 00101 WRITE_REG(_hdev, _val, _name, uint32_t) 00102 /* Wrapper macro to write a value to a uint16_t register */ 00103 #define WRITE_REG_U16(_hdev, _val, _name) \ 00104 WRITE_REG(_hdev, _val, _name, uint16_t) 00105 /* Wrapper macro to write a value to a uint8_t register */ 00106 #define WRITE_REG_U8(_hdev, _val, _name) \ 00107 WRITE_REG(_hdev, _val, _name, uint8_t) 00108 /* Wrapper macro to write a value to a float32_t register */ 00109 #define WRITE_REG_FLOAT(_hdev, _val, _name) \ 00110 WRITE_REG(_hdev, _val, _name, float32_t) 00111 00112 /* 00113 * Encapsulates the read from a specified register 00114 * NOTE - this will cause the calling function to return on error 00115 */ 00116 #define READ_REG(_hdev, _val, _name, _type) \ 00117 do { \ 00118 ADMW_RESULT _res; \ 00119 _type _regval; \ 00120 _res = admw1001_ReadRegister((_hdev), \ 00121 REG_##_name, \ 00122 &_regval, sizeof(_regval)); \ 00123 if (_res != ADMW_SUCCESS) \ 00124 return _res; \ 00125 _val = _regval; \ 00126 } while(false) 00127 00128 /* Wrapper macro to read a value from a uint32_t register */ 00129 #define READ_REG_U32(_hdev, _val, _name) \ 00130 READ_REG(_hdev, _val, _name, uint32_t) 00131 /* Wrapper macro to read a value from a uint16_t register */ 00132 #define READ_REG_U16(_hdev, _val, _name) \ 00133 READ_REG(_hdev, _val, _name, uint16_t) 00134 /* Wrapper macro to read a value from a uint8_t register */ 00135 #define READ_REG_U8(_hdev, _val, _name) \ 00136 READ_REG(_hdev, _val, _name, uint8_t) 00137 /* Wrapper macro to read a value from a float32_t register */ 00138 #define READ_REG_FLOAT(_hdev, _val, _name) \ 00139 READ_REG(_hdev, _val, _name, float32_t) 00140 00141 /* 00142 * Wrapper macro to write an array of values to a uint8_t register 00143 * NOTE - this is intended only for writing to a keyhole data register 00144 */ 00145 #define WRITE_REG_U8_ARRAY(_hdev, _arr, _len, _name) \ 00146 do { \ 00147 ADMW_RESULT _res; \ 00148 _res = admw1001_WriteRegister(_hdev, \ 00149 REG_##_name, \ 00150 _arr, _len); \ 00151 if (_res != ADMW_SUCCESS) \ 00152 return _res; \ 00153 } while(false) 00154 00155 /* 00156 * Wrapper macro to read an array of values from a uint8_t register 00157 * NOTE - this is intended only for reading from a keyhole data register 00158 */ 00159 #define READ_REG_U8_ARRAY(_hdev, _arr, _len, _name) \ 00160 do { \ 00161 ADMW_RESULT _res; \ 00162 _res = admw1001_ReadRegister((_hdev), \ 00163 REG##_name, \ 00164 _arr, _len); \ 00165 if (_res != ADMW_SUCCESS) \ 00166 return _res; \ 00167 } while(false) 00168 00169 #define ADMW1001_CHANNEL_IS_ADC(c) \ 00170 ((c) >= ADMW1001_CH_ID_ANLG_1_UNIVERSAL && (c) <= ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL) 00171 00172 #define ADMW1001_CHANNEL_IS_ADC_CJC(c) \ 00173 ((c) >= ADMW1001_CH_ID_ANLG_1_UNIVERSAL && (c) <= ADMW1001_CH_ID_ANLG_2_UNIVERSAL) 00174 00175 #define ADMW1001_CHANNEL_IS_ADC_SENSOR(c) \ 00176 ((c) >= ADMW1001_CH_ID_ANLG_1_UNIVERSAL && (c) <= ADMW1001_CH_ID_ANLG_2_UNIVERSAL) 00177 00178 #define ADMW1001_CHANNEL_IS_ADC_VOLTAGE(c) \ 00179 ((c) == ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL || ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL) 00180 00181 #define ADMW1001_CHANNEL_IS_ADC_CURRENT(c) \ 00182 ((c) == ADMW1001_CH_ID_ANLG_1_UNIVERSAL || (c) == ADMW1001_CH_ID_ANLG_2_UNIVERSAL) 00183 00184 #define ADMW1001_CHANNEL_IS_VIRTUAL(c) \ 00185 ((c) == ADMW1001_CH_ID_DIG_SPI_1 || (c) == ADMW1001_CH_ID_DIG_SPI_2) 00186 00187 typedef struct { 00188 unsigned nDeviceIndex; 00189 ADMW_SPI_HANDLE hSpi; 00190 ADMW_GPIO_HANDLE hGpio; 00191 00192 } ADMW_DEVICE_CONTEXT; 00193 00194 static ADMW_DEVICE_CONTEXT gDeviceCtx[ADMW_PLATFORM_MAX_DEVICES]; 00195 00196 /* 00197 * Open an ADMW device instance. 00198 */ 00199 ADMW_RESULT admw_Open( 00200 unsigned const nDeviceIndex, 00201 ADMW_CONNECTION * const pConnectionInfo, 00202 ADMW_DEVICE_HANDLE * const phDevice) 00203 { 00204 ADMW_DEVICE_CONTEXT *pCtx; 00205 ADMW_RESULT eRet; 00206 00207 if (nDeviceIndex >= ADMW_PLATFORM_MAX_DEVICES) 00208 return ADMW_INVALID_DEVICE_NUM ; 00209 00210 pCtx = &gDeviceCtx[nDeviceIndex]; 00211 pCtx->nDeviceIndex = nDeviceIndex; 00212 00213 eRet = admw_LogOpen(&pConnectionInfo->log ); 00214 if (eRet != ADMW_SUCCESS ) 00215 return eRet; 00216 00217 eRet = admw_GpioOpen(&pConnectionInfo->gpio , &pCtx->hGpio); 00218 if (eRet != ADMW_SUCCESS ) 00219 return eRet; 00220 00221 eRet = admw_SpiOpen(&pConnectionInfo->spi , &pCtx->hSpi); 00222 if (eRet != ADMW_SUCCESS ) 00223 return eRet; 00224 00225 *phDevice = pCtx; 00226 return ADMW_SUCCESS ; 00227 } 00228 00229 /* 00230 * Get the current state of the specified GPIO input signal. 00231 */ 00232 ADMW_RESULT admw_GetGpioState( 00233 ADMW_DEVICE_HANDLE const hDevice, 00234 ADMW_GPIO_PIN const ePinId, 00235 bool * const pbAsserted) 00236 { 00237 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00238 00239 return admw_GpioGet(pCtx->hGpio, ePinId, pbAsserted); 00240 } 00241 00242 /* 00243 * Register an application-defined callback function for GPIO interrupts. 00244 */ 00245 ADMW_RESULT admw_RegisterGpioCallback( 00246 ADMW_DEVICE_HANDLE const hDevice, 00247 ADMW_GPIO_PIN const ePinId, 00248 ADMW_GPIO_CALLBACK const callbackFunction, 00249 void * const pCallbackParam) 00250 { 00251 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00252 00253 if (callbackFunction) { 00254 return admw_GpioIrqEnable(pCtx->hGpio, ePinId, callbackFunction, 00255 pCallbackParam); 00256 } else { 00257 return admw_GpioIrqDisable(pCtx->hGpio, ePinId); 00258 } 00259 } 00260 00261 /*! 00262 * @brief Reset the specified ADMW device. 00263 * 00264 * @param[in] hDevice - handle of ADMW device to reset. 00265 * 00266 * @return Status 00267 * - #ADMW_SUCCESS Call completed successfully. 00268 * - #ADMW_FAILURE If reseet faisl 00269 * 00270 * @details Toggle reset pin of the ADMW device low for a 00271 * minimum of 4 usec. 00272 * 00273 */ 00274 ADMW_RESULT admw_Reset(ADMW_DEVICE_HANDLE const hDevice) 00275 { 00276 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00277 ADMW_RESULT eRet; 00278 00279 /* Pulse the Reset GPIO pin low for a minimum of 4 microseconds */ 00280 eRet = admw_GpioSet(pCtx->hGpio, ADMW_GPIO_PIN_RESET , false); 00281 if (eRet != ADMW_SUCCESS ) 00282 return eRet; 00283 00284 admw_TimeDelayUsec(4); 00285 00286 eRet = admw_GpioSet(pCtx->hGpio, ADMW_GPIO_PIN_RESET , true); 00287 if (eRet != ADMW_SUCCESS ) 00288 return eRet; 00289 00290 return ADMW_SUCCESS ; 00291 } 00292 00293 /*! 00294 * @brief Get general status of ADMW module. 00295 * 00296 * @param[in] 00297 * @param[out] pStatus : Pointer to CORE Status struct. 00298 * 00299 * @return Status 00300 * - #ADMW_SUCCESS Call completed successfully. 00301 * - #ADMW_FAILURE If status register read fails. 00302 * 00303 * @details Read the general status register for the ADMW 00304 * module. Indicates Error, Alert conditions, data ready 00305 * and command running. 00306 * 00307 */ 00308 ADMW_RESULT admw_GetStatus( 00309 ADMW_DEVICE_HANDLE const hDevice, 00310 ADMW_STATUS * const pStatus) 00311 { 00312 ADMW_CORE_Status_t statusReg; 00313 READ_REG_U8(hDevice, statusReg.VALUE8, CORE_STATUS); 00314 00315 ADMW_CORE_Alert_Status_2_t alert2Reg; 00316 READ_REG_U16(hDevice, alert2Reg.VALUE16, CORE_ALERT_STATUS_2); 00317 00318 memset(pStatus, 0, sizeof(*pStatus)); 00319 00320 if (!statusReg.Cmd_Running) /* Active-low, so invert it */ 00321 pStatus->deviceStatus |= ADMW_DEVICE_STATUS_BUSY ; 00322 if (statusReg.Drdy) 00323 pStatus->deviceStatus |= ADMW_DEVICE_STATUS_DATAREADY ; 00324 if (statusReg.FIFO_Error) 00325 pStatus->deviceStatus |= ADMW_DEVICE_STATUS_FIFO_ERROR ; 00326 if (statusReg.Alert_Active) { 00327 pStatus->deviceStatus |= ADMW_DEVICE_STATUS_ALERT ; 00328 00329 ADMW_CORE_Alert_Code_t alertCodeReg; 00330 READ_REG_U16(hDevice, alertCodeReg.VALUE16, CORE_ALERT_CODE); 00331 pStatus->alertCode = alertCodeReg.Alert_Code; 00332 00333 ADMW_CORE_Channel_Alert_Status_t channelAlertStatusReg; 00334 READ_REG_U16(hDevice, channelAlertStatusReg.VALUE16, 00335 CORE_CHANNEL_ALERT_STATUS); 00336 00337 for (unsigned i = 0; i < ADMW1001_MAX_CHANNELS ; i++) { 00338 if (channelAlertStatusReg.VALUE16 & (1 << i)) { 00339 ADMW_CORE_Alert_Code_Ch_t channelAlertCodeReg; 00340 READ_REG_U16(hDevice, channelAlertCodeReg.VALUE16, CORE_ALERT_CODE_CHn(i)); 00341 pStatus->channelAlertCodes [i] = channelAlertCodeReg.Alert_Code_Ch; 00342 00343 ADMW_CORE_Alert_Detail_Ch_t alertDetailReg; 00344 READ_REG_U16(hDevice, alertDetailReg.VALUE16, 00345 CORE_ALERT_DETAIL_CHn(i)); 00346 00347 if (alertDetailReg.Time_Out) 00348 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_TIMEOUT ; 00349 if (alertDetailReg.Under_Range) 00350 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_UNDER_RANGE ; 00351 if (alertDetailReg.Over_Range) 00352 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_OVER_RANGE ; 00353 if (alertDetailReg.Low_Limit) 00354 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LOW_LIMIT ; 00355 if (alertDetailReg.High_Limit) 00356 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_HIGH_LIMIT ; 00357 if (alertDetailReg.Sensor_Open) 00358 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_SENSOR_OPEN ; 00359 if (alertDetailReg.Ref_Detect) 00360 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_REF_DETECT ; 00361 if (alertDetailReg.Config_Err) 00362 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_CONFIG_ERR ; 00363 if (alertDetailReg.LUT_Error_Ch) 00364 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LUT_ERR ; 00365 if (alertDetailReg.Sensor_Not_Ready) 00366 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_SENSOR_NOT_READY ; 00367 if (alertDetailReg.Comp_Not_Ready) 00368 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_COMP_NOT_READY ; 00369 if (alertDetailReg.Correction_UnderRange) 00370 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LUT_UNDER_RANGE ; 00371 if (alertDetailReg.Correction_OverRange) 00372 pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LUT_OVER_RANGE ; 00373 } 00374 } 00375 00376 if (alert2Reg.Configuration_Error) 00377 pStatus->deviceStatus |= ADMW_DEVICE_STATUS_CONFIG_ERROR ; 00378 if (alert2Reg.LUT_Error) 00379 pStatus->deviceStatus |= ADMW_DEVICE_STATUS_LUT_ERROR ; 00380 } 00381 00382 if (statusReg.Error) { 00383 pStatus->deviceStatus |= ADMW_DEVICE_STATUS_ERROR ; 00384 00385 ADMW_CORE_Error_Code_t errorCodeReg; 00386 READ_REG_U16(hDevice, errorCodeReg.VALUE16, CORE_ERROR_CODE); 00387 pStatus->errorCode = errorCodeReg.Error_Code; 00388 00389 ADMW_CORE_Diagnostics_Status_t diagStatusReg; 00390 READ_REG_U16(hDevice, diagStatusReg.VALUE16, CORE_DIAGNOSTICS_STATUS); 00391 00392 if (diagStatusReg.Diag_Checksum_Error) 00393 pStatus->diagnosticsStatus |= ADMW_DIAGNOSTICS_STATUS_CHECKSUM_ERROR ; 00394 if (diagStatusReg.Diag_Conversion_Error) 00395 pStatus->diagnosticsStatus |= ADMW_DIAGNOSTICS_STATUS_CONVERSION_ERROR ; 00396 if (diagStatusReg.Diag_Calibration_Error) 00397 pStatus->diagnosticsStatus |= ADMW_DIAGNOSTICS_STATUS_CALIBRATION_ERROR ; 00398 } 00399 00400 if (statusReg.Alert_Active || statusReg.Error) { 00401 ADMW_CORE_Debug_Code_t debugCodeReg; 00402 READ_REG_U32(hDevice, debugCodeReg.VALUE32, CORE_DEBUG_CODE); 00403 pStatus->debugCode = debugCodeReg.Debug_Code; 00404 } 00405 00406 return ADMW_SUCCESS ; 00407 } 00408 00409 ADMW_RESULT admw_GetCommandRunningState( 00410 ADMW_DEVICE_HANDLE hDevice, 00411 bool *pbCommandRunning) 00412 { 00413 ADMW_CORE_Status_t statusReg; 00414 00415 READ_REG_U8(hDevice, statusReg.VALUE8, CORE_STATUS); 00416 00417 /* We should never normally see 0xFF here if the module is operational */ 00418 if (statusReg.VALUE8 == 0xFF) 00419 return ADMW_ERR_NOT_INITIALIZED ; 00420 00421 *pbCommandRunning = !statusReg.Cmd_Running; /* Active-low, so invert it */ 00422 00423 return ADMW_SUCCESS ; 00424 } 00425 00426 static ADMW_RESULT executeCommand( 00427 ADMW_DEVICE_HANDLE const hDevice, 00428 ADMW_CORE_Command_Special_Command const command, 00429 bool const bWaitForCompletion) 00430 { 00431 ADMW_CORE_Command_t commandReg; 00432 bool bCommandRunning; 00433 ADMW_RESULT eRet; 00434 00435 /* 00436 * Don't allow another command to be issued if one is already running, but 00437 * make an exception for ENUM_CORE_COMMAND_NOP which can be used to 00438 * request a running command to be stopped (e.g. continuous measurement) 00439 */ 00440 if (command != ENUM_CORE_COMMAND_NOP) { 00441 eRet = admw_GetCommandRunningState(hDevice, &bCommandRunning); 00442 if (eRet) 00443 return eRet; 00444 00445 if (bCommandRunning) 00446 return ADMW_IN_USE ; 00447 } 00448 00449 commandReg.Special_Command = command; 00450 WRITE_REG_U8(hDevice, commandReg.VALUE8, CORE_COMMAND); 00451 00452 if (bWaitForCompletion) { 00453 do { 00454 /* Allow a minimum 50usec delay for status update before checking */ 00455 admw_TimeDelayUsec(50); 00456 00457 eRet = admw_GetCommandRunningState(hDevice, &bCommandRunning); 00458 if (eRet) 00459 return eRet; 00460 } while (bCommandRunning); 00461 } 00462 00463 return ADMW_SUCCESS ; 00464 } 00465 00466 ADMW_RESULT admw_Shutdown( 00467 ADMW_DEVICE_HANDLE const hDevice) 00468 { 00469 return executeCommand(hDevice, CORE_COMMAND_POWER_DOWN, false); 00470 } 00471 00472 00473 ADMW_RESULT admw_ApplyConfigUpdates( 00474 ADMW_DEVICE_HANDLE const hDevice) 00475 { 00476 return executeCommand(hDevice, CORE_COMMAND_LATCH_CONFIG, true); 00477 } 00478 00479 /*! 00480 * @brief Start a measurement cycle. 00481 * 00482 * @param[out] 00483 * 00484 * @return Status 00485 * - #ADMW_SUCCESS Call completed successfully. 00486 * - #ADMW_FAILURE 00487 * 00488 * @details Sends the latch config command. Configuration for channels in 00489 * conversion cycle should be completed before this function. 00490 * Channel enabled bit should be set before this function. 00491 * Starts a conversion and configures the format of the sample. 00492 * 00493 */ 00494 ADMW_RESULT admw_StartMeasurement( 00495 ADMW_DEVICE_HANDLE const hDevice, 00496 ADMW_MEASUREMENT_MODE const eMeasurementMode) 00497 { 00498 switch (eMeasurementMode) { 00499 case ADMW_MEASUREMENT_MODE_NORMAL : 00500 return executeCommand(hDevice, CORE_COMMAND_CONVERT_WITH_RAW, false); 00501 case ADMW_MEASUREMENT_MODE_OMIT_RAW : 00502 return executeCommand(hDevice, CORE_COMMAND_CONVERT, false); 00503 default: 00504 ADMW_LOG_ERROR("Invalid measurement mode %d specified", 00505 eMeasurementMode); 00506 return ADMW_INVALID_PARAM ; 00507 } 00508 } 00509 00510 /* 00511 * Store the configuration settings to persistent memory on the device. 00512 * The settings can be saved to 4 different flash memory areas (slots). 00513 * No other command must be running when this is called. 00514 * Do not power down the device while this command is running. 00515 */ 00516 ADMW_RESULT admw_SaveConfig( 00517 ADMW_DEVICE_HANDLE const hDevice, 00518 ADMW_USER_CONFIG_SLOT const eSlotId) 00519 { 00520 switch (eSlotId) { 00521 case ADMW_FLASH_CONFIG_1: 00522 return executeCommand(hDevice, CORE_COMMAND_SAVE_CONFIG_1, true); 00523 default: 00524 ADMW_LOG_ERROR("Invalid user config target slot %d specified", 00525 eSlotId); 00526 return ADMW_INVALID_PARAM ; 00527 } 00528 } 00529 00530 /* 00531 * Restore the configuration settings from persistent memory on the device. 00532 * No other command must be running when this is called. 00533 */ 00534 ADMW_RESULT admw_RestoreConfig( 00535 ADMW_DEVICE_HANDLE const hDevice, 00536 ADMW_USER_CONFIG_SLOT const eSlotId) 00537 { 00538 switch (eSlotId) { 00539 case ADMW_FLASH_CONFIG_1: 00540 return executeCommand(hDevice, CORE_COMMAND_LOAD_CONFIG_1, true); 00541 default: 00542 ADMW_LOG_ERROR("Invalid user config source slot %d specified", 00543 eSlotId); 00544 return ADMW_INVALID_PARAM ; 00545 } 00546 } 00547 00548 /* 00549 * Store the LUT data to persistent memory on the device. 00550 * No other command must be running when this is called. 00551 * Do not power down the device while this command is running. 00552 */ 00553 ADMW_RESULT admw_SaveLutData( 00554 ADMW_DEVICE_HANDLE const hDevice) 00555 { 00556 return executeCommand(hDevice, CORE_COMMAND_SAVE_LUT, true); 00557 } 00558 00559 /* 00560 * Restore the LUT data from persistent memory on the device. 00561 * No other command must be running when this is called. 00562 */ 00563 ADMW_RESULT admw_RestoreLutData( 00564 ADMW_DEVICE_HANDLE const hDevice) 00565 { 00566 return executeCommand(hDevice, CORE_COMMAND_LOAD_LUT, true); 00567 } 00568 00569 /* 00570 * Stop the measurement cycles on the device. 00571 * To be used only if a measurement command is currently running. 00572 */ 00573 ADMW_RESULT admw_StopMeasurement( 00574 ADMW_DEVICE_HANDLE const hDevice) 00575 { 00576 return executeCommand(hDevice, CORE_COMMAND_NOP, true); 00577 } 00578 00579 /* 00580 * Read a set of data samples from the device. 00581 * This may be called at any time. 00582 */ 00583 ADMW_RESULT admw_GetData( 00584 ADMW_DEVICE_HANDLE const hDevice, 00585 ADMW_MEASUREMENT_MODE const eMeasurementMode, 00586 ADMW_DATA_SAMPLE * const pSamples, 00587 uint8_t const nBytesPerSample, 00588 uint32_t const nRequested, 00589 uint32_t * const pnReturned) 00590 { 00591 ADMW1001_Sensor_Result_t sensorResult; 00592 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00593 uint16_t command = ADMW1001_HOST_COMMS_READ_CMD | 00594 (REG_CORE_DATA_FIFO & ADMW1001_HOST_COMMS_ADR_MASK); 00595 uint8_t commandData[2] = { 00596 command >> 8, 00597 command & 0xFF 00598 }; 00599 uint8_t commandResponse[2]; 00600 unsigned nValidSamples = 0; 00601 ADMW_RESULT eRet = ADMW_SUCCESS ; 00602 00603 do { 00604 eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse, 00605 sizeof(command), false); 00606 if (eRet) { 00607 ADMW_LOG_ERROR("Failed to send read command for FIFO register"); 00608 return eRet; 00609 } 00610 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00611 } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) || 00612 (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1)); 00613 00614 for (unsigned i = 0; i < nRequested; i++) { 00615 bool bHoldCs = true; 00616 00617 /* Keep the CS signal asserted for all but the last sample */ 00618 if ((i + 1) == nRequested) 00619 bHoldCs = false; 00620 00621 getDataCnt++; 00622 00623 eRet = admw_SpiTransfer(pCtx->hSpi, NULL, &sensorResult, 00624 nBytesPerSample, bHoldCs); 00625 if (eRet) { 00626 ADMW_LOG_ERROR("Failed to read data from FIFO register"); 00627 return eRet; 00628 } 00629 00630 if (! sensorResult.Ch_Valid) { 00631 /* 00632 * Reading an invalid sample indicates that there are no 00633 * more samples available or we've lost sync with the device. 00634 * In the latter case, it might be recoverable, but return here 00635 * to let the application check the device status and decide itself. 00636 */ 00637 eRet = ADMW_INCOMPLETE ; 00638 break; 00639 } 00640 00641 ADMW_DATA_SAMPLE *pSample = &pSamples[nValidSamples]; 00642 00643 pSample->status = (ADMW_DEVICE_STATUS_FLAGS )0; 00644 if (sensorResult.Ch_Error) 00645 pSample->status |= ADMW_DEVICE_STATUS_ERROR ; 00646 if (sensorResult.Ch_Alert) 00647 pSample->status |= ADMW_DEVICE_STATUS_ALERT ; 00648 00649 if (sensorResult.Ch_Raw) 00650 pSample->rawValue = sensorResult.Raw_Sample; 00651 else 00652 pSample->rawValue = 0; 00653 00654 pSample->channelId = sensorResult.Channel_ID; 00655 pSample->processedValue = sensorResult.Sensor_Result; 00656 00657 nValidSamples++; 00658 00659 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00660 } 00661 *pnReturned = nValidSamples; 00662 00663 return eRet; 00664 } 00665 00666 /* 00667 * Close the given ADMW device. 00668 */ 00669 ADMW_RESULT admw_Close( 00670 ADMW_DEVICE_HANDLE const hDevice) 00671 { 00672 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00673 00674 admw_GpioClose(pCtx->hGpio); 00675 admw_SpiClose(pCtx->hSpi); 00676 admw_LogClose(); 00677 00678 return ADMW_SUCCESS ; 00679 } 00680 00681 ADMW_RESULT admw1001_WriteRegister( 00682 ADMW_DEVICE_HANDLE hDevice, 00683 uint16_t nAddress, 00684 void *pData, 00685 unsigned nLength) 00686 { 00687 ADMW_RESULT eRet; 00688 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00689 uint16_t command = ADMW1001_HOST_COMMS_WRITE_CMD | 00690 (nAddress & ADMW1001_HOST_COMMS_ADR_MASK); 00691 uint8_t commandData[2] = { 00692 command >> 8, 00693 command & 0xFF 00694 }; 00695 uint8_t commandResponse[2]; 00696 00697 do { 00698 eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse, 00699 sizeof(command), false); 00700 if (eRet) { 00701 ADMW_LOG_ERROR("Failed to send write command for register %u", 00702 nAddress); 00703 return eRet; 00704 } 00705 00706 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00707 } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) || 00708 (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1)); 00709 00710 eRet = admw_SpiTransfer(pCtx->hSpi, pData, NULL, nLength, false); 00711 if (eRet) { 00712 ADMW_LOG_ERROR("Failed to write data (%dB) to register %u", 00713 nLength, nAddress); 00714 return eRet; 00715 } 00716 00717 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00718 00719 return ADMW_SUCCESS ; 00720 } 00721 00722 ADMW_RESULT admw1001_Write_Debug_Register( 00723 ADMW_DEVICE_HANDLE hDevice, 00724 uint16_t nAddress, 00725 void *pData, 00726 unsigned nLength) 00727 { 00728 ADMW_RESULT eRet; 00729 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00730 uint16_t command = ADMW1001_HOST_COMMS_DEBUG_WRITE_CMD | 00731 (nAddress & ADMW1001_HOST_COMMS_ADR_MASK); 00732 uint8_t commandData[2] = { 00733 command >> 8, 00734 command & 0xFF 00735 }; 00736 uint8_t commandResponse[2]; 00737 00738 do { 00739 eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse, 00740 sizeof(command), false); 00741 if (eRet) { 00742 ADMW_LOG_ERROR("Failed to send write command for register %u", 00743 nAddress); 00744 return eRet; 00745 } 00746 00747 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00748 } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) || 00749 (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1)); 00750 00751 eRet = admw_SpiTransfer(pCtx->hSpi, pData, NULL, nLength, false); 00752 if (eRet) { 00753 ADMW_LOG_ERROR("Failed to write data (%dB) to register %u", 00754 nLength, nAddress); 00755 return eRet; 00756 } 00757 00758 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00759 00760 return ADMW_SUCCESS ; 00761 } 00762 ADMW_RESULT admw1001_ReadRegister( 00763 ADMW_DEVICE_HANDLE hDevice, 00764 uint16_t nAddress, 00765 void *pData, 00766 unsigned nLength) 00767 { 00768 ADMW_RESULT eRet; 00769 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00770 uint16_t command = ADMW1001_HOST_COMMS_READ_CMD | 00771 (nAddress & ADMW1001_HOST_COMMS_ADR_MASK); 00772 uint8_t commandData[2] = { 00773 command >> 8, 00774 command & 0xFF 00775 }; 00776 uint8_t commandResponse[2]; 00777 00778 do { 00779 eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse, 00780 sizeof(command), false); 00781 if (eRet) { 00782 ADMW_LOG_ERROR("Failed to send read command for register %u", 00783 nAddress); 00784 return eRet; 00785 } 00786 00787 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00788 } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) || 00789 (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1)); 00790 00791 eRet = admw_SpiTransfer(pCtx->hSpi, NULL, pData, nLength, false); 00792 if (eRet) { 00793 ADMW_LOG_ERROR("Failed to read data (%uB) from register %u", 00794 nLength, nAddress); 00795 return eRet; 00796 } 00797 00798 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00799 00800 return ADMW_SUCCESS ; 00801 } 00802 00803 ADMW_RESULT admw1001_Read_Debug_Register( 00804 ADMW_DEVICE_HANDLE hDevice, 00805 uint16_t nAddress, 00806 void *pData, 00807 unsigned nLength) 00808 { 00809 ADMW_RESULT eRet; 00810 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00811 uint16_t command = ADMW1001_HOST_COMMS_DEBUG_READ_CMD | 00812 (nAddress & ADMW1001_HOST_COMMS_ADR_MASK); 00813 uint8_t commandData[2] = { 00814 command >> 8, 00815 command & 0xFF 00816 }; 00817 uint8_t commandResponse[2]; 00818 00819 do { 00820 eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse, 00821 sizeof(command), false); 00822 if (eRet) { 00823 ADMW_LOG_ERROR("Failed to send read command for register %u", 00824 nAddress); 00825 return eRet; 00826 } 00827 00828 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00829 } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) || 00830 (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1)); 00831 00832 eRet = admw_SpiTransfer(pCtx->hSpi, NULL, pData, nLength, false); 00833 if (eRet) { 00834 ADMW_LOG_ERROR("Failed to read data (%uB) from register %u", 00835 nLength, nAddress); 00836 return eRet; 00837 } 00838 00839 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00840 00841 return ADMW_SUCCESS ; 00842 } 00843 ADMW_RESULT admw_GetDeviceReadyState( 00844 ADMW_DEVICE_HANDLE const hDevice, 00845 bool * const bReady) 00846 { 00847 ADMW_SPI_Chip_Type_t chipTypeReg; 00848 00849 READ_REG_U8(hDevice, chipTypeReg.VALUE8, SPI_CHIP_TYPE); 00850 /* If we read this register successfully, assume the device is ready */ 00851 *bReady = (chipTypeReg.VALUE8 == REG_SPI_CHIP_TYPE_RESET); 00852 00853 return ADMW_SUCCESS ; 00854 } 00855 00856 ADMW_RESULT admw1001_GetDataReadyModeInfo( 00857 ADMW_DEVICE_HANDLE const hDevice, 00858 ADMW_MEASUREMENT_MODE const eMeasurementMode, 00859 ADMW1001_OPERATING_MODE * const peOperatingMode, 00860 ADMW1001_DATAREADY_MODE * const peDataReadyMode, 00861 uint32_t * const pnSamplesPerDataready, 00862 uint32_t * const pnSamplesPerCycle, 00863 uint8_t * const pnBytesPerSample) 00864 { 00865 unsigned nChannelsEnabled = 0; 00866 unsigned nSamplesPerCycle = 0; 00867 00868 ADMW_CORE_Mode_t modeReg; 00869 READ_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE); 00870 00871 if (eMeasurementMode == (modeReg.Conversion_Mode == CORE_MODE_SINGLECYCLE)) 00872 *peOperatingMode = ADMW1001_OPERATING_MODE_SINGLECYCLE ; 00873 else 00874 *peOperatingMode = ADMW1001_OPERATING_MODE_CONTINUOUS ; 00875 00876 if (eMeasurementMode == ADMW_MEASUREMENT_MODE_OMIT_RAW ) { 00877 *pnBytesPerSample = 5; 00878 } else { 00879 *pnBytesPerSample = 8; 00880 } 00881 00882 for (ADMW1001_CH_ID chId = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ; 00883 chId < ADMW1001_MAX_CHANNELS ; 00884 chId++) { 00885 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 00886 ADMW_CORE_Channel_Count_t channelCountReg; 00887 00888 if (ADMW1001_CHANNEL_IS_VIRTUAL(chId)) 00889 continue; 00890 00891 READ_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(chId)); 00892 READ_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(chId)); 00893 00894 if (channelCountReg.Channel_Enable && !sensorDetailsReg.Do_Not_Publish) { 00895 ADMW_CORE_Sensor_Type_t sensorTypeReg; 00896 unsigned nActualChannels = 1; 00897 00898 READ_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(chId)); 00899 00900 if (chId == ADMW1001_CH_ID_DIG_SPI_0 ) { 00901 /* Some sensors automatically generate samples on additional 00902 * "virtual" channels so these channels must be counted as 00903 * active when those sensors are selected and we use the count 00904 * from the corresponding "physical" channel 00905 */ 00906 if ((sensorTypeReg.Sensor_Type >= 00907 CORE_SENSOR_TYPE_SPI_ACCELEROMETER_A) && 00908 (sensorTypeReg.Sensor_Type <= 00909 CORE_SENSOR_TYPE_SPI_ACCELEROMETER_B)) { 00910 nActualChannels += 2; 00911 } 00912 } 00913 00914 nChannelsEnabled += nActualChannels; 00915 00916 nSamplesPerCycle += nActualChannels * 00917 (channelCountReg.Channel_Count + 1); 00918 } 00919 } 00920 00921 if (nChannelsEnabled == 0) { 00922 *pnSamplesPerDataready = 0; 00923 *pnSamplesPerCycle = 0; 00924 return ADMW_SUCCESS ; 00925 } 00926 00927 *pnSamplesPerCycle = nSamplesPerCycle; 00928 00929 if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) { 00930 *pnSamplesPerDataready = 1; 00931 } else { 00932 *pnSamplesPerDataready = nSamplesPerCycle; 00933 } 00934 00935 if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) { 00936 *peDataReadyMode = ADMW1001_DATAREADY_PER_CONVERSION ; 00937 } else { 00938 *peDataReadyMode = ADMW1001_DATAREADY_PER_CYCLE ; 00939 } 00940 00941 return ADMW_SUCCESS ; 00942 } 00943 00944 ADMW_RESULT admw_GetProductID( 00945 ADMW_DEVICE_HANDLE hDevice, 00946 ADMW_PRODUCT_ID *pProductId) 00947 { 00948 ADMW_SPI_Product_ID_L_t productIdLoReg; 00949 ADMW_SPI_Product_ID_H_t productIdHiReg; 00950 00951 READ_REG_U8(hDevice, productIdLoReg.VALUE8, SPI_PRODUCT_ID_L); 00952 READ_REG_U8(hDevice, productIdHiReg.VALUE8, SPI_PRODUCT_ID_H); 00953 00954 *pProductId = (ADMW_PRODUCT_ID )((productIdHiReg.VALUE8 << 8) | 00955 productIdLoReg.VALUE8); 00956 return ADMW_SUCCESS ; 00957 } 00958 00959 static ADMW_RESULT admw_SetPowerMode( 00960 ADMW_DEVICE_HANDLE hDevice, 00961 ADMW1001_POWER_MODE powerMode) 00962 { 00963 ADMW_CORE_Power_Config_t powerConfigReg; 00964 00965 if (powerMode == ADMW1001_POWER_MODE_HIBERNATION ) { 00966 powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_HIBERNATION; 00967 } else if (powerMode == ADMW1001_POWER_MODE_ACTIVE ) { 00968 powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_ACTIVE_MODE; 00969 } else { 00970 ADMW_LOG_ERROR("Invalid power mode %d specified", powerMode); 00971 return ADMW_INVALID_PARAM ; 00972 } 00973 00974 WRITE_REG_U8(hDevice, powerConfigReg.VALUE8, CORE_POWER_CONFIG); 00975 00976 return ADMW_SUCCESS ; 00977 } 00978 00979 ADMW_RESULT admw1001_SetPowerConfig( 00980 ADMW_DEVICE_HANDLE hDevice, 00981 ADMW1001_POWER_CONFIG *pPowerConfig) 00982 { 00983 ADMW_RESULT eRet; 00984 00985 eRet = admw_SetPowerMode(hDevice, pPowerConfig->powerMode ); 00986 if (eRet != ADMW_SUCCESS ) { 00987 ADMW_LOG_ERROR("Failed to set power mode"); 00988 return eRet; 00989 } 00990 00991 return ADMW_SUCCESS ; 00992 } 00993 00994 static ADMW_RESULT admw_SetMode( 00995 ADMW_DEVICE_HANDLE hDevice, 00996 ADMW1001_OPERATING_MODE eOperatingMode, 00997 ADMW1001_DATAREADY_MODE eDataReadyMode) 00998 { 00999 ADMW_CORE_Mode_t modeReg; 01000 01001 modeReg.VALUE8 = REG_RESET_VAL(CORE_MODE); 01002 01003 if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) { 01004 modeReg.Conversion_Mode = CORE_MODE_SINGLECYCLE; 01005 } else if (eOperatingMode == ADMW1001_OPERATING_MODE_CONTINUOUS ) { 01006 modeReg.Conversion_Mode = CORE_MODE_CONTINUOUS; 01007 } else { 01008 ADMW_LOG_ERROR("Invalid operating mode %d specified", 01009 eOperatingMode); 01010 return ADMW_INVALID_PARAM ; 01011 } 01012 01013 if (eDataReadyMode == ADMW1001_DATAREADY_PER_CONVERSION ) { 01014 modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CONVERSION; 01015 } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_CYCLE ) { 01016 modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CYCLE; 01017 } else { 01018 ADMW_LOG_ERROR("Invalid data-ready mode %d specified", eDataReadyMode); 01019 return ADMW_INVALID_PARAM ; 01020 } 01021 01022 WRITE_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE); 01023 01024 return ADMW_SUCCESS ; 01025 } 01026 01027 ADMW_RESULT admw_SetCycleControl(ADMW_DEVICE_HANDLE hDevice, 01028 uint32_t nCycleInterval, 01029 bool vBiasEnable) 01030 { 01031 ADMW_CORE_Cycle_Control_t cycleControlReg; 01032 01033 cycleControlReg.VALUE16 = REG_RESET_VAL(CORE_CYCLE_CONTROL); 01034 01035 if (nCycleInterval < (1000 * (1 << 12))) { 01036 cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_MILLISECONDS; 01037 nCycleInterval /= 1000; 01038 } else { 01039 cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_SECONDS; 01040 nCycleInterval /= 1000000; 01041 } 01042 01043 if (vBiasEnable == true) { 01044 cycleControlReg.Vbias = 1; 01045 } 01046 CHECK_REG_FIELD_VAL(CORE_CYCLE_CONTROL_CYCLE_TIME, nCycleInterval); 01047 cycleControlReg.Cycle_Time = nCycleInterval; 01048 01049 WRITE_REG_U16(hDevice, cycleControlReg.VALUE16, CORE_CYCLE_CONTROL); 01050 01051 return ADMW_SUCCESS ; 01052 } 01053 01054 static ADMW_RESULT admw_SetExternalReferenceValues( 01055 ADMW_DEVICE_HANDLE hDevice, 01056 float32_t externalRef1Value) 01057 { 01058 WRITE_REG_FLOAT(hDevice, externalRef1Value, CORE_EXTERNAL_REFERENCE_RESISTOR); 01059 01060 return ADMW_SUCCESS ; 01061 } 01062 01063 ADMW_RESULT admw1001_SetMeasurementConfig( 01064 ADMW_DEVICE_HANDLE hDevice, 01065 ADMW1001_MEASUREMENT_CONFIG *pMeasConfig) 01066 { 01067 ADMW_RESULT eRet; 01068 01069 eRet = admw_SetMode(hDevice, 01070 pMeasConfig->operatingMode , 01071 pMeasConfig->dataReadyMode ); 01072 if (eRet != ADMW_SUCCESS ) { 01073 ADMW_LOG_ERROR("Failed to set operating mode"); 01074 return eRet; 01075 } 01076 01077 eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval , 01078 pMeasConfig->vBiasEnable ); 01079 if (eRet != ADMW_SUCCESS ) { 01080 ADMW_LOG_ERROR("Failed to set cycle control"); 01081 return eRet; 01082 } 01083 01084 if(pMeasConfig->externalRef1Value >0) { 01085 eRet = admw_SetExternalReferenceValues(hDevice, 01086 pMeasConfig->externalRef1Value ); 01087 } 01088 01089 if (eRet != ADMW_SUCCESS ) { 01090 ADMW_LOG_ERROR("Failed to set external reference values"); 01091 return eRet; 01092 } 01093 01094 return ADMW_SUCCESS ; 01095 } 01096 01097 ADMW_RESULT admw1001_SetDiagnosticsConfig( 01098 ADMW_DEVICE_HANDLE hDevice, 01099 ADMW1001_DIAGNOSTICS_CONFIG *pDiagnosticsConfig) 01100 { 01101 ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg; 01102 01103 diagnosticsControlReg.VALUE16 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL); 01104 01105 if (pDiagnosticsConfig->disableGlobalDiag ) 01106 diagnosticsControlReg.Diag_Global_En = 0; 01107 else 01108 diagnosticsControlReg.Diag_Global_En = 1; 01109 01110 if (pDiagnosticsConfig->disableMeasurementDiag ) 01111 diagnosticsControlReg.Diag_Meas_En = 0; 01112 else 01113 diagnosticsControlReg.Diag_Meas_En = 1; 01114 01115 switch (pDiagnosticsConfig->osdFrequency ) { 01116 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_DISABLED : 01117 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_OFF; 01118 break; 01119 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_CYCLE : 01120 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1_CYCLE; 01121 break; 01122 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_100_CYCLES : 01123 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_100_CYCLES; 01124 break; 01125 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_1000_CYCLES : 01126 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1000_CYCLES; 01127 break; 01128 default: 01129 ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified", 01130 pDiagnosticsConfig->osdFrequency ); 01131 return ADMW_INVALID_PARAM ; 01132 } 01133 01134 WRITE_REG_U16(hDevice, diagnosticsControlReg.VALUE16, CORE_DIAGNOSTICS_CONTROL); 01135 01136 return ADMW_SUCCESS ; 01137 } 01138 01139 ADMW_RESULT admw1001_SetChannelCount( 01140 ADMW_DEVICE_HANDLE hDevice, 01141 ADMW1001_CH_ID eChannelId, 01142 uint32_t nMeasurementsPerCycle) 01143 { 01144 ADMW_CORE_Channel_Count_t channelCountReg; 01145 01146 channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn); 01147 01148 if (nMeasurementsPerCycle > 0) { 01149 nMeasurementsPerCycle -= 1; 01150 01151 CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT, 01152 nMeasurementsPerCycle); 01153 01154 channelCountReg.Channel_Enable = 1; 01155 channelCountReg.Channel_Count = nMeasurementsPerCycle; 01156 } else { 01157 channelCountReg.Channel_Enable = 0; 01158 } 01159 01160 WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId)); 01161 01162 return ADMW_SUCCESS ; 01163 } 01164 01165 ADMW_RESULT admw1001_SetChannelOptions( 01166 ADMW_DEVICE_HANDLE hDevice, 01167 ADMW1001_CH_ID eChannelId, 01168 ADMW1001_CHANNEL_PRIORITY ePriority) 01169 { 01170 ADMW_CORE_Channel_Options_t channelOptionsReg; 01171 01172 channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn); 01173 01174 CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority); 01175 channelOptionsReg.Channel_Priority = ePriority; 01176 01177 WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId)); 01178 01179 return ADMW_SUCCESS ; 01180 } 01181 01182 ADMW_RESULT admw1001_SetChannelSkipCount( 01183 ADMW_DEVICE_HANDLE hDevice, 01184 ADMW1001_CH_ID eChannelId, 01185 uint32_t nCycleSkipCount) 01186 { 01187 ADMW_CORE_Channel_Skip_t channelSkipReg; 01188 01189 channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn); 01190 01191 CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount); 01192 01193 channelSkipReg.Channel_Skip = nCycleSkipCount; 01194 01195 WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId)); 01196 01197 return ADMW_SUCCESS ; 01198 } 01199 01200 static ADMW_RESULT admw_SetChannelAdcSensorType( 01201 ADMW_DEVICE_HANDLE hDevice, 01202 ADMW1001_CH_ID eChannelId, 01203 ADMW1001_ADC_SENSOR_TYPE sensorType) 01204 { 01205 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01206 01207 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01208 01209 /* Ensure that the sensor type is valid for this channel */ 01210 switch(sensorType) { 01211 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 : 01212 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 : 01213 case ADMW1001_ADC_SENSOR_RTD_3WIRE_1 : 01214 case ADMW1001_ADC_SENSOR_RTD_3WIRE_2 : 01215 case ADMW1001_ADC_SENSOR_RTD_3WIRE_3 : 01216 case ADMW1001_ADC_SENSOR_RTD_3WIRE_4 : 01217 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 : 01218 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 : 01219 case ADMW1001_ADC_SENSOR_RTD_4WIRE_1 : 01220 case ADMW1001_ADC_SENSOR_RTD_4WIRE_2 : 01221 case ADMW1001_ADC_SENSOR_RTD_4WIRE_3 : 01222 case ADMW1001_ADC_SENSOR_RTD_4WIRE_4 : 01223 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_1 : 01224 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_2 : 01225 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_3 : 01226 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_4 : 01227 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_1 : 01228 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_2 : 01229 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_3 : 01230 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_4 : 01231 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 : 01232 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 : 01233 case ADMW1001_ADC_SENSOR_RTD_2WIRE_1 : 01234 case ADMW1001_ADC_SENSOR_RTD_2WIRE_2 : 01235 case ADMW1001_ADC_SENSOR_RTD_2WIRE_3 : 01236 case ADMW1001_ADC_SENSOR_RTD_2WIRE_4 : 01237 case ADMW1001_ADC_SENSOR_DIODE_2C_TYPEA : 01238 case ADMW1001_ADC_SENSOR_DIODE_3C_TYPEA : 01239 case ADMW1001_ADC_SENSOR_DIODE_2C_1 : 01240 case ADMW1001_ADC_SENSOR_DIODE_3C_1 : 01241 case ADMW1001_ADC_SENSOR_THERMISTOR_A_10K : 01242 case ADMW1001_ADC_SENSOR_THERMISTOR_B_10K : 01243 case ADMW1001_ADC_SENSOR_THERMISTOR_1 : 01244 case ADMW1001_ADC_SENSOR_THERMISTOR_2 : 01245 case ADMW1001_ADC_SENSOR_THERMISTOR_3 : 01246 case ADMW1001_ADC_SENSOR_THERMISTOR_4 : 01247 if (! (ADMW1001_CHANNEL_IS_ADC_SENSOR(eChannelId) || 01248 ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId))) { 01249 ADMW_LOG_ERROR( 01250 "Invalid ADC sensor type %d specified for channel %d", 01251 sensorType, eChannelId); 01252 return ADMW_INVALID_PARAM ; 01253 } 01254 break; 01255 case ADMW1001_ADC_SENSOR_VOLTAGE : 01256 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_A : 01257 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_B : 01258 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_1 : 01259 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_2 : 01260 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J : 01261 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K : 01262 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T : 01263 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_1 : 01264 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_2 : 01265 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_3 : 01266 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_4 : 01267 if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) { 01268 ADMW_LOG_ERROR( 01269 "Invalid ADC sensor type %d specified for channel %d", 01270 sensorType, eChannelId); 01271 return ADMW_INVALID_PARAM ; 01272 } 01273 break; 01274 case ADMW1001_ADC_SENSOR_CURRENT : 01275 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_A : 01276 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_1 : 01277 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_2 : 01278 if (! ADMW1001_CHANNEL_IS_ADC_CURRENT(eChannelId)) { 01279 ADMW_LOG_ERROR( 01280 "Invalid ADC sensor type %d specified for channel %d", 01281 sensorType, eChannelId); 01282 return ADMW_INVALID_PARAM ; 01283 } 01284 break; 01285 default: 01286 ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified", 01287 sensorType); 01288 return ADMW_INVALID_PARAM ; 01289 } 01290 01291 sensorTypeReg.Sensor_Type = sensorType; 01292 01293 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01294 01295 return ADMW_SUCCESS ; 01296 } 01297 01298 static ADMW_RESULT admw_SetChannelAdcSensorDetails( 01299 ADMW_DEVICE_HANDLE hDevice, 01300 ADMW1001_CH_ID eChannelId, 01301 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01302 /* 01303 * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers 01304 * General details: 01305 * - Measurement_Units 01306 * - Compensation_Channel 01307 * - CJC_Publish (if "CJC" was removed from the name) 01308 * ADC-specific details: 01309 * - PGA_Gain 01310 * - Reference_Select 01311 * - Reference_Buffer_Disable 01312 */ 01313 { 01314 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ; 01315 ADMW1001_ADC_REFERENCE_TYPE refType = pAdcChannelConfig->reference; 01316 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01317 01318 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01319 01320 switch(pChannelConfig->measurementUnit ) { 01321 case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT : 01322 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF; 01323 break; 01324 case ADMW1001_MEASUREMENT_UNIT_CELSIUS : 01325 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC; 01326 break; 01327 case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED : 01328 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01329 break; 01330 default: 01331 ADMW_LOG_ERROR("Invalid measurement unit %d specified", 01332 pChannelConfig->measurementUnit ); 01333 return ADMW_INVALID_PARAM ; 01334 } 01335 01336 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01337 sensorDetailsReg.Compensation_Disable = 1; 01338 sensorDetailsReg.Compensation_Channel = 0; 01339 } else { 01340 sensorDetailsReg.Compensation_Disable = 0; 01341 sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ; 01342 } 01343 01344 switch(refType) { 01345 case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL : 01346 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT; 01347 break; 01348 case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 : 01349 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1; 01350 break; 01351 case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD : 01352 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD; 01353 break; 01354 default: 01355 ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType); 01356 return ADMW_INVALID_PARAM ; 01357 } 01358 01359 switch(pAdcChannelConfig->gain ) { 01360 case ADMW1001_ADC_GAIN_1X : 01361 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1; 01362 break; 01363 case ADMW1001_ADC_GAIN_2X : 01364 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2; 01365 break; 01366 case ADMW1001_ADC_GAIN_4X : 01367 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4; 01368 break; 01369 case ADMW1001_ADC_GAIN_8X : 01370 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8; 01371 break; 01372 case ADMW1001_ADC_GAIN_16X : 01373 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16; 01374 break; 01375 case ADMW1001_ADC_GAIN_32X : 01376 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32; 01377 break; 01378 case ADMW1001_ADC_GAIN_64X : 01379 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64; 01380 break; 01381 case ADMW1001_ADC_GAIN_128X : 01382 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128; 01383 break; 01384 default: 01385 ADMW_LOG_ERROR("Invalid ADC gain %d specified", 01386 pAdcChannelConfig->gain ); 01387 return ADMW_INVALID_PARAM ; 01388 } 01389 01390 switch(pAdcChannelConfig->rtdCurve ) { 01391 case ADMW1001_ADC_RTD_CURVE_EUROPEAN : 01392 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE; 01393 break; 01394 case ADMW1001_ADC_RTD_CURVE_AMERICAN : 01395 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE; 01396 break; 01397 case ADMW1001_ADC_RTD_CURVE_JAPANESE : 01398 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE; 01399 break; 01400 case ADMW1001_ADC_RTD_CURVE_ITS90 : 01401 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE; 01402 break; 01403 default: 01404 ADMW_LOG_ERROR("Invalid RTD Curve %d specified", 01405 pAdcChannelConfig->rtdCurve ); 01406 return ADMW_INVALID_PARAM ; 01407 } 01408 01409 if (pChannelConfig->disablePublishing ) { 01410 sensorDetailsReg.Do_Not_Publish = 1; 01411 } else { 01412 sensorDetailsReg.Do_Not_Publish = 0; 01413 } 01414 01415 switch (pChannelConfig->lutSelect ) { 01416 case ADMW1001_LUT_DEFAULT : 01417 case ADMW1001_LUT_UNITY : 01418 case ADMW1001_LUT_CUSTOM : 01419 sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ; 01420 break; 01421 default: 01422 ADMW_LOG_ERROR("Invalid LUT selection %d specified", 01423 pChannelConfig->lutSelect ); 01424 return ADMW_INVALID_PARAM ; 01425 } 01426 01427 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01428 01429 return ADMW_SUCCESS ; 01430 } 01431 01432 static ADMW_RESULT admw_SetChannelAdcFilter( 01433 ADMW_DEVICE_HANDLE hDevice, 01434 ADMW1001_CH_ID eChannelId, 01435 ADMW1001_ADC_FILTER_CONFIG *pFilterConfig) 01436 { 01437 ADMW_CORE_Measurement_Setup_t MeasSetupReg; 01438 MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn); 01439 01440 if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC4 ) { 01441 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4; 01442 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01443 } else if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC3 ) { 01444 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3; 01445 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01446 } else { 01447 ADMW_LOG_ERROR("Invalid ADC filter type %d specified", 01448 pFilterConfig->type ); 01449 return ADMW_INVALID_PARAM ; 01450 } 01451 01452 /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */ 01453 MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ; 01454 01455 if(pFilterConfig->notch1p2 ) 01456 MeasSetupReg.NOTCH_EN_2 = 1; 01457 else 01458 MeasSetupReg.NOTCH_EN_2 = 0; 01459 01460 switch(pFilterConfig->groundSwitch ) { 01461 case ADMW1001_ADC_GND_SW_OPEN : 01462 MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_OPEN; 01463 break; 01464 case ADMW1001_ADC_GND_SW_CLOSED : 01465 MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_CLOSED; 01466 break; 01467 default: 01468 ADMW_LOG_ERROR("Invalid ground switch state %d specified", 01469 pFilterConfig->groundSwitch ); 01470 return ADMW_INVALID_PARAM ; 01471 } 01472 01473 WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId)); 01474 01475 return ADMW_SUCCESS ; 01476 } 01477 01478 static ADMW_RESULT admw_SetChannelAdcCurrentConfig( 01479 ADMW_DEVICE_HANDLE hDevice, 01480 ADMW1001_CH_ID eChannelId, 01481 ADMW1001_ADC_EXC_CURRENT_CONFIG *pCurrentConfig) 01482 { 01483 ADMW_CORE_Channel_Excitation_t channelExcitationReg; 01484 01485 channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn); 01486 01487 if (pCurrentConfig->outputLevel == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT ) 01488 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE; 01489 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_EXTERNAL ) 01490 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL; 01491 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_50uA ) 01492 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA; 01493 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_100uA ) 01494 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA; 01495 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_250uA ) 01496 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA; 01497 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_500uA ) 01498 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA; 01499 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_1000uA ) 01500 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA; 01501 else { 01502 ADMW_LOG_ERROR("Invalid ADC excitation current %d specified", 01503 pCurrentConfig->outputLevel ); 01504 return ADMW_INVALID_PARAM ; 01505 } 01506 01507 01508 01509 switch(pCurrentConfig->diodeRatio ) { 01510 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_100UA: 01511 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_10UA_100UA; 01512 break; 01513 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_160UA: 01514 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_20UA_160UA; 01515 break; 01516 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_300UA: 01517 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_50UA_300UA; 01518 break; 01519 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_600UA: 01520 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_100UA_600UA; 01521 break; 01522 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_50UA_100UA: 01523 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_10UA_50UA_100UA; 01524 break; 01525 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_100UA_160UA: 01526 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_20UA_100UA_160UA; 01527 break; 01528 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_150UA_300UA: 01529 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_50UA_150UA_300UA; 01530 break; 01531 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_300UA_600UA: 01532 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_100UA_300UA_600UA; 01533 break; 01534 default: 01535 ADMW_LOG_ERROR("Invalid diode ratio %d specified", 01536 pCurrentConfig->diodeRatio ); 01537 return ADMW_INVALID_PARAM ; 01538 } 01539 01540 WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId)); 01541 01542 return ADMW_SUCCESS ; 01543 } 01544 01545 ADMW_RESULT admw_SetAdcChannelConfig( 01546 ADMW_DEVICE_HANDLE hDevice, 01547 ADMW1001_CH_ID eChannelId, 01548 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01549 { 01550 ADMW_RESULT eRet; 01551 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = 01552 &pChannelConfig->adcChannelConfig ; 01553 01554 eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId, 01555 pAdcChannelConfig->sensor ); 01556 if (eRet != ADMW_SUCCESS ) { 01557 ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d", 01558 eChannelId); 01559 return eRet; 01560 } 01561 01562 eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId, 01563 pChannelConfig); 01564 if (eRet != ADMW_SUCCESS ) { 01565 ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d", 01566 eChannelId); 01567 return eRet; 01568 } 01569 01570 eRet = admw_SetChannelAdcFilter(hDevice, eChannelId, 01571 &pAdcChannelConfig->filter ); 01572 if (eRet != ADMW_SUCCESS ) { 01573 ADMW_LOG_ERROR("Failed to set ADC filter for channel %d", 01574 eChannelId); 01575 return eRet; 01576 } 01577 01578 eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId, 01579 &pAdcChannelConfig->current ); 01580 if (eRet != ADMW_SUCCESS ) { 01581 ADMW_LOG_ERROR("Failed to set ADC current for channel %d", 01582 eChannelId); 01583 return eRet; 01584 } 01585 01586 return ADMW_SUCCESS ; 01587 } 01588 01589 static ADMW_RESULT admw_SetChannelDigitalSensorDetails( 01590 ADMW_DEVICE_HANDLE hDevice, 01591 ADMW1001_CH_ID eChannelId, 01592 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01593 { 01594 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01595 01596 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01597 01598 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01599 sensorDetailsReg.Compensation_Disable = 1; 01600 sensorDetailsReg.Compensation_Channel = 0; 01601 } else { 01602 ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor"); 01603 return ADMW_INVALID_PARAM ; 01604 } 01605 01606 if (pChannelConfig->measurementUnit == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) { 01607 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01608 } else { 01609 ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel"); 01610 return ADMW_INVALID_PARAM ; 01611 } 01612 01613 if (pChannelConfig->disablePublishing ) 01614 sensorDetailsReg.Do_Not_Publish = 1; 01615 else 01616 sensorDetailsReg.Do_Not_Publish = 0; 01617 01618 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01619 01620 return ADMW_SUCCESS ; 01621 } 01622 01623 static ADMW_RESULT admw_SetDigitalSensorCommands( 01624 ADMW_DEVICE_HANDLE hDevice, 01625 ADMW1001_CH_ID eChannelId, 01626 ADMW1001_DIGITAL_SENSOR_COMMAND *pConfigCommand, 01627 ADMW1001_DIGITAL_SENSOR_COMMAND *pDataRequestCommand) 01628 { 01629 ADMW_CORE_Digital_Sensor_Num_Cmds_t numCmdsReg; 01630 01631 numCmdsReg.VALUE8 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_NUM_CMDSn); 01632 01633 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_CFG_CMDS, 01634 pConfigCommand->commandLength ); 01635 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_READ_CMDS, 01636 pDataRequestCommand->commandLength ); 01637 01638 numCmdsReg.Digital_Sensor_Num_Cfg_Cmds = pConfigCommand->commandLength ; 01639 numCmdsReg.Digital_Sensor_Num_Read_Cmds = pDataRequestCommand->commandLength ; 01640 01641 WRITE_REG_U8(hDevice, numCmdsReg.VALUE8, 01642 CORE_DIGITAL_SENSOR_NUM_CMDSn(eChannelId)); 01643 01644 /* 01645 * NOTE - the fall-through cases in the switch statement below are 01646 * intentional. 01647 */ 01648 switch (pConfigCommand->commandLength ) { 01649 case 7: 01650 WRITE_REG_U8(hDevice, pConfigCommand->command [6], 01651 CORE_DIGITAL_SENSOR_COMMAND7n(eChannelId)); 01652 case 6: 01653 WRITE_REG_U8(hDevice, pConfigCommand->command [5], 01654 CORE_DIGITAL_SENSOR_COMMAND6n(eChannelId)); 01655 case 5: 01656 WRITE_REG_U8(hDevice, pConfigCommand->command [4], 01657 CORE_DIGITAL_SENSOR_COMMAND5n(eChannelId)); 01658 case 4: 01659 WRITE_REG_U8(hDevice, pConfigCommand->command [3], 01660 CORE_DIGITAL_SENSOR_COMMAND4n(eChannelId)); 01661 case 3: 01662 WRITE_REG_U8(hDevice, pConfigCommand->command [2], 01663 CORE_DIGITAL_SENSOR_COMMAND3n(eChannelId)); 01664 case 2: 01665 WRITE_REG_U8(hDevice, pConfigCommand->command [1], 01666 CORE_DIGITAL_SENSOR_COMMAND2n(eChannelId)); 01667 case 1: 01668 WRITE_REG_U8(hDevice, pConfigCommand->command [0], 01669 CORE_DIGITAL_SENSOR_COMMAND1n(eChannelId)); 01670 case 0: 01671 default: 01672 break; 01673 }; 01674 01675 switch (pDataRequestCommand->commandLength ) { 01676 case 7: 01677 WRITE_REG_U8(hDevice, pDataRequestCommand->command [6], 01678 CORE_DIGITAL_SENSOR_READ_CMD7n(eChannelId)); 01679 case 6: 01680 WRITE_REG_U8(hDevice, pDataRequestCommand->command [5], 01681 CORE_DIGITAL_SENSOR_READ_CMD6n(eChannelId)); 01682 case 5: 01683 WRITE_REG_U8(hDevice, pDataRequestCommand->command [4], 01684 CORE_DIGITAL_SENSOR_READ_CMD5n(eChannelId)); 01685 case 4: 01686 WRITE_REG_U8(hDevice, pDataRequestCommand->command [3], 01687 CORE_DIGITAL_SENSOR_READ_CMD4n(eChannelId)); 01688 case 3: 01689 WRITE_REG_U8(hDevice, pDataRequestCommand->command [2], 01690 CORE_DIGITAL_SENSOR_READ_CMD3n(eChannelId)); 01691 case 2: 01692 WRITE_REG_U8(hDevice, pDataRequestCommand->command [1], 01693 CORE_DIGITAL_SENSOR_READ_CMD2n(eChannelId)); 01694 case 1: 01695 WRITE_REG_U8(hDevice, pDataRequestCommand->command [0], 01696 CORE_DIGITAL_SENSOR_READ_CMD1n(eChannelId)); 01697 case 0: 01698 default: 01699 break; 01700 }; 01701 01702 return ADMW_SUCCESS ; 01703 } 01704 01705 static ADMW_RESULT admw_SetDigitalSensorFormat( 01706 ADMW_DEVICE_HANDLE hDevice, 01707 ADMW1001_CH_ID eChannelId, 01708 ADMW1001_DIGITAL_SENSOR_DATA_FORMAT *pDataFormat) 01709 { 01710 ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg; 01711 01712 sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn); 01713 01714 if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) { 01715 if (pDataFormat->frameLength == 0) { 01716 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01717 return ADMW_INVALID_PARAM ; 01718 } 01719 if (pDataFormat->numDataBits == 0) { 01720 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01721 return ADMW_INVALID_PARAM ; 01722 } 01723 01724 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES, 01725 pDataFormat->frameLength - 1); 01726 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS, 01727 pDataFormat->numDataBits - 1); 01728 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET, 01729 pDataFormat->bitOffset); 01730 01731 sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1; 01732 sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1; 01733 sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset; 01734 sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0; 01735 sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0; 01736 01737 switch (pDataFormat->coding) { 01738 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR: 01739 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR; 01740 break; 01741 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT: 01742 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL; 01743 break; 01744 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY: 01745 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY; 01746 break; 01747 default: 01748 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format"); 01749 return ADMW_INVALID_PARAM ; 01750 } 01751 } else { 01752 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE; 01753 } 01754 01755 WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16, 01756 CORE_DIGITAL_SENSOR_CONFIGn(eChannelId)); 01757 01758 01759 return ADMW_SUCCESS ; 01760 } 01761 01762 static ADMW_RESULT admw_SetDigitalCalibrationParam( 01763 ADMW_DEVICE_HANDLE hDevice, 01764 ADMW1001_CH_ID eChannelId, 01765 ADMW1001_DIGITAL_CALIBRATION_COMMAND *pCalibrationParam) 01766 { 01767 ADMW_CORE_Calibration_Parameter_t calibrationParamReg; 01768 01769 calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn); 01770 01771 if (pCalibrationParam->enableCalibrationParam == false) 01772 calibrationParamReg.Calibration_Parameter_Enable = 0; 01773 else 01774 calibrationParamReg.Calibration_Parameter_Enable = 1; 01775 01776 CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER, 01777 pCalibrationParam->calibrationParam ); 01778 01779 calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam ; 01780 01781 WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32, 01782 CORE_CALIBRATION_PARAMETERn(eChannelId)); 01783 01784 return ADMW_SUCCESS ; 01785 } 01786 01787 static ADMW_RESULT admw_SetChannelI2cSensorType( 01788 ADMW_DEVICE_HANDLE hDevice, 01789 ADMW1001_CH_ID eChannelId, 01790 ADMW1001_I2C_SENSOR_TYPE sensorType) 01791 { 01792 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01793 01794 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01795 01796 /* Ensure that the sensor type is valid for this channel */ 01797 switch(sensorType) { 01798 case ADMW1001_I2C_SENSOR_HUMIDITY_A : 01799 case ADMW1001_I2C_SENSOR_HUMIDITY_B : 01800 sensorTypeReg.Sensor_Type = sensorType; 01801 break; 01802 default: 01803 ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType); 01804 return ADMW_INVALID_PARAM ; 01805 } 01806 01807 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01808 01809 return ADMW_SUCCESS ; 01810 } 01811 01812 static ADMW_RESULT admw_SetChannelI2cSensorAddress( 01813 ADMW_DEVICE_HANDLE hDevice, 01814 ADMW1001_CH_ID eChannelId, 01815 uint32_t deviceAddress) 01816 { 01817 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress); 01818 WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId)); 01819 01820 return ADMW_SUCCESS ; 01821 } 01822 01823 static ADMW_RESULT admw_SetDigitalChannelComms( 01824 ADMW_DEVICE_HANDLE hDevice, 01825 ADMW1001_CH_ID eChannelId, 01826 ADMW1001_DIGITAL_SENSOR_COMMS *pDigitalComms) 01827 { 01828 ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms; 01829 01830 digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn); 01831 01832 if(pDigitalComms->useCustomCommsConfig ) { 01833 digitalSensorComms.Digital_Sensor_Comms_En = 1; 01834 01835 if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) { 01836 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K; 01837 } else if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) { 01838 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K; 01839 } else { 01840 ADMW_LOG_ERROR("Invalid I2C clock speed %d specified", 01841 pDigitalComms->i2cClockSpeed ); 01842 return ADMW_INVALID_PARAM ; 01843 } 01844 01845 if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) { 01846 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0; 01847 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) { 01848 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1; 01849 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) { 01850 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2; 01851 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) { 01852 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3; 01853 } else { 01854 ADMW_LOG_ERROR("Invalid SPI mode %d specified", 01855 pDigitalComms->spiMode ); 01856 return ADMW_INVALID_PARAM ; 01857 } 01858 01859 switch (pDigitalComms->spiClock ) { 01860 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ : 01861 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ; 01862 break; 01863 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ : 01864 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ; 01865 break; 01866 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ : 01867 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ; 01868 break; 01869 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ : 01870 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ; 01871 break; 01872 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ : 01873 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ; 01874 break; 01875 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ : 01876 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ; 01877 break; 01878 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ : 01879 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ; 01880 break; 01881 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ : 01882 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ; 01883 break; 01884 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ : 01885 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ; 01886 break; 01887 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ : 01888 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ; 01889 break; 01890 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ : 01891 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ; 01892 break; 01893 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ : 01894 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ; 01895 break; 01896 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ : 01897 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ; 01898 break; 01899 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ : 01900 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ; 01901 break; 01902 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ : 01903 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ; 01904 break; 01905 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ : 01906 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ; 01907 break; 01908 default: 01909 ADMW_LOG_ERROR("Invalid SPI clock %d specified", 01910 pDigitalComms->spiClock ); 01911 return ADMW_INVALID_PARAM ; 01912 } 01913 } else { 01914 digitalSensorComms.Digital_Sensor_Comms_En = 0; 01915 } 01916 01917 WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId)); 01918 01919 return ADMW_SUCCESS ; 01920 } 01921 01922 ADMW_RESULT admw_SetI2cChannelConfig( 01923 ADMW_DEVICE_HANDLE hDevice, 01924 ADMW1001_CH_ID eChannelId, 01925 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01926 { 01927 ADMW_RESULT eRet; 01928 ADMW1001_I2C_CHANNEL_CONFIG *pI2cChannelConfig = 01929 &pChannelConfig->i2cChannelConfig ; 01930 01931 eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId, 01932 pI2cChannelConfig->sensor ); 01933 if (eRet != ADMW_SUCCESS ) { 01934 ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d", 01935 eChannelId); 01936 return eRet; 01937 } 01938 01939 eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId, 01940 pI2cChannelConfig->deviceAddress ); 01941 if (eRet != ADMW_SUCCESS ) { 01942 ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d", 01943 eChannelId); 01944 return eRet; 01945 } 01946 01947 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 01948 pChannelConfig); 01949 if (eRet != ADMW_SUCCESS ) { 01950 ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d", 01951 eChannelId); 01952 return eRet; 01953 } 01954 01955 eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId, 01956 &pI2cChannelConfig->configurationCommand , 01957 &pI2cChannelConfig->dataRequestCommand ); 01958 if (eRet != ADMW_SUCCESS ) { 01959 ADMW_LOG_ERROR("Failed to set I2C sensor commands for channel %d", 01960 eChannelId); 01961 return eRet; 01962 } 01963 01964 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 01965 &pI2cChannelConfig->dataFormat ); 01966 if (eRet != ADMW_SUCCESS ) { 01967 ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d", 01968 eChannelId); 01969 return eRet; 01970 } 01971 01972 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 01973 &pI2cChannelConfig->digitalCalibrationParam ); 01974 if (eRet != ADMW_SUCCESS ) { 01975 ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d", 01976 eChannelId); 01977 return eRet; 01978 } 01979 01980 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 01981 &pI2cChannelConfig->configureComms ); 01982 if (eRet != ADMW_SUCCESS ) { 01983 ADMW_LOG_ERROR("Failed to set I2C comms for channel %d", 01984 eChannelId); 01985 return eRet; 01986 } 01987 01988 return ADMW_SUCCESS ; 01989 } 01990 01991 static ADMW_RESULT admw_SetChannelSpiSensorType( 01992 ADMW_DEVICE_HANDLE hDevice, 01993 ADMW1001_CH_ID eChannelId, 01994 ADMW1001_SPI_SENSOR_TYPE sensorType) 01995 { 01996 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01997 01998 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01999 02000 /* Ensure that the sensor type is valid for this channel */ 02001 switch(sensorType) { 02002 case ADMW1001_SPI_SENSOR_PRESSURE_A : 02003 case ADMW1001_SPI_SENSOR_ACCELEROMETER_A : 02004 case ADMW1001_SPI_SENSOR_ACCELEROMETER_B : 02005 02006 sensorTypeReg.Sensor_Type = sensorType; 02007 break; 02008 default: 02009 ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType); 02010 return ADMW_INVALID_PARAM ; 02011 } 02012 02013 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 02014 02015 return ADMW_SUCCESS ; 02016 } 02017 02018 ADMW_RESULT admw_SetSpiChannelConfig( 02019 ADMW_DEVICE_HANDLE hDevice, 02020 ADMW1001_CH_ID eChannelId, 02021 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 02022 { 02023 ADMW_RESULT eRet; 02024 ADMW1001_SPI_CHANNEL_CONFIG *pSpiChannelConfig = 02025 &pChannelConfig->spiChannelConfig ; 02026 02027 eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId, 02028 pSpiChannelConfig->sensor ); 02029 if (eRet != ADMW_SUCCESS ) { 02030 ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d", 02031 eChannelId); 02032 return eRet; 02033 } 02034 02035 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 02036 pChannelConfig); 02037 if (eRet != ADMW_SUCCESS ) { 02038 ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d", 02039 eChannelId); 02040 return eRet; 02041 } 02042 02043 eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId, 02044 &pSpiChannelConfig->configurationCommand , 02045 &pSpiChannelConfig->dataRequestCommand ); 02046 if (eRet != ADMW_SUCCESS ) { 02047 ADMW_LOG_ERROR("Failed to set SPI sensor commands for channel %d", 02048 eChannelId); 02049 return eRet; 02050 } 02051 02052 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 02053 &pSpiChannelConfig->dataFormat ); 02054 if (eRet != ADMW_SUCCESS ) { 02055 ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d", 02056 eChannelId); 02057 return eRet; 02058 } 02059 02060 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 02061 &pSpiChannelConfig->digitalCalibrationParam ); 02062 if (eRet != ADMW_SUCCESS ) { 02063 ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d", 02064 eChannelId); 02065 return eRet; 02066 } 02067 02068 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 02069 &pSpiChannelConfig->configureComms ); 02070 if (eRet != ADMW_SUCCESS ) { 02071 ADMW_LOG_ERROR("Failed to set SPI comms for channel %d", 02072 eChannelId); 02073 return eRet; 02074 } 02075 02076 return ADMW_SUCCESS ; 02077 } 02078 02079 ADMW_RESULT admw1001_SetChannelThresholdLimits( 02080 ADMW_DEVICE_HANDLE hDevice, 02081 ADMW1001_CH_ID eChannelId, 02082 float32_t fHighThresholdLimit, 02083 float32_t fLowThresholdLimit) 02084 { 02085 /* 02086 * If the low/high limits are *both* set to 0 in memory, or NaNs, assume 02087 * that they are unset, or not required, and use infinity defaults instead 02088 */ 02089 if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) { 02090 fHighThresholdLimit = INFINITY; 02091 fLowThresholdLimit = -INFINITY; 02092 } else { 02093 if (isnan(fHighThresholdLimit)) 02094 fHighThresholdLimit = INFINITY; 02095 if (isnan(fLowThresholdLimit)) 02096 fLowThresholdLimit = -INFINITY; 02097 } 02098 02099 WRITE_REG_FLOAT(hDevice, fHighThresholdLimit, 02100 CORE_HIGH_THRESHOLD_LIMITn(eChannelId)); 02101 WRITE_REG_FLOAT(hDevice, fLowThresholdLimit, 02102 CORE_LOW_THRESHOLD_LIMITn(eChannelId)); 02103 02104 return ADMW_SUCCESS ; 02105 } 02106 02107 ADMW_RESULT admw1001_SetOffsetGain( 02108 ADMW_DEVICE_HANDLE hDevice, 02109 ADMW1001_CH_ID eChannelId, 02110 float32_t fOffsetAdjustment, 02111 float32_t fGainAdjustment) 02112 { 02113 /* Replace with default values if NaNs are specified (or 0.0 for gain) */ 02114 if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f)) 02115 fGainAdjustment = 1.0f; 02116 if (isnan(fOffsetAdjustment)) 02117 fOffsetAdjustment = 0.0f; 02118 02119 WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId)); 02120 WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId)); 02121 02122 return ADMW_SUCCESS ; 02123 } 02124 02125 ADMW_RESULT admw1001_SetSensorParameter( 02126 ADMW_DEVICE_HANDLE hDevice, 02127 ADMW1001_CH_ID eChannelId, 02128 float32_t fSensorParam) 02129 { 02130 if (fSensorParam == 0.0f) 02131 fSensorParam = NAN; 02132 02133 WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId)); 02134 02135 return ADMW_SUCCESS ; 02136 } 02137 02138 ADMW_RESULT admw1001_SetChannelSettlingTime( 02139 ADMW_DEVICE_HANDLE hDevice, 02140 ADMW1001_CH_ID eChannelId, 02141 uint32_t nSettlingTime) 02142 { 02143 ADMW_CORE_Settling_Time_t settlingTimeReg; 02144 02145 if (nSettlingTime < (1 << 12)) { 02146 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MICROSECONDS; 02147 } else if (nSettlingTime < (1000 * (1 << 12))) { 02148 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MILLISECONDS; 02149 nSettlingTime /= 1000; 02150 } else { 02151 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_SECONDS; 02152 nSettlingTime /= 1000000; 02153 } 02154 02155 CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime); 02156 settlingTimeReg.Settling_Time = nSettlingTime; 02157 02158 WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId)); 02159 02160 return ADMW_SUCCESS ; 02161 } 02162 02163 ADMW_RESULT admw1001_SetChannelConfig( 02164 ADMW_DEVICE_HANDLE hDevice, 02165 ADMW1001_CH_ID eChannelId, 02166 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 02167 { 02168 ADMW_RESULT eRet; 02169 02170 if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) { 02171 eRet = admw1001_SetChannelCount(hDevice, eChannelId, 02172 pChannelConfig->enableChannel ? 02173 pChannelConfig->measurementsPerCycle : 0); 02174 if (eRet != ADMW_SUCCESS ) { 02175 ADMW_LOG_ERROR("Failed to set measurement count for channel %d", 02176 eChannelId); 02177 return eRet; 02178 } 02179 02180 eRet = admw1001_SetChannelOptions(hDevice, eChannelId, 02181 pChannelConfig->priority ); 02182 if (eRet != ADMW_SUCCESS ) { 02183 ADMW_LOG_ERROR("Failed to set priority for channel %d", 02184 eChannelId); 02185 return eRet; 02186 } 02187 02188 /* If the channel is not enabled, we can skip the following steps */ 02189 if (pChannelConfig->enableChannel ) { 02190 eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId, 02191 pChannelConfig->cycleSkipCount ); 02192 if (eRet != ADMW_SUCCESS ) { 02193 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d", 02194 eChannelId); 02195 return eRet; 02196 } 02197 02198 switch (eChannelId) { 02199 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL : 02200 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL : 02201 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL : 02202 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL : 02203 eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig); 02204 break; 02205 case ADMW1001_CH_ID_DIG_I2C_0 : 02206 case ADMW1001_CH_ID_DIG_I2C_1 : 02207 eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig); 02208 break; 02209 case ADMW1001_CH_ID_DIG_SPI_0 : 02210 eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig); 02211 break; 02212 default: 02213 ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId); 02214 return ADMW_INVALID_PARAM ; 02215 } 02216 02217 eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId, 02218 pChannelConfig->extraSettlingTime ); 02219 if (eRet != ADMW_SUCCESS ) { 02220 ADMW_LOG_ERROR("Failed to set settling time for channel %d", 02221 eChannelId); 02222 return eRet; 02223 } 02224 } 02225 } 02226 02227 if (pChannelConfig->enableChannel ) { 02228 /* Threshold limits can be configured individually for virtual channels */ 02229 eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId, 02230 pChannelConfig->highThreshold , 02231 pChannelConfig->lowThreshold ); 02232 if (eRet != ADMW_SUCCESS ) { 02233 ADMW_LOG_ERROR("Failed to set threshold limits for channel %d", 02234 eChannelId); 02235 return eRet; 02236 } 02237 02238 /* Offset and gain can be configured individually for virtual channels */ 02239 eRet = admw1001_SetOffsetGain(hDevice, eChannelId, 02240 pChannelConfig->offsetAdjustment , 02241 pChannelConfig->gainAdjustment ); 02242 if (eRet != ADMW_SUCCESS ) { 02243 ADMW_LOG_ERROR("Failed to set offset/gain for channel %d", 02244 eChannelId); 02245 return eRet; 02246 } 02247 02248 /* Set sensor specific parameter */ 02249 eRet = admw1001_SetSensorParameter(hDevice, eChannelId, 02250 pChannelConfig->sensorParameter ); 02251 if (eRet != ADMW_SUCCESS ) { 02252 ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d", 02253 eChannelId); 02254 return eRet; 02255 } 02256 } 02257 02258 return ADMW_SUCCESS ; 02259 } 02260 02261 ADMW_RESULT admw_SetConfig( 02262 ADMW_DEVICE_HANDLE const hDevice, 02263 ADMW_CONFIG * const pConfig) 02264 { 02265 ADMW1001_CONFIG *pDeviceConfig; 02266 ADMW_PRODUCT_ID productId; 02267 ADMW_RESULT eRet; 02268 02269 if (pConfig->productId != ADMW_PRODUCT_ID_ADMW1001 ) { 02270 ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)", 02271 pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 ); 02272 return ADMW_INVALID_PARAM ; 02273 } 02274 02275 if (!((pConfig->versionId .major ==VERSIONID_MAJOR) && 02276 (pConfig->versionId .minor ==VERSIONID_MINOR))) { 02277 ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported", 02278 pConfig->versionId ); 02279 return ADMW_INVALID_PARAM ; 02280 } 02281 02282 02283 /* Check that the actual Product ID is a match? */ 02284 eRet = admw_GetProductID(hDevice, &productId); 02285 if (eRet) { 02286 ADMW_LOG_ERROR("Failed to read device Product ID register"); 02287 return eRet; 02288 } 02289 if (pConfig->productId != productId) { 02290 ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)", 02291 pConfig->productId , productId); 02292 return ADMW_INVALID_PARAM ; 02293 } 02294 02295 pDeviceConfig = &pConfig->admw1001 ; 02296 02297 eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power ); 02298 if (eRet) { 02299 ADMW_LOG_ERROR("Failed to set power configuration"); 02300 return eRet; 02301 } 02302 02303 eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement ); 02304 if (eRet) { 02305 ADMW_LOG_ERROR("Failed to set measurement configuration"); 02306 return eRet; 02307 } 02308 02309 eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics ); 02310 if (eRet) { 02311 ADMW_LOG_ERROR("Failed to set diagnostics configuration"); 02312 return eRet; 02313 } 02314 02315 for (ADMW1001_CH_ID id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ; 02316 id < ADMW1001_MAX_CHANNELS ; 02317 id++) { 02318 eRet = admw1001_SetChannelConfig(hDevice, id, 02319 &pDeviceConfig->channels [id]); 02320 if (eRet) { 02321 ADMW_LOG_ERROR("Failed to set channel %d configuration", id); 02322 return eRet; 02323 } 02324 } 02325 02326 return ADMW_SUCCESS ; 02327 } 02328 02329 ADMW_RESULT admw1001_SetLutData( 02330 ADMW_DEVICE_HANDLE const hDevice, 02331 ADMW1001_LUT * const pLutData) 02332 { 02333 ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header; 02334 ADMW1001_LUT_TABLE *pLutTable = pLutData->tables; 02335 unsigned actualLength = 0; 02336 02337 if (pLutData->header.signature != ADMW_LUT_SIGNATURE) { 02338 ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)", 02339 ADMW_LUT_SIGNATURE, pLutHeader->signature); 02340 return ADMW_INVALID_SIGNATURE ; 02341 } 02342 02343 for (unsigned i = 0; i < pLutHeader->numTables; i++) { 02344 ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor; 02345 ADMW1001_LUT_TABLE_DATA *pData = &pLutTable->data; 02346 unsigned short calculatedCrc; 02347 02348 switch (pDesc->geometry) { 02349 case ADMW1001_LUT_GEOMETRY_COEFFS: 02350 switch (pDesc->equation) { 02351 case ADMW1001_LUT_EQUATION_POLYN: 02352 case ADMW1001_LUT_EQUATION_POLYNEXP: 02353 case ADMW1001_LUT_EQUATION_QUADRATIC: 02354 case ADMW1001_LUT_EQUATION_STEINHART: 02355 case ADMW1001_LUT_EQUATION_LOGARITHMIC: 02356 case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN: 02357 break; 02358 default: 02359 ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u", 02360 pDesc->equation, i); 02361 return ADMW_INVALID_PARAM ; 02362 } 02363 break; 02364 case ADMW1001_LUT_GEOMETRY_NES_1D: 02365 case ADMW1001_LUT_GEOMETRY_NES_2D: 02366 case ADMW1001_LUT_GEOMETRY_ES_1D: 02367 case ADMW1001_LUT_GEOMETRY_ES_2D: 02368 if (pDesc->equation != ADMW1001_LUT_EQUATION_LUT) { 02369 ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u", 02370 pDesc->equation, i); 02371 return ADMW_INVALID_PARAM ; 02372 } 02373 break; 02374 default: 02375 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u", 02376 pDesc->geometry, i); 02377 return ADMW_INVALID_PARAM ; 02378 } 02379 02380 switch (pDesc->dataType) { 02381 case ADMW1001_LUT_DATA_TYPE_FLOAT32: 02382 case ADMW1001_LUT_DATA_TYPE_FLOAT64: 02383 break; 02384 default: 02385 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u", 02386 pDesc->dataType, i); 02387 return ADMW_INVALID_PARAM ; 02388 } 02389 02390 calculatedCrc = admw_crc16_ccitt(pData, pDesc->length); 02391 if (calculatedCrc != pDesc->crc16) { 02392 ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)", 02393 i, pDesc->crc16, calculatedCrc); 02394 return ADMW_CRC_ERROR ; 02395 } 02396 02397 actualLength += sizeof(*pDesc) + pDesc->length; 02398 02399 /* Move to the next look-up table */ 02400 pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length); 02401 } 02402 02403 if (actualLength != pLutHeader->totalLength) { 02404 ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)", 02405 pLutHeader->totalLength, actualLength); 02406 return ADMW_WRONG_SIZE ; 02407 } 02408 02409 if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) { 02410 ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded", 02411 ADMW_LUT_MAX_SIZE); 02412 return ADMW_WRONG_SIZE ; 02413 } 02414 02415 /* Write the LUT data to the device */ 02416 unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength; 02417 WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET); 02418 WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA); 02419 02420 return ADMW_SUCCESS ; 02421 } 02422 02423 ADMW_RESULT admw1001_SetLutDataRaw( 02424 ADMW_DEVICE_HANDLE const hDevice, 02425 ADMW1001_LUT_RAW * const pLutData) 02426 { 02427 return admw1001_SetLutData(hDevice, 02428 (ADMW1001_LUT *)pLutData); 02429 } 02430 02431 static ADMW_RESULT getLutTableSize( 02432 ADMW1001_LUT_DESCRIPTOR * const pDesc, 02433 ADMW1001_LUT_TABLE_DATA * const pData, 02434 unsigned *pLength) 02435 { 02436 switch (pDesc->geometry) { 02437 case ADMW1001_LUT_GEOMETRY_COEFFS: 02438 if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN) 02439 *pLength = ADMW1001_LUT_2D_POLYN_COEFF_LIST_SIZE(pData->coeffList2d); 02440 else 02441 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList); 02442 break; 02443 case ADMW1001_LUT_GEOMETRY_NES_1D: 02444 *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes); 02445 break; 02446 case ADMW1001_LUT_GEOMETRY_NES_2D: 02447 *pLength = ADMW1001_LUT_2D_NES_SIZE(pData->lut2dNes); 02448 break; 02449 case ADMW1001_LUT_GEOMETRY_ES_1D: 02450 *pLength = ADMW1001_LUT_1D_ES_SIZE(pData->lut1dEs); 02451 break; 02452 case ADMW1001_LUT_GEOMETRY_ES_2D: 02453 *pLength = ADMW1001_LUT_2D_ES_SIZE(pData->lut2dEs); 02454 break; 02455 default: 02456 ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n", 02457 pDesc->geometry); 02458 return ADMW_INVALID_PARAM ; 02459 } 02460 02461 return ADMW_SUCCESS ; 02462 } 02463 02464 ADMW_RESULT admw1001_AssembleLutData( 02465 ADMW1001_LUT * pLutBuffer, 02466 unsigned nLutBufferSize, 02467 unsigned const nNumTables, 02468 ADMW1001_LUT_DESCRIPTOR * const ppDesc[], 02469 ADMW1001_LUT_TABLE_DATA * const ppData[]) 02470 { 02471 ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header; 02472 uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr); 02473 02474 if (sizeof(*pHdr) > nLutBufferSize) { 02475 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02476 return ADMW_INVALID_PARAM ; 02477 } 02478 02479 /* First initialise the top-level header */ 02480 pHdr->signature = ADMW_LUT_SIGNATURE; 02481 pHdr->version.major = 1; 02482 pHdr->version.minor = 0; 02483 pHdr->numTables = 0; 02484 pHdr->totalLength = 0; 02485 02486 /* 02487 * Walk through the list of table pointers provided, appending the table 02488 * descriptor+data from each one to the provided LUT buffer 02489 */ 02490 for (unsigned i = 0; i < nNumTables; i++) { 02491 ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i]; 02492 ADMW1001_LUT_TABLE_DATA * const pData = ppData[i]; 02493 ADMW_RESULT res; 02494 unsigned dataLength = 0; 02495 02496 /* Calculate the length of the table data */ 02497 res = getLutTableSize(pDesc, pData, &dataLength); 02498 if (res != ADMW_SUCCESS ) 02499 return res; 02500 02501 /* Fill in the table descriptor length and CRC fields */ 02502 pDesc->length = dataLength; 02503 pDesc->crc16 = admw_crc16_ccitt(pData, dataLength); 02504 02505 if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) { 02506 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02507 return ADMW_INVALID_PARAM ; 02508 } 02509 02510 /* Append the table to the LUT buffer (desc + data) */ 02511 memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc)); 02512 pHdr->totalLength += sizeof(*pDesc); 02513 memcpy(pLutTableData + pHdr->totalLength, pData, dataLength); 02514 pHdr->totalLength += dataLength; 02515 02516 pHdr->numTables++; 02517 } 02518 02519 return ADMW_SUCCESS ; 02520 } 02521 02522 ADMW_RESULT deviceInformation(ADMW_DEVICE_HANDLE hDevice) 02523 { 02524 uint16_t nAddress = REG_CORE_REVISION; 02525 char nData[ADMW_VERSION_REG_VAL_SIZE]; //4 Bytes of version register data 02526 ADMW_RESULT res; 02527 res=admw1001_ReadRegister(hDevice,nAddress,nData,sizeof(nData)); 02528 if(res != ADMW_SUCCESS ) { 02529 //if reading version register failed, sending 00.00.0000 as ADMW1001 firmware version 02530 //strcat(nData, ADMW1001_FIRMWARE_VERSION_DEFAULT); 02531 ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]); 02532 } else { 02533 char buffer[ADMW_FORMATTED_VERSION_SIZE]; //00.00.0000 8 digits + 2 Bytes "." + one null character at the end 02534 strcat(nData, buffer); 02535 ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]); 02536 } 02537 return ADMW_SUCCESS ; 02538 } 02539 02540 ADMW_RESULT admw1001_getFirmwareStatus( 02541 ADMW_DEVICE_HANDLE const hDevice, 02542 bool * const bFirmwareStatus) 02543 { 02544 bool bitCommand; 02545 ADMW_RESULT eRet; 02546 uint8_t pinreg = 0x1; 02547 02548 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 02549 static uint8_t DataBuffer[SPI_BUFFER_SIZE] = {0}; 02550 uint16_t nSize; 02551 02552 //Construct Read Status command 02553 DataBuffer[0] = 0x07; 02554 DataBuffer[1] = 0x0E; //Packet ID 02555 02556 DataBuffer[2] = 0x00; 02557 DataBuffer[3] = 0x00; //Data words 02558 02559 DataBuffer[4] = 0x53; 02560 DataBuffer[5] = 0x00; //Command ID 02561 02562 DataBuffer[6] = 0x00; 02563 DataBuffer[7] = 0x00; 02564 DataBuffer[8] = 0x00; 02565 DataBuffer[9] = 0x00; //Address 02566 02567 DataBuffer[10] = 0x53; 02568 DataBuffer[11] = 0x00; 02569 DataBuffer[12] = 0x00; 02570 DataBuffer[13] = 0x00; //Checksum 02571 02572 nSize = SFL_READ_STATUS_HDR_SIZE; 02573 02574 do { 02575 // Get the SFL command irq pin to check if SFL is ready to receive commands 02576 // Status pin is not checked since SFL is just booted, there should not be any issue with SFL 02577 eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand ); 02578 if( eRet != ADMW_SUCCESS ) { 02579 return eRet; 02580 } 02581 02582 // Command IRQ pin should be low and Status IRQ pin should be high for SFL to be in good state and ready to recieve commands 02583 // pinreg == '0x00' - Error occured in SFL 02584 // pinreg == '0x01' - SFL is ready to recieve commands 02585 // pinreg == '0x02' - Error occured in handling any commands in SFL 02586 // pinreg == '0x03' - SFL not booted 02587 02588 pinreg = (bitCommand); 02589 02590 } while(pinreg != 0x0u); 02591 02592 eRet = admw_SpiTransfer(pCtx->hSpi, DataBuffer, NULL, 02593 nSize, false); 02594 if (eRet) { 02595 return eRet; 02596 } 02597 02598 //wait for command irq line to go low after sending read status header 02599 wait_ms( 100 ); 02600 02601 do { 02602 // Get the SFL command irq pin to check if SFL is ready to receive commands 02603 // Status pin is not checked since SFL is just booted, there should not be any issue with SFL 02604 eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand ); 02605 if( eRet != ADMW_SUCCESS ) { 02606 return eRet; 02607 } 02608 02609 // Command IRQ pin should be low and Status IRQ pin should be high for SFL to be in good state and ready to recieve commands 02610 // pinreg == '0x00' - Error occured in SFL 02611 // pinreg == '0x01' - SFL is ready to recieve commands 02612 // pinreg == '0x02' - Error occured in handling any commands in SFL 02613 // pinreg == '0x03' - SFL not booted 02614 02615 pinreg = (bitCommand); 02616 02617 } while(pinreg != 0x0u); 02618 02619 nSize = SFL_READ_STATUS_RESPONSE_SIZE; 02620 02621 eRet = admw_SpiReceive(pCtx->hSpi, NULL, DataBuffer, 02622 nSize, false); 02623 02624 if (eRet) { 02625 return eRet; 02626 } 02627 02628 //Verifying the application version from the response to check if firmware is present or not 02629 /* 02630 Flash Memory description 02631 ______________ 02632 | Secure | 0x0000 0000 02633 | Flashloader | 02634 |______________| 0x0000 3BFF 02635 | Security |------------------ 02636 | Page | 0x0000 3C00 02637 | | 02638 |______________| 0x0000 3FFF 02639 | |------------------ 02640 | App Info | 0x0000 4000 02641 | Page | 02642 |______________| 0x0000 4800 02643 | |------------------ 02644 | Application | 02645 | Image | Application resides only in this region 02646 |______________|------------------ 02647 | Reserved | 0x0003 FFF8 02648 | for | Reserved memory region 02649 | Signature | 0x0003 FFFF 02650 |______________|------------------ 02651 02652 Application version is stored in the App Info Page, the app version is updated in this region everytime the new application firmware is downloaded. 02653 Here we verify if Application version is present in the Read Status response 02654 If the app version bytes value is 0xFFFFFFFF then there is no firmware else there exist a firmware 02655 02656 Read Status Response: 02657 ____________________________________________________________________________________________________________________________________ 02658 | | | | | | 02659 |uint16_t nFlashLoaderVersion | uint16_t nStatus | uint32_t nApplicationVersion | uint32_t nApplicationHash[8] | uint16_t nChecksum | 02660 |_____________________________|__________________|______________________________|______________________________|_____________________| 02661 02662 */ 02663 02664 if( ((DataBuffer[4] == 0xFF) && 02665 (DataBuffer[5] == 0xFF) && 02666 (DataBuffer[6] == 0xFF) && 02667 (DataBuffer[7] == 0xFF)) || 02668 ((DataBuffer[4] == 0x00) && 02669 (DataBuffer[5] == 0x00) && 02670 (DataBuffer[6] == 0x00) && 02671 (DataBuffer[7] == 0x00))) { 02672 *bFirmwareStatus = false; 02673 } else { 02674 *bFirmwareStatus = true; 02675 } 02676 02677 return eRet; 02678 }
Generated on Wed Jul 13 2022 03:04:54 by 1.7.2