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