Bumped Mbed FW version to 01.20.0080

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     else if (statusReg.Drdy)
00320         pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_DATAREADY ;
00321     else if(statusReg.FIFO_Error == ADMW_DEVICE_STATUS_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 == ADMW_DEVICE_STATUS_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 static ADMW_RESULT  admw_SetExtVrefBufferMode(
01067     ADMW_DEVICE_HANDLE  hDevice,
01068     ADMW1001_VREF_BUFFER_MODE  extVrefBufferMode)
01069 {
01070     ADMW_CORE_EXT_VBUFF_t VrefBuffReg = { 0 };
01071 
01072     if (extVrefBufferMode == ADMW1001_VREF_BUFF_MODE_DISABLE_BOTH )
01073     {
01074         VrefBuffReg.EXT_VBUFF = CORE_EXT_VBUFF_BOTH_INACTIVE_MODE;
01075     }
01076     else if (extVrefBufferMode == ADMW1001_VREF_BUFF_MODE_ONLY_POS )
01077     {
01078         VrefBuffReg.EXT_VBUFF = CORE_EXT_VBUFF_ONLY_VPOS_MODE;
01079     }
01080     else if (extVrefBufferMode == ADMW1001_VREF_BUFF_MODE_ENABLE_BOTH )
01081     {
01082         VrefBuffReg.EXT_VBUFF = CORE_EXT_VBUFF_BOTH_ACTIVE_MODE;
01083     }
01084     else
01085     {
01086         ADMW_LOG_ERROR("Unsupported Ext Vref Buffer mode %d specified", extVrefBufferMode);
01087         return ADMW_INVALID_PARAM ;
01088     }
01089 
01090     WRITE_REG_U8(hDevice, VrefBuffReg.VALUE8, CORE_EXT_VBUFF);
01091 
01092     return ADMW_SUCCESS ;
01093 
01094 }
01095 
01096 ADMW_RESULT  admw1001_SetMeasurementConfig(
01097     ADMW_DEVICE_HANDLE  hDevice,
01098     ADMW1001_MEASUREMENT_CONFIG  *pMeasConfig)
01099 {
01100     ADMW_RESULT  eRet;
01101 
01102     eRet = admw_SetMode(hDevice,
01103                         pMeasConfig->operatingMode ,
01104                         pMeasConfig->dataReadyMode );
01105     if (eRet != ADMW_SUCCESS ) {
01106         ADMW_LOG_ERROR("Failed to set operating mode");
01107         return eRet;
01108     }
01109 
01110     eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval ,
01111                                 pMeasConfig->vBiasEnable ,
01112                                 pMeasConfig->excitationState ,
01113                                 pMeasConfig->groundSwitch  );
01114     if (eRet != ADMW_SUCCESS ) {
01115         ADMW_LOG_ERROR("Failed to set cycle control");
01116         return eRet;
01117     }
01118 
01119     if (pMeasConfig->fifoNumCycles  > 0) {
01120         eRet = admw_SetFifoNumCycles(hDevice,
01121                                      pMeasConfig->fifoNumCycles );
01122     }
01123 
01124     if (eRet != ADMW_SUCCESS ) {
01125         ADMW_LOG_ERROR("Failed to set the FIFO number of cycles.");
01126         return eRet;
01127     }
01128 
01129     if(pMeasConfig->externalRef1Value  > 0) {
01130         eRet = admw_SetExternalReferenceValues(hDevice,
01131                                                pMeasConfig->externalRef1Value );
01132     }
01133 
01134     if (eRet != ADMW_SUCCESS ) {
01135         ADMW_LOG_ERROR("Failed to set external reference values");
01136         return eRet;
01137     }
01138 
01139     if((pMeasConfig->AVDDVoltage  >= 3.0) && (pMeasConfig->AVDDVoltage  <= 3.6)) {
01140         eRet = admw_SetAVDDVoltage(hDevice,
01141                                    pMeasConfig->AVDDVoltage );
01142     }
01143 
01144     if (eRet != ADMW_SUCCESS ) {
01145         ADMW_LOG_ERROR("Failed to set AVDD Voltge");
01146         return eRet;
01147     }
01148 
01149     eRet = admw_SetRSenseValue(hDevice, pMeasConfig->RSenseValue );
01150     if (eRet != ADMW_SUCCESS ) {
01151         ADMW_LOG_ERROR("Failed to set RSenseValue");
01152         return eRet;
01153     }
01154 
01155     eRet = admw_SetExternalReferenceVoltage(hDevice, pMeasConfig->externalRefVoltage );
01156     if (eRet != ADMW_SUCCESS ) {
01157         ADMW_LOG_ERROR("Failed to set External reference Voltage");
01158         return eRet;
01159     }
01160     eRet = admw_SetExtVrefBufferMode(hDevice, (ADMW1001_VREF_BUFFER_MODE )pMeasConfig->extVrefBuffMode );
01161     if (eRet != ADMW_SUCCESS )
01162     {
01163         ADMW_LOG_ERROR("Failed to set External Vref Buffer Mode");
01164         return eRet;
01165     }
01166 
01167     return ADMW_SUCCESS ;
01168 }
01169 ADMW_RESULT  admw1001_SetDiagnosticsConfig(
01170     ADMW_DEVICE_HANDLE  hDevice,
01171     ADMW1001_DIAGNOSTICS_CONFIG  *pDiagnosticsConfig)
01172 {
01173     ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg;
01174 
01175     diagnosticsControlReg.VALUE8 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL);
01176 
01177     if (pDiagnosticsConfig->disableMeasurementDiag )
01178         diagnosticsControlReg.Diag_Meas_En = 0;
01179     else
01180         diagnosticsControlReg.Diag_Meas_En = 1;
01181 
01182     if(pDiagnosticsConfig->osdFrequency  <= 0x7F) {
01183         diagnosticsControlReg.Diag_OSD_Freq = pDiagnosticsConfig->osdFrequency ;
01184     } else {
01185         ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified",
01186                        pDiagnosticsConfig->osdFrequency );
01187         return ADMW_INVALID_PARAM ;
01188     }
01189     WRITE_REG_U8(hDevice, diagnosticsControlReg.VALUE8, CORE_DIAGNOSTICS_CONTROL);
01190 
01191     return ADMW_SUCCESS ;
01192 }
01193 
01194 uint16_t totalChannelCount(ADMW_DEVICE_HANDLE  hDevice,ADMW1001_CHANNEL_CONFIG *pChannelConfig)
01195 {
01196     uint16_t channelCount=0;
01197     channelCount=pChannelConfig->measurementsPerCycle ;
01198     return channelCount;
01199 }
01200 
01201 ADMW_RESULT  admw1001_SetChannelCount(
01202     ADMW_DEVICE_HANDLE  hDevice,
01203     ADMW1001_CH_ID  eChannelId,
01204     uint32_t nMeasurementsPerCycle)
01205 {
01206     ADMW_CORE_Channel_Count_t channelCountReg;
01207 
01208     channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn);
01209 
01210     if (nMeasurementsPerCycle > 0) {
01211         nMeasurementsPerCycle -= 1;
01212 
01213         CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT,
01214                             nMeasurementsPerCycle);
01215 
01216         channelCountReg.Channel_Enable = 1;
01217         channelCountReg.Channel_Count = nMeasurementsPerCycle;
01218     } else {
01219         channelCountReg.Channel_Enable = 0;
01220     }
01221 
01222     WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId));
01223 
01224     return ADMW_SUCCESS ;
01225 }
01226 
01227 ADMW_RESULT  admw1001_SetChannelOptions(
01228     ADMW_DEVICE_HANDLE  hDevice,
01229     ADMW1001_CH_ID  eChannelId,
01230     ADMW1001_CHANNEL_PRIORITY  ePriority)
01231 {
01232     ADMW_CORE_Channel_Options_t channelOptionsReg;
01233 
01234     channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn);
01235 
01236     CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority);
01237     channelOptionsReg.Channel_Priority = ePriority;
01238 
01239     WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId));
01240 
01241     return ADMW_SUCCESS ;
01242 }
01243 
01244 ADMW_RESULT  admw1001_SetChannelSkipCount(
01245     ADMW_DEVICE_HANDLE  hDevice,
01246     ADMW1001_CH_ID  eChannelId,
01247     uint32_t nCycleSkipCount)
01248 {
01249     ADMW_CORE_Channel_Skip_t channelSkipReg;
01250 
01251     channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn);
01252 
01253     CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount);
01254 
01255     channelSkipReg.Channel_Skip = nCycleSkipCount;
01256 
01257     WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId));
01258 
01259     return ADMW_SUCCESS ;
01260 }
01261 
01262 static ADMW_RESULT  admw_SetChannelAdcSensorType(
01263     ADMW_DEVICE_HANDLE           hDevice,
01264     ADMW1001_CH_ID               eChannelId,
01265     ADMW1001_ADC_SENSOR_TYPE     sensorType)
01266 {
01267     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01268 
01269     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01270 
01271     /* Ensure that the sensor type is valid for this channel */
01272     switch(sensorType) {
01273         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT10 :
01274 
01275         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT50 :
01276         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 :
01277         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT200 :
01278         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT500 :
01279         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 :
01280         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000_0P00375 :
01281         case ADMW1001_ADC_SENSOR_RTD_2WIRE_NI120 :
01282         case ADMW1001_ADC_SENSOR_RTD_2WIRE_CUSTOM :
01283         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT10 :
01284 
01285         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT50 :
01286         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 :
01287         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT200 :
01288         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT500 :
01289         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 :
01290         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000_0P00375 :
01291         case ADMW1001_ADC_SENSOR_RTD_4WIRE_NI120 :
01292         case ADMW1001_ADC_SENSOR_RTD_4WIRE_CUSTOM :
01293         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT10 :
01294 
01295         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT50 :
01296         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 :
01297         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT200 :
01298         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT500 :
01299         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 :
01300         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000_0P00375  :
01301 
01302         case ADMW1001_ADC_SENSOR_RTD_3WIRE_NI120 :
01303         case ADMW1001_ADC_SENSOR_RTD_3WIRE_CUSTOM :
01304         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE :
01305         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE :
01306         case ADMW1001_ADC_SENSOR_DIODE :
01307         case ADMW1001_ADC_SENSOR_THERMISTOR_44004_44033_2P252K_AT_25C :
01308         case ADMW1001_ADC_SENSOR_THERMISTOR_44005_44030_3K_AT_25C :
01309         case ADMW1001_ADC_SENSOR_THERMISTOR_44007_44034_5K_AT_25C :
01310         case ADMW1001_ADC_SENSOR_THERMISTOR_44006_44031_10K_AT_25C :
01311         case ADMW1001_ADC_SENSOR_THERMISTOR_44008_44032_30K_AT_25C :
01312         case ADMW1001_ADC_SENSOR_THERMISTOR_YSI_400 :
01313         case ADMW1001_ADC_SENSOR_THERMISTOR_SPECTRUM_1003K_1K :
01314         case ADMW1001_ADC_SENSOR_THERMISTOR_CUSTOM_STEINHART_HART :
01315         case ADMW1001_ADC_SENSOR_THERMISTOR_CUSTOM_TABLE :
01316         case ADMW1001_ADC_SENSOR_SINGLE_ENDED_ABSOLUTE :
01317         case ADMW1001_ADC_SENSOR_DIFFERENTIAL_ABSOLUTE :
01318         case ADMW1001_ADC_SENSOR_SINGLE_ENDED_RATIO :
01319         case ADMW1001_ADC_SENSOR_DIFFERENTIAL_RATIO :
01320 
01321             if (! (ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId) ||
01322                     ADMW1001_CHANNEL_IS_ADC(eChannelId) )) {
01323                 ADMW_LOG_ERROR(
01324                     "Invalid ADC sensor type %d specified for channel %d",
01325                     sensorType, eChannelId);
01326                 return ADMW_INVALID_PARAM ;
01327             }
01328             break;
01329         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J :
01330         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K :
01331         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T :
01332         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_E :
01333         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_N :
01334         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_R :
01335         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_S :
01336         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_B :
01337         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_CUSTOM :
01338             if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) {
01339                 ADMW_LOG_ERROR(
01340                     "Invalid ADC sensor type %d specified for channel %d",
01341                     sensorType, eChannelId);
01342                 return ADMW_INVALID_PARAM ;
01343             }
01344             break;
01345         default:
01346             ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified",
01347                            sensorType);
01348             return ADMW_INVALID_PARAM ;
01349     }
01350 
01351     sensorTypeReg.Sensor_Type = sensorType;
01352 
01353     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01354 
01355     return ADMW_SUCCESS ;
01356 }
01357 
01358 static ADMW_RESULT  admw_SetChannelAdcSensorDetails(
01359     ADMW_DEVICE_HANDLE       hDevice,
01360     ADMW1001_CH_ID           eChannelId,
01361     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01362 /*
01363  * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers
01364  * General details:
01365  * - Measurement_Units
01366  * - Compensation_Channel
01367  * - CJC_Publish (if "CJC" was removed from the name)
01368  * ADC-specific details:
01369  * - PGA_Gain
01370  * - Reference_Select
01371  * - Reference_Buffer_Disable
01372  */
01373 {
01374     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ;
01375     ADMW1001_ADC_REFERENCE_TYPE  refType            = pAdcChannelConfig->reference ;
01376     ADMW_CORE_Sensor_Details_t  sensorDetailsReg;
01377 
01378     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01379 
01380     switch(pChannelConfig->measurementUnit ) {
01381         case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT :
01382             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF;
01383             break;
01384         case ADMW1001_MEASUREMENT_UNIT_CELSIUS :
01385             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC;
01386             break;
01387         case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED :
01388             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01389             break;
01390         default:
01391             ADMW_LOG_ERROR("Invalid measurement unit %d specified",
01392                            pChannelConfig->measurementUnit );
01393             return ADMW_INVALID_PARAM ;
01394     }
01395 
01396     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01397         sensorDetailsReg.Compensation_Disable = 1;
01398         sensorDetailsReg.Compensation_Channel = 0;
01399     } else {
01400         sensorDetailsReg.Compensation_Disable = 0;
01401         sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ;
01402     }
01403 
01404     switch(refType) {
01405         case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL :
01406             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT;
01407             break;
01408         case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 :
01409             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1;
01410             break;
01411         case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD :
01412             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD;
01413             break;
01414         default:
01415             ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType);
01416             return ADMW_INVALID_PARAM ;
01417     }
01418 
01419     switch(pAdcChannelConfig->gain ) {
01420         case ADMW1001_ADC_GAIN_1X :
01421             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1;
01422             break;
01423         case ADMW1001_ADC_GAIN_2X :
01424             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2;
01425             break;
01426         case ADMW1001_ADC_GAIN_4X :
01427             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4;
01428             break;
01429         case ADMW1001_ADC_GAIN_8X :
01430             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8;
01431             break;
01432         case ADMW1001_ADC_GAIN_16X :
01433             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16;
01434             break;
01435         case ADMW1001_ADC_GAIN_32X :
01436             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32;
01437             break;
01438         case ADMW1001_ADC_GAIN_64X :
01439             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64;
01440             break;
01441         default:
01442             ADMW_LOG_ERROR("Invalid ADC gain %d specified",
01443                            pAdcChannelConfig->gain );
01444             return ADMW_INVALID_PARAM ;
01445     }
01446 
01447     switch(pAdcChannelConfig->rtdCurve ) {
01448         case ADMW1001_ADC_RTD_CURVE_EUROPEAN :
01449             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE;
01450             break;
01451         case ADMW1001_ADC_RTD_CURVE_AMERICAN :
01452             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE;
01453             break;
01454         case ADMW1001_ADC_RTD_CURVE_JAPANESE :
01455             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE;
01456             break;
01457         case ADMW1001_ADC_RTD_CURVE_ITS90 :
01458             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE;
01459             break;
01460         default:
01461             ADMW_LOG_ERROR("Invalid RTD Curve %d specified",
01462                            pAdcChannelConfig->rtdCurve );
01463             return ADMW_INVALID_PARAM ;
01464     }
01465 
01466     if (pChannelConfig->disablePublishing ) {
01467         sensorDetailsReg.Do_Not_Publish = 1;
01468     } else {
01469         sensorDetailsReg.Do_Not_Publish = 0;
01470     }
01471 
01472     switch (pChannelConfig->lutSelect ) {
01473         case ADMW1001_LUT_DEFAULT :
01474         case ADMW1001_LUT_CUSTOM :
01475             sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ;
01476             break;
01477         default:
01478             ADMW_LOG_ERROR("Invalid LUT selection %d specified",
01479                            pChannelConfig->lutSelect );
01480             return ADMW_INVALID_PARAM ;
01481     }
01482 
01483     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01484 
01485     return ADMW_SUCCESS ;
01486 }
01487 
01488 static ADMW_RESULT  admw_SetChannelAdcMeasurementSetup(
01489     ADMW_DEVICE_HANDLE  hDevice,
01490     ADMW1001_CH_ID  eChannelId,
01491     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig)
01492 {
01493     ADMW_CORE_Measurement_Setup_t MeasSetupReg;
01494     ADMW1001_ADC_FILTER_CONFIG  *pFilterConfig = &pAdcChannelConfig->filter ;
01495     MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn);
01496     MeasSetupReg.Buffer_Bypass = pAdcChannelConfig->bufferBypass ;
01497 
01498     if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC4 ) {
01499         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4;
01500         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01501     } else if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC3 ) {
01502         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3;
01503         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01504     } else {
01505         ADMW_LOG_ERROR("Invalid ADC filter type %d specified",
01506                        pFilterConfig->type );
01507         return ADMW_INVALID_PARAM ;
01508     }
01509 
01510     /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */
01511     MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ;
01512 
01513     if(pFilterConfig->notch1p2 )
01514         MeasSetupReg.NOTCH_EN_2 = 1;
01515     else
01516         MeasSetupReg.NOTCH_EN_2 = 0;
01517 
01518     WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId));
01519 
01520     return ADMW_SUCCESS ;
01521 }
01522 
01523 static ADMW_RESULT  admw_SetChannelAdcCurrentConfig(
01524     ADMW_DEVICE_HANDLE  hDevice,
01525     ADMW1001_CH_ID  eChannelId,
01526     ADMW1001_ADC_EXC_CURRENT_CONFIG  *pCurrentConfig)
01527 {
01528     ADMW_CORE_Channel_Excitation_t channelExcitationReg;
01529 
01530     channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn);
01531 
01532     if (pCurrentConfig->outputLevel  == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT )
01533         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE;
01534     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_EXTERNAL )
01535         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL;
01536     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_50uA )
01537         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA;
01538     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_100uA )
01539         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA;
01540     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_250uA )
01541         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA;
01542     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_500uA )
01543         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA;
01544     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_1000uA )
01545         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA;
01546     else {
01547         ADMW_LOG_ERROR("Invalid ADC excitation current %d specified",
01548                        pCurrentConfig->outputLevel );
01549         return ADMW_INVALID_PARAM ;
01550     }
01551 
01552     WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId));
01553 
01554     return ADMW_SUCCESS ;
01555 }
01556 
01557 ADMW_RESULT  admw_SetAdcChannelConfig(
01558     ADMW_DEVICE_HANDLE  hDevice,
01559     ADMW1001_CH_ID  eChannelId,
01560     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01561 {
01562     ADMW_RESULT  eRet;
01563     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig =
01564         &pChannelConfig->adcChannelConfig ;
01565 
01566     eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId,
01567                                         pAdcChannelConfig->sensor );
01568     if (eRet != ADMW_SUCCESS ) {
01569         ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d",
01570                        eChannelId);
01571         return eRet;
01572     }
01573 
01574     eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId,
01575                                            pChannelConfig);
01576     if (eRet != ADMW_SUCCESS ) {
01577         ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d",
01578                        eChannelId);
01579         return eRet;
01580     }
01581 
01582     eRet = admw_SetChannelAdcMeasurementSetup(hDevice, eChannelId,
01583             pAdcChannelConfig);
01584     if (eRet != ADMW_SUCCESS ) {
01585         ADMW_LOG_ERROR("Failed to set ADC filter for channel %d",
01586                        eChannelId);
01587         return eRet;
01588     }
01589 
01590     eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId,
01591                                            &pAdcChannelConfig->current );
01592     if (eRet != ADMW_SUCCESS ) {
01593         ADMW_LOG_ERROR("Failed to set ADC current for channel %d",
01594                        eChannelId);
01595         return eRet;
01596     }
01597 
01598     return ADMW_SUCCESS ;
01599 }
01600 
01601 static ADMW_RESULT  admw_SetChannelDigitalSensorDetails(
01602     ADMW_DEVICE_HANDLE  hDevice,
01603     ADMW1001_CH_ID  eChannelId,
01604     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01605 {
01606     ADMW_CORE_Sensor_Details_t sensorDetailsReg;
01607 
01608     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01609 
01610     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01611         sensorDetailsReg.Compensation_Disable = 1;
01612         sensorDetailsReg.Compensation_Channel = 0;
01613     } else {
01614         ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor");
01615         return ADMW_INVALID_PARAM ;
01616     }
01617 
01618     if (pChannelConfig->measurementUnit  == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) {
01619         sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01620     } else {
01621         ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel");
01622         return ADMW_INVALID_PARAM ;
01623     }
01624 
01625     if (pChannelConfig->disablePublishing )
01626         sensorDetailsReg.Do_Not_Publish = 1;
01627     else
01628         sensorDetailsReg.Do_Not_Publish = 0;
01629 
01630     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01631 
01632     return ADMW_SUCCESS ;
01633 }
01634 
01635 static ADMW_RESULT  admw_SetDigitalSensorFormat(
01636     ADMW_DEVICE_HANDLE  hDevice,
01637     ADMW1001_CH_ID  eChannelId,
01638     ADMW1001_DIGITAL_SENSOR_DATA_FORMAT  *pDataFormat)
01639 {
01640     ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg;
01641 
01642     sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn);
01643 
01644     if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) {
01645         if (pDataFormat->frameLength == 0) {
01646             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01647             return ADMW_INVALID_PARAM ;
01648         }
01649         if (pDataFormat->numDataBits == 0) {
01650             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01651             return ADMW_INVALID_PARAM ;
01652         }
01653 
01654         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES,
01655                             pDataFormat->frameLength - 1);
01656         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS,
01657                             pDataFormat->numDataBits - 1);
01658         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET,
01659                             pDataFormat->bitOffset);
01660 
01661         sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1;
01662         sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1;
01663         sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset;
01664         sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0;
01665         sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0;
01666 
01667         switch (pDataFormat->coding) {
01668             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR:
01669                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR;
01670                 break;
01671             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT:
01672                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL;
01673                 break;
01674             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY:
01675                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY;
01676                 break;
01677             default:
01678                 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format");
01679                 return ADMW_INVALID_PARAM ;
01680         }
01681     } else {
01682         sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE;
01683     }
01684 
01685     WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16,
01686                   CORE_DIGITAL_SENSOR_CONFIGn(eChannelId));
01687 
01688 
01689     return ADMW_SUCCESS ;
01690 }
01691 
01692 
01693 static ADMW_RESULT  admw_SetChannelI2cSensorType(
01694     ADMW_DEVICE_HANDLE  hDevice,
01695     ADMW1001_CH_ID  eChannelId,
01696     ADMW1001_I2C_SENSOR_TYPE  sensorType)
01697 {
01698     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01699 
01700     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01701 
01702     /* Ensure that the sensor type is valid for this channel */
01703     switch(sensorType) {
01704         case ADMW1001_I2C_SENSOR_HUMIDITY :
01705         case ADMW1001_I2C_SENSOR_TEMPERATURE_ADT742X :
01706             sensorTypeReg.Sensor_Type = sensorType;
01707             break;
01708         default:
01709             ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType);
01710             return ADMW_INVALID_PARAM ;
01711     }
01712 
01713     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01714 
01715     return ADMW_SUCCESS ;
01716 }
01717 
01718 static ADMW_RESULT  admw_SetChannelI2cSensorAddress(
01719     ADMW_DEVICE_HANDLE  hDevice,
01720     ADMW1001_CH_ID  eChannelId,
01721     uint32_t deviceAddress)
01722 {
01723     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress);
01724     WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId));
01725 
01726     return ADMW_SUCCESS ;
01727 }
01728 
01729 static ADMW_RESULT  admw_SetDigitalChannelComms(
01730     ADMW_DEVICE_HANDLE  hDevice,
01731     ADMW1001_CH_ID  eChannelId,
01732     ADMW1001_DIGITAL_SENSOR_COMMS  *pDigitalComms)
01733 {
01734     ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms;
01735 
01736     digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn);
01737 
01738     if(pDigitalComms->useCustomCommsConfig ) {
01739 
01740         if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) {
01741             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K;
01742         } else if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) {
01743             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K;
01744         } else {
01745             ADMW_LOG_ERROR("Invalid I2C clock speed %d specified",
01746                            pDigitalComms->i2cClockSpeed );
01747             return ADMW_INVALID_PARAM ;
01748         }
01749 }
01750     WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId));
01751 
01752     return ADMW_SUCCESS ;
01753 }
01754 
01755 ADMW_RESULT  admw_SetI2cChannelConfig(
01756     ADMW_DEVICE_HANDLE  hDevice,
01757     ADMW1001_CH_ID  eChannelId,
01758     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01759 {
01760     ADMW_RESULT  eRet;
01761     ADMW1001_I2C_CHANNEL_CONFIG  *pI2cChannelConfig =
01762         &pChannelConfig->i2cChannelConfig ;
01763 
01764     eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId,
01765                                         pI2cChannelConfig->sensor );
01766     if (eRet != ADMW_SUCCESS ) {
01767         ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d",
01768                        eChannelId);
01769         return eRet;
01770     }
01771 
01772     eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId,
01773                                            pI2cChannelConfig->deviceAddress );
01774     if (eRet != ADMW_SUCCESS ) {
01775         ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d",
01776                        eChannelId);
01777         return eRet;
01778     }
01779 
01780     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
01781             pChannelConfig);
01782     if (eRet != ADMW_SUCCESS ) {
01783         ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d",
01784                        eChannelId);
01785         return eRet;
01786     }
01787 
01788     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
01789                                        &pI2cChannelConfig->dataFormat );
01790     if (eRet != ADMW_SUCCESS ) {
01791         ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d",
01792                        eChannelId);
01793         return eRet;
01794     }
01795 
01796 
01797     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
01798                                        &pI2cChannelConfig->configureComms );
01799     if (eRet != ADMW_SUCCESS ) {
01800         ADMW_LOG_ERROR("Failed to set I2C comms for channel %d",
01801                        eChannelId);
01802         return eRet;
01803     }
01804 
01805     return ADMW_SUCCESS ;
01806 }
01807 
01808 static ADMW_RESULT  admw_SetChannelSpiSensorType(
01809     ADMW_DEVICE_HANDLE  hDevice,
01810     ADMW1001_CH_ID  eChannelId,
01811     ADMW1001_SPI_SENSOR_TYPE  sensorType)
01812 {
01813     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01814 
01815     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01816 
01817     /* Ensure that the sensor type is valid for this channel */
01818     switch(sensorType) {
01819         case ADMW1001_SPI_SENSOR:
01820 
01821             sensorTypeReg.Sensor_Type = sensorType;
01822             break;
01823         default:
01824             ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType);
01825             return ADMW_INVALID_PARAM ;
01826     }
01827 
01828     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01829 
01830     return ADMW_SUCCESS ;
01831 }
01832 
01833 
01834 ADMW_RESULT  admw1001_SetChannelThresholdLimits(
01835     ADMW_DEVICE_HANDLE  hDevice,
01836     ADMW1001_CH_ID  eChannelId,
01837     float32_t fHighThresholdLimit,
01838     float32_t fLowThresholdLimit)
01839 {
01840     /*
01841      * If the low/high limits are *both* set to 0 in memory, or NaNs, assume
01842      * that they are unset, or not required, and use infinity defaults instead
01843      */
01844     if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) {
01845         fHighThresholdLimit = INFINITY;
01846         fLowThresholdLimit = -INFINITY;
01847     } else {
01848         if (isnan(fHighThresholdLimit))
01849             fHighThresholdLimit = INFINITY;
01850         if (isnan(fLowThresholdLimit))
01851             fLowThresholdLimit = -INFINITY;
01852     }
01853 
01854     WRITE_REG_FLOAT(hDevice, fHighThresholdLimit,
01855                     CORE_HIGH_THRESHOLD_LIMITn(eChannelId));
01856     WRITE_REG_FLOAT(hDevice, fLowThresholdLimit,
01857                     CORE_LOW_THRESHOLD_LIMITn(eChannelId));
01858 
01859     return ADMW_SUCCESS ;
01860 }
01861 
01862 ADMW_RESULT  admw1001_SetOffsetGain(
01863     ADMW_DEVICE_HANDLE  hDevice,
01864     ADMW1001_CH_ID  eChannelId,
01865     float32_t fOffsetAdjustment,
01866     float32_t fGainAdjustment)
01867 {
01868     /* Replace with default values if NaNs are specified (or 0.0 for gain) */
01869     if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f))
01870         fGainAdjustment = 1.0f;
01871     if (isnan(fOffsetAdjustment))
01872         fOffsetAdjustment = 0.0f;
01873 
01874     WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId));
01875     WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId));
01876 
01877     return ADMW_SUCCESS ;
01878 }
01879 
01880 ADMW_RESULT  admw1001_SetSensorParameter(
01881     ADMW_DEVICE_HANDLE  hDevice,
01882     ADMW1001_CH_ID  eChannelId,
01883     float32_t fSensorParam)
01884 {
01885     if (fSensorParam == 0.0f)
01886         fSensorParam = NAN;
01887 
01888     //WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId));
01889 
01890     return ADMW_SUCCESS ;
01891 }
01892 
01893 ADMW_RESULT  admw1001_SetChannelSettlingTime(
01894     ADMW_DEVICE_HANDLE  hDevice,
01895     ADMW1001_CH_ID  eChannelId,
01896     uint32_t nSettlingTime)
01897 {
01898     ADMW_CORE_Settling_Time_t settlingTimeReg;
01899 
01900     CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime);
01901     settlingTimeReg.Settling_Time = nSettlingTime;
01902 
01903     WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId));
01904 
01905     return ADMW_SUCCESS ;
01906 }
01907 
01908 ADMW_RESULT  admw1001_SetChannelConfig(
01909     ADMW_DEVICE_HANDLE  hDevice,
01910     ADMW1001_CH_ID  eChannelId,
01911     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01912 {
01913     ADMW_RESULT  eRet;
01914 
01915         eRet = admw1001_SetChannelCount(hDevice, eChannelId,
01916                                         pChannelConfig->enableChannel  ?
01917                                         pChannelConfig->measurementsPerCycle  : 0);
01918         if (eRet != ADMW_SUCCESS ) {
01919             ADMW_LOG_ERROR("Failed to set measurement count for channel %d",
01920                            eChannelId);
01921             return eRet;
01922         }
01923 
01924         eRet = admw1001_SetChannelOptions(hDevice, eChannelId,
01925                                           pChannelConfig->priority );
01926         if (eRet != ADMW_SUCCESS ) {
01927             ADMW_LOG_ERROR("Failed to set priority for channel %d",
01928                            eChannelId);
01929             return eRet;
01930         }
01931 
01932         /* If the channel is not enabled, we can skip the following steps */
01933         if (pChannelConfig->enableChannel ) {
01934             eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId,
01935                                                 pChannelConfig->cycleSkipCount );
01936             if (eRet != ADMW_SUCCESS ) {
01937                 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d",
01938                                eChannelId);
01939                 return eRet;
01940             }
01941 
01942             switch (eChannelId) {
01943                 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL :
01944                 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL :
01945                 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL :
01946                 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL :
01947                     eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig);
01948                     break;
01949                 case ADMW1001_CH_ID_DIG_I2C_0 :
01950                 case ADMW1001_CH_ID_DIG_I2C_1 :
01951                     eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig);
01952                     break;
01953                 default:
01954                     ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId);
01955                     eRet = ADMW_INVALID_PARAM ;
01956 #if 0
01957                     /* when using i2c sensors there is an error ( dataformat->length=0)
01958                     the code below catches this error and this causes further problems.*/
01959                     break;
01960             }
01961             if (eRet != ADMW_SUCCESS ) {
01962                 ADMW_LOG_ERROR("Failed to set config for channel %d",
01963                                eChannelId);
01964                 return eRet;
01965 #endif
01966             }
01967 
01968             eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId,
01969                                                    pChannelConfig->extraSettlingTime );
01970             if (eRet != ADMW_SUCCESS ) {
01971                 ADMW_LOG_ERROR("Failed to set settling time for channel %d",
01972                                eChannelId);
01973                 return eRet;
01974             }
01975         }
01976 
01977     if (pChannelConfig->enableChannel ) {
01978         /* Threshold limits can be configured individually for virtual channels */
01979         eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId,
01980                 pChannelConfig->highThreshold ,
01981                 pChannelConfig->lowThreshold );
01982         if (eRet != ADMW_SUCCESS ) {
01983             ADMW_LOG_ERROR("Failed to set threshold limits for channel %d",
01984                            eChannelId);
01985             return eRet;
01986         }
01987 
01988         /* Offset and gain can be configured individually for virtual channels */
01989         eRet = admw1001_SetOffsetGain(hDevice, eChannelId,
01990                                       pChannelConfig->offsetAdjustment ,
01991                                       pChannelConfig->gainAdjustment );
01992         if (eRet != ADMW_SUCCESS ) {
01993             ADMW_LOG_ERROR("Failed to set offset/gain for channel %d",
01994                            eChannelId);
01995             return eRet;
01996         }
01997 
01998         /* Set sensor specific parameter */
01999         eRet = admw1001_SetSensorParameter(hDevice, eChannelId,
02000                                            pChannelConfig->sensorParameter );
02001         if (eRet != ADMW_SUCCESS ) {
02002             ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d",
02003                            eChannelId);
02004             return eRet;
02005         }
02006     }
02007 
02008     return ADMW_SUCCESS ;
02009 }
02010 
02011 ADMW_RESULT  admw_SetConfig(
02012     ADMW_DEVICE_HANDLE     const hDevice,
02013     ADMW_CONFIG          * const pConfig)
02014 {
02015     ADMW1001_CONFIG  *pDeviceConfig;
02016     ADMW_PRODUCT_ID  productId;
02017     ADMW_RESULT  eRet;
02018 
02019     if (pConfig->productId  != ADMW_PRODUCT_ID_ADMW1001 ) {
02020         ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)",
02021                        pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 );
02022         return ADMW_INVALID_PARAM ;
02023     }
02024 
02025     if (!((pConfig->versionId .major ==VERSIONID_MAJOR) &&
02026             (pConfig->versionId .minor ==VERSIONID_MINOR))) {
02027         ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported",
02028                        pConfig->versionId );
02029         return ADMW_INVALID_PARAM ;
02030     }
02031 
02032 
02033     /* Check that the actual Product ID is a match? */
02034     eRet = admw_GetProductID(hDevice, &productId);
02035     if (eRet) {
02036         ADMW_LOG_ERROR("Failed to read device Product ID register");
02037         return eRet;
02038     }
02039     if (pConfig->productId  != productId) {
02040         ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)",
02041                        pConfig->productId , productId);
02042         return ADMW_INVALID_PARAM ;
02043     }
02044 
02045     pDeviceConfig = &pConfig->admw1001 ;
02046 
02047     eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power );
02048     if (eRet) {
02049         ADMW_LOG_ERROR("Failed to set power configuration");
02050         return eRet;
02051     }
02052 
02053     eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement );
02054     if (eRet) {
02055         ADMW_LOG_ERROR("Failed to set measurement configuration");
02056         return eRet;
02057     }
02058 
02059     eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics );
02060     if (eRet) {
02061         ADMW_LOG_ERROR("Failed to set diagnostics configuration");
02062         return eRet;
02063     }
02064 
02065     for (ADMW1001_CH_ID  id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
02066             id < ADMW1001_MAX_CHANNELS ;
02067             id++) {
02068         eRet = admw1001_SetChannelConfig(hDevice, id,
02069                                          &pDeviceConfig->channels [id]);
02070         if (eRet) {
02071             ADMW_LOG_ERROR("Failed to set channel %d configuration", id);
02072             return eRet;
02073         }
02074     }
02075 
02076     return ADMW_SUCCESS ;
02077 }
02078 
02079 
02080 ADMW_RESULT  admw1001_SetLutDataRaw(
02081     ADMW_DEVICE_HANDLE     const hDevice,
02082     ADMW1001_LUT_RAW   * const pLutData)
02083 {
02084     return admw1001_SetLutData(hDevice,
02085                                (ADMW1001_LUT *)pLutData);
02086 }
02087 
02088 static ADMW_RESULT  getLutTableSize(
02089     ADMW1001_LUT_DESCRIPTOR * const pDesc,
02090     ADMW1001_LUT_TABLE_DATA  * const pData,
02091     unsigned *pLength)
02092 {
02093     switch (pDesc->geometry) {
02094         case ADMW1001_LUT_GEOMETRY_NES_1D:
02095             *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes);
02096             break;
02097         default:
02098             ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n",
02099                            pDesc->geometry);
02100             return ADMW_INVALID_PARAM ;
02101     }
02102 
02103     return ADMW_SUCCESS ;
02104 }
02105 
02106 ADMW_RESULT  admw1001_AssembleLutData(
02107     ADMW1001_LUT                  * pLutBuffer,
02108     unsigned                              nLutBufferSize,
02109     unsigned                        const nNumTables,
02110     ADMW1001_LUT_DESCRIPTOR * const ppDesc[],
02111     ADMW1001_LUT_TABLE_DATA  * const ppData[])
02112 {
02113     ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header;
02114     uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr);
02115 
02116     if (sizeof(*pHdr) > nLutBufferSize)
02117     {
02118         ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02119         return ADMW_INVALID_PARAM ;
02120     }
02121 
02122     /* First initialise the top-level header */
02123     pHdr->signature = ADMW_LUT_SIGNATURE;
02124     pHdr->version.major = 1;
02125     pHdr->version.minor = 0;
02126     pHdr->numTables = 0;
02127     pHdr->totalLength = 0;
02128 
02129     /*
02130      * Walk through the list of table pointers provided, appending the table
02131      * descriptor+data from each one to the provided LUT buffer
02132      */
02133     for (unsigned i = 0; i < nNumTables; i++)
02134     {
02135         ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i];
02136         ADMW1001_LUT_TABLE_DATA  * const pData = ppData[i];
02137         ADMW_RESULT  res;
02138         unsigned dataLength = 0;
02139 
02140         /* Calculate the length of the table data */
02141         res = getLutTableSize(pDesc, pData, &dataLength);
02142         if (res != ADMW_SUCCESS )
02143             return res;
02144 
02145         /* Fill in the table descriptor length and CRC fields */
02146         pDesc->length = dataLength;
02147 
02148         if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize)
02149         {
02150             ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02151             return ADMW_INVALID_PARAM ;
02152         }
02153 
02154         /* Append the table to the LUT buffer (desc + data) */
02155         memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc));
02156         pHdr->totalLength += sizeof(*pDesc);
02157         memcpy(pLutTableData + pHdr->totalLength, pData, dataLength);
02158         pHdr->totalLength += dataLength;
02159 
02160         pHdr->numTables++;
02161     }
02162 
02163     return ADMW_SUCCESS ;
02164 }
02165 ADMW_RESULT  admw1001_SetLutData(
02166     ADMW_DEVICE_HANDLE    const hDevice,
02167     ADMW1001_LUT       * const pLutData)
02168 {
02169 #pragma diag_suppress=Pa039
02170     ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header;
02171     ADMW1001_LUT_TABLE  *pLutTable = pLutData->tables;
02172 
02173     unsigned actualLength = 0;
02174 
02175     if (pLutData->header.signature != ADMW_LUT_SIGNATURE)
02176     {
02177         ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)",
02178                             ADMW_LUT_SIGNATURE, pLutHeader->signature);
02179         return ADMW_INVALID_SIGNATURE ;
02180     }
02181     if ((pLutData->tables->descriptor.geometry!= ADMW1001_LUT_GEOMETRY_NES_1D) &&
02182         (pLutData->tables->data.lut1dNes.nElements > MAX_LUT_NUM_ENTRIES))
02183     {
02184         return ADMW_INVALID_PARAM ;
02185     }
02186     for (unsigned i = 0; i < pLutHeader->numTables; i++)
02187     {
02188         ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor;
02189 
02190         switch (pDesc->geometry)
02191         {
02192         case ADMW1001_LUT_GEOMETRY_COEFFS:
02193                 switch (pDesc->equation)
02194                 {
02195                 case ADMW1001_LUT_EQUATION_POLYN:
02196                 case ADMW1001_LUT_EQUATION_POLYNEXP:
02197                 case ADMW1001_LUT_EQUATION_QUADRATIC:
02198                 case ADMW1001_LUT_EQUATION_STEINHART:
02199                 case ADMW1001_LUT_EQUATION_LOGARITHMIC:
02200                 case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN:
02201                 break;
02202                 default:
02203                     ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02204                                         pDesc->equation, i);
02205                     return ADMW_INVALID_PARAM ;
02206                 }
02207             break;
02208         case ADMW1001_LUT_GEOMETRY_NES_1D:
02209             break;
02210         default:
02211             ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u",
02212                                 pDesc->geometry, i);
02213             return ADMW_INVALID_PARAM ;
02214         }
02215 
02216         switch (pDesc->dataType)
02217         {
02218         case ADMW1001_LUT_DATA_TYPE_FLOAT32:
02219         case ADMW1001_LUT_DATA_TYPE_FLOAT64:
02220             break;
02221         default:
02222             ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u",
02223                                 pDesc->dataType, i);
02224             return ADMW_INVALID_PARAM ;
02225         }
02226 
02227 
02228         actualLength += sizeof(*pDesc) + pDesc->length;
02229 
02230         /* Move to the next look-up table */
02231         pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length);
02232     }
02233 
02234     if (actualLength != pLutHeader->totalLength)
02235     {
02236         ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)",
02237                             pLutHeader->totalLength, actualLength);
02238         return ADMW_WRONG_SIZE ;
02239     }
02240 
02241     if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE)
02242     {
02243         ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded",
02244                             ADMW_LUT_MAX_SIZE);
02245         return ADMW_WRONG_SIZE ;
02246     }
02247 
02248     /* Write the LUT data to the device */
02249     unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength;
02250     WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET);
02251     WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA);
02252 
02253     return ADMW_SUCCESS ;
02254 }