initial commit

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers admw_1001.c Source File

admw_1001.c

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