Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
admw_1001.c
00001 /* 00002 Copyright 2019 (c) Analog Devices, Inc. 00003 00004 All rights reserved. 00005 00006 Redistribution and use in source and binary forms, with or without 00007 modification, are permitted provided that the following conditions are met: 00008 - Redistributions of source code must retain the above copyright 00009 notice, this list of conditions and the following disclaimer. 00010 - Redistributions in binary form must reproduce the above copyright 00011 notice, this list of conditions and the following disclaimer in 00012 the documentation and/or other materials provided with the 00013 distribution. 00014 - Neither the name of Analog Devices, Inc. nor the names of its 00015 contributors may be used to endorse or promote products derived 00016 from this software without specific prior written permission. 00017 - The use of this software may or may not infringe the patent rights 00018 of one or more patent holders. This license does not release you 00019 from the requirement that you obtain separate licenses from these 00020 patent holders to use this software. 00021 - Use of the software either in source or binary form, must be run 00022 on or directly connected to an Analog Devices Inc. component. 00023 00024 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR 00025 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, 00026 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00027 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00029 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 */ 00035 00036 /*! 00037 ****************************************************************************** 00038 * @file: 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_SetRSenseValue( 00995 ADMW_DEVICE_HANDLE hDevice, 00996 float32_t RSenseValue) 00997 { 00998 ADMW_CORE_External_Reference_Resistor_t RefResistorConfigReg; 00999 01000 RefResistorConfigReg.Ext_Refin1_Value = RSenseValue; 01001 01002 WRITE_REG_FLOAT(hDevice, RefResistorConfigReg.VALUE32, CORE_EXTERNAL_REFERENCE_RESISTOR); 01003 01004 return ADMW_SUCCESS ; 01005 01006 } 01007 01008 static ADMW_RESULT admw_SetMode( 01009 ADMW_DEVICE_HANDLE hDevice, 01010 ADMW1001_OPERATING_MODE eOperatingMode, 01011 ADMW1001_DATAREADY_MODE eDataReadyMode) 01012 { 01013 ADMW_CORE_Mode_t modeReg; 01014 01015 modeReg.VALUE8 = REG_RESET_VAL(CORE_MODE); 01016 01017 if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) { 01018 modeReg.Conversion_Mode = CORE_MODE_SINGLECYCLE; 01019 } else if (eOperatingMode == ADMW1001_OPERATING_MODE_CONTINUOUS ) { 01020 modeReg.Conversion_Mode = CORE_MODE_CONTINUOUS; 01021 } else { 01022 ADMW_LOG_ERROR("Invalid operating mode %d specified", 01023 eOperatingMode); 01024 return ADMW_INVALID_PARAM ; 01025 } 01026 01027 if (eDataReadyMode == ADMW1001_DATAREADY_PER_CONVERSION ) { 01028 modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CONVERSION; 01029 } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_CYCLE ) { 01030 modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CYCLE; 01031 } else { 01032 ADMW_LOG_ERROR("Invalid data-ready mode %d specified", eDataReadyMode); 01033 return ADMW_INVALID_PARAM ; 01034 } 01035 01036 WRITE_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE); 01037 01038 return ADMW_SUCCESS ; 01039 } 01040 01041 ADMW_RESULT admw_SetCycleControl(ADMW_DEVICE_HANDLE hDevice, 01042 uint32_t nCycleInterval, 01043 bool vBiasEnable) 01044 { 01045 ADMW_CORE_Cycle_Control_t cycleControlReg; 01046 01047 cycleControlReg.VALUE16 = REG_RESET_VAL(CORE_CYCLE_CONTROL); 01048 01049 if (nCycleInterval < (1000 * (1 << 12))) { 01050 cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_MILLISECONDS; 01051 nCycleInterval /= 1000; 01052 } else { 01053 cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_SECONDS; 01054 nCycleInterval /= 1000000; 01055 } 01056 01057 if (vBiasEnable == true) { 01058 cycleControlReg.Vbias = 1; 01059 } 01060 CHECK_REG_FIELD_VAL(CORE_CYCLE_CONTROL_CYCLE_TIME, nCycleInterval); 01061 cycleControlReg.Cycle_Time = nCycleInterval; 01062 01063 WRITE_REG_U16(hDevice, cycleControlReg.VALUE16, CORE_CYCLE_CONTROL); 01064 01065 return ADMW_SUCCESS ; 01066 } 01067 01068 static ADMW_RESULT admw_SetExternalReferenceValues( 01069 ADMW_DEVICE_HANDLE hDevice, 01070 float32_t externalRef1Value) 01071 { 01072 WRITE_REG_FLOAT(hDevice, externalRef1Value, CORE_EXTERNAL_REFERENCE_RESISTOR); 01073 01074 return ADMW_SUCCESS ; 01075 } 01076 01077 ADMW_RESULT admw1001_SetMeasurementConfig( 01078 ADMW_DEVICE_HANDLE hDevice, 01079 ADMW1001_MEASUREMENT_CONFIG *pMeasConfig) 01080 { 01081 ADMW_RESULT eRet; 01082 01083 eRet = admw_SetMode(hDevice, 01084 pMeasConfig->operatingMode , 01085 pMeasConfig->dataReadyMode ); 01086 if (eRet != ADMW_SUCCESS ) { 01087 ADMW_LOG_ERROR("Failed to set operating mode"); 01088 return eRet; 01089 } 01090 01091 eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval , 01092 pMeasConfig->vBiasEnable ); 01093 if (eRet != ADMW_SUCCESS ) { 01094 ADMW_LOG_ERROR("Failed to set cycle control"); 01095 return eRet; 01096 } 01097 01098 if(pMeasConfig->externalRef1Value >0) { 01099 eRet = admw_SetExternalReferenceValues(hDevice, 01100 pMeasConfig->externalRef1Value ); 01101 } 01102 01103 if (eRet != ADMW_SUCCESS ) { 01104 ADMW_LOG_ERROR("Failed to set external reference values"); 01105 return eRet; 01106 } 01107 01108 eRet = admw_SetRSenseValue(hDevice, pMeasConfig->RSenseValue ); 01109 if (eRet != ADMW_SUCCESS ) 01110 { 01111 ADMW_LOG_ERROR("Failed to set RSenseValue"); 01112 return eRet; 01113 } 01114 return ADMW_SUCCESS ; 01115 } 01116 01117 ADMW_RESULT admw1001_SetDiagnosticsConfig( 01118 ADMW_DEVICE_HANDLE hDevice, 01119 ADMW1001_DIAGNOSTICS_CONFIG *pDiagnosticsConfig) 01120 { 01121 ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg; 01122 01123 diagnosticsControlReg.VALUE16 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL); 01124 01125 if (pDiagnosticsConfig->disableGlobalDiag ) 01126 diagnosticsControlReg.Diag_Global_En = 0; 01127 else 01128 diagnosticsControlReg.Diag_Global_En = 1; 01129 01130 if (pDiagnosticsConfig->disableMeasurementDiag ) 01131 diagnosticsControlReg.Diag_Meas_En = 0; 01132 else 01133 diagnosticsControlReg.Diag_Meas_En = 1; 01134 01135 switch (pDiagnosticsConfig->osdFrequency ) { 01136 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_DISABLED : 01137 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_OFF; 01138 break; 01139 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_CYCLE : 01140 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1_CYCLE; 01141 break; 01142 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_100_CYCLES : 01143 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_100_CYCLES; 01144 break; 01145 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_1000_CYCLES : 01146 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1000_CYCLES; 01147 break; 01148 default: 01149 ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified", 01150 pDiagnosticsConfig->osdFrequency ); 01151 return ADMW_INVALID_PARAM ; 01152 } 01153 01154 WRITE_REG_U16(hDevice, diagnosticsControlReg.VALUE16, CORE_DIAGNOSTICS_CONTROL); 01155 01156 return ADMW_SUCCESS ; 01157 } 01158 01159 ADMW_RESULT admw1001_SetChannelCount( 01160 ADMW_DEVICE_HANDLE hDevice, 01161 ADMW1001_CH_ID eChannelId, 01162 uint32_t nMeasurementsPerCycle) 01163 { 01164 ADMW_CORE_Channel_Count_t channelCountReg; 01165 01166 channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn); 01167 01168 if (nMeasurementsPerCycle > 0) { 01169 nMeasurementsPerCycle -= 1; 01170 01171 CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT, 01172 nMeasurementsPerCycle); 01173 01174 channelCountReg.Channel_Enable = 1; 01175 channelCountReg.Channel_Count = nMeasurementsPerCycle; 01176 } else { 01177 channelCountReg.Channel_Enable = 0; 01178 } 01179 01180 WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId)); 01181 01182 return ADMW_SUCCESS ; 01183 } 01184 01185 ADMW_RESULT admw1001_SetChannelOptions( 01186 ADMW_DEVICE_HANDLE hDevice, 01187 ADMW1001_CH_ID eChannelId, 01188 ADMW1001_CHANNEL_PRIORITY ePriority) 01189 { 01190 ADMW_CORE_Channel_Options_t channelOptionsReg; 01191 01192 channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn); 01193 01194 CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority); 01195 channelOptionsReg.Channel_Priority = ePriority; 01196 01197 WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId)); 01198 01199 return ADMW_SUCCESS ; 01200 } 01201 01202 ADMW_RESULT admw1001_SetChannelSkipCount( 01203 ADMW_DEVICE_HANDLE hDevice, 01204 ADMW1001_CH_ID eChannelId, 01205 uint32_t nCycleSkipCount) 01206 { 01207 ADMW_CORE_Channel_Skip_t channelSkipReg; 01208 01209 channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn); 01210 01211 CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount); 01212 01213 channelSkipReg.Channel_Skip = nCycleSkipCount; 01214 01215 WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId)); 01216 01217 return ADMW_SUCCESS ; 01218 } 01219 01220 static ADMW_RESULT admw_SetChannelAdcSensorType( 01221 ADMW_DEVICE_HANDLE hDevice, 01222 ADMW1001_CH_ID eChannelId, 01223 ADMW1001_ADC_SENSOR_TYPE sensorType) 01224 { 01225 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01226 01227 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01228 01229 /* Ensure that the sensor type is valid for this channel */ 01230 switch(sensorType) { 01231 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 : 01232 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 : 01233 case ADMW1001_ADC_SENSOR_RTD_3WIRE_1 : 01234 case ADMW1001_ADC_SENSOR_RTD_3WIRE_2 : 01235 case ADMW1001_ADC_SENSOR_RTD_3WIRE_3 : 01236 case ADMW1001_ADC_SENSOR_RTD_3WIRE_4 : 01237 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 : 01238 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 : 01239 case ADMW1001_ADC_SENSOR_RTD_4WIRE_1 : 01240 case ADMW1001_ADC_SENSOR_RTD_4WIRE_2 : 01241 case ADMW1001_ADC_SENSOR_RTD_4WIRE_3 : 01242 case ADMW1001_ADC_SENSOR_RTD_4WIRE_4 : 01243 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_1 : 01244 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_2 : 01245 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_3 : 01246 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_4 : 01247 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_1 : 01248 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_2 : 01249 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_3 : 01250 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_4 : 01251 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 : 01252 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 : 01253 case ADMW1001_ADC_SENSOR_RTD_2WIRE_1 : 01254 case ADMW1001_ADC_SENSOR_RTD_2WIRE_2 : 01255 case ADMW1001_ADC_SENSOR_RTD_2WIRE_3 : 01256 case ADMW1001_ADC_SENSOR_RTD_2WIRE_4 : 01257 case ADMW1001_ADC_SENSOR_DIODE_2C_TYPEA : 01258 case ADMW1001_ADC_SENSOR_DIODE_3C_TYPEA : 01259 case ADMW1001_ADC_SENSOR_DIODE_2C_1 : 01260 case ADMW1001_ADC_SENSOR_DIODE_3C_1 : 01261 case ADMW1001_ADC_SENSOR_THERMISTOR_A_10K : 01262 case ADMW1001_ADC_SENSOR_THERMISTOR_B_10K : 01263 case ADMW1001_ADC_SENSOR_THERMISTOR_1 : 01264 case ADMW1001_ADC_SENSOR_THERMISTOR_2 : 01265 case ADMW1001_ADC_SENSOR_THERMISTOR_3 : 01266 case ADMW1001_ADC_SENSOR_THERMISTOR_4 : 01267 if (! (ADMW1001_CHANNEL_IS_ADC_SENSOR(eChannelId) || 01268 ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId))) { 01269 ADMW_LOG_ERROR( 01270 "Invalid ADC sensor type %d specified for channel %d", 01271 sensorType, eChannelId); 01272 return ADMW_INVALID_PARAM ; 01273 } 01274 break; 01275 case ADMW1001_ADC_SENSOR_VOLTAGE : 01276 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_A : 01277 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_B : 01278 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_1 : 01279 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_2 : 01280 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J : 01281 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K : 01282 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T : 01283 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_1 : 01284 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_2 : 01285 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_3 : 01286 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_4 : 01287 if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) { 01288 ADMW_LOG_ERROR( 01289 "Invalid ADC sensor type %d specified for channel %d", 01290 sensorType, eChannelId); 01291 return ADMW_INVALID_PARAM ; 01292 } 01293 break; 01294 case ADMW1001_ADC_SENSOR_CURRENT : 01295 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_A : 01296 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_1 : 01297 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_2 : 01298 if (! ADMW1001_CHANNEL_IS_ADC_CURRENT(eChannelId)) { 01299 ADMW_LOG_ERROR( 01300 "Invalid ADC sensor type %d specified for channel %d", 01301 sensorType, eChannelId); 01302 return ADMW_INVALID_PARAM ; 01303 } 01304 break; 01305 default: 01306 ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified", 01307 sensorType); 01308 return ADMW_INVALID_PARAM ; 01309 } 01310 01311 sensorTypeReg.Sensor_Type = sensorType; 01312 01313 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01314 01315 return ADMW_SUCCESS ; 01316 } 01317 01318 static ADMW_RESULT admw_SetChannelAdcSensorDetails( 01319 ADMW_DEVICE_HANDLE hDevice, 01320 ADMW1001_CH_ID eChannelId, 01321 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01322 /* 01323 * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers 01324 * General details: 01325 * - Measurement_Units 01326 * - Compensation_Channel 01327 * - CJC_Publish (if "CJC" was removed from the name) 01328 * ADC-specific details: 01329 * - PGA_Gain 01330 * - Reference_Select 01331 * - Reference_Buffer_Disable 01332 */ 01333 { 01334 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ; 01335 ADMW1001_ADC_REFERENCE_TYPE refType = pAdcChannelConfig->reference; 01336 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01337 01338 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01339 01340 switch(pChannelConfig->measurementUnit ) { 01341 case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT : 01342 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF; 01343 break; 01344 case ADMW1001_MEASUREMENT_UNIT_CELSIUS : 01345 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC; 01346 break; 01347 case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED : 01348 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01349 break; 01350 default: 01351 ADMW_LOG_ERROR("Invalid measurement unit %d specified", 01352 pChannelConfig->measurementUnit ); 01353 return ADMW_INVALID_PARAM ; 01354 } 01355 01356 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01357 sensorDetailsReg.Compensation_Disable = 1; 01358 sensorDetailsReg.Compensation_Channel = 0; 01359 } else { 01360 sensorDetailsReg.Compensation_Disable = 0; 01361 sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ; 01362 } 01363 01364 switch(refType) { 01365 case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL : 01366 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT; 01367 break; 01368 case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 : 01369 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1; 01370 break; 01371 case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD : 01372 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD; 01373 break; 01374 default: 01375 ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType); 01376 return ADMW_INVALID_PARAM ; 01377 } 01378 01379 switch(pAdcChannelConfig->gain ) { 01380 case ADMW1001_ADC_GAIN_1X : 01381 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1; 01382 break; 01383 case ADMW1001_ADC_GAIN_2X : 01384 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2; 01385 break; 01386 case ADMW1001_ADC_GAIN_4X : 01387 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4; 01388 break; 01389 case ADMW1001_ADC_GAIN_8X : 01390 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8; 01391 break; 01392 case ADMW1001_ADC_GAIN_16X : 01393 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16; 01394 break; 01395 case ADMW1001_ADC_GAIN_32X : 01396 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32; 01397 break; 01398 case ADMW1001_ADC_GAIN_64X : 01399 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64; 01400 break; 01401 case ADMW1001_ADC_GAIN_128X : 01402 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128; 01403 break; 01404 default: 01405 ADMW_LOG_ERROR("Invalid ADC gain %d specified", 01406 pAdcChannelConfig->gain ); 01407 return ADMW_INVALID_PARAM ; 01408 } 01409 01410 switch(pAdcChannelConfig->rtdCurve ) { 01411 case ADMW1001_ADC_RTD_CURVE_EUROPEAN : 01412 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE; 01413 break; 01414 case ADMW1001_ADC_RTD_CURVE_AMERICAN : 01415 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE; 01416 break; 01417 case ADMW1001_ADC_RTD_CURVE_JAPANESE : 01418 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE; 01419 break; 01420 case ADMW1001_ADC_RTD_CURVE_ITS90 : 01421 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE; 01422 break; 01423 default: 01424 ADMW_LOG_ERROR("Invalid RTD Curve %d specified", 01425 pAdcChannelConfig->rtdCurve ); 01426 return ADMW_INVALID_PARAM ; 01427 } 01428 01429 if (pChannelConfig->disablePublishing ) { 01430 sensorDetailsReg.Do_Not_Publish = 1; 01431 } else { 01432 sensorDetailsReg.Do_Not_Publish = 0; 01433 } 01434 01435 switch (pChannelConfig->lutSelect ) { 01436 case ADMW1001_LUT_DEFAULT : 01437 case ADMW1001_LUT_UNITY : 01438 case ADMW1001_LUT_CUSTOM : 01439 sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ; 01440 break; 01441 default: 01442 ADMW_LOG_ERROR("Invalid LUT selection %d specified", 01443 pChannelConfig->lutSelect ); 01444 return ADMW_INVALID_PARAM ; 01445 } 01446 01447 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01448 01449 return ADMW_SUCCESS ; 01450 } 01451 01452 static ADMW_RESULT admw_SetChannelAdcMeasurementSetup( 01453 ADMW_DEVICE_HANDLE hDevice, 01454 ADMW1001_CH_ID eChannelId, 01455 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig) 01456 { 01457 ADMW_CORE_Measurement_Setup_t MeasSetupReg; 01458 ADMW1001_ADC_FILTER_CONFIG *pFilterConfig = &pAdcChannelConfig->filter ; 01459 MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn); 01460 01461 MeasSetupReg.PST_MEAS_EXC_CTRL = pAdcChannelConfig->current .excitationState ; 01462 MeasSetupReg.Buffer_Bypass = pAdcChannelConfig->bufferBypass ; 01463 01464 if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC4 ) { 01465 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4; 01466 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01467 } else if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC3 ) { 01468 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3; 01469 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01470 } else { 01471 ADMW_LOG_ERROR("Invalid ADC filter type %d specified", 01472 pFilterConfig->type ); 01473 return ADMW_INVALID_PARAM ; 01474 } 01475 01476 /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */ 01477 MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ; 01478 01479 if(pFilterConfig->notch1p2 ) 01480 MeasSetupReg.NOTCH_EN_2 = 1; 01481 else 01482 MeasSetupReg.NOTCH_EN_2 = 0; 01483 01484 switch(pFilterConfig->groundSwitch ) { 01485 case ADMW1001_ADC_GND_SW_OPEN : 01486 MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_OPEN; 01487 break; 01488 case ADMW1001_ADC_GND_SW_CLOSED : 01489 MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_CLOSED; 01490 break; 01491 default: 01492 ADMW_LOG_ERROR("Invalid ground switch state %d specified", 01493 pFilterConfig->groundSwitch ); 01494 return ADMW_INVALID_PARAM ; 01495 } 01496 01497 WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId)); 01498 01499 return ADMW_SUCCESS ; 01500 } 01501 01502 static ADMW_RESULT admw_SetChannelAdcCurrentConfig( 01503 ADMW_DEVICE_HANDLE hDevice, 01504 ADMW1001_CH_ID eChannelId, 01505 ADMW1001_ADC_EXC_CURRENT_CONFIG *pCurrentConfig) 01506 { 01507 ADMW_CORE_Channel_Excitation_t channelExcitationReg; 01508 01509 channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn); 01510 01511 if (pCurrentConfig->outputLevel == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT ) 01512 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE; 01513 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_EXTERNAL ) 01514 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL; 01515 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_50uA ) 01516 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA; 01517 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_100uA ) 01518 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA; 01519 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_250uA ) 01520 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA; 01521 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_500uA ) 01522 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA; 01523 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_1000uA ) 01524 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA; 01525 else { 01526 ADMW_LOG_ERROR("Invalid ADC excitation current %d specified", 01527 pCurrentConfig->outputLevel ); 01528 return ADMW_INVALID_PARAM ; 01529 } 01530 01531 01532 01533 switch(pCurrentConfig->diodeRatio ) { 01534 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_100UA: 01535 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_10UA_100UA; 01536 break; 01537 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_160UA: 01538 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_20UA_160UA; 01539 break; 01540 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_300UA: 01541 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_50UA_300UA; 01542 break; 01543 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_600UA: 01544 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_100UA_600UA; 01545 break; 01546 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_50UA_100UA: 01547 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_10UA_50UA_100UA; 01548 break; 01549 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_100UA_160UA: 01550 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_20UA_100UA_160UA; 01551 break; 01552 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_150UA_300UA: 01553 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_50UA_150UA_300UA; 01554 break; 01555 case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_300UA_600UA: 01556 channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_100UA_300UA_600UA; 01557 break; 01558 default: 01559 ADMW_LOG_ERROR("Invalid diode ratio %d specified", 01560 pCurrentConfig->diodeRatio ); 01561 return ADMW_INVALID_PARAM ; 01562 } 01563 01564 WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId)); 01565 01566 return ADMW_SUCCESS ; 01567 } 01568 01569 ADMW_RESULT admw_SetAdcChannelConfig( 01570 ADMW_DEVICE_HANDLE hDevice, 01571 ADMW1001_CH_ID eChannelId, 01572 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01573 { 01574 ADMW_RESULT eRet; 01575 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = 01576 &pChannelConfig->adcChannelConfig ; 01577 01578 eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId, 01579 pAdcChannelConfig->sensor ); 01580 if (eRet != ADMW_SUCCESS ) { 01581 ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d", 01582 eChannelId); 01583 return eRet; 01584 } 01585 01586 eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId, 01587 pChannelConfig); 01588 if (eRet != ADMW_SUCCESS ) { 01589 ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d", 01590 eChannelId); 01591 return eRet; 01592 } 01593 01594 eRet = admw_SetChannelAdcMeasurementSetup(hDevice, eChannelId, 01595 pAdcChannelConfig); 01596 if (eRet != ADMW_SUCCESS ) { 01597 ADMW_LOG_ERROR("Failed to set ADC filter for channel %d", 01598 eChannelId); 01599 return eRet; 01600 } 01601 01602 eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId, 01603 &pAdcChannelConfig->current ); 01604 if (eRet != ADMW_SUCCESS ) { 01605 ADMW_LOG_ERROR("Failed to set ADC current for channel %d", 01606 eChannelId); 01607 return eRet; 01608 } 01609 01610 return ADMW_SUCCESS ; 01611 } 01612 01613 static ADMW_RESULT admw_SetChannelDigitalSensorDetails( 01614 ADMW_DEVICE_HANDLE hDevice, 01615 ADMW1001_CH_ID eChannelId, 01616 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01617 { 01618 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01619 01620 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01621 01622 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01623 sensorDetailsReg.Compensation_Disable = 1; 01624 sensorDetailsReg.Compensation_Channel = 0; 01625 } else { 01626 ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor"); 01627 return ADMW_INVALID_PARAM ; 01628 } 01629 01630 if (pChannelConfig->measurementUnit == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) { 01631 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01632 } else { 01633 ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel"); 01634 return ADMW_INVALID_PARAM ; 01635 } 01636 01637 if (pChannelConfig->disablePublishing ) 01638 sensorDetailsReg.Do_Not_Publish = 1; 01639 else 01640 sensorDetailsReg.Do_Not_Publish = 0; 01641 01642 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01643 01644 return ADMW_SUCCESS ; 01645 } 01646 01647 static ADMW_RESULT admw_SetDigitalSensorCommands( 01648 ADMW_DEVICE_HANDLE hDevice, 01649 ADMW1001_CH_ID eChannelId, 01650 ADMW1001_DIGITAL_SENSOR_COMMAND *pConfigCommand, 01651 ADMW1001_DIGITAL_SENSOR_COMMAND *pDataRequestCommand) 01652 { 01653 ADMW_CORE_Digital_Sensor_Num_Cmds_t numCmdsReg; 01654 01655 numCmdsReg.VALUE8 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_NUM_CMDSn); 01656 01657 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_CFG_CMDS, 01658 pConfigCommand->commandLength ); 01659 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_READ_CMDS, 01660 pDataRequestCommand->commandLength ); 01661 01662 numCmdsReg.Digital_Sensor_Num_Cfg_Cmds = pConfigCommand->commandLength ; 01663 numCmdsReg.Digital_Sensor_Num_Read_Cmds = pDataRequestCommand->commandLength ; 01664 01665 WRITE_REG_U8(hDevice, numCmdsReg.VALUE8, 01666 CORE_DIGITAL_SENSOR_NUM_CMDSn(eChannelId)); 01667 01668 /* 01669 * NOTE - the fall-through cases in the switch statement below are 01670 * intentional. 01671 */ 01672 switch (pConfigCommand->commandLength ) { 01673 case 7: 01674 WRITE_REG_U8(hDevice, pConfigCommand->command [6], 01675 CORE_DIGITAL_SENSOR_COMMAND7n(eChannelId)); 01676 case 6: 01677 WRITE_REG_U8(hDevice, pConfigCommand->command [5], 01678 CORE_DIGITAL_SENSOR_COMMAND6n(eChannelId)); 01679 case 5: 01680 WRITE_REG_U8(hDevice, pConfigCommand->command [4], 01681 CORE_DIGITAL_SENSOR_COMMAND5n(eChannelId)); 01682 case 4: 01683 WRITE_REG_U8(hDevice, pConfigCommand->command [3], 01684 CORE_DIGITAL_SENSOR_COMMAND4n(eChannelId)); 01685 case 3: 01686 WRITE_REG_U8(hDevice, pConfigCommand->command [2], 01687 CORE_DIGITAL_SENSOR_COMMAND3n(eChannelId)); 01688 case 2: 01689 WRITE_REG_U8(hDevice, pConfigCommand->command [1], 01690 CORE_DIGITAL_SENSOR_COMMAND2n(eChannelId)); 01691 case 1: 01692 WRITE_REG_U8(hDevice, pConfigCommand->command [0], 01693 CORE_DIGITAL_SENSOR_COMMAND1n(eChannelId)); 01694 case 0: 01695 default: 01696 break; 01697 }; 01698 01699 switch (pDataRequestCommand->commandLength ) { 01700 case 7: 01701 WRITE_REG_U8(hDevice, pDataRequestCommand->command [6], 01702 CORE_DIGITAL_SENSOR_READ_CMD7n(eChannelId)); 01703 case 6: 01704 WRITE_REG_U8(hDevice, pDataRequestCommand->command [5], 01705 CORE_DIGITAL_SENSOR_READ_CMD6n(eChannelId)); 01706 case 5: 01707 WRITE_REG_U8(hDevice, pDataRequestCommand->command [4], 01708 CORE_DIGITAL_SENSOR_READ_CMD5n(eChannelId)); 01709 case 4: 01710 WRITE_REG_U8(hDevice, pDataRequestCommand->command [3], 01711 CORE_DIGITAL_SENSOR_READ_CMD4n(eChannelId)); 01712 case 3: 01713 WRITE_REG_U8(hDevice, pDataRequestCommand->command [2], 01714 CORE_DIGITAL_SENSOR_READ_CMD3n(eChannelId)); 01715 case 2: 01716 WRITE_REG_U8(hDevice, pDataRequestCommand->command [1], 01717 CORE_DIGITAL_SENSOR_READ_CMD2n(eChannelId)); 01718 case 1: 01719 WRITE_REG_U8(hDevice, pDataRequestCommand->command [0], 01720 CORE_DIGITAL_SENSOR_READ_CMD1n(eChannelId)); 01721 case 0: 01722 default: 01723 break; 01724 }; 01725 01726 return ADMW_SUCCESS ; 01727 } 01728 01729 static ADMW_RESULT admw_SetDigitalSensorFormat( 01730 ADMW_DEVICE_HANDLE hDevice, 01731 ADMW1001_CH_ID eChannelId, 01732 ADMW1001_DIGITAL_SENSOR_DATA_FORMAT *pDataFormat) 01733 { 01734 ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg; 01735 01736 sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn); 01737 01738 if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) { 01739 if (pDataFormat->frameLength == 0) { 01740 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01741 return ADMW_INVALID_PARAM ; 01742 } 01743 if (pDataFormat->numDataBits == 0) { 01744 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01745 return ADMW_INVALID_PARAM ; 01746 } 01747 01748 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES, 01749 pDataFormat->frameLength - 1); 01750 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS, 01751 pDataFormat->numDataBits - 1); 01752 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET, 01753 pDataFormat->bitOffset); 01754 01755 sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1; 01756 sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1; 01757 sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset; 01758 sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0; 01759 sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0; 01760 01761 switch (pDataFormat->coding) { 01762 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR: 01763 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR; 01764 break; 01765 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT: 01766 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL; 01767 break; 01768 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY: 01769 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY; 01770 break; 01771 default: 01772 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format"); 01773 return ADMW_INVALID_PARAM ; 01774 } 01775 } else { 01776 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE; 01777 } 01778 01779 WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16, 01780 CORE_DIGITAL_SENSOR_CONFIGn(eChannelId)); 01781 01782 01783 return ADMW_SUCCESS ; 01784 } 01785 01786 static ADMW_RESULT admw_SetDigitalCalibrationParam( 01787 ADMW_DEVICE_HANDLE hDevice, 01788 ADMW1001_CH_ID eChannelId, 01789 ADMW1001_DIGITAL_CALIBRATION_COMMAND *pCalibrationParam) 01790 { 01791 ADMW_CORE_Calibration_Parameter_t calibrationParamReg; 01792 01793 calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn); 01794 01795 if (pCalibrationParam->enableCalibrationParam == false) 01796 calibrationParamReg.Calibration_Parameter_Enable = 0; 01797 else 01798 calibrationParamReg.Calibration_Parameter_Enable = 1; 01799 01800 CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER, 01801 pCalibrationParam->calibrationParam ); 01802 01803 calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam ; 01804 01805 WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32, 01806 CORE_CALIBRATION_PARAMETERn(eChannelId)); 01807 01808 return ADMW_SUCCESS ; 01809 } 01810 01811 static ADMW_RESULT admw_SetChannelI2cSensorType( 01812 ADMW_DEVICE_HANDLE hDevice, 01813 ADMW1001_CH_ID eChannelId, 01814 ADMW1001_I2C_SENSOR_TYPE sensorType) 01815 { 01816 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01817 01818 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01819 01820 /* Ensure that the sensor type is valid for this channel */ 01821 switch(sensorType) { 01822 case ADMW1001_I2C_SENSOR_HUMIDITY_A : 01823 case ADMW1001_I2C_SENSOR_HUMIDITY_B : 01824 sensorTypeReg.Sensor_Type = sensorType; 01825 break; 01826 default: 01827 ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType); 01828 return ADMW_INVALID_PARAM ; 01829 } 01830 01831 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01832 01833 return ADMW_SUCCESS ; 01834 } 01835 01836 static ADMW_RESULT admw_SetChannelI2cSensorAddress( 01837 ADMW_DEVICE_HANDLE hDevice, 01838 ADMW1001_CH_ID eChannelId, 01839 uint32_t deviceAddress) 01840 { 01841 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress); 01842 WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId)); 01843 01844 return ADMW_SUCCESS ; 01845 } 01846 01847 static ADMW_RESULT admw_SetDigitalChannelComms( 01848 ADMW_DEVICE_HANDLE hDevice, 01849 ADMW1001_CH_ID eChannelId, 01850 ADMW1001_DIGITAL_SENSOR_COMMS *pDigitalComms) 01851 { 01852 ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms; 01853 01854 digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn); 01855 01856 if(pDigitalComms->useCustomCommsConfig ) { 01857 digitalSensorComms.Digital_Sensor_Comms_En = 1; 01858 01859 if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) { 01860 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K; 01861 } else if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) { 01862 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K; 01863 } else { 01864 ADMW_LOG_ERROR("Invalid I2C clock speed %d specified", 01865 pDigitalComms->i2cClockSpeed ); 01866 return ADMW_INVALID_PARAM ; 01867 } 01868 01869 if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) { 01870 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0; 01871 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) { 01872 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1; 01873 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) { 01874 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2; 01875 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) { 01876 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3; 01877 } else { 01878 ADMW_LOG_ERROR("Invalid SPI mode %d specified", 01879 pDigitalComms->spiMode ); 01880 return ADMW_INVALID_PARAM ; 01881 } 01882 01883 switch (pDigitalComms->spiClock ) { 01884 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ : 01885 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ; 01886 break; 01887 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ : 01888 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ; 01889 break; 01890 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ : 01891 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ; 01892 break; 01893 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ : 01894 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ; 01895 break; 01896 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ : 01897 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ; 01898 break; 01899 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ : 01900 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ; 01901 break; 01902 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ : 01903 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ; 01904 break; 01905 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ : 01906 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ; 01907 break; 01908 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ : 01909 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ; 01910 break; 01911 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ : 01912 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ; 01913 break; 01914 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ : 01915 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ; 01916 break; 01917 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ : 01918 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ; 01919 break; 01920 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ : 01921 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ; 01922 break; 01923 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ : 01924 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ; 01925 break; 01926 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ : 01927 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ; 01928 break; 01929 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ : 01930 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ; 01931 break; 01932 default: 01933 ADMW_LOG_ERROR("Invalid SPI clock %d specified", 01934 pDigitalComms->spiClock ); 01935 return ADMW_INVALID_PARAM ; 01936 } 01937 } else { 01938 digitalSensorComms.Digital_Sensor_Comms_En = 0; 01939 } 01940 01941 WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId)); 01942 01943 return ADMW_SUCCESS ; 01944 } 01945 01946 ADMW_RESULT admw_SetI2cChannelConfig( 01947 ADMW_DEVICE_HANDLE hDevice, 01948 ADMW1001_CH_ID eChannelId, 01949 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01950 { 01951 ADMW_RESULT eRet; 01952 ADMW1001_I2C_CHANNEL_CONFIG *pI2cChannelConfig = 01953 &pChannelConfig->i2cChannelConfig ; 01954 01955 eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId, 01956 pI2cChannelConfig->sensor ); 01957 if (eRet != ADMW_SUCCESS ) { 01958 ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d", 01959 eChannelId); 01960 return eRet; 01961 } 01962 01963 eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId, 01964 pI2cChannelConfig->deviceAddress ); 01965 if (eRet != ADMW_SUCCESS ) { 01966 ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d", 01967 eChannelId); 01968 return eRet; 01969 } 01970 01971 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 01972 pChannelConfig); 01973 if (eRet != ADMW_SUCCESS ) { 01974 ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d", 01975 eChannelId); 01976 return eRet; 01977 } 01978 01979 eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId, 01980 &pI2cChannelConfig->configurationCommand , 01981 &pI2cChannelConfig->dataRequestCommand ); 01982 if (eRet != ADMW_SUCCESS ) { 01983 ADMW_LOG_ERROR("Failed to set I2C sensor commands for channel %d", 01984 eChannelId); 01985 return eRet; 01986 } 01987 01988 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 01989 &pI2cChannelConfig->dataFormat ); 01990 if (eRet != ADMW_SUCCESS ) { 01991 ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d", 01992 eChannelId); 01993 return eRet; 01994 } 01995 01996 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 01997 &pI2cChannelConfig->digitalCalibrationParam ); 01998 if (eRet != ADMW_SUCCESS ) { 01999 ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d", 02000 eChannelId); 02001 return eRet; 02002 } 02003 02004 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 02005 &pI2cChannelConfig->configureComms ); 02006 if (eRet != ADMW_SUCCESS ) { 02007 ADMW_LOG_ERROR("Failed to set I2C comms for channel %d", 02008 eChannelId); 02009 return eRet; 02010 } 02011 02012 return ADMW_SUCCESS ; 02013 } 02014 02015 static ADMW_RESULT admw_SetChannelSpiSensorType( 02016 ADMW_DEVICE_HANDLE hDevice, 02017 ADMW1001_CH_ID eChannelId, 02018 ADMW1001_SPI_SENSOR_TYPE sensorType) 02019 { 02020 ADMW_CORE_Sensor_Type_t sensorTypeReg; 02021 02022 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 02023 02024 /* Ensure that the sensor type is valid for this channel */ 02025 switch(sensorType) { 02026 case ADMW1001_SPI_SENSOR_PRESSURE_A : 02027 case ADMW1001_SPI_SENSOR_ACCELEROMETER_A : 02028 case ADMW1001_SPI_SENSOR_ACCELEROMETER_B : 02029 02030 sensorTypeReg.Sensor_Type = sensorType; 02031 break; 02032 default: 02033 ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType); 02034 return ADMW_INVALID_PARAM ; 02035 } 02036 02037 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 02038 02039 return ADMW_SUCCESS ; 02040 } 02041 02042 ADMW_RESULT admw_SetSpiChannelConfig( 02043 ADMW_DEVICE_HANDLE hDevice, 02044 ADMW1001_CH_ID eChannelId, 02045 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 02046 { 02047 ADMW_RESULT eRet; 02048 ADMW1001_SPI_CHANNEL_CONFIG *pSpiChannelConfig = 02049 &pChannelConfig->spiChannelConfig ; 02050 02051 eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId, 02052 pSpiChannelConfig->sensor ); 02053 if (eRet != ADMW_SUCCESS ) { 02054 ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d", 02055 eChannelId); 02056 return eRet; 02057 } 02058 02059 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 02060 pChannelConfig); 02061 if (eRet != ADMW_SUCCESS ) { 02062 ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d", 02063 eChannelId); 02064 return eRet; 02065 } 02066 02067 eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId, 02068 &pSpiChannelConfig->configurationCommand , 02069 &pSpiChannelConfig->dataRequestCommand ); 02070 if (eRet != ADMW_SUCCESS ) { 02071 ADMW_LOG_ERROR("Failed to set SPI sensor commands for channel %d", 02072 eChannelId); 02073 return eRet; 02074 } 02075 02076 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 02077 &pSpiChannelConfig->dataFormat ); 02078 if (eRet != ADMW_SUCCESS ) { 02079 ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d", 02080 eChannelId); 02081 return eRet; 02082 } 02083 02084 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 02085 &pSpiChannelConfig->digitalCalibrationParam ); 02086 if (eRet != ADMW_SUCCESS ) { 02087 ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d", 02088 eChannelId); 02089 return eRet; 02090 } 02091 02092 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 02093 &pSpiChannelConfig->configureComms ); 02094 if (eRet != ADMW_SUCCESS ) { 02095 ADMW_LOG_ERROR("Failed to set SPI comms for channel %d", 02096 eChannelId); 02097 return eRet; 02098 } 02099 02100 return ADMW_SUCCESS ; 02101 } 02102 02103 ADMW_RESULT admw1001_SetChannelThresholdLimits( 02104 ADMW_DEVICE_HANDLE hDevice, 02105 ADMW1001_CH_ID eChannelId, 02106 float32_t fHighThresholdLimit, 02107 float32_t fLowThresholdLimit) 02108 { 02109 /* 02110 * If the low/high limits are *both* set to 0 in memory, or NaNs, assume 02111 * that they are unset, or not required, and use infinity defaults instead 02112 */ 02113 if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) { 02114 fHighThresholdLimit = INFINITY; 02115 fLowThresholdLimit = -INFINITY; 02116 } else { 02117 if (isnan(fHighThresholdLimit)) 02118 fHighThresholdLimit = INFINITY; 02119 if (isnan(fLowThresholdLimit)) 02120 fLowThresholdLimit = -INFINITY; 02121 } 02122 02123 WRITE_REG_FLOAT(hDevice, fHighThresholdLimit, 02124 CORE_HIGH_THRESHOLD_LIMITn(eChannelId)); 02125 WRITE_REG_FLOAT(hDevice, fLowThresholdLimit, 02126 CORE_LOW_THRESHOLD_LIMITn(eChannelId)); 02127 02128 return ADMW_SUCCESS ; 02129 } 02130 02131 ADMW_RESULT admw1001_SetOffsetGain( 02132 ADMW_DEVICE_HANDLE hDevice, 02133 ADMW1001_CH_ID eChannelId, 02134 float32_t fOffsetAdjustment, 02135 float32_t fGainAdjustment) 02136 { 02137 /* Replace with default values if NaNs are specified (or 0.0 for gain) */ 02138 if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f)) 02139 fGainAdjustment = 1.0f; 02140 if (isnan(fOffsetAdjustment)) 02141 fOffsetAdjustment = 0.0f; 02142 02143 WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId)); 02144 WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId)); 02145 02146 return ADMW_SUCCESS ; 02147 } 02148 02149 ADMW_RESULT admw1001_SetSensorParameter( 02150 ADMW_DEVICE_HANDLE hDevice, 02151 ADMW1001_CH_ID eChannelId, 02152 float32_t fSensorParam) 02153 { 02154 if (fSensorParam == 0.0f) 02155 fSensorParam = NAN; 02156 02157 WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId)); 02158 02159 return ADMW_SUCCESS ; 02160 } 02161 02162 ADMW_RESULT admw1001_SetChannelSettlingTime( 02163 ADMW_DEVICE_HANDLE hDevice, 02164 ADMW1001_CH_ID eChannelId, 02165 uint32_t nSettlingTime) 02166 { 02167 ADMW_CORE_Settling_Time_t settlingTimeReg; 02168 02169 if (nSettlingTime < (1 << 12)) { 02170 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MICROSECONDS; 02171 } else if (nSettlingTime < (1000 * (1 << 12))) { 02172 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MILLISECONDS; 02173 nSettlingTime /= 1000; 02174 } else { 02175 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_SECONDS; 02176 nSettlingTime /= 1000000; 02177 } 02178 02179 CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime); 02180 settlingTimeReg.Settling_Time = nSettlingTime; 02181 02182 WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId)); 02183 02184 return ADMW_SUCCESS ; 02185 } 02186 02187 ADMW_RESULT admw1001_SetChannelConfig( 02188 ADMW_DEVICE_HANDLE hDevice, 02189 ADMW1001_CH_ID eChannelId, 02190 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 02191 { 02192 ADMW_RESULT eRet; 02193 02194 if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) { 02195 eRet = admw1001_SetChannelCount(hDevice, eChannelId, 02196 pChannelConfig->enableChannel ? 02197 pChannelConfig->measurementsPerCycle : 0); 02198 if (eRet != ADMW_SUCCESS ) { 02199 ADMW_LOG_ERROR("Failed to set measurement count for channel %d", 02200 eChannelId); 02201 return eRet; 02202 } 02203 02204 eRet = admw1001_SetChannelOptions(hDevice, eChannelId, 02205 pChannelConfig->priority ); 02206 if (eRet != ADMW_SUCCESS ) { 02207 ADMW_LOG_ERROR("Failed to set priority for channel %d", 02208 eChannelId); 02209 return eRet; 02210 } 02211 02212 /* If the channel is not enabled, we can skip the following steps */ 02213 if (pChannelConfig->enableChannel ) { 02214 eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId, 02215 pChannelConfig->cycleSkipCount ); 02216 if (eRet != ADMW_SUCCESS ) { 02217 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d", 02218 eChannelId); 02219 return eRet; 02220 } 02221 02222 switch (eChannelId) { 02223 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL : 02224 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL : 02225 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL : 02226 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL : 02227 eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig); 02228 break; 02229 case ADMW1001_CH_ID_DIG_I2C_0 : 02230 case ADMW1001_CH_ID_DIG_I2C_1 : 02231 eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig); 02232 break; 02233 case ADMW1001_CH_ID_DIG_SPI_0 : 02234 eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig); 02235 break; 02236 default: 02237 ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId); 02238 return ADMW_INVALID_PARAM ; 02239 } 02240 02241 eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId, 02242 pChannelConfig->extraSettlingTime ); 02243 if (eRet != ADMW_SUCCESS ) { 02244 ADMW_LOG_ERROR("Failed to set settling time for channel %d", 02245 eChannelId); 02246 return eRet; 02247 } 02248 } 02249 } 02250 02251 if (pChannelConfig->enableChannel ) { 02252 /* Threshold limits can be configured individually for virtual channels */ 02253 eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId, 02254 pChannelConfig->highThreshold , 02255 pChannelConfig->lowThreshold ); 02256 if (eRet != ADMW_SUCCESS ) { 02257 ADMW_LOG_ERROR("Failed to set threshold limits for channel %d", 02258 eChannelId); 02259 return eRet; 02260 } 02261 02262 /* Offset and gain can be configured individually for virtual channels */ 02263 eRet = admw1001_SetOffsetGain(hDevice, eChannelId, 02264 pChannelConfig->offsetAdjustment , 02265 pChannelConfig->gainAdjustment ); 02266 if (eRet != ADMW_SUCCESS ) { 02267 ADMW_LOG_ERROR("Failed to set offset/gain for channel %d", 02268 eChannelId); 02269 return eRet; 02270 } 02271 02272 /* Set sensor specific parameter */ 02273 eRet = admw1001_SetSensorParameter(hDevice, eChannelId, 02274 pChannelConfig->sensorParameter ); 02275 if (eRet != ADMW_SUCCESS ) { 02276 ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d", 02277 eChannelId); 02278 return eRet; 02279 } 02280 } 02281 02282 return ADMW_SUCCESS ; 02283 } 02284 02285 ADMW_RESULT admw_SetConfig( 02286 ADMW_DEVICE_HANDLE const hDevice, 02287 ADMW_CONFIG * const pConfig) 02288 { 02289 ADMW1001_CONFIG *pDeviceConfig; 02290 ADMW_PRODUCT_ID productId; 02291 ADMW_RESULT eRet; 02292 02293 if (pConfig->productId != ADMW_PRODUCT_ID_ADMW1001 ) { 02294 ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)", 02295 pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 ); 02296 return ADMW_INVALID_PARAM ; 02297 } 02298 02299 if (!((pConfig->versionId .major ==VERSIONID_MAJOR) && 02300 (pConfig->versionId .minor ==VERSIONID_MINOR))) { 02301 ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported", 02302 pConfig->versionId ); 02303 return ADMW_INVALID_PARAM ; 02304 } 02305 02306 02307 /* Check that the actual Product ID is a match? */ 02308 eRet = admw_GetProductID(hDevice, &productId); 02309 if (eRet) { 02310 ADMW_LOG_ERROR("Failed to read device Product ID register"); 02311 return eRet; 02312 } 02313 if (pConfig->productId != productId) { 02314 ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)", 02315 pConfig->productId , productId); 02316 return ADMW_INVALID_PARAM ; 02317 } 02318 02319 pDeviceConfig = &pConfig->admw1001 ; 02320 02321 eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power ); 02322 if (eRet) { 02323 ADMW_LOG_ERROR("Failed to set power configuration"); 02324 return eRet; 02325 } 02326 02327 eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement ); 02328 if (eRet) { 02329 ADMW_LOG_ERROR("Failed to set measurement configuration"); 02330 return eRet; 02331 } 02332 02333 eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics ); 02334 if (eRet) { 02335 ADMW_LOG_ERROR("Failed to set diagnostics configuration"); 02336 return eRet; 02337 } 02338 02339 for (ADMW1001_CH_ID id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ; 02340 id < ADMW1001_MAX_CHANNELS ; 02341 id++) { 02342 eRet = admw1001_SetChannelConfig(hDevice, id, 02343 &pDeviceConfig->channels [id]); 02344 if (eRet) { 02345 ADMW_LOG_ERROR("Failed to set channel %d configuration", id); 02346 return eRet; 02347 } 02348 } 02349 02350 return ADMW_SUCCESS ; 02351 } 02352 02353 ADMW_RESULT admw1001_SetLutData( 02354 ADMW_DEVICE_HANDLE const hDevice, 02355 ADMW1001_LUT * const pLutData) 02356 { 02357 ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header; 02358 ADMW1001_LUT_TABLE *pLutTable = pLutData->tables; 02359 unsigned actualLength = 0; 02360 02361 if (pLutData->header.signature != ADMW_LUT_SIGNATURE) { 02362 ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)", 02363 ADMW_LUT_SIGNATURE, pLutHeader->signature); 02364 return ADMW_INVALID_SIGNATURE ; 02365 } 02366 02367 for (unsigned i = 0; i < pLutHeader->numTables; i++) { 02368 ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor; 02369 ADMW1001_LUT_TABLE_DATA *pData = &pLutTable->data; 02370 unsigned short calculatedCrc; 02371 02372 switch (pDesc->geometry) { 02373 case ADMW1001_LUT_GEOMETRY_COEFFS: 02374 switch (pDesc->equation) { 02375 case ADMW1001_LUT_EQUATION_POLYN: 02376 case ADMW1001_LUT_EQUATION_POLYNEXP: 02377 case ADMW1001_LUT_EQUATION_QUADRATIC: 02378 case ADMW1001_LUT_EQUATION_STEINHART: 02379 case ADMW1001_LUT_EQUATION_LOGARITHMIC: 02380 case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN: 02381 break; 02382 default: 02383 ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u", 02384 pDesc->equation, i); 02385 return ADMW_INVALID_PARAM ; 02386 } 02387 break; 02388 case ADMW1001_LUT_GEOMETRY_NES_1D: 02389 case ADMW1001_LUT_GEOMETRY_NES_2D: 02390 case ADMW1001_LUT_GEOMETRY_ES_1D: 02391 case ADMW1001_LUT_GEOMETRY_ES_2D: 02392 if (pDesc->equation != ADMW1001_LUT_EQUATION_LUT) { 02393 ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u", 02394 pDesc->equation, i); 02395 return ADMW_INVALID_PARAM ; 02396 } 02397 break; 02398 default: 02399 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u", 02400 pDesc->geometry, i); 02401 return ADMW_INVALID_PARAM ; 02402 } 02403 02404 switch (pDesc->dataType) { 02405 case ADMW1001_LUT_DATA_TYPE_FLOAT32: 02406 case ADMW1001_LUT_DATA_TYPE_FLOAT64: 02407 break; 02408 default: 02409 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u", 02410 pDesc->dataType, i); 02411 return ADMW_INVALID_PARAM ; 02412 } 02413 02414 calculatedCrc = admw_crc16_ccitt(pData, pDesc->length); 02415 if (calculatedCrc != pDesc->crc16) { 02416 ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)", 02417 i, pDesc->crc16, calculatedCrc); 02418 return ADMW_CRC_ERROR ; 02419 } 02420 02421 actualLength += sizeof(*pDesc) + pDesc->length; 02422 02423 /* Move to the next look-up table */ 02424 pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length); 02425 } 02426 02427 if (actualLength != pLutHeader->totalLength) { 02428 ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)", 02429 pLutHeader->totalLength, actualLength); 02430 return ADMW_WRONG_SIZE ; 02431 } 02432 02433 if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) { 02434 ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded", 02435 ADMW_LUT_MAX_SIZE); 02436 return ADMW_WRONG_SIZE ; 02437 } 02438 02439 /* Write the LUT data to the device */ 02440 unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength; 02441 WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET); 02442 WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA); 02443 02444 return ADMW_SUCCESS ; 02445 } 02446 02447 ADMW_RESULT admw1001_SetLutDataRaw( 02448 ADMW_DEVICE_HANDLE const hDevice, 02449 ADMW1001_LUT_RAW * const pLutData) 02450 { 02451 return admw1001_SetLutData(hDevice, 02452 (ADMW1001_LUT *)pLutData); 02453 } 02454 02455 static ADMW_RESULT getLutTableSize( 02456 ADMW1001_LUT_DESCRIPTOR * const pDesc, 02457 ADMW1001_LUT_TABLE_DATA * const pData, 02458 unsigned *pLength) 02459 { 02460 switch (pDesc->geometry) { 02461 case ADMW1001_LUT_GEOMETRY_COEFFS: 02462 if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN) 02463 *pLength = ADMW1001_LUT_2D_POLYN_COEFF_LIST_SIZE(pData->coeffList2d); 02464 else 02465 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList); 02466 break; 02467 case ADMW1001_LUT_GEOMETRY_NES_1D: 02468 *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes); 02469 break; 02470 case ADMW1001_LUT_GEOMETRY_NES_2D: 02471 *pLength = ADMW1001_LUT_2D_NES_SIZE(pData->lut2dNes); 02472 break; 02473 case ADMW1001_LUT_GEOMETRY_ES_1D: 02474 *pLength = ADMW1001_LUT_1D_ES_SIZE(pData->lut1dEs); 02475 break; 02476 case ADMW1001_LUT_GEOMETRY_ES_2D: 02477 *pLength = ADMW1001_LUT_2D_ES_SIZE(pData->lut2dEs); 02478 break; 02479 default: 02480 ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n", 02481 pDesc->geometry); 02482 return ADMW_INVALID_PARAM ; 02483 } 02484 02485 return ADMW_SUCCESS ; 02486 } 02487 02488 ADMW_RESULT admw1001_AssembleLutData( 02489 ADMW1001_LUT * pLutBuffer, 02490 unsigned nLutBufferSize, 02491 unsigned const nNumTables, 02492 ADMW1001_LUT_DESCRIPTOR * const ppDesc[], 02493 ADMW1001_LUT_TABLE_DATA * const ppData[]) 02494 { 02495 ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header; 02496 uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr); 02497 02498 if (sizeof(*pHdr) > nLutBufferSize) { 02499 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02500 return ADMW_INVALID_PARAM ; 02501 } 02502 02503 /* First initialise the top-level header */ 02504 pHdr->signature = ADMW_LUT_SIGNATURE; 02505 pHdr->version.major = 1; 02506 pHdr->version.minor = 0; 02507 pHdr->numTables = 0; 02508 pHdr->totalLength = 0; 02509 02510 /* 02511 * Walk through the list of table pointers provided, appending the table 02512 * descriptor+data from each one to the provided LUT buffer 02513 */ 02514 for (unsigned i = 0; i < nNumTables; i++) { 02515 ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i]; 02516 ADMW1001_LUT_TABLE_DATA * const pData = ppData[i]; 02517 ADMW_RESULT res; 02518 unsigned dataLength = 0; 02519 02520 /* Calculate the length of the table data */ 02521 res = getLutTableSize(pDesc, pData, &dataLength); 02522 if (res != ADMW_SUCCESS ) 02523 return res; 02524 02525 /* Fill in the table descriptor length and CRC fields */ 02526 pDesc->length = dataLength; 02527 pDesc->crc16 = admw_crc16_ccitt(pData, dataLength); 02528 02529 if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) { 02530 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02531 return ADMW_INVALID_PARAM ; 02532 } 02533 02534 /* Append the table to the LUT buffer (desc + data) */ 02535 memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc)); 02536 pHdr->totalLength += sizeof(*pDesc); 02537 memcpy(pLutTableData + pHdr->totalLength, pData, dataLength); 02538 pHdr->totalLength += dataLength; 02539 02540 pHdr->numTables++; 02541 } 02542 02543 return ADMW_SUCCESS ; 02544 } 02545 02546 ADMW_RESULT deviceInformation(ADMW_DEVICE_HANDLE hDevice) 02547 { 02548 uint16_t nAddress = REG_CORE_REVISION; 02549 char nData[ADMW_VERSION_REG_VAL_SIZE]; //4 Bytes of version register data 02550 ADMW_RESULT res; 02551 res=admw1001_ReadRegister(hDevice,nAddress,nData,sizeof(nData)); 02552 if(res != ADMW_SUCCESS ) { 02553 //if reading version register failed, sending 00.00.0000 as ADMW1001 firmware version 02554 //strcat(nData, ADMW1001_FIRMWARE_VERSION_DEFAULT); 02555 ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]); 02556 } else { 02557 char buffer[ADMW_FORMATTED_VERSION_SIZE]; //00.00.0000 8 digits + 2 Bytes "." + one null character at the end 02558 strcat(nData, buffer); 02559 ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]); 02560 } 02561 return ADMW_SUCCESS ; 02562 } 02563 02564 ADMW_RESULT admw1001_getFirmwareStatus( 02565 ADMW_DEVICE_HANDLE const hDevice, 02566 bool * const bFirmwareStatus) 02567 { 02568 bool bitCommand; 02569 ADMW_RESULT eRet; 02570 uint8_t pinreg = 0x1; 02571 02572 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 02573 static uint8_t DataBuffer[SPI_BUFFER_SIZE] = {0}; 02574 uint16_t nSize; 02575 02576 //Construct Read Status command 02577 DataBuffer[0] = 0x07; 02578 DataBuffer[1] = 0x0E; //Packet ID 02579 02580 DataBuffer[2] = 0x00; 02581 DataBuffer[3] = 0x00; //Data words 02582 02583 DataBuffer[4] = 0x53; 02584 DataBuffer[5] = 0x00; //Command ID 02585 02586 DataBuffer[6] = 0x00; 02587 DataBuffer[7] = 0x00; 02588 DataBuffer[8] = 0x00; 02589 DataBuffer[9] = 0x00; //Address 02590 02591 DataBuffer[10] = 0x53; 02592 DataBuffer[11] = 0x00; 02593 DataBuffer[12] = 0x00; 02594 DataBuffer[13] = 0x00; //Checksum 02595 02596 nSize = SFL_READ_STATUS_HDR_SIZE; 02597 02598 do { 02599 // Get the SFL command irq pin to check if SFL is ready to receive commands 02600 // Status pin is not checked since SFL is just booted, there should not be any issue with SFL 02601 eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand ); 02602 if( eRet != ADMW_SUCCESS ) { 02603 return eRet; 02604 } 02605 02606 // 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 02607 // pinreg == '0x00' - Error occured in SFL 02608 // pinreg == '0x01' - SFL is ready to recieve commands 02609 // pinreg == '0x02' - Error occured in handling any commands in SFL 02610 // pinreg == '0x03' - SFL not booted 02611 02612 pinreg = (bitCommand); 02613 02614 } while(pinreg != 0x0u); 02615 02616 eRet = admw_SpiTransfer(pCtx->hSpi, DataBuffer, NULL, 02617 nSize, false); 02618 if (eRet) { 02619 return eRet; 02620 } 02621 02622 //wait for command irq line to go low after sending read status header 02623 wait_ms( 100 ); 02624 02625 do { 02626 // Get the SFL command irq pin to check if SFL is ready to receive commands 02627 // Status pin is not checked since SFL is just booted, there should not be any issue with SFL 02628 eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand ); 02629 if( eRet != ADMW_SUCCESS ) { 02630 return eRet; 02631 } 02632 02633 // 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 02634 // pinreg == '0x00' - Error occured in SFL 02635 // pinreg == '0x01' - SFL is ready to recieve commands 02636 // pinreg == '0x02' - Error occured in handling any commands in SFL 02637 // pinreg == '0x03' - SFL not booted 02638 02639 pinreg = (bitCommand); 02640 02641 } while(pinreg != 0x0u); 02642 02643 nSize = SFL_READ_STATUS_RESPONSE_SIZE; 02644 02645 eRet = admw_SpiReceive(pCtx->hSpi, NULL, DataBuffer, 02646 nSize, false); 02647 02648 if (eRet) { 02649 return eRet; 02650 } 02651 02652 //Verifying the application version from the response to check if firmware is present or not 02653 /* 02654 Flash Memory description 02655 ______________ 02656 | Secure | 0x0000 0000 02657 | Flashloader | 02658 |______________| 0x0000 3BFF 02659 | Security |------------------ 02660 | Page | 0x0000 3C00 02661 | | 02662 |______________| 0x0000 3FFF 02663 | |------------------ 02664 | App Info | 0x0000 4000 02665 | Page | 02666 |______________| 0x0000 4800 02667 | |------------------ 02668 | Application | 02669 | Image | Application resides only in this region 02670 |______________|------------------ 02671 | Reserved | 0x0003 FFF8 02672 | for | Reserved memory region 02673 | Signature | 0x0003 FFFF 02674 |______________|------------------ 02675 02676 Application version is stored in the App Info Page, the app version is updated in this region everytime the new application firmware is downloaded. 02677 Here we verify if Application version is present in the Read Status response 02678 If the app version bytes value is 0xFFFFFFFF then there is no firmware else there exist a firmware 02679 02680 Read Status Response: 02681 ____________________________________________________________________________________________________________________________________ 02682 | | | | | | 02683 |uint16_t nFlashLoaderVersion | uint16_t nStatus | uint32_t nApplicationVersion | uint32_t nApplicationHash[8] | uint16_t nChecksum | 02684 |_____________________________|__________________|______________________________|______________________________|_____________________| 02685 02686 */ 02687 02688 if( ((DataBuffer[4] == 0xFF) && 02689 (DataBuffer[5] == 0xFF) && 02690 (DataBuffer[6] == 0xFF) && 02691 (DataBuffer[7] == 0xFF)) || 02692 ((DataBuffer[4] == 0x00) && 02693 (DataBuffer[5] == 0x00) && 02694 (DataBuffer[6] == 0x00) && 02695 (DataBuffer[7] == 0x00))) { 02696 *bFirmwareStatus = false; 02697 } else { 02698 *bFirmwareStatus = true; 02699 } 02700 02701 return eRet; 02702 }
Generated on Wed Jul 13 2022 06:44:45 by
1.7.2