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