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