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