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 01156 ADMW_RESULT admw1001_SetMeasurementConfig( 01157 ADMW_DEVICE_HANDLE hDevice, 01158 ADMW1001_MEASUREMENT_CONFIG *pMeasConfig) 01159 { 01160 ADMW_RESULT eRet; 01161 01162 eRet = admw_SetMode(hDevice, 01163 pMeasConfig->operatingMode , 01164 pMeasConfig->dataReadyMode ); 01165 if (eRet != ADMW_SUCCESS ) { 01166 ADMW_LOG_ERROR("Failed to set operating mode"); 01167 return eRet; 01168 } 01169 01170 eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval , 01171 pMeasConfig->vBiasEnable , 01172 pMeasConfig->excitationState , 01173 pMeasConfig->groundSwitch ); 01174 if (eRet != ADMW_SUCCESS ) { 01175 ADMW_LOG_ERROR("Failed to set cycle control"); 01176 return eRet; 01177 } 01178 01179 if(pMeasConfig->externalRef1Value > 0) { 01180 eRet = admw_SetExternalReferenceValues(hDevice, 01181 pMeasConfig->externalRef1Value ); 01182 } 01183 01184 if (eRet != ADMW_SUCCESS ) { 01185 ADMW_LOG_ERROR("Failed to set external reference values"); 01186 return eRet; 01187 } 01188 01189 eRet = admw_SetRSenseValue(hDevice, pMeasConfig->RSenseValue ); 01190 if (eRet != ADMW_SUCCESS ) { 01191 ADMW_LOG_ERROR("Failed to set RSenseValue"); 01192 return eRet; 01193 } 01194 01195 eRet = admw_SetExternalReferenceVoltage(hDevice, pMeasConfig->externalRefVoltage ); 01196 if (eRet != ADMW_SUCCESS ) { 01197 ADMW_LOG_ERROR("Failed to set External reference Voltage"); 01198 return eRet; 01199 } 01200 01201 return ADMW_SUCCESS ; 01202 } 01203 01204 ADMW_RESULT admw1001_SetDiagnosticsConfig( 01205 ADMW_DEVICE_HANDLE hDevice, 01206 ADMW1001_DIAGNOSTICS_CONFIG *pDiagnosticsConfig) 01207 { 01208 ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg; 01209 01210 diagnosticsControlReg.VALUE8 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL); 01211 01212 if (pDiagnosticsConfig->disableMeasurementDiag ) 01213 diagnosticsControlReg.Diag_Meas_En = 0; 01214 else 01215 diagnosticsControlReg.Diag_Meas_En = 1; 01216 01217 switch (pDiagnosticsConfig->osdFrequency ) { 01218 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_DISABLED : 01219 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_OFF; 01220 break; 01221 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_CYCLE : 01222 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1_CYCLE; 01223 break; 01224 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_100_CYCLES : 01225 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_10_CYCLES; 01226 break; 01227 case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_1000_CYCLES : 01228 diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_100_CYCLES; 01229 break; 01230 default: 01231 ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified", 01232 pDiagnosticsConfig->osdFrequency ); 01233 return ADMW_INVALID_PARAM ; 01234 } 01235 01236 WRITE_REG_U8(hDevice, diagnosticsControlReg.VALUE8, CORE_DIAGNOSTICS_CONTROL); 01237 01238 return ADMW_SUCCESS ; 01239 } 01240 01241 ADMW_RESULT admw1001_SetChannelCount( 01242 ADMW_DEVICE_HANDLE hDevice, 01243 ADMW1001_CH_ID eChannelId, 01244 uint32_t nMeasurementsPerCycle) 01245 { 01246 ADMW_CORE_Channel_Count_t channelCountReg; 01247 01248 channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn); 01249 01250 if (nMeasurementsPerCycle > 0) { 01251 nMeasurementsPerCycle -= 1; 01252 01253 CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT, 01254 nMeasurementsPerCycle); 01255 01256 channelCountReg.Channel_Enable = 1; 01257 channelCountReg.Channel_Count = nMeasurementsPerCycle; 01258 } else { 01259 channelCountReg.Channel_Enable = 0; 01260 } 01261 01262 WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId)); 01263 01264 return ADMW_SUCCESS ; 01265 } 01266 01267 ADMW_RESULT admw1001_SetChannelOptions( 01268 ADMW_DEVICE_HANDLE hDevice, 01269 ADMW1001_CH_ID eChannelId, 01270 ADMW1001_CHANNEL_PRIORITY ePriority) 01271 { 01272 ADMW_CORE_Channel_Options_t channelOptionsReg; 01273 01274 channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn); 01275 01276 CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority); 01277 channelOptionsReg.Channel_Priority = ePriority; 01278 01279 WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId)); 01280 01281 return ADMW_SUCCESS ; 01282 } 01283 01284 ADMW_RESULT admw1001_SetChannelSkipCount( 01285 ADMW_DEVICE_HANDLE hDevice, 01286 ADMW1001_CH_ID eChannelId, 01287 uint32_t nCycleSkipCount) 01288 { 01289 ADMW_CORE_Channel_Skip_t channelSkipReg; 01290 01291 channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn); 01292 01293 CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount); 01294 01295 channelSkipReg.Channel_Skip = nCycleSkipCount; 01296 01297 WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId)); 01298 01299 return ADMW_SUCCESS ; 01300 } 01301 01302 static ADMW_RESULT admw_SetChannelAdcSensorType( 01303 ADMW_DEVICE_HANDLE hDevice, 01304 ADMW1001_CH_ID eChannelId, 01305 ADMW1001_ADC_SENSOR_TYPE sensorType) 01306 { 01307 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01308 01309 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01310 01311 /* Ensure that the sensor type is valid for this channel */ 01312 switch(sensorType) { 01313 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 : 01314 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 : 01315 case ADMW1001_ADC_SENSOR_RTD_3WIRE_1 : 01316 case ADMW1001_ADC_SENSOR_RTD_3WIRE_2 : 01317 case ADMW1001_ADC_SENSOR_RTD_3WIRE_3 : 01318 case ADMW1001_ADC_SENSOR_RTD_3WIRE_4 : 01319 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 : 01320 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 : 01321 case ADMW1001_ADC_SENSOR_RTD_4WIRE_1 : 01322 case ADMW1001_ADC_SENSOR_RTD_4WIRE_2 : 01323 case ADMW1001_ADC_SENSOR_RTD_4WIRE_3 : 01324 case ADMW1001_ADC_SENSOR_RTD_4WIRE_4 : 01325 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_1 : 01326 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_2 : 01327 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_3 : 01328 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_4 : 01329 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_1 : 01330 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_2 : 01331 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_3 : 01332 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_4 : 01333 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 : 01334 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 : 01335 case ADMW1001_ADC_SENSOR_RTD_2WIRE_1 : 01336 case ADMW1001_ADC_SENSOR_RTD_2WIRE_2 : 01337 case ADMW1001_ADC_SENSOR_RTD_2WIRE_3 : 01338 case ADMW1001_ADC_SENSOR_RTD_2WIRE_4 : 01339 case ADMW1001_ADC_SENSOR_DIODE_2C_TYPEA : 01340 case ADMW1001_ADC_SENSOR_DIODE_3C_TYPEA : 01341 case ADMW1001_ADC_SENSOR_DIODE_2C_1 : 01342 case ADMW1001_ADC_SENSOR_DIODE_3C_1 : 01343 case ADMW1001_ADC_SENSOR_THERMISTOR_A_10K : 01344 case ADMW1001_ADC_SENSOR_THERMISTOR_B_10K : 01345 case ADMW1001_ADC_SENSOR_THERMISTOR_1 : 01346 case ADMW1001_ADC_SENSOR_THERMISTOR_2 : 01347 case ADMW1001_ADC_SENSOR_THERMISTOR_3 : 01348 case ADMW1001_ADC_SENSOR_THERMISTOR_4 : 01349 case ADMW1001_ADC_SENSOR_SINGLE_ENDED_ABSOLUTE : 01350 case ADMW1001_ADC_SENSOR_DIFFERENTIAL_ABSOLUTE : 01351 case ADMW1001_ADC_SENSOR_SINGLE_ENDED_RATIO : 01352 case ADMW1001_ADC_SENSOR_DIFFERENTIAL_RATIO : 01353 if (! (ADMW1001_CHANNEL_IS_ADC_SENSOR(eChannelId) || 01354 ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId) || ADMW1001_CHANNEL_IS_ADC(eChannelId) )) { 01355 ADMW_LOG_ERROR( 01356 "Invalid ADC sensor type %d specified for channel %d", 01357 sensorType, eChannelId); 01358 return ADMW_INVALID_PARAM ; 01359 } 01360 break; 01361 case ADMW1001_ADC_SENSOR_VOLTAGE : 01362 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_A : 01363 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_B : 01364 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_1 : 01365 case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_2 : 01366 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J : 01367 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K : 01368 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T : 01369 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_1 : 01370 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_2 : 01371 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_3 : 01372 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_4 : 01373 if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) { 01374 ADMW_LOG_ERROR( 01375 "Invalid ADC sensor type %d specified for channel %d", 01376 sensorType, eChannelId); 01377 return ADMW_INVALID_PARAM ; 01378 } 01379 break; 01380 case ADMW1001_ADC_SENSOR_CURRENT : 01381 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_A : 01382 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_1 : 01383 case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_2 : 01384 if (! ADMW1001_CHANNEL_IS_ADC_CURRENT(eChannelId)) { 01385 ADMW_LOG_ERROR( 01386 "Invalid ADC sensor type %d specified for channel %d", 01387 sensorType, eChannelId); 01388 return ADMW_INVALID_PARAM ; 01389 } 01390 break; 01391 default: 01392 ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified", 01393 sensorType); 01394 return ADMW_INVALID_PARAM ; 01395 } 01396 01397 sensorTypeReg.Sensor_Type = sensorType; 01398 01399 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01400 01401 return ADMW_SUCCESS ; 01402 } 01403 01404 static ADMW_RESULT admw_SetChannelAdcSensorDetails( 01405 ADMW_DEVICE_HANDLE hDevice, 01406 ADMW1001_CH_ID eChannelId, 01407 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01408 /* 01409 * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers 01410 * General details: 01411 * - Measurement_Units 01412 * - Compensation_Channel 01413 * - CJC_Publish (if "CJC" was removed from the name) 01414 * ADC-specific details: 01415 * - PGA_Gain 01416 * - Reference_Select 01417 * - Reference_Buffer_Disable 01418 */ 01419 { 01420 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ; 01421 ADMW1001_ADC_REFERENCE_TYPE refType = pAdcChannelConfig->reference; 01422 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01423 01424 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01425 01426 switch(pChannelConfig->measurementUnit ) { 01427 case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT : 01428 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF; 01429 break; 01430 case ADMW1001_MEASUREMENT_UNIT_CELSIUS : 01431 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC; 01432 break; 01433 case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED : 01434 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01435 break; 01436 default: 01437 ADMW_LOG_ERROR("Invalid measurement unit %d specified", 01438 pChannelConfig->measurementUnit ); 01439 return ADMW_INVALID_PARAM ; 01440 } 01441 01442 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01443 sensorDetailsReg.Compensation_Disable = 1; 01444 sensorDetailsReg.Compensation_Channel = 0; 01445 } else { 01446 sensorDetailsReg.Compensation_Disable = 0; 01447 sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ; 01448 } 01449 01450 switch(refType) { 01451 case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL : 01452 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT; 01453 break; 01454 case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 : 01455 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1; 01456 break; 01457 case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD : 01458 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD; 01459 break; 01460 default: 01461 ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType); 01462 return ADMW_INVALID_PARAM ; 01463 } 01464 01465 switch(pAdcChannelConfig->gain ) { 01466 case ADMW1001_ADC_GAIN_1X : 01467 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1; 01468 break; 01469 case ADMW1001_ADC_GAIN_2X : 01470 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2; 01471 break; 01472 case ADMW1001_ADC_GAIN_4X : 01473 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4; 01474 break; 01475 case ADMW1001_ADC_GAIN_8X : 01476 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8; 01477 break; 01478 case ADMW1001_ADC_GAIN_16X : 01479 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16; 01480 break; 01481 case ADMW1001_ADC_GAIN_32X : 01482 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32; 01483 break; 01484 case ADMW1001_ADC_GAIN_64X : 01485 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64; 01486 break; 01487 case ADMW1001_ADC_GAIN_128X : 01488 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128; 01489 break; 01490 default: 01491 ADMW_LOG_ERROR("Invalid ADC gain %d specified", 01492 pAdcChannelConfig->gain ); 01493 return ADMW_INVALID_PARAM ; 01494 } 01495 01496 switch(pAdcChannelConfig->rtdCurve ) { 01497 case ADMW1001_ADC_RTD_CURVE_EUROPEAN : 01498 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE; 01499 break; 01500 case ADMW1001_ADC_RTD_CURVE_AMERICAN : 01501 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE; 01502 break; 01503 case ADMW1001_ADC_RTD_CURVE_JAPANESE : 01504 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE; 01505 break; 01506 case ADMW1001_ADC_RTD_CURVE_ITS90 : 01507 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE; 01508 break; 01509 default: 01510 ADMW_LOG_ERROR("Invalid RTD Curve %d specified", 01511 pAdcChannelConfig->rtdCurve ); 01512 return ADMW_INVALID_PARAM ; 01513 } 01514 01515 if (pChannelConfig->disablePublishing ) { 01516 sensorDetailsReg.Do_Not_Publish = 1; 01517 } else { 01518 sensorDetailsReg.Do_Not_Publish = 0; 01519 } 01520 01521 switch (pChannelConfig->lutSelect ) { 01522 case ADMW1001_LUT_DEFAULT : 01523 case ADMW1001_LUT_UNITY : 01524 case ADMW1001_LUT_CUSTOM : 01525 sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ; 01526 break; 01527 default: 01528 ADMW_LOG_ERROR("Invalid LUT selection %d specified", 01529 pChannelConfig->lutSelect ); 01530 return ADMW_INVALID_PARAM ; 01531 } 01532 01533 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01534 01535 return ADMW_SUCCESS ; 01536 } 01537 01538 static ADMW_RESULT admw_SetChannelAdcMeasurementSetup( 01539 ADMW_DEVICE_HANDLE hDevice, 01540 ADMW1001_CH_ID eChannelId, 01541 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig) 01542 { 01543 ADMW_CORE_Measurement_Setup_t MeasSetupReg; 01544 ADMW1001_ADC_FILTER_CONFIG *pFilterConfig = &pAdcChannelConfig->filter ; 01545 MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn); 01546 MeasSetupReg.Buffer_Bypass = pAdcChannelConfig->bufferBypass ; 01547 01548 if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC4 ) { 01549 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4; 01550 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01551 } else if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC3 ) { 01552 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3; 01553 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01554 } else { 01555 ADMW_LOG_ERROR("Invalid ADC filter type %d specified", 01556 pFilterConfig->type ); 01557 return ADMW_INVALID_PARAM ; 01558 } 01559 01560 /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */ 01561 MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ; 01562 01563 if(pFilterConfig->notch1p2 ) 01564 MeasSetupReg.NOTCH_EN_2 = 1; 01565 else 01566 MeasSetupReg.NOTCH_EN_2 = 0; 01567 01568 WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId)); 01569 01570 return ADMW_SUCCESS ; 01571 } 01572 01573 static ADMW_RESULT admw_SetChannelAdcCurrentConfig( 01574 ADMW_DEVICE_HANDLE hDevice, 01575 ADMW1001_CH_ID eChannelId, 01576 ADMW1001_ADC_EXC_CURRENT_CONFIG *pCurrentConfig) 01577 { 01578 ADMW_CORE_Channel_Excitation_t channelExcitationReg; 01579 01580 channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn); 01581 01582 if (pCurrentConfig->outputLevel == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT ) 01583 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE; 01584 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_EXTERNAL ) 01585 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL; 01586 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_50uA ) 01587 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA; 01588 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_100uA ) 01589 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA; 01590 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_250uA ) 01591 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA; 01592 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_500uA ) 01593 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA; 01594 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_1000uA ) 01595 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA; 01596 else { 01597 ADMW_LOG_ERROR("Invalid ADC excitation current %d specified", 01598 pCurrentConfig->outputLevel ); 01599 return ADMW_INVALID_PARAM ; 01600 } 01601 01602 WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId)); 01603 01604 return ADMW_SUCCESS ; 01605 } 01606 01607 ADMW_RESULT admw_SetAdcChannelConfig( 01608 ADMW_DEVICE_HANDLE hDevice, 01609 ADMW1001_CH_ID eChannelId, 01610 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01611 { 01612 ADMW_RESULT eRet; 01613 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = 01614 &pChannelConfig->adcChannelConfig ; 01615 01616 eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId, 01617 pAdcChannelConfig->sensor ); 01618 if (eRet != ADMW_SUCCESS ) { 01619 ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d", 01620 eChannelId); 01621 return eRet; 01622 } 01623 01624 eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId, 01625 pChannelConfig); 01626 if (eRet != ADMW_SUCCESS ) { 01627 ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d", 01628 eChannelId); 01629 return eRet; 01630 } 01631 01632 eRet = admw_SetChannelAdcMeasurementSetup(hDevice, eChannelId, 01633 pAdcChannelConfig); 01634 if (eRet != ADMW_SUCCESS ) { 01635 ADMW_LOG_ERROR("Failed to set ADC filter for channel %d", 01636 eChannelId); 01637 return eRet; 01638 } 01639 01640 eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId, 01641 &pAdcChannelConfig->current ); 01642 if (eRet != ADMW_SUCCESS ) { 01643 ADMW_LOG_ERROR("Failed to set ADC current for channel %d", 01644 eChannelId); 01645 return eRet; 01646 } 01647 01648 return ADMW_SUCCESS ; 01649 } 01650 01651 static ADMW_RESULT admw_SetChannelDigitalSensorDetails( 01652 ADMW_DEVICE_HANDLE hDevice, 01653 ADMW1001_CH_ID eChannelId, 01654 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01655 { 01656 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01657 01658 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01659 01660 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01661 sensorDetailsReg.Compensation_Disable = 1; 01662 sensorDetailsReg.Compensation_Channel = 0; 01663 } else { 01664 ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor"); 01665 return ADMW_INVALID_PARAM ; 01666 } 01667 01668 if (pChannelConfig->measurementUnit == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) { 01669 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01670 } else { 01671 ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel"); 01672 return ADMW_INVALID_PARAM ; 01673 } 01674 01675 if (pChannelConfig->disablePublishing ) 01676 sensorDetailsReg.Do_Not_Publish = 1; 01677 else 01678 sensorDetailsReg.Do_Not_Publish = 0; 01679 01680 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01681 01682 return ADMW_SUCCESS ; 01683 } 01684 01685 static ADMW_RESULT admw_SetDigitalSensorFormat( 01686 ADMW_DEVICE_HANDLE hDevice, 01687 ADMW1001_CH_ID eChannelId, 01688 ADMW1001_DIGITAL_SENSOR_DATA_FORMAT *pDataFormat) 01689 { 01690 ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg; 01691 01692 sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn); 01693 01694 if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) { 01695 if (pDataFormat->frameLength == 0) { 01696 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01697 return ADMW_INVALID_PARAM ; 01698 } 01699 if (pDataFormat->numDataBits == 0) { 01700 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01701 return ADMW_INVALID_PARAM ; 01702 } 01703 01704 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES, 01705 pDataFormat->frameLength - 1); 01706 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS, 01707 pDataFormat->numDataBits - 1); 01708 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET, 01709 pDataFormat->bitOffset); 01710 01711 sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1; 01712 sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1; 01713 sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset; 01714 sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0; 01715 sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0; 01716 01717 switch (pDataFormat->coding) { 01718 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR: 01719 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR; 01720 break; 01721 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT: 01722 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL; 01723 break; 01724 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY: 01725 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY; 01726 break; 01727 default: 01728 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format"); 01729 return ADMW_INVALID_PARAM ; 01730 } 01731 } else { 01732 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE; 01733 } 01734 01735 WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16, 01736 CORE_DIGITAL_SENSOR_CONFIGn(eChannelId)); 01737 01738 01739 return ADMW_SUCCESS ; 01740 } 01741 01742 static ADMW_RESULT admw_SetDigitalCalibrationParam( 01743 ADMW_DEVICE_HANDLE hDevice, 01744 ADMW1001_CH_ID eChannelId, 01745 ADMW1001_DIGITAL_CALIBRATION_COMMAND *pCalibrationParam) 01746 { 01747 // ADMW_CORE_Calibration_Parameter_t calibrationParamReg; 01748 // 01749 // calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn); 01750 // 01751 // if (pCalibrationParam->enableCalibrationParam == false) 01752 // calibrationParamReg.Calibration_Parameter_Enable = 0; 01753 // else 01754 // calibrationParamReg.Calibration_Parameter_Enable = 1; 01755 // 01756 // CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER, 01757 // pCalibrationParam->calibrationParam); 01758 // 01759 // calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam; 01760 // 01761 // WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32, 01762 // CORE_CALIBRATION_PARAMETERn(eChannelId)); 01763 // 01764 return ADMW_SUCCESS ; 01765 } 01766 01767 static ADMW_RESULT admw_SetChannelI2cSensorType( 01768 ADMW_DEVICE_HANDLE hDevice, 01769 ADMW1001_CH_ID eChannelId, 01770 ADMW1001_I2C_SENSOR_TYPE sensorType) 01771 { 01772 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01773 01774 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01775 01776 /* Ensure that the sensor type is valid for this channel */ 01777 switch(sensorType) { 01778 case ADMW1001_I2C_SENSOR_HUMIDITY_A : 01779 case ADMW1001_I2C_SENSOR_HUMIDITY_B : 01780 sensorTypeReg.Sensor_Type = sensorType; 01781 break; 01782 default: 01783 ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType); 01784 return ADMW_INVALID_PARAM ; 01785 } 01786 01787 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01788 01789 return ADMW_SUCCESS ; 01790 } 01791 01792 static ADMW_RESULT admw_SetChannelI2cSensorAddress( 01793 ADMW_DEVICE_HANDLE hDevice, 01794 ADMW1001_CH_ID eChannelId, 01795 uint32_t deviceAddress) 01796 { 01797 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress); 01798 WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId)); 01799 01800 return ADMW_SUCCESS ; 01801 } 01802 01803 static ADMW_RESULT admw_SetDigitalChannelComms( 01804 ADMW_DEVICE_HANDLE hDevice, 01805 ADMW1001_CH_ID eChannelId, 01806 ADMW1001_DIGITAL_SENSOR_COMMS *pDigitalComms) 01807 { 01808 ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms; 01809 01810 digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn); 01811 01812 if(pDigitalComms->useCustomCommsConfig ) { 01813 digitalSensorComms.Digital_Sensor_Comms_En = 1; 01814 01815 if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) { 01816 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K; 01817 } else if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) { 01818 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K; 01819 } else { 01820 ADMW_LOG_ERROR("Invalid I2C clock speed %d specified", 01821 pDigitalComms->i2cClockSpeed ); 01822 return ADMW_INVALID_PARAM ; 01823 } 01824 01825 if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) { 01826 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0; 01827 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) { 01828 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1; 01829 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) { 01830 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2; 01831 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) { 01832 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3; 01833 } else { 01834 ADMW_LOG_ERROR("Invalid SPI mode %d specified", 01835 pDigitalComms->spiMode ); 01836 return ADMW_INVALID_PARAM ; 01837 } 01838 01839 switch (pDigitalComms->spiClock ) { 01840 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ : 01841 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ; 01842 break; 01843 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ : 01844 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ; 01845 break; 01846 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ : 01847 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ; 01848 break; 01849 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ : 01850 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ; 01851 break; 01852 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ : 01853 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ; 01854 break; 01855 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ : 01856 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ; 01857 break; 01858 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ : 01859 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ; 01860 break; 01861 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ : 01862 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ; 01863 break; 01864 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ : 01865 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ; 01866 break; 01867 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ : 01868 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ; 01869 break; 01870 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ : 01871 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ; 01872 break; 01873 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ : 01874 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ; 01875 break; 01876 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ : 01877 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ; 01878 break; 01879 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ : 01880 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ; 01881 break; 01882 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ : 01883 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ; 01884 break; 01885 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ : 01886 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ; 01887 break; 01888 default: 01889 ADMW_LOG_ERROR("Invalid SPI clock %d specified", 01890 pDigitalComms->spiClock ); 01891 return ADMW_INVALID_PARAM ; 01892 } 01893 } else { 01894 digitalSensorComms.Digital_Sensor_Comms_En = 0; 01895 } 01896 01897 WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId)); 01898 01899 return ADMW_SUCCESS ; 01900 } 01901 01902 ADMW_RESULT admw_SetI2cChannelConfig( 01903 ADMW_DEVICE_HANDLE hDevice, 01904 ADMW1001_CH_ID eChannelId, 01905 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01906 { 01907 ADMW_RESULT eRet; 01908 ADMW1001_I2C_CHANNEL_CONFIG *pI2cChannelConfig = 01909 &pChannelConfig->i2cChannelConfig ; 01910 01911 eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId, 01912 pI2cChannelConfig->sensor ); 01913 if (eRet != ADMW_SUCCESS ) { 01914 ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d", 01915 eChannelId); 01916 return eRet; 01917 } 01918 01919 eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId, 01920 pI2cChannelConfig->deviceAddress ); 01921 if (eRet != ADMW_SUCCESS ) { 01922 ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d", 01923 eChannelId); 01924 return eRet; 01925 } 01926 01927 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 01928 pChannelConfig); 01929 if (eRet != ADMW_SUCCESS ) { 01930 ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d", 01931 eChannelId); 01932 return eRet; 01933 } 01934 01935 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 01936 &pI2cChannelConfig->dataFormat ); 01937 if (eRet != ADMW_SUCCESS ) { 01938 ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d", 01939 eChannelId); 01940 return eRet; 01941 } 01942 01943 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 01944 &pI2cChannelConfig->digitalCalibrationParam ); 01945 if (eRet != ADMW_SUCCESS ) { 01946 ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d", 01947 eChannelId); 01948 return eRet; 01949 } 01950 01951 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 01952 &pI2cChannelConfig->configureComms ); 01953 if (eRet != ADMW_SUCCESS ) { 01954 ADMW_LOG_ERROR("Failed to set I2C comms for channel %d", 01955 eChannelId); 01956 return eRet; 01957 } 01958 01959 return ADMW_SUCCESS ; 01960 } 01961 01962 static ADMW_RESULT admw_SetChannelSpiSensorType( 01963 ADMW_DEVICE_HANDLE hDevice, 01964 ADMW1001_CH_ID eChannelId, 01965 ADMW1001_SPI_SENSOR_TYPE sensorType) 01966 { 01967 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01968 01969 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01970 01971 /* Ensure that the sensor type is valid for this channel */ 01972 switch(sensorType) { 01973 case ADMW1001_SPI_SENSOR_PRESSURE_A : 01974 case ADMW1001_SPI_SENSOR_ACCELEROMETER_A : 01975 case ADMW1001_SPI_SENSOR_ACCELEROMETER_B : 01976 01977 sensorTypeReg.Sensor_Type = sensorType; 01978 break; 01979 default: 01980 ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType); 01981 return ADMW_INVALID_PARAM ; 01982 } 01983 01984 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01985 01986 return ADMW_SUCCESS ; 01987 } 01988 01989 ADMW_RESULT admw_SetSpiChannelConfig( 01990 ADMW_DEVICE_HANDLE hDevice, 01991 ADMW1001_CH_ID eChannelId, 01992 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01993 { 01994 ADMW_RESULT eRet; 01995 ADMW1001_SPI_CHANNEL_CONFIG *pSpiChannelConfig = 01996 &pChannelConfig->spiChannelConfig ; 01997 01998 eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId, 01999 pSpiChannelConfig->sensor ); 02000 if (eRet != ADMW_SUCCESS ) { 02001 ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d", 02002 eChannelId); 02003 return eRet; 02004 } 02005 02006 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 02007 pChannelConfig); 02008 if (eRet != ADMW_SUCCESS ) { 02009 ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d", 02010 eChannelId); 02011 return eRet; 02012 } 02013 02014 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 02015 &pSpiChannelConfig->dataFormat ); 02016 if (eRet != ADMW_SUCCESS ) { 02017 ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d", 02018 eChannelId); 02019 return eRet; 02020 } 02021 02022 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 02023 &pSpiChannelConfig->digitalCalibrationParam ); 02024 if (eRet != ADMW_SUCCESS ) { 02025 ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d", 02026 eChannelId); 02027 return eRet; 02028 } 02029 02030 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 02031 &pSpiChannelConfig->configureComms ); 02032 if (eRet != ADMW_SUCCESS ) { 02033 ADMW_LOG_ERROR("Failed to set SPI comms for channel %d", 02034 eChannelId); 02035 return eRet; 02036 } 02037 02038 return ADMW_SUCCESS ; 02039 } 02040 02041 ADMW_RESULT admw1001_SetChannelThresholdLimits( 02042 ADMW_DEVICE_HANDLE hDevice, 02043 ADMW1001_CH_ID eChannelId, 02044 float32_t fHighThresholdLimit, 02045 float32_t fLowThresholdLimit) 02046 { 02047 /* 02048 * If the low/high limits are *both* set to 0 in memory, or NaNs, assume 02049 * that they are unset, or not required, and use infinity defaults instead 02050 */ 02051 if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) { 02052 fHighThresholdLimit = INFINITY; 02053 fLowThresholdLimit = -INFINITY; 02054 } else { 02055 if (isnan(fHighThresholdLimit)) 02056 fHighThresholdLimit = INFINITY; 02057 if (isnan(fLowThresholdLimit)) 02058 fLowThresholdLimit = -INFINITY; 02059 } 02060 02061 WRITE_REG_FLOAT(hDevice, fHighThresholdLimit, 02062 CORE_HIGH_THRESHOLD_LIMITn(eChannelId)); 02063 WRITE_REG_FLOAT(hDevice, fLowThresholdLimit, 02064 CORE_LOW_THRESHOLD_LIMITn(eChannelId)); 02065 02066 return ADMW_SUCCESS ; 02067 } 02068 02069 ADMW_RESULT admw1001_SetOffsetGain( 02070 ADMW_DEVICE_HANDLE hDevice, 02071 ADMW1001_CH_ID eChannelId, 02072 float32_t fOffsetAdjustment, 02073 float32_t fGainAdjustment) 02074 { 02075 /* Replace with default values if NaNs are specified (or 0.0 for gain) */ 02076 if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f)) 02077 fGainAdjustment = 1.0f; 02078 if (isnan(fOffsetAdjustment)) 02079 fOffsetAdjustment = 0.0f; 02080 02081 WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId)); 02082 WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId)); 02083 02084 return ADMW_SUCCESS ; 02085 } 02086 02087 ADMW_RESULT admw1001_SetSensorParameter( 02088 ADMW_DEVICE_HANDLE hDevice, 02089 ADMW1001_CH_ID eChannelId, 02090 float32_t fSensorParam) 02091 { 02092 if (fSensorParam == 0.0f) 02093 fSensorParam = NAN; 02094 02095 //WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId)); 02096 02097 return ADMW_SUCCESS ; 02098 } 02099 02100 ADMW_RESULT admw1001_SetChannelSettlingTime( 02101 ADMW_DEVICE_HANDLE hDevice, 02102 ADMW1001_CH_ID eChannelId, 02103 uint32_t nSettlingTime) 02104 { 02105 ADMW_CORE_Settling_Time_t settlingTimeReg; 02106 02107 if (nSettlingTime < (1 << 12)) { 02108 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MICROSECONDS; 02109 } else if (nSettlingTime < (1000 * (1 << 12))) { 02110 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MILLISECONDS; 02111 nSettlingTime /= 1000; 02112 } else { 02113 settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_SECONDS; 02114 nSettlingTime /= 1000000; 02115 } 02116 02117 CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime); 02118 settlingTimeReg.Settling_Time = nSettlingTime; 02119 02120 WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId)); 02121 02122 return ADMW_SUCCESS ; 02123 } 02124 02125 ADMW_RESULT admw1001_SetChannelConfig( 02126 ADMW_DEVICE_HANDLE hDevice, 02127 ADMW1001_CH_ID eChannelId, 02128 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 02129 { 02130 ADMW_RESULT eRet; 02131 02132 if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) { 02133 eRet = admw1001_SetChannelCount(hDevice, eChannelId, 02134 pChannelConfig->enableChannel ? 02135 pChannelConfig->measurementsPerCycle : 0); 02136 if (eRet != ADMW_SUCCESS ) { 02137 ADMW_LOG_ERROR("Failed to set measurement count for channel %d", 02138 eChannelId); 02139 return eRet; 02140 } 02141 02142 eRet = admw1001_SetChannelOptions(hDevice, eChannelId, 02143 pChannelConfig->priority ); 02144 if (eRet != ADMW_SUCCESS ) { 02145 ADMW_LOG_ERROR("Failed to set priority for channel %d", 02146 eChannelId); 02147 return eRet; 02148 } 02149 02150 /* If the channel is not enabled, we can skip the following steps */ 02151 if (pChannelConfig->enableChannel ) { 02152 eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId, 02153 pChannelConfig->cycleSkipCount ); 02154 if (eRet != ADMW_SUCCESS ) { 02155 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d", 02156 eChannelId); 02157 return eRet; 02158 } 02159 02160 switch (eChannelId) { 02161 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL : 02162 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL : 02163 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL : 02164 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL : 02165 eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig); 02166 break; 02167 case ADMW1001_CH_ID_DIG_I2C_0 : 02168 case ADMW1001_CH_ID_DIG_I2C_1 : 02169 eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig); 02170 break; 02171 case ADMW1001_CH_ID_DIG_SPI_0 : 02172 eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig); 02173 break; 02174 default: 02175 ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId); 02176 eRet = ADMW_INVALID_PARAM ; 02177 #if 0 02178 /* when using i2c sensors there is an error ( dataformat->length=0) 02179 the code below catches this error and this causes further problems.*/ 02180 break; 02181 } 02182 if (eRet != ADMW_SUCCESS ) { 02183 ADMW_LOG_ERROR("Failed to set config for channel %d", 02184 eChannelId); 02185 return eRet; 02186 #endif 02187 } 02188 02189 eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId, 02190 pChannelConfig->extraSettlingTime ); 02191 if (eRet != ADMW_SUCCESS ) { 02192 ADMW_LOG_ERROR("Failed to set settling time for channel %d", 02193 eChannelId); 02194 return eRet; 02195 } 02196 } 02197 } 02198 02199 if (pChannelConfig->enableChannel ) { 02200 /* Threshold limits can be configured individually for virtual channels */ 02201 eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId, 02202 pChannelConfig->highThreshold , 02203 pChannelConfig->lowThreshold ); 02204 if (eRet != ADMW_SUCCESS ) { 02205 ADMW_LOG_ERROR("Failed to set threshold limits for channel %d", 02206 eChannelId); 02207 return eRet; 02208 } 02209 02210 /* Offset and gain can be configured individually for virtual channels */ 02211 eRet = admw1001_SetOffsetGain(hDevice, eChannelId, 02212 pChannelConfig->offsetAdjustment , 02213 pChannelConfig->gainAdjustment ); 02214 if (eRet != ADMW_SUCCESS ) { 02215 ADMW_LOG_ERROR("Failed to set offset/gain for channel %d", 02216 eChannelId); 02217 return eRet; 02218 } 02219 02220 /* Set sensor specific parameter */ 02221 eRet = admw1001_SetSensorParameter(hDevice, eChannelId, 02222 pChannelConfig->sensorParameter ); 02223 if (eRet != ADMW_SUCCESS ) { 02224 ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d", 02225 eChannelId); 02226 return eRet; 02227 } 02228 } 02229 02230 return ADMW_SUCCESS ; 02231 } 02232 02233 ADMW_RESULT admw_SetConfig( 02234 ADMW_DEVICE_HANDLE const hDevice, 02235 ADMW_CONFIG * const pConfig) 02236 { 02237 ADMW1001_CONFIG *pDeviceConfig; 02238 ADMW_PRODUCT_ID productId; 02239 ADMW_RESULT eRet; 02240 02241 if (pConfig->productId != ADMW_PRODUCT_ID_ADMW1001 ) { 02242 ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)", 02243 pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 ); 02244 return ADMW_INVALID_PARAM ; 02245 } 02246 02247 if (!((pConfig->versionId .major ==VERSIONID_MAJOR) && 02248 (pConfig->versionId .minor ==VERSIONID_MINOR))) { 02249 ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported", 02250 pConfig->versionId ); 02251 return ADMW_INVALID_PARAM ; 02252 } 02253 02254 02255 /* Check that the actual Product ID is a match? */ 02256 eRet = admw_GetProductID(hDevice, &productId); 02257 if (eRet) { 02258 ADMW_LOG_ERROR("Failed to read device Product ID register"); 02259 return eRet; 02260 } 02261 if (pConfig->productId != productId) { 02262 ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)", 02263 pConfig->productId , productId); 02264 return ADMW_INVALID_PARAM ; 02265 } 02266 02267 pDeviceConfig = &pConfig->admw1001 ; 02268 02269 eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power ); 02270 if (eRet) { 02271 ADMW_LOG_ERROR("Failed to set power configuration"); 02272 return eRet; 02273 } 02274 02275 eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement ); 02276 if (eRet) { 02277 ADMW_LOG_ERROR("Failed to set measurement configuration"); 02278 return eRet; 02279 } 02280 02281 eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics ); 02282 if (eRet) { 02283 ADMW_LOG_ERROR("Failed to set diagnostics configuration"); 02284 return eRet; 02285 } 02286 02287 for (ADMW1001_CH_ID id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ; 02288 id < ADMW1001_MAX_CHANNELS ; 02289 id++) { 02290 eRet = admw1001_SetChannelConfig(hDevice, id, 02291 &pDeviceConfig->channels [id]); 02292 if (eRet) { 02293 ADMW_LOG_ERROR("Failed to set channel %d configuration", id); 02294 return eRet; 02295 } 02296 } 02297 02298 return ADMW_SUCCESS ; 02299 } 02300 02301 ADMW_RESULT admw1001_SetLutData( 02302 ADMW_DEVICE_HANDLE const hDevice, 02303 ADMW1001_LUT * const pLutData) 02304 { 02305 ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header; 02306 ADMW1001_LUT_TABLE *pLutTable = pLutData->tables; 02307 unsigned actualLength = 0; 02308 02309 if (pLutData->header.signature != ADMW_LUT_SIGNATURE) { 02310 ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)", 02311 ADMW_LUT_SIGNATURE, pLutHeader->signature); 02312 return ADMW_INVALID_SIGNATURE ; 02313 } 02314 02315 for (unsigned i = 0; i < pLutHeader->numTables; i++) { 02316 ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor; 02317 ADMW1001_LUT_TABLE_DATA *pData = &pLutTable->data; 02318 unsigned short calculatedCrc; 02319 02320 switch (pDesc->geometry) { 02321 case ADMW1001_LUT_GEOMETRY_COEFFS: 02322 switch (pDesc->equation) { 02323 case ADMW1001_LUT_EQUATION_POLYN: 02324 case ADMW1001_LUT_EQUATION_POLYNEXP: 02325 case ADMW1001_LUT_EQUATION_QUADRATIC: 02326 case ADMW1001_LUT_EQUATION_STEINHART: 02327 case ADMW1001_LUT_EQUATION_LOGARITHMIC: 02328 case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN: 02329 break; 02330 default: 02331 ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u", 02332 pDesc->equation, i); 02333 return ADMW_INVALID_PARAM ; 02334 } 02335 break; 02336 case ADMW1001_LUT_GEOMETRY_NES_1D: 02337 case ADMW1001_LUT_GEOMETRY_NES_2D: 02338 case ADMW1001_LUT_GEOMETRY_ES_1D: 02339 case ADMW1001_LUT_GEOMETRY_ES_2D: 02340 if (pDesc->equation != ADMW1001_LUT_EQUATION_LUT) { 02341 ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u", 02342 pDesc->equation, i); 02343 return ADMW_INVALID_PARAM ; 02344 } 02345 break; 02346 default: 02347 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u", 02348 pDesc->geometry, i); 02349 return ADMW_INVALID_PARAM ; 02350 } 02351 02352 switch (pDesc->dataType) { 02353 case ADMW1001_LUT_DATA_TYPE_FLOAT32: 02354 case ADMW1001_LUT_DATA_TYPE_FLOAT64: 02355 break; 02356 default: 02357 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u", 02358 pDesc->dataType, i); 02359 return ADMW_INVALID_PARAM ; 02360 } 02361 02362 calculatedCrc = admw_crc16_ccitt(pData, pDesc->length); 02363 if (calculatedCrc != pDesc->crc16) { 02364 ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)", 02365 i, pDesc->crc16, calculatedCrc); 02366 return ADMW_CRC_ERROR ; 02367 } 02368 02369 actualLength += sizeof(*pDesc) + pDesc->length; 02370 02371 /* Move to the next look-up table */ 02372 pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length); 02373 } 02374 02375 if (actualLength != pLutHeader->totalLength) { 02376 ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)", 02377 pLutHeader->totalLength, actualLength); 02378 return ADMW_WRONG_SIZE ; 02379 } 02380 02381 if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) { 02382 ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded", 02383 ADMW_LUT_MAX_SIZE); 02384 return ADMW_WRONG_SIZE ; 02385 } 02386 02387 /* Write the LUT data to the device */ 02388 unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength; 02389 WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET); 02390 WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA); 02391 02392 return ADMW_SUCCESS ; 02393 } 02394 02395 ADMW_RESULT admw1001_SetLutDataRaw( 02396 ADMW_DEVICE_HANDLE const hDevice, 02397 ADMW1001_LUT_RAW * const pLutData) 02398 { 02399 return admw1001_SetLutData(hDevice, 02400 (ADMW1001_LUT *)pLutData); 02401 } 02402 02403 static ADMW_RESULT getLutTableSize( 02404 ADMW1001_LUT_DESCRIPTOR * const pDesc, 02405 ADMW1001_LUT_TABLE_DATA * const pData, 02406 unsigned *pLength) 02407 { 02408 switch (pDesc->geometry) { 02409 case ADMW1001_LUT_GEOMETRY_COEFFS: 02410 if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN) 02411 *pLength = ADMW1001_LUT_2D_POLYN_COEFF_LIST_SIZE(pData->coeffList2d); 02412 else 02413 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList); 02414 break; 02415 case ADMW1001_LUT_GEOMETRY_NES_1D: 02416 *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes); 02417 break; 02418 case ADMW1001_LUT_GEOMETRY_NES_2D: 02419 *pLength = ADMW1001_LUT_2D_NES_SIZE(pData->lut2dNes); 02420 break; 02421 case ADMW1001_LUT_GEOMETRY_ES_1D: 02422 *pLength = ADMW1001_LUT_1D_ES_SIZE(pData->lut1dEs); 02423 break; 02424 case ADMW1001_LUT_GEOMETRY_ES_2D: 02425 *pLength = ADMW1001_LUT_2D_ES_SIZE(pData->lut2dEs); 02426 break; 02427 default: 02428 ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n", 02429 pDesc->geometry); 02430 return ADMW_INVALID_PARAM ; 02431 } 02432 02433 return ADMW_SUCCESS ; 02434 } 02435 02436 ADMW_RESULT admw1001_AssembleLutData( 02437 ADMW1001_LUT * pLutBuffer, 02438 unsigned nLutBufferSize, 02439 unsigned const nNumTables, 02440 ADMW1001_LUT_DESCRIPTOR * const ppDesc[], 02441 ADMW1001_LUT_TABLE_DATA * const ppData[]) 02442 { 02443 ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header; 02444 uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr); 02445 02446 if (sizeof(*pHdr) > nLutBufferSize) { 02447 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02448 return ADMW_INVALID_PARAM ; 02449 } 02450 02451 /* First initialise the top-level header */ 02452 pHdr->signature = ADMW_LUT_SIGNATURE; 02453 pHdr->version.major = 1; 02454 pHdr->version.minor = 0; 02455 pHdr->numTables = 0; 02456 pHdr->totalLength = 0; 02457 02458 /* 02459 * Walk through the list of table pointers provided, appending the table 02460 * descriptor+data from each one to the provided LUT buffer 02461 */ 02462 for (unsigned i = 0; i < nNumTables; i++) { 02463 ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i]; 02464 ADMW1001_LUT_TABLE_DATA * const pData = ppData[i]; 02465 ADMW_RESULT res; 02466 unsigned dataLength = 0; 02467 02468 /* Calculate the length of the table data */ 02469 res = getLutTableSize(pDesc, pData, &dataLength); 02470 if (res != ADMW_SUCCESS ) 02471 return res; 02472 02473 /* Fill in the table descriptor length and CRC fields */ 02474 pDesc->length = dataLength; 02475 pDesc->crc16 = admw_crc16_ccitt(pData, dataLength); 02476 02477 if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) { 02478 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02479 return ADMW_INVALID_PARAM ; 02480 } 02481 02482 /* Append the table to the LUT buffer (desc + data) */ 02483 memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc)); 02484 pHdr->totalLength += sizeof(*pDesc); 02485 memcpy(pLutTableData + pHdr->totalLength, pData, dataLength); 02486 pHdr->totalLength += dataLength; 02487 02488 pHdr->numTables++; 02489 } 02490 02491 return ADMW_SUCCESS ; 02492 }
Generated on Tue Jul 12 2022 23:20:48 by
1.7.2