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 #include "inc/mbedVersion.h" 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 admw_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 00409 static ADMW_RESULT executeCommand( 00410 ADMW_DEVICE_HANDLE const hDevice, 00411 ADMW_CORE_Command_Special_Command const command, 00412 bool const bWaitForCompletion) 00413 { 00414 ADMW_CORE_Command_t commandReg; 00415 bool bCommandRunning; 00416 ADMW_RESULT eRet; 00417 00418 /* 00419 * Don't allow another command to be issued if one is already running, but 00420 * make an exception for ENUM_CORE_COMMAND_NOP which can be used to 00421 * request a running command to be stopped (e.g. continuous measurement) 00422 */ 00423 if (command != ENUM_CORE_COMMAND_NOP) { 00424 eRet = admw_GetCommandRunningState(hDevice, &bCommandRunning); 00425 if (eRet) 00426 return eRet; 00427 00428 if (bCommandRunning) 00429 return ADMW_IN_USE ; 00430 } 00431 00432 commandReg.Special_Command = command; 00433 WRITE_REG_U8(hDevice, commandReg.VALUE8, CORE_COMMAND); 00434 00435 if (bWaitForCompletion) { 00436 do { 00437 /* Allow a minimum 100usec delay for status update before checking */ 00438 admw_TimeDelayUsec(100); 00439 00440 eRet = admw_GetCommandRunningState(hDevice, &bCommandRunning); 00441 if (eRet) 00442 return eRet; 00443 } while (bCommandRunning); 00444 } 00445 00446 return ADMW_SUCCESS ; 00447 } 00448 00449 ADMW_RESULT admw_ApplyConfigUpdates( 00450 ADMW_DEVICE_HANDLE const hDevice) 00451 { 00452 return executeCommand(hDevice, CORE_COMMAND_LATCH_CONFIG, true); 00453 } 00454 00455 /*! 00456 * @brief Start a measurement cycle. 00457 * 00458 * @param[out] 00459 * 00460 * @return Status 00461 * - #ADMW_SUCCESS Call completed successfully. 00462 * - #ADMW_FAILURE 00463 * 00464 * @details Sends the latch config command. Configuration for channels in 00465 * conversion cycle should be completed before this function. 00466 * Channel enabled bit should be set before this function. 00467 * Starts a conversion and configures the format of the sample. 00468 * 00469 */ 00470 ADMW_RESULT admw_StartMeasurement( 00471 ADMW_DEVICE_HANDLE const hDevice, 00472 ADMW_MEASUREMENT_MODE const eMeasurementMode) 00473 { 00474 switch (eMeasurementMode) { 00475 case ADMW_MEASUREMENT_MODE_NORMAL : 00476 return executeCommand(hDevice, CORE_COMMAND_CONVERT_WITH_RAW, false); 00477 case ADMW_MEASUREMENT_MODE_OMIT_RAW : 00478 return executeCommand(hDevice, CORE_COMMAND_CONVERT, false); 00479 default: 00480 ADMW_LOG_ERROR("Invalid measurement mode %d specified", 00481 eMeasurementMode); 00482 return ADMW_INVALID_PARAM ; 00483 } 00484 } 00485 00486 /* 00487 * Store the configuration settings to persistent memory on the device. 00488 * The settings can be saved to 4 different flash memory areas (slots). 00489 * No other command must be running when this is called. 00490 * Do not power down the device while this command is running. 00491 */ 00492 ADMW_RESULT admw_SaveConfig( 00493 ADMW_DEVICE_HANDLE const hDevice, 00494 ADMW_USER_CONFIG_SLOT const eSlotId) 00495 { 00496 switch (eSlotId) { 00497 case ADMW_FLASH_CONFIG_1: 00498 return executeCommand(hDevice, CORE_COMMAND_SAVE_CONFIG_1, true); 00499 default: 00500 ADMW_LOG_ERROR("Invalid user config target slot %d specified", 00501 eSlotId); 00502 return ADMW_INVALID_PARAM ; 00503 } 00504 } 00505 00506 /* 00507 * Restore the configuration settings from persistent memory on the device. 00508 * No other command must be running when this is called. 00509 */ 00510 ADMW_RESULT admw_RestoreConfig( 00511 ADMW_DEVICE_HANDLE const hDevice, 00512 ADMW_USER_CONFIG_SLOT const eSlotId) 00513 { 00514 switch (eSlotId) { 00515 case ADMW_FLASH_CONFIG_1: 00516 return executeCommand(hDevice, CORE_COMMAND_LOAD_CONFIG_1, true); 00517 default: 00518 ADMW_LOG_ERROR("Invalid user config source slot %d specified", 00519 eSlotId); 00520 return ADMW_INVALID_PARAM ; 00521 } 00522 } 00523 00524 /* 00525 * Store the LUT data to persistent memory on the device. 00526 * No other command must be running when this is called. 00527 * Do not power down the device while this command is running. 00528 */ 00529 ADMW_RESULT admw_SaveLutData( 00530 ADMW_DEVICE_HANDLE const hDevice) 00531 { 00532 return executeCommand(hDevice, CORE_COMMAND_SAVE_LUT, true); 00533 } 00534 00535 /* 00536 * Restore the LUT data from persistent memory on the device. 00537 * No other command must be running when this is called. 00538 */ 00539 ADMW_RESULT admw_RestoreLutData( 00540 ADMW_DEVICE_HANDLE const hDevice) 00541 { 00542 return executeCommand(hDevice, CORE_COMMAND_LOAD_LUT, true); 00543 } 00544 00545 /* 00546 * Stop the measurement cycles on the device. 00547 * To be used only if a measurement command is currently running. 00548 */ 00549 ADMW_RESULT admw_StopMeasurement( 00550 ADMW_DEVICE_HANDLE const hDevice) 00551 { 00552 return executeCommand(hDevice, CORE_COMMAND_NOP, true); 00553 } 00554 00555 /* 00556 * 00557 */ 00558 ADMW_RESULT admw1001_sendRun( ADMW_DEVICE_HANDLE const hDevice) 00559 { 00560 bool bitCommand; 00561 ADMW_RESULT eRet; 00562 uint8_t pinreg = 0x1; 00563 00564 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00565 static uint8_t DataBuffer[SPI_BUFFER_SIZE] = {0}; 00566 uint16_t nSize; 00567 00568 //Construct Read Status command 00569 DataBuffer[0] = 0x07; 00570 DataBuffer[1] = 0x0E; //Packet ID 00571 00572 DataBuffer[2] = 0x00; 00573 DataBuffer[3] = 0x00; //Data words 00574 00575 DataBuffer[4] = 0x45; 00576 DataBuffer[5] = 0x00; //Command ID 00577 00578 DataBuffer[6] = 0x00; 00579 DataBuffer[7] = 0x50; 00580 DataBuffer[8] = 0x00; 00581 DataBuffer[9] = 0x00; //Address 00582 00583 DataBuffer[10] = 0x95; 00584 DataBuffer[11] = 0x00; 00585 DataBuffer[12] = 0x00; 00586 DataBuffer[13] = 0x00; //Checksum 00587 00588 nSize = SFL_READ_STATUS_HDR_SIZE; 00589 00590 do { 00591 // Get the SFL command irq pin to check if SFL is ready to receive commands 00592 // Status pin is not checked since SFL is just booted, there should not be any issue with SFL 00593 eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand ); 00594 if( eRet != ADMW_SUCCESS ) { 00595 return eRet; 00596 } 00597 00598 // 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 00599 // pinreg == '0x00' - Error occured in SFL 00600 // pinreg == '0x01' - SFL is ready to recieve commands 00601 // pinreg == '0x02' - Error occured in handling any commands in SFL 00602 // pinreg == '0x03' - SFL not booted 00603 00604 pinreg = (bitCommand); 00605 00606 } while(pinreg != 0x0u); 00607 00608 eRet = admw_SpiTransfer(pCtx->hSpi, DataBuffer, NULL, 00609 nSize, false); 00610 00611 return eRet; 00612 } 00613 00614 /* 00615 * Read a set of data samples from the device. 00616 * This may be called at any time. 00617 */ 00618 00619 ADMW_RESULT admw_GetData( 00620 ADMW_DEVICE_HANDLE const hDevice, 00621 ADMW_MEASUREMENT_MODE const eMeasurementMode, 00622 ADMW_DATA_SAMPLE * const pSamples, 00623 uint8_t const nBytesPerSample, 00624 uint32_t const nRequested, 00625 uint32_t * const pnReturned) 00626 { 00627 ADMW1001_Sensor_Result_t sensorResult; 00628 ADMW_DEVICE_CONTEXT *pCtx = hDevice; 00629 uint16_t command = ADMW1001_HOST_COMMS_READ_CMD | 00630 (REG_CORE_DATA_FIFO & ADMW1001_HOST_COMMS_ADR_MASK); 00631 uint8_t commandData[2] = { 00632 command >> 8, 00633 command & 0xFF 00634 }; 00635 uint8_t commandResponse[2]; 00636 unsigned nValidSamples = 0; 00637 ADMW_RESULT eRet = ADMW_SUCCESS ; 00638 00639 do { 00640 eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse, 00641 sizeof(command), false); 00642 if (eRet) { 00643 ADMW_LOG_ERROR("Failed to send read command for FIFO register"); 00644 return eRet; 00645 } 00646 admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY); 00647 } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) || 00648 (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1)); 00649 00650 for (unsigned i = 0; i < nRequested; i++) { 00651 bool bHoldCs = true; 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 wait_ms(100); 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 (modeReg.Conversion_Mode == CORE_MODE_SINGLECYCLE) 00907 *peOperatingMode = ADMW1001_OPERATING_MODE_SINGLECYCLE ; 00908 else 00909 *peOperatingMode = ADMW1001_OPERATING_MODE_CONTINUOUS ; 00910 00911 if (eMeasurementMode == ADMW_MEASUREMENT_MODE_OMIT_RAW ) { 00912 *pnBytesPerSample = 8; 00913 } else { 00914 *pnBytesPerSample = 12; 00915 } 00916 00917 for (ADMW1001_CH_ID chId = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ; 00918 chId < ADMW1001_MAX_CHANNELS ; 00919 chId++) { 00920 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 00921 ADMW_CORE_Channel_Count_t channelCountReg; 00922 00923 if (ADMW1001_CHANNEL_IS_VIRTUAL(chId)) 00924 continue; 00925 00926 READ_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(chId)); 00927 READ_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(chId)); 00928 00929 if (channelCountReg.Channel_Enable && !sensorDetailsReg.Do_Not_Publish) { 00930 unsigned nActualChannels = 1; 00931 00932 if (chId == ADMW1001_CH_ID_DIG_SPI_0 ) { 00933 /* Some sensors automatically generate samples on additional 00934 * "virtual" channels so these channels must be counted as 00935 * active when those sensors are selected and we use the count 00936 * from the corresponding "physical" channel 00937 */ 00938 #if 0 /* SPI sensors arent supported at present to be added back once there is 00939 * support for these sensors 00940 */ 00941 ADMW_CORE_Sensor_Type_t sensorTypeReg; 00942 00943 READ_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(chId)); 00944 00945 if ((sensorTypeReg.Sensor_Type >= 00946 CORE_SENSOR_TYPE_SPI_ACCELEROMETER_A) && 00947 (sensorTypeReg.Sensor_Type <= 00948 CORE_SENSOR_TYPE_SPI_ACCELEROMETER_B)) { 00949 nActualChannels += 2; 00950 } 00951 #endif 00952 } 00953 00954 nChannelsEnabled += nActualChannels; 00955 00956 nSamplesPerCycle += nActualChannels * 00957 (channelCountReg.Channel_Count + 1); 00958 } 00959 } 00960 00961 if (nChannelsEnabled == 0) { 00962 *pnSamplesPerDataready = 0; 00963 *pnSamplesPerCycle = 0; 00964 return ADMW_SUCCESS ; 00965 } 00966 00967 *pnSamplesPerCycle = nSamplesPerCycle; 00968 00969 if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) { 00970 *pnSamplesPerDataready = 1; 00971 } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CYCLE) { 00972 *pnSamplesPerDataready = nSamplesPerCycle; 00973 } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_FIFO_FILL) { 00974 ADMW_CORE_Fifo_Num_Cycles_t fifoNumCyclesReg; 00975 00976 READ_REG_U8(hDevice, fifoNumCyclesReg.VALUE8, CORE_FIFO_NUM_CYCLES); 00977 00978 *pnSamplesPerDataready = nSamplesPerCycle * fifoNumCyclesReg.Fifo_Num_Cycles; 00979 } else { 00980 ADMW_LOG_ERROR("Invalid DRDY mode %d specified", 00981 modeReg.Drdy_Mode); 00982 return ADMW_INVALID_PARAM ; 00983 } 00984 00985 if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) { 00986 *peDataReadyMode = ADMW1001_DATAREADY_PER_CONVERSION ; 00987 } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CYCLE) { 00988 *peDataReadyMode = ADMW1001_DATAREADY_PER_CYCLE ; 00989 } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_FIFO_FILL) { 00990 *peDataReadyMode = ADMW1001_DATAREADY_PER_FIFO_FILL ; 00991 } else { 00992 ADMW_LOG_ERROR("Invalid DRDY mode %d specified", 00993 modeReg.Drdy_Mode); 00994 return ADMW_INVALID_PARAM ; 00995 } 00996 00997 return ADMW_SUCCESS ; 00998 } 00999 01000 ADMW_RESULT admw_GetProductID( 01001 ADMW_DEVICE_HANDLE hDevice, 01002 ADMW_PRODUCT_ID *pProductId) 01003 { 01004 ADMW_SPI_Product_ID_L_t productIdLoReg; 01005 ADMW_SPI_Product_ID_H_t productIdHiReg; 01006 01007 READ_REG_U8(hDevice, productIdLoReg.VALUE8, SPI_PRODUCT_ID_L); 01008 READ_REG_U8(hDevice, productIdHiReg.VALUE8, SPI_PRODUCT_ID_H); 01009 01010 *pProductId = (ADMW_PRODUCT_ID )((productIdHiReg.VALUE8 << 8) | 01011 productIdLoReg.VALUE8); 01012 return ADMW_SUCCESS ; 01013 } 01014 01015 static ADMW_RESULT admw_SetPowerMode( 01016 ADMW_DEVICE_HANDLE hDevice, 01017 ADMW1001_POWER_MODE powerMode) 01018 { 01019 ADMW_CORE_Power_Config_t powerConfigReg = { 0 }; 01020 01021 if (powerMode == ADMW1001_POWER_MODE_HIBERNATION ) { 01022 powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_HIBERNATION; 01023 } else if (powerMode == ADMW1001_POWER_MODE_ACTIVE ) { 01024 powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_ACTIVE_MODE; 01025 } else { 01026 ADMW_LOG_ERROR("Invalid power mode %d specified", powerMode); 01027 return ADMW_INVALID_PARAM ; 01028 } 01029 01030 WRITE_REG_U8(hDevice, powerConfigReg.VALUE8, CORE_POWER_CONFIG); 01031 01032 return ADMW_SUCCESS ; 01033 } 01034 01035 ADMW_RESULT admw1001_SetPowerConfig( 01036 ADMW_DEVICE_HANDLE hDevice, 01037 ADMW1001_POWER_CONFIG *pPowerConfig) 01038 { 01039 ADMW_RESULT eRet; 01040 01041 eRet = admw_SetPowerMode(hDevice, pPowerConfig->powerMode ); 01042 if (eRet != ADMW_SUCCESS ) { 01043 ADMW_LOG_ERROR("Failed to set power mode"); 01044 return eRet; 01045 } 01046 01047 return ADMW_SUCCESS ; 01048 } 01049 01050 static ADMW_RESULT admw_SetRSenseValue( 01051 ADMW_DEVICE_HANDLE hDevice, 01052 float32_t RSenseValue) 01053 { 01054 ADMW_CORE_External_Reference_Resistor_t RefResistorConfigReg; 01055 01056 RefResistorConfigReg.Ext_Refin1_Value = RSenseValue; 01057 01058 WRITE_REG_FLOAT(hDevice, RefResistorConfigReg.VALUE32, CORE_EXTERNAL_REFERENCE_RESISTOR); 01059 01060 return ADMW_SUCCESS ; 01061 01062 } 01063 static ADMW_RESULT admw_SetMode( 01064 ADMW_DEVICE_HANDLE hDevice, 01065 ADMW1001_OPERATING_MODE eOperatingMode, 01066 ADMW1001_DATAREADY_MODE eDataReadyMode) 01067 { 01068 ADMW_CORE_Mode_t modeReg; 01069 01070 modeReg.VALUE8 = REG_RESET_VAL(CORE_MODE); 01071 01072 if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) { 01073 modeReg.Conversion_Mode = CORE_MODE_SINGLECYCLE; 01074 } else if (eOperatingMode == ADMW1001_OPERATING_MODE_CONTINUOUS ) { 01075 modeReg.Conversion_Mode = CORE_MODE_CONTINUOUS; 01076 } else { 01077 ADMW_LOG_ERROR("Invalid operating mode %d specified", 01078 eOperatingMode); 01079 return ADMW_INVALID_PARAM ; 01080 } 01081 01082 if (eDataReadyMode == ADMW1001_DATAREADY_PER_CONVERSION ) { 01083 modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CONVERSION; 01084 } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_CYCLE ) { 01085 modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CYCLE; 01086 } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_FIFO_FILL ) { 01087 modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_FIFO_FILL; 01088 } else { 01089 ADMW_LOG_ERROR("Invalid data-ready mode %d specified", eDataReadyMode); 01090 return ADMW_INVALID_PARAM ; 01091 } 01092 01093 WRITE_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE); 01094 01095 return ADMW_SUCCESS ; 01096 } 01097 01098 ADMW_RESULT admw_SetCycleControl(ADMW_DEVICE_HANDLE hDevice, 01099 uint32_t nCycleInterval, 01100 bool vBiasEnable, 01101 bool vPostExecCurrentState, 01102 bool vGroundSwitch) 01103 { 01104 ADMW_CORE_Cycle_Control_t cycleControlReg; 01105 01106 cycleControlReg.VALUE16 = REG_RESET_VAL(CORE_CYCLE_CONTROL); 01107 01108 if (nCycleInterval < (1 << 12)) { 01109 cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_SECONDS; 01110 } else { 01111 ADMW_LOG_ERROR("Invalid nCycleInterval %d specified", nCycleInterval); 01112 return ADMW_INVALID_PARAM ; 01113 } 01114 01115 if (vBiasEnable == true) { 01116 cycleControlReg.Vbias = 1; 01117 } 01118 CHECK_REG_FIELD_VAL(CORE_CYCLE_CONTROL_CYCLE_TIME, nCycleInterval); 01119 cycleControlReg.Cycle_Time = nCycleInterval; 01120 01121 switch(vPostExecCurrentState) { 01122 case ADMW1001_ADC_EXC_STATE_CYCLE_POWER : 01123 cycleControlReg.PST_MEAS_EXC_CTRL = CORE_CYCLE_CONTROL_POWERCYCLE; 01124 break; 01125 case ADMW1001_ADC_EXC_STATE_ALWAYS_ON : 01126 cycleControlReg.PST_MEAS_EXC_CTRL = CORE_CYCLE_CONTROL_ALWAYSON; 01127 break; 01128 default: 01129 ADMW_LOG_ERROR("Invalid Post measurement Excitation Current state %d specified", 01130 vPostExecCurrentState); 01131 return ADMW_INVALID_PARAM ; 01132 } 01133 01134 switch(vGroundSwitch) { 01135 case ADMW1001_ADC_GND_SW_OPEN : 01136 cycleControlReg.GND_SW_CTRL = CORE_CYCLE_CONTROL_OPEN_SW; 01137 break; 01138 case ADMW1001_ADC_GND_SW_CLOSED : 01139 cycleControlReg.GND_SW_CTRL = CORE_CYCLE_CONTROL_CLOSE_SW; 01140 break; 01141 default: 01142 ADMW_LOG_ERROR("Invalid ground switch state %d specified", 01143 vGroundSwitch); 01144 return ADMW_INVALID_PARAM ; 01145 } 01146 01147 WRITE_REG_U16(hDevice, cycleControlReg.VALUE16, CORE_CYCLE_CONTROL); 01148 01149 return ADMW_SUCCESS ; 01150 } 01151 static ADMW_RESULT admw_SetExternalReferenceVoltage( 01152 ADMW_DEVICE_HANDLE hDevice, 01153 float32_t externalRefVoltage) 01154 { 01155 WRITE_REG_FLOAT(hDevice, externalRefVoltage, CORE_EXTERNAL_VOLTAGE_REFERENCE); 01156 01157 return ADMW_SUCCESS ; 01158 } 01159 static ADMW_RESULT admw_SetFifoNumCycles( 01160 ADMW_DEVICE_HANDLE hDevice, 01161 uint8_t fifoNumCycles) 01162 { 01163 WRITE_REG_U8(hDevice, fifoNumCycles, CORE_FIFO_NUM_CYCLES); 01164 01165 return ADMW_SUCCESS ; 01166 } 01167 01168 static ADMW_RESULT admw_SetExternalReferenceValues( 01169 ADMW_DEVICE_HANDLE hDevice, 01170 float32_t externalRef1Value) 01171 { 01172 WRITE_REG_FLOAT(hDevice, externalRef1Value, CORE_EXTERNAL_REFERENCE_RESISTOR); 01173 01174 return ADMW_SUCCESS ; 01175 } 01176 static ADMW_RESULT admw_SetAVDDVoltage( 01177 ADMW_DEVICE_HANDLE hDevice, 01178 float32_t AVDDVoltage) 01179 { 01180 01181 WRITE_REG_FLOAT(hDevice, AVDDVoltage, CORE_AVDD_VOLTAGE); 01182 01183 return ADMW_SUCCESS ; 01184 } 01185 01186 ADMW_RESULT admw1001_SetMeasurementConfig( 01187 ADMW_DEVICE_HANDLE hDevice, 01188 ADMW1001_MEASUREMENT_CONFIG *pMeasConfig) 01189 { 01190 ADMW_RESULT eRet; 01191 01192 eRet = admw_SetMode(hDevice, 01193 pMeasConfig->operatingMode , 01194 pMeasConfig->dataReadyMode ); 01195 if (eRet != ADMW_SUCCESS ) { 01196 ADMW_LOG_ERROR("Failed to set operating mode"); 01197 return eRet; 01198 } 01199 01200 eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval , 01201 pMeasConfig->vBiasEnable , 01202 pMeasConfig->excitationState , 01203 pMeasConfig->groundSwitch ); 01204 if (eRet != ADMW_SUCCESS ) { 01205 ADMW_LOG_ERROR("Failed to set cycle control"); 01206 return eRet; 01207 } 01208 01209 if (pMeasConfig->fifoNumCycles > 0) { 01210 eRet = admw_SetFifoNumCycles(hDevice, 01211 pMeasConfig->fifoNumCycles ); 01212 } 01213 01214 if (eRet != ADMW_SUCCESS ) { 01215 ADMW_LOG_ERROR("Failed to set the FIFO number of cycles."); 01216 return eRet; 01217 } 01218 01219 if(pMeasConfig->externalRef1Value > 0) { 01220 eRet = admw_SetExternalReferenceValues(hDevice, 01221 pMeasConfig->externalRef1Value ); 01222 } 01223 01224 if (eRet != ADMW_SUCCESS ) { 01225 ADMW_LOG_ERROR("Failed to set external reference values"); 01226 return eRet; 01227 } 01228 01229 if((pMeasConfig->AVDDVoltage >= 3.0) && (pMeasConfig->AVDDVoltage <= 3.6)) { 01230 eRet = admw_SetAVDDVoltage(hDevice, 01231 pMeasConfig->AVDDVoltage ); 01232 } 01233 01234 if (eRet != ADMW_SUCCESS ) { 01235 ADMW_LOG_ERROR("Failed to set AVDD Voltge"); 01236 return eRet; 01237 } 01238 01239 eRet = admw_SetRSenseValue(hDevice, pMeasConfig->RSenseValue ); 01240 if (eRet != ADMW_SUCCESS ) { 01241 ADMW_LOG_ERROR("Failed to set RSenseValue"); 01242 return eRet; 01243 } 01244 01245 eRet = admw_SetExternalReferenceVoltage(hDevice, pMeasConfig->externalRefVoltage ); 01246 if (eRet != ADMW_SUCCESS ) { 01247 ADMW_LOG_ERROR("Failed to set External reference Voltage"); 01248 return eRet; 01249 } 01250 01251 return ADMW_SUCCESS ; 01252 } 01253 ADMW_RESULT admw1001_SetDiagnosticsConfig( 01254 ADMW_DEVICE_HANDLE hDevice, 01255 ADMW1001_DIAGNOSTICS_CONFIG *pDiagnosticsConfig) 01256 { 01257 ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg; 01258 01259 diagnosticsControlReg.VALUE8 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL); 01260 01261 if (pDiagnosticsConfig->disableMeasurementDiag ) 01262 diagnosticsControlReg.Diag_Meas_En = 0; 01263 else 01264 diagnosticsControlReg.Diag_Meas_En = 1; 01265 01266 if(pDiagnosticsConfig->osdFrequency <= 0x7F) { 01267 diagnosticsControlReg.Diag_OSD_Freq = pDiagnosticsConfig->osdFrequency ; 01268 } else { 01269 ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified", 01270 pDiagnosticsConfig->osdFrequency ); 01271 return ADMW_INVALID_PARAM ; 01272 } 01273 WRITE_REG_U8(hDevice, diagnosticsControlReg.VALUE8, CORE_DIAGNOSTICS_CONTROL); 01274 01275 return ADMW_SUCCESS ; 01276 } 01277 01278 ADMW_RESULT admw1001_SetChannelCount( 01279 ADMW_DEVICE_HANDLE hDevice, 01280 ADMW1001_CH_ID eChannelId, 01281 uint32_t nMeasurementsPerCycle) 01282 { 01283 ADMW_CORE_Channel_Count_t channelCountReg; 01284 01285 channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn); 01286 01287 if (nMeasurementsPerCycle > 0) { 01288 nMeasurementsPerCycle -= 1; 01289 01290 CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT, 01291 nMeasurementsPerCycle); 01292 01293 channelCountReg.Channel_Enable = 1; 01294 channelCountReg.Channel_Count = nMeasurementsPerCycle; 01295 } else { 01296 channelCountReg.Channel_Enable = 0; 01297 } 01298 01299 WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId)); 01300 01301 return ADMW_SUCCESS ; 01302 } 01303 01304 ADMW_RESULT admw1001_SetChannelOptions( 01305 ADMW_DEVICE_HANDLE hDevice, 01306 ADMW1001_CH_ID eChannelId, 01307 ADMW1001_CHANNEL_PRIORITY ePriority) 01308 { 01309 ADMW_CORE_Channel_Options_t channelOptionsReg; 01310 01311 channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn); 01312 01313 CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority); 01314 channelOptionsReg.Channel_Priority = ePriority; 01315 01316 WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId)); 01317 01318 return ADMW_SUCCESS ; 01319 } 01320 01321 ADMW_RESULT admw1001_SetChannelSkipCount( 01322 ADMW_DEVICE_HANDLE hDevice, 01323 ADMW1001_CH_ID eChannelId, 01324 uint32_t nCycleSkipCount) 01325 { 01326 ADMW_CORE_Channel_Skip_t channelSkipReg; 01327 01328 channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn); 01329 01330 CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount); 01331 01332 channelSkipReg.Channel_Skip = nCycleSkipCount; 01333 01334 WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId)); 01335 01336 return ADMW_SUCCESS ; 01337 } 01338 01339 static ADMW_RESULT admw_SetChannelAdcSensorType( 01340 ADMW_DEVICE_HANDLE hDevice, 01341 ADMW1001_CH_ID eChannelId, 01342 ADMW1001_ADC_SENSOR_TYPE sensorType) 01343 { 01344 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01345 01346 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01347 01348 /* Ensure that the sensor type is valid for this channel */ 01349 switch(sensorType) { 01350 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT10 : 01351 01352 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT50 : 01353 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 : 01354 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT200 : 01355 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT500 : 01356 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 : 01357 case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000_0P00375 : 01358 case ADMW1001_ADC_SENSOR_RTD_2WIRE_NI120 : 01359 case ADMW1001_ADC_SENSOR_RTD_2WIRE_CUSTOM : 01360 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT10 : 01361 01362 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT50 : 01363 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 : 01364 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT200 : 01365 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT500 : 01366 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 : 01367 case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000_0P00375 : 01368 case ADMW1001_ADC_SENSOR_RTD_4WIRE_NI120 : 01369 case ADMW1001_ADC_SENSOR_RTD_4WIRE_CUSTOM : 01370 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT10 : 01371 01372 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT50 : 01373 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 : 01374 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT200 : 01375 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT500 : 01376 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 : 01377 case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000_0P00375 : 01378 01379 case ADMW1001_ADC_SENSOR_RTD_3WIRE_NI120 : 01380 case ADMW1001_ADC_SENSOR_RTD_3WIRE_CUSTOM : 01381 case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE : 01382 case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE : 01383 case ADMW1001_ADC_SENSOR_DIODE : 01384 case ADMW1001_ADC_SENSOR_THERMISTOR_44004_44033_2P252K_AT_25C : 01385 case ADMW1001_ADC_SENSOR_THERMISTOR_44005_44030_3K_AT_25C : 01386 case ADMW1001_ADC_SENSOR_THERMISTOR_44007_44034_5K_AT_25C : 01387 case ADMW1001_ADC_SENSOR_THERMISTOR_44006_44031_10K_AT_25C : 01388 case ADMW1001_ADC_SENSOR_THERMISTOR_44008_44032_30K_AT_25C : 01389 case ADMW1001_ADC_SENSOR_THERMISTOR_YSI_400 : 01390 case ADMW1001_ADC_SENSOR_THERMISTOR_SPECTRUM_1003K_1K : 01391 case ADMW1001_ADC_SENSOR_THERMISTOR_CUSTOM_STEINHART_HART : 01392 case ADMW1001_ADC_SENSOR_THERMISTOR_CUSTOM_TABLE : 01393 case ADMW1001_ADC_SENSOR_SINGLE_ENDED_ABSOLUTE : 01394 case ADMW1001_ADC_SENSOR_DIFFERENTIAL_ABSOLUTE : 01395 case ADMW1001_ADC_SENSOR_SINGLE_ENDED_RATIO : 01396 case ADMW1001_ADC_SENSOR_DIFFERENTIAL_RATIO : 01397 01398 if (! (ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId) || 01399 ADMW1001_CHANNEL_IS_ADC(eChannelId) )) { 01400 ADMW_LOG_ERROR( 01401 "Invalid ADC sensor type %d specified for channel %d", 01402 sensorType, eChannelId); 01403 return ADMW_INVALID_PARAM ; 01404 } 01405 break; 01406 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J : 01407 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K : 01408 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T : 01409 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_E : 01410 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_N : 01411 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_R : 01412 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_S : 01413 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_B : 01414 case ADMW1001_ADC_SENSOR_THERMOCOUPLE_CUSTOM : 01415 if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) { 01416 ADMW_LOG_ERROR( 01417 "Invalid ADC sensor type %d specified for channel %d", 01418 sensorType, eChannelId); 01419 return ADMW_INVALID_PARAM ; 01420 } 01421 break; 01422 default: 01423 ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified", 01424 sensorType); 01425 return ADMW_INVALID_PARAM ; 01426 } 01427 01428 sensorTypeReg.Sensor_Type = sensorType; 01429 01430 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01431 01432 return ADMW_SUCCESS ; 01433 } 01434 01435 static ADMW_RESULT admw_SetChannelAdcSensorDetails( 01436 ADMW_DEVICE_HANDLE hDevice, 01437 ADMW1001_CH_ID eChannelId, 01438 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01439 /* 01440 * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers 01441 * General details: 01442 * - Measurement_Units 01443 * - Compensation_Channel 01444 * - CJC_Publish (if "CJC" was removed from the name) 01445 * ADC-specific details: 01446 * - PGA_Gain 01447 * - Reference_Select 01448 * - Reference_Buffer_Disable 01449 */ 01450 { 01451 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ; 01452 ADMW1001_ADC_REFERENCE_TYPE refType = pAdcChannelConfig->reference ; 01453 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01454 01455 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01456 01457 switch(pChannelConfig->measurementUnit ) { 01458 case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT : 01459 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF; 01460 break; 01461 case ADMW1001_MEASUREMENT_UNIT_CELSIUS : 01462 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC; 01463 break; 01464 case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED : 01465 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01466 break; 01467 default: 01468 ADMW_LOG_ERROR("Invalid measurement unit %d specified", 01469 pChannelConfig->measurementUnit ); 01470 return ADMW_INVALID_PARAM ; 01471 } 01472 01473 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01474 sensorDetailsReg.Compensation_Disable = 1; 01475 sensorDetailsReg.Compensation_Channel = 0; 01476 } else { 01477 sensorDetailsReg.Compensation_Disable = 0; 01478 sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ; 01479 } 01480 01481 switch(refType) { 01482 case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL : 01483 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT; 01484 break; 01485 case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 : 01486 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1; 01487 break; 01488 case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD : 01489 sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD; 01490 break; 01491 default: 01492 ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType); 01493 return ADMW_INVALID_PARAM ; 01494 } 01495 01496 switch(pAdcChannelConfig->gain ) { 01497 case ADMW1001_ADC_GAIN_1X : 01498 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1; 01499 break; 01500 case ADMW1001_ADC_GAIN_2X : 01501 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2; 01502 break; 01503 case ADMW1001_ADC_GAIN_4X : 01504 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4; 01505 break; 01506 case ADMW1001_ADC_GAIN_8X : 01507 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8; 01508 break; 01509 case ADMW1001_ADC_GAIN_16X : 01510 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16; 01511 break; 01512 case ADMW1001_ADC_GAIN_32X : 01513 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32; 01514 break; 01515 case ADMW1001_ADC_GAIN_64X : 01516 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64; 01517 break; 01518 case ADMW1001_ADC_GAIN_128X : 01519 sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128; 01520 break; 01521 default: 01522 ADMW_LOG_ERROR("Invalid ADC gain %d specified", 01523 pAdcChannelConfig->gain ); 01524 return ADMW_INVALID_PARAM ; 01525 } 01526 01527 switch(pAdcChannelConfig->rtdCurve ) { 01528 case ADMW1001_ADC_RTD_CURVE_EUROPEAN : 01529 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE; 01530 break; 01531 case ADMW1001_ADC_RTD_CURVE_AMERICAN : 01532 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE; 01533 break; 01534 case ADMW1001_ADC_RTD_CURVE_JAPANESE : 01535 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE; 01536 break; 01537 case ADMW1001_ADC_RTD_CURVE_ITS90 : 01538 sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE; 01539 break; 01540 default: 01541 ADMW_LOG_ERROR("Invalid RTD Curve %d specified", 01542 pAdcChannelConfig->rtdCurve ); 01543 return ADMW_INVALID_PARAM ; 01544 } 01545 01546 if (pChannelConfig->disablePublishing ) { 01547 sensorDetailsReg.Do_Not_Publish = 1; 01548 } else { 01549 sensorDetailsReg.Do_Not_Publish = 0; 01550 } 01551 01552 switch (pChannelConfig->lutSelect ) { 01553 case ADMW1001_LUT_DEFAULT : 01554 case ADMW1001_LUT_CUSTOM : 01555 sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ; 01556 break; 01557 default: 01558 ADMW_LOG_ERROR("Invalid LUT selection %d specified", 01559 pChannelConfig->lutSelect ); 01560 return ADMW_INVALID_PARAM ; 01561 } 01562 01563 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01564 01565 return ADMW_SUCCESS ; 01566 } 01567 01568 static ADMW_RESULT admw_SetChannelAdcMeasurementSetup( 01569 ADMW_DEVICE_HANDLE hDevice, 01570 ADMW1001_CH_ID eChannelId, 01571 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig) 01572 { 01573 ADMW_CORE_Measurement_Setup_t MeasSetupReg; 01574 ADMW1001_ADC_FILTER_CONFIG *pFilterConfig = &pAdcChannelConfig->filter ; 01575 MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn); 01576 MeasSetupReg.Buffer_Bypass = pAdcChannelConfig->bufferBypass ; 01577 01578 if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC4 ) { 01579 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4; 01580 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01581 } else if (pFilterConfig->type == ADMW1001_ADC_FILTER_SINC3 ) { 01582 MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3; 01583 MeasSetupReg.ADC_SF = pFilterConfig->sf ; 01584 } else { 01585 ADMW_LOG_ERROR("Invalid ADC filter type %d specified", 01586 pFilterConfig->type ); 01587 return ADMW_INVALID_PARAM ; 01588 } 01589 01590 /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */ 01591 MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ; 01592 01593 if(pFilterConfig->notch1p2 ) 01594 MeasSetupReg.NOTCH_EN_2 = 1; 01595 else 01596 MeasSetupReg.NOTCH_EN_2 = 0; 01597 01598 WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId)); 01599 01600 return ADMW_SUCCESS ; 01601 } 01602 01603 static ADMW_RESULT admw_SetChannelAdcCurrentConfig( 01604 ADMW_DEVICE_HANDLE hDevice, 01605 ADMW1001_CH_ID eChannelId, 01606 ADMW1001_ADC_EXC_CURRENT_CONFIG *pCurrentConfig) 01607 { 01608 ADMW_CORE_Channel_Excitation_t channelExcitationReg; 01609 01610 channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn); 01611 01612 if (pCurrentConfig->outputLevel == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT ) 01613 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE; 01614 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_EXTERNAL ) 01615 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL; 01616 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_50uA ) 01617 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA; 01618 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_100uA ) 01619 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA; 01620 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_250uA ) 01621 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA; 01622 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_500uA ) 01623 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA; 01624 else if (pCurrentConfig->outputLevel == ADMW1001_ADC_EXC_CURRENT_1000uA ) 01625 channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA; 01626 else { 01627 ADMW_LOG_ERROR("Invalid ADC excitation current %d specified", 01628 pCurrentConfig->outputLevel ); 01629 return ADMW_INVALID_PARAM ; 01630 } 01631 01632 WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId)); 01633 01634 return ADMW_SUCCESS ; 01635 } 01636 01637 ADMW_RESULT admw_SetAdcChannelConfig( 01638 ADMW_DEVICE_HANDLE hDevice, 01639 ADMW1001_CH_ID eChannelId, 01640 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01641 { 01642 ADMW_RESULT eRet; 01643 ADMW1001_ADC_CHANNEL_CONFIG *pAdcChannelConfig = 01644 &pChannelConfig->adcChannelConfig ; 01645 01646 eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId, 01647 pAdcChannelConfig->sensor ); 01648 if (eRet != ADMW_SUCCESS ) { 01649 ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d", 01650 eChannelId); 01651 return eRet; 01652 } 01653 01654 eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId, 01655 pChannelConfig); 01656 if (eRet != ADMW_SUCCESS ) { 01657 ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d", 01658 eChannelId); 01659 return eRet; 01660 } 01661 01662 eRet = admw_SetChannelAdcMeasurementSetup(hDevice, eChannelId, 01663 pAdcChannelConfig); 01664 if (eRet != ADMW_SUCCESS ) { 01665 ADMW_LOG_ERROR("Failed to set ADC filter for channel %d", 01666 eChannelId); 01667 return eRet; 01668 } 01669 01670 eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId, 01671 &pAdcChannelConfig->current ); 01672 if (eRet != ADMW_SUCCESS ) { 01673 ADMW_LOG_ERROR("Failed to set ADC current for channel %d", 01674 eChannelId); 01675 return eRet; 01676 } 01677 01678 return ADMW_SUCCESS ; 01679 } 01680 01681 static ADMW_RESULT admw_SetChannelDigitalSensorDetails( 01682 ADMW_DEVICE_HANDLE hDevice, 01683 ADMW1001_CH_ID eChannelId, 01684 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01685 { 01686 ADMW_CORE_Sensor_Details_t sensorDetailsReg; 01687 01688 sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn); 01689 01690 if (pChannelConfig->compensationChannel == ADMW1001_CH_ID_NONE ) { 01691 sensorDetailsReg.Compensation_Disable = 1; 01692 sensorDetailsReg.Compensation_Channel = 0; 01693 } else { 01694 ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor"); 01695 return ADMW_INVALID_PARAM ; 01696 } 01697 01698 if (pChannelConfig->measurementUnit == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) { 01699 sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED; 01700 } else { 01701 ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel"); 01702 return ADMW_INVALID_PARAM ; 01703 } 01704 01705 if (pChannelConfig->disablePublishing ) 01706 sensorDetailsReg.Do_Not_Publish = 1; 01707 else 01708 sensorDetailsReg.Do_Not_Publish = 0; 01709 01710 WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId)); 01711 01712 return ADMW_SUCCESS ; 01713 } 01714 01715 static ADMW_RESULT admw_SetDigitalSensorFormat( 01716 ADMW_DEVICE_HANDLE hDevice, 01717 ADMW1001_CH_ID eChannelId, 01718 ADMW1001_DIGITAL_SENSOR_DATA_FORMAT *pDataFormat) 01719 { 01720 ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg; 01721 01722 sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn); 01723 01724 if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) { 01725 if (pDataFormat->frameLength == 0) { 01726 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01727 return ADMW_INVALID_PARAM ; 01728 } 01729 if (pDataFormat->numDataBits == 0) { 01730 ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format"); 01731 return ADMW_INVALID_PARAM ; 01732 } 01733 01734 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES, 01735 pDataFormat->frameLength - 1); 01736 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS, 01737 pDataFormat->numDataBits - 1); 01738 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET, 01739 pDataFormat->bitOffset); 01740 01741 sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1; 01742 sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1; 01743 sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset; 01744 sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0; 01745 sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0; 01746 01747 switch (pDataFormat->coding) { 01748 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR: 01749 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR; 01750 break; 01751 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT: 01752 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL; 01753 break; 01754 case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY: 01755 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY; 01756 break; 01757 default: 01758 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format"); 01759 return ADMW_INVALID_PARAM ; 01760 } 01761 } else { 01762 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE; 01763 } 01764 01765 WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16, 01766 CORE_DIGITAL_SENSOR_CONFIGn(eChannelId)); 01767 01768 01769 return ADMW_SUCCESS ; 01770 } 01771 01772 static ADMW_RESULT admw_SetDigitalCalibrationParam( 01773 ADMW_DEVICE_HANDLE hDevice, 01774 ADMW1001_CH_ID eChannelId, 01775 ADMW1001_DIGITAL_CALIBRATION_COMMAND *pCalibrationParam) 01776 { 01777 // ADMW_CORE_Calibration_Parameter_t calibrationParamReg; 01778 // 01779 // calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn); 01780 // 01781 // if (pCalibrationParam->enableCalibrationParam == false) 01782 // calibrationParamReg.Calibration_Parameter_Enable = 0; 01783 // else 01784 // calibrationParamReg.Calibration_Parameter_Enable = 1; 01785 // 01786 // CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER, 01787 // pCalibrationParam->calibrationParam); 01788 // 01789 // calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam; 01790 // 01791 // WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32, 01792 // CORE_CALIBRATION_PARAMETERn(eChannelId)); 01793 // 01794 return ADMW_SUCCESS ; 01795 } 01796 01797 static ADMW_RESULT admw_SetChannelI2cSensorType( 01798 ADMW_DEVICE_HANDLE hDevice, 01799 ADMW1001_CH_ID eChannelId, 01800 ADMW1001_I2C_SENSOR_TYPE sensorType) 01801 { 01802 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01803 01804 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01805 01806 /* Ensure that the sensor type is valid for this channel */ 01807 switch(sensorType) { 01808 case ADMW1001_I2C_SENSOR_HUMIDITY : 01809 case ADMW1001_I2C_SENSOR_TEMPERATURE_ADT742X : 01810 sensorTypeReg.Sensor_Type = sensorType; 01811 break; 01812 default: 01813 ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType); 01814 return ADMW_INVALID_PARAM ; 01815 } 01816 01817 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 01818 01819 return ADMW_SUCCESS ; 01820 } 01821 01822 static ADMW_RESULT admw_SetChannelI2cSensorAddress( 01823 ADMW_DEVICE_HANDLE hDevice, 01824 ADMW1001_CH_ID eChannelId, 01825 uint32_t deviceAddress) 01826 { 01827 CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress); 01828 WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId)); 01829 01830 return ADMW_SUCCESS ; 01831 } 01832 01833 static ADMW_RESULT admw_SetDigitalChannelComms( 01834 ADMW_DEVICE_HANDLE hDevice, 01835 ADMW1001_CH_ID eChannelId, 01836 ADMW1001_DIGITAL_SENSOR_COMMS *pDigitalComms) 01837 { 01838 ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms; 01839 01840 digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn); 01841 01842 if(pDigitalComms->useCustomCommsConfig ) { 01843 01844 if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) { 01845 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K; 01846 } else if(pDigitalComms->i2cClockSpeed == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) { 01847 digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K; 01848 } else { 01849 ADMW_LOG_ERROR("Invalid I2C clock speed %d specified", 01850 pDigitalComms->i2cClockSpeed ); 01851 return ADMW_INVALID_PARAM ; 01852 } 01853 01854 if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) { 01855 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0; 01856 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) { 01857 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1; 01858 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) { 01859 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2; 01860 } else if(pDigitalComms->spiMode == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) { 01861 digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3; 01862 } else { 01863 ADMW_LOG_ERROR("Invalid SPI mode %d specified", 01864 pDigitalComms->spiMode ); 01865 return ADMW_INVALID_PARAM ; 01866 } 01867 01868 switch (pDigitalComms->spiClock ) { 01869 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ : 01870 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ; 01871 break; 01872 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ : 01873 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ; 01874 break; 01875 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ : 01876 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ; 01877 break; 01878 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ : 01879 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ; 01880 break; 01881 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ : 01882 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ; 01883 break; 01884 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ : 01885 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ; 01886 break; 01887 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ : 01888 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ; 01889 break; 01890 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ : 01891 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ; 01892 break; 01893 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ : 01894 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ; 01895 break; 01896 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ : 01897 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ; 01898 break; 01899 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ : 01900 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ; 01901 break; 01902 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ : 01903 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ; 01904 break; 01905 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ : 01906 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ; 01907 break; 01908 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ : 01909 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ; 01910 break; 01911 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ : 01912 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ; 01913 break; 01914 case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ : 01915 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ; 01916 break; 01917 default: 01918 ADMW_LOG_ERROR("Invalid SPI clock %d specified", 01919 pDigitalComms->spiClock ); 01920 return ADMW_INVALID_PARAM ; 01921 } 01922 } 01923 01924 01925 WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId)); 01926 01927 return ADMW_SUCCESS ; 01928 } 01929 01930 ADMW_RESULT admw_SetI2cChannelConfig( 01931 ADMW_DEVICE_HANDLE hDevice, 01932 ADMW1001_CH_ID eChannelId, 01933 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 01934 { 01935 ADMW_RESULT eRet; 01936 ADMW1001_I2C_CHANNEL_CONFIG *pI2cChannelConfig = 01937 &pChannelConfig->i2cChannelConfig ; 01938 01939 eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId, 01940 pI2cChannelConfig->sensor ); 01941 if (eRet != ADMW_SUCCESS ) { 01942 ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d", 01943 eChannelId); 01944 return eRet; 01945 } 01946 01947 eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId, 01948 pI2cChannelConfig->deviceAddress ); 01949 if (eRet != ADMW_SUCCESS ) { 01950 ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d", 01951 eChannelId); 01952 return eRet; 01953 } 01954 01955 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 01956 pChannelConfig); 01957 if (eRet != ADMW_SUCCESS ) { 01958 ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d", 01959 eChannelId); 01960 return eRet; 01961 } 01962 01963 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 01964 &pI2cChannelConfig->dataFormat ); 01965 if (eRet != ADMW_SUCCESS ) { 01966 ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d", 01967 eChannelId); 01968 return eRet; 01969 } 01970 01971 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 01972 &pI2cChannelConfig->digitalCalibrationParam ); 01973 if (eRet != ADMW_SUCCESS ) { 01974 ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d", 01975 eChannelId); 01976 return eRet; 01977 } 01978 01979 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 01980 &pI2cChannelConfig->configureComms ); 01981 if (eRet != ADMW_SUCCESS ) { 01982 ADMW_LOG_ERROR("Failed to set I2C comms for channel %d", 01983 eChannelId); 01984 return eRet; 01985 } 01986 01987 return ADMW_SUCCESS ; 01988 } 01989 01990 static ADMW_RESULT admw_SetChannelSpiSensorType( 01991 ADMW_DEVICE_HANDLE hDevice, 01992 ADMW1001_CH_ID eChannelId, 01993 ADMW1001_SPI_SENSOR_TYPE sensorType) 01994 { 01995 ADMW_CORE_Sensor_Type_t sensorTypeReg; 01996 01997 sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn); 01998 01999 /* Ensure that the sensor type is valid for this channel */ 02000 switch(sensorType) { 02001 case ADMW1001_SPI_SENSOR: 02002 02003 sensorTypeReg.Sensor_Type = sensorType; 02004 break; 02005 default: 02006 ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType); 02007 return ADMW_INVALID_PARAM ; 02008 } 02009 02010 WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId)); 02011 02012 return ADMW_SUCCESS ; 02013 } 02014 02015 ADMW_RESULT admw_SetSpiChannelConfig( 02016 ADMW_DEVICE_HANDLE hDevice, 02017 ADMW1001_CH_ID eChannelId, 02018 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 02019 { 02020 ADMW_RESULT eRet; 02021 ADMW1001_SPI_CHANNEL_CONFIG *pSpiChannelConfig = 02022 &pChannelConfig->spiChannelConfig ; 02023 02024 eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId, 02025 pSpiChannelConfig->sensor ); 02026 if (eRet != ADMW_SUCCESS ) { 02027 ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d", 02028 eChannelId); 02029 return eRet; 02030 } 02031 02032 eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId, 02033 pChannelConfig); 02034 if (eRet != ADMW_SUCCESS ) { 02035 ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d", 02036 eChannelId); 02037 return eRet; 02038 } 02039 02040 eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId, 02041 &pSpiChannelConfig->dataFormat ); 02042 if (eRet != ADMW_SUCCESS ) { 02043 ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d", 02044 eChannelId); 02045 return eRet; 02046 } 02047 02048 eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId, 02049 &pSpiChannelConfig->digitalCalibrationParam ); 02050 if (eRet != ADMW_SUCCESS ) { 02051 ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d", 02052 eChannelId); 02053 return eRet; 02054 } 02055 02056 eRet = admw_SetDigitalChannelComms(hDevice, eChannelId, 02057 &pSpiChannelConfig->configureComms ); 02058 if (eRet != ADMW_SUCCESS ) { 02059 ADMW_LOG_ERROR("Failed to set SPI comms for channel %d", 02060 eChannelId); 02061 return eRet; 02062 } 02063 02064 return ADMW_SUCCESS ; 02065 } 02066 02067 ADMW_RESULT admw1001_SetChannelThresholdLimits( 02068 ADMW_DEVICE_HANDLE hDevice, 02069 ADMW1001_CH_ID eChannelId, 02070 float32_t fHighThresholdLimit, 02071 float32_t fLowThresholdLimit) 02072 { 02073 /* 02074 * If the low/high limits are *both* set to 0 in memory, or NaNs, assume 02075 * that they are unset, or not required, and use infinity defaults instead 02076 */ 02077 if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) { 02078 fHighThresholdLimit = INFINITY; 02079 fLowThresholdLimit = -INFINITY; 02080 } else { 02081 if (isnan(fHighThresholdLimit)) 02082 fHighThresholdLimit = INFINITY; 02083 if (isnan(fLowThresholdLimit)) 02084 fLowThresholdLimit = -INFINITY; 02085 } 02086 02087 WRITE_REG_FLOAT(hDevice, fHighThresholdLimit, 02088 CORE_HIGH_THRESHOLD_LIMITn(eChannelId)); 02089 WRITE_REG_FLOAT(hDevice, fLowThresholdLimit, 02090 CORE_LOW_THRESHOLD_LIMITn(eChannelId)); 02091 02092 return ADMW_SUCCESS ; 02093 } 02094 02095 ADMW_RESULT admw1001_SetOffsetGain( 02096 ADMW_DEVICE_HANDLE hDevice, 02097 ADMW1001_CH_ID eChannelId, 02098 float32_t fOffsetAdjustment, 02099 float32_t fGainAdjustment) 02100 { 02101 /* Replace with default values if NaNs are specified (or 0.0 for gain) */ 02102 if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f)) 02103 fGainAdjustment = 1.0f; 02104 if (isnan(fOffsetAdjustment)) 02105 fOffsetAdjustment = 0.0f; 02106 02107 WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId)); 02108 WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId)); 02109 02110 return ADMW_SUCCESS ; 02111 } 02112 02113 ADMW_RESULT admw1001_SetSensorParameter( 02114 ADMW_DEVICE_HANDLE hDevice, 02115 ADMW1001_CH_ID eChannelId, 02116 float32_t fSensorParam) 02117 { 02118 if (fSensorParam == 0.0f) 02119 fSensorParam = NAN; 02120 02121 //WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId)); 02122 02123 return ADMW_SUCCESS ; 02124 } 02125 02126 ADMW_RESULT admw1001_SetChannelSettlingTime( 02127 ADMW_DEVICE_HANDLE hDevice, 02128 ADMW1001_CH_ID eChannelId, 02129 uint32_t nSettlingTime) 02130 { 02131 ADMW_CORE_Settling_Time_t settlingTimeReg; 02132 02133 CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime); 02134 settlingTimeReg.Settling_Time = nSettlingTime; 02135 02136 WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId)); 02137 02138 return ADMW_SUCCESS ; 02139 } 02140 02141 ADMW_RESULT admw1001_SetChannelConfig( 02142 ADMW_DEVICE_HANDLE hDevice, 02143 ADMW1001_CH_ID eChannelId, 02144 ADMW1001_CHANNEL_CONFIG *pChannelConfig) 02145 { 02146 ADMW_RESULT eRet; 02147 02148 if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) { 02149 eRet = admw1001_SetChannelCount(hDevice, eChannelId, 02150 pChannelConfig->enableChannel ? 02151 pChannelConfig->measurementsPerCycle : 0); 02152 if (eRet != ADMW_SUCCESS ) { 02153 ADMW_LOG_ERROR("Failed to set measurement count for channel %d", 02154 eChannelId); 02155 return eRet; 02156 } 02157 02158 eRet = admw1001_SetChannelOptions(hDevice, eChannelId, 02159 pChannelConfig->priority ); 02160 if (eRet != ADMW_SUCCESS ) { 02161 ADMW_LOG_ERROR("Failed to set priority for channel %d", 02162 eChannelId); 02163 return eRet; 02164 } 02165 02166 /* If the channel is not enabled, we can skip the following steps */ 02167 if (pChannelConfig->enableChannel ) { 02168 eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId, 02169 pChannelConfig->cycleSkipCount ); 02170 if (eRet != ADMW_SUCCESS ) { 02171 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d", 02172 eChannelId); 02173 return eRet; 02174 } 02175 02176 switch (eChannelId) { 02177 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL : 02178 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL : 02179 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL : 02180 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL : 02181 eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig); 02182 break; 02183 case ADMW1001_CH_ID_DIG_I2C_0 : 02184 case ADMW1001_CH_ID_DIG_I2C_1 : 02185 eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig); 02186 break; 02187 case ADMW1001_CH_ID_DIG_SPI_0 : 02188 eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig); 02189 break; 02190 default: 02191 ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId); 02192 eRet = ADMW_INVALID_PARAM ; 02193 #if 0 02194 /* when using i2c sensors there is an error ( dataformat->length=0) 02195 the code below catches this error and this causes further problems.*/ 02196 break; 02197 } 02198 if (eRet != ADMW_SUCCESS ) { 02199 ADMW_LOG_ERROR("Failed to set config for channel %d", 02200 eChannelId); 02201 return eRet; 02202 #endif 02203 } 02204 02205 eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId, 02206 pChannelConfig->extraSettlingTime ); 02207 if (eRet != ADMW_SUCCESS ) { 02208 ADMW_LOG_ERROR("Failed to set settling time for channel %d", 02209 eChannelId); 02210 return eRet; 02211 } 02212 } 02213 } 02214 02215 if (pChannelConfig->enableChannel ) { 02216 /* Threshold limits can be configured individually for virtual channels */ 02217 eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId, 02218 pChannelConfig->highThreshold , 02219 pChannelConfig->lowThreshold ); 02220 if (eRet != ADMW_SUCCESS ) { 02221 ADMW_LOG_ERROR("Failed to set threshold limits for channel %d", 02222 eChannelId); 02223 return eRet; 02224 } 02225 02226 /* Offset and gain can be configured individually for virtual channels */ 02227 eRet = admw1001_SetOffsetGain(hDevice, eChannelId, 02228 pChannelConfig->offsetAdjustment , 02229 pChannelConfig->gainAdjustment ); 02230 if (eRet != ADMW_SUCCESS ) { 02231 ADMW_LOG_ERROR("Failed to set offset/gain for channel %d", 02232 eChannelId); 02233 return eRet; 02234 } 02235 02236 /* Set sensor specific parameter */ 02237 eRet = admw1001_SetSensorParameter(hDevice, eChannelId, 02238 pChannelConfig->sensorParameter ); 02239 if (eRet != ADMW_SUCCESS ) { 02240 ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d", 02241 eChannelId); 02242 return eRet; 02243 } 02244 } 02245 02246 return ADMW_SUCCESS ; 02247 } 02248 02249 ADMW_RESULT admw_SetConfig( 02250 ADMW_DEVICE_HANDLE const hDevice, 02251 ADMW_CONFIG * const pConfig) 02252 { 02253 ADMW1001_CONFIG *pDeviceConfig; 02254 ADMW_PRODUCT_ID productId; 02255 ADMW_RESULT eRet; 02256 02257 if (pConfig->productId != ADMW_PRODUCT_ID_ADMW1001 ) { 02258 ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)", 02259 pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 ); 02260 return ADMW_INVALID_PARAM ; 02261 } 02262 02263 if (!((pConfig->versionId .major ==VERSIONID_MAJOR) && 02264 (pConfig->versionId .minor ==VERSIONID_MINOR))) { 02265 ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported", 02266 pConfig->versionId ); 02267 return ADMW_INVALID_PARAM ; 02268 } 02269 02270 02271 /* Check that the actual Product ID is a match? */ 02272 eRet = admw_GetProductID(hDevice, &productId); 02273 if (eRet) { 02274 ADMW_LOG_ERROR("Failed to read device Product ID register"); 02275 return eRet; 02276 } 02277 if (pConfig->productId != productId) { 02278 ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)", 02279 pConfig->productId , productId); 02280 return ADMW_INVALID_PARAM ; 02281 } 02282 02283 pDeviceConfig = &pConfig->admw1001 ; 02284 02285 eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power ); 02286 if (eRet) { 02287 ADMW_LOG_ERROR("Failed to set power configuration"); 02288 return eRet; 02289 } 02290 02291 eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement ); 02292 if (eRet) { 02293 ADMW_LOG_ERROR("Failed to set measurement configuration"); 02294 return eRet; 02295 } 02296 02297 eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics ); 02298 if (eRet) { 02299 ADMW_LOG_ERROR("Failed to set diagnostics configuration"); 02300 return eRet; 02301 } 02302 02303 for (ADMW1001_CH_ID id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ; 02304 id < ADMW1001_MAX_CHANNELS ; 02305 id++) { 02306 eRet = admw1001_SetChannelConfig(hDevice, id, 02307 &pDeviceConfig->channels [id]); 02308 if (eRet) { 02309 ADMW_LOG_ERROR("Failed to set channel %d configuration", id); 02310 return eRet; 02311 } 02312 } 02313 02314 return ADMW_SUCCESS ; 02315 } 02316 02317 02318 ADMW_RESULT admw1001_SetLutDataRaw( 02319 ADMW_DEVICE_HANDLE const hDevice, 02320 ADMW1001_LUT_RAW * const pLutData) 02321 { 02322 return admw1001_SetLutData(hDevice, 02323 (ADMW1001_LUT *)pLutData); 02324 } 02325 02326 static ADMW_RESULT getLutTableSize( 02327 ADMW1001_LUT_DESCRIPTOR * const pDesc, 02328 ADMW1001_LUT_TABLE_DATA * const pData, 02329 unsigned *pLength) 02330 { 02331 switch (pDesc->geometry) { 02332 case ADMW1001_LUT_GEOMETRY_COEFFS: 02333 if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN) 02334 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList); 02335 break; 02336 case ADMW1001_LUT_GEOMETRY_NES_1D: 02337 *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes); 02338 break; 02339 default: 02340 ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n", 02341 pDesc->geometry); 02342 return ADMW_INVALID_PARAM ; 02343 } 02344 02345 return ADMW_SUCCESS ; 02346 } 02347 02348 ADMW_RESULT admw1001_AssembleLutData( 02349 ADMW1001_LUT * pLutBuffer, 02350 unsigned nLutBufferSize, 02351 unsigned const nNumTables, 02352 ADMW1001_LUT_DESCRIPTOR * const ppDesc[], 02353 ADMW1001_LUT_TABLE_DATA * const ppData[]) 02354 { 02355 ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header; 02356 uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr); 02357 02358 if (sizeof(*pHdr) > nLutBufferSize) { 02359 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02360 return ADMW_INVALID_PARAM ; 02361 } 02362 02363 /* First initialise the top-level header */ 02364 pHdr->signature = ADMW_LUT_SIGNATURE; 02365 pHdr->version.major = 1; 02366 pHdr->version.minor = 0; 02367 pHdr->numTables = 0; 02368 pHdr->totalLength = 0; 02369 02370 /* 02371 * Walk through the list of table pointers provided, appending the table 02372 * descriptor+data from each one to the provided LUT buffer 02373 */ 02374 for (unsigned i = 0; i < nNumTables; i++) { 02375 ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i]; 02376 ADMW1001_LUT_TABLE_DATA * const pData = ppData[i]; 02377 ADMW_RESULT res; 02378 unsigned dataLength = 0; 02379 02380 /* Calculate the length of the table data */ 02381 res = getLutTableSize(pDesc, pData, &dataLength); 02382 if (res != ADMW_SUCCESS ) 02383 return res; 02384 02385 /* Fill in the table descriptor length and CRC fields */ 02386 pDesc->length = dataLength; 02387 pDesc->crc16 = admw_crc16_ccitt(pData, dataLength); 02388 02389 if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) { 02390 ADMW_LOG_ERROR("Insufficient LUT buffer size provided"); 02391 return ADMW_INVALID_PARAM ; 02392 } 02393 02394 /* Append the table to the LUT buffer (desc + data) */ 02395 memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc)); 02396 pHdr->totalLength += sizeof(*pDesc); 02397 memcpy(pLutTableData + pHdr->totalLength, pData, dataLength); 02398 pHdr->totalLength += dataLength; 02399 02400 pHdr->numTables++; 02401 } 02402 02403 return ADMW_SUCCESS ; 02404 } 02405 ADMW_RESULT admw1001_SetLutData( 02406 ADMW_DEVICE_HANDLE const hDevice, 02407 ADMW1001_LUT * const pLutData) 02408 { 02409 ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header; 02410 ADMW1001_LUT_TABLE *pLutTable = pLutData->tables; 02411 02412 unsigned actualLength = 0; 02413 02414 if (pLutData->header.signature != ADMW_LUT_SIGNATURE) { 02415 ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)", 02416 ADMW_LUT_SIGNATURE, pLutHeader->signature); 02417 return ADMW_INVALID_SIGNATURE ; 02418 } 02419 if ((pLutData->tables->descriptor.geometry!= ADMW1001_LUT_GEOMETRY_NES_1D) && 02420 (pLutData->tables->data.lut1dNes.nElements > MAX_LUT_NUM_ENTRIES)) { 02421 return ADMW_INVALID_PARAM ; 02422 } 02423 02424 for (unsigned i = 0; i < pLutHeader->numTables; i++) { 02425 ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor; 02426 ADMW1001_LUT_TABLE_DATA *pData = &pLutTable->data; 02427 unsigned short calculatedCrc; 02428 02429 switch (pDesc->geometry) { 02430 case ADMW1001_LUT_GEOMETRY_COEFFS: 02431 switch (pDesc->equation) { 02432 case ADMW1001_LUT_EQUATION_POLYN: 02433 case ADMW1001_LUT_EQUATION_POLYNEXP: 02434 case ADMW1001_LUT_EQUATION_QUADRATIC: 02435 case ADMW1001_LUT_EQUATION_STEINHART: 02436 case ADMW1001_LUT_EQUATION_LOGARITHMIC: 02437 case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN: 02438 break; 02439 default: 02440 ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u", 02441 pDesc->equation, i); 02442 return ADMW_INVALID_PARAM ; 02443 } 02444 break; 02445 case ADMW1001_LUT_GEOMETRY_NES_1D: 02446 break; 02447 default: 02448 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u", 02449 pDesc->geometry, i); 02450 return ADMW_INVALID_PARAM ; 02451 } 02452 02453 switch (pDesc->dataType) { 02454 case ADMW1001_LUT_DATA_TYPE_FLOAT32: 02455 case ADMW1001_LUT_DATA_TYPE_FLOAT64: 02456 break; 02457 default: 02458 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u", 02459 pDesc->dataType, i); 02460 return ADMW_INVALID_PARAM ; 02461 } 02462 02463 calculatedCrc = admw_crc16_ccitt(pData, pDesc->length); 02464 if (calculatedCrc != pDesc->crc16) { 02465 ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)", 02466 i, pDesc->crc16, calculatedCrc); 02467 return ADMW_CRC_ERROR ; 02468 } 02469 02470 actualLength += sizeof(*pDesc) + pDesc->length; 02471 02472 /* Move to the next look-up table */ 02473 pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length); 02474 } 02475 02476 if (actualLength != pLutHeader->totalLength) { 02477 ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)", 02478 pLutHeader->totalLength, actualLength); 02479 return ADMW_WRONG_SIZE ; 02480 } 02481 02482 if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) { 02483 ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded", 02484 ADMW_LUT_MAX_SIZE); 02485 return ADMW_WRONG_SIZE ; 02486 } 02487 02488 /* Write the LUT data to the device */ 02489 unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength; 02490 WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET); 02491 WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA); 02492 02493 return ADMW_SUCCESS ; 02494 }
Generated on Wed Jul 13 2022 05:15:07 by
1.7.2