Diaz George / Mbed OS EV-PRO-MW1001
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 
00056 #include "crc16.h"
00057 #define VERSIONID_MAJOR 2
00058 #define VERSIONID_MINOR 0
00059 
00060 uint32_t    getDataCnt = 0;
00061 
00062 /*
00063  * The following macros are used to encapsulate the register access code
00064  * to improve readability in the functions further below in this file
00065  */
00066 #define STRINGIFY(name) #name
00067 
00068 /* Expand the full name of the reset value macro for the specified register */
00069 #define REG_RESET_VAL(_name) REG_##_name##_RESET
00070 
00071 /* Checks if a value is outside the bounds of the specified register field */
00072 #define CHECK_REG_FIELD_VAL(_field, _val)                               \
00073     do {                                                                \
00074         uint32_t _mask  = BITM_##_field;                                \
00075         uint32_t _shift = BITP_##_field;                                \
00076         if ((((_val) << _shift) & ~(_mask)) != 0) {                     \
00077             ADMW_LOG_ERROR("Value 0x%08X invalid for register field %s",\
00078                                 (uint32_t)(_val),                       \
00079                                 STRINGIFY(ADMW_##_field));              \
00080             return ADMW_INVALID_PARAM;                                  \
00081         }                                                               \
00082     } while(false)
00083 
00084 /*
00085  * Encapsulates the write to a specified register
00086  * NOTE - this will cause the calling function to return on error
00087  */
00088 #define WRITE_REG(_hdev, _val, _name, _type)                            \
00089     do {                                                                \
00090         ADMW_RESULT _res;                                               \
00091         _type _regval = _val;                                           \
00092         _res = admw1001_WriteRegister((_hdev),                          \
00093                                             REG_##_name,                \
00094                                             &_regval, sizeof(_regval)); \
00095         if (_res != ADMW_SUCCESS)                                       \
00096             return _res;                                                \
00097     } while(false)
00098 
00099 /* Wrapper macro to write a value to a uint32_t register */
00100 #define WRITE_REG_U32(_hdev, _val, _name)                               \
00101     WRITE_REG(_hdev, _val, _name, uint32_t)
00102 /* Wrapper macro to write a value to a uint16_t register */
00103 #define WRITE_REG_U16(_hdev, _val, _name)                               \
00104     WRITE_REG(_hdev, _val, _name, uint16_t)
00105 /* Wrapper macro to write a value to a uint8_t register */
00106 #define WRITE_REG_U8(_hdev, _val, _name)                                \
00107     WRITE_REG(_hdev, _val, _name, uint8_t)
00108 /* Wrapper macro to write a value to a float32_t register */
00109 #define WRITE_REG_FLOAT(_hdev, _val, _name)                             \
00110     WRITE_REG(_hdev, _val, _name, float32_t)
00111 
00112 /*
00113  * Encapsulates the read from a specified register
00114  * NOTE - this will cause the calling function to return on error
00115  */
00116 #define READ_REG(_hdev, _val, _name, _type)                             \
00117     do {                                                                \
00118         ADMW_RESULT _res;                                               \
00119         _type _regval;                                                  \
00120         _res = admw1001_ReadRegister((_hdev),                           \
00121                                            REG_##_name,                 \
00122                                            &_regval, sizeof(_regval));  \
00123         if (_res != ADMW_SUCCESS)                                       \
00124             return _res;                                                \
00125         _val = _regval;                                                 \
00126     } while(false)
00127 
00128 /* Wrapper macro to read a value from a uint32_t register */
00129 #define READ_REG_U32(_hdev, _val, _name)                                \
00130     READ_REG(_hdev, _val, _name, uint32_t)
00131 /* Wrapper macro to read a value from a uint16_t register */
00132 #define READ_REG_U16(_hdev, _val, _name)                                \
00133     READ_REG(_hdev, _val, _name, uint16_t)
00134 /* Wrapper macro to read a value from a uint8_t register */
00135 #define READ_REG_U8(_hdev, _val, _name)                                 \
00136     READ_REG(_hdev, _val, _name, uint8_t)
00137 /* Wrapper macro to read a value from a float32_t register */
00138 #define READ_REG_FLOAT(_hdev, _val, _name)                              \
00139     READ_REG(_hdev, _val, _name, float32_t)
00140 
00141 /*
00142  * Wrapper macro to write an array of values to a uint8_t register
00143  * NOTE - this is intended only for writing to a keyhole data register
00144  */
00145 #define WRITE_REG_U8_ARRAY(_hdev, _arr, _len, _name)                    \
00146     do {                                                                \
00147         ADMW_RESULT _res;                                               \
00148         _res = admw1001_WriteRegister(_hdev,                            \
00149                                             REG_##_name,                \
00150                                             _arr, _len);                \
00151         if (_res != ADMW_SUCCESS)                                       \
00152             return _res;                                                \
00153     } while(false)
00154 
00155 /*
00156  * Wrapper macro to read an array of values from a uint8_t register
00157  * NOTE - this is intended only for reading from a keyhole data register
00158  */
00159 #define READ_REG_U8_ARRAY(_hdev, _arr, _len, _name)                     \
00160     do {                                                                \
00161         ADMW_RESULT _res;                                               \
00162         _res = admw1001_ReadRegister((_hdev),                           \
00163                                            REG##_name,                  \
00164                                            _arr, _len);                 \
00165         if (_res != ADMW_SUCCESS)                                       \
00166             return _res;                                                \
00167     } while(false)
00168 
00169 #define ADMW1001_CHANNEL_IS_ADC(c)                                      \
00170     ((c) >= ADMW1001_CH_ID_ANLG_1_UNIVERSAL && (c) <= ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL)
00171 
00172 #define ADMW1001_CHANNEL_IS_ADC_CJC(c)                                  \
00173     ((c) >= ADMW1001_CH_ID_ANLG_1_UNIVERSAL && (c) <= ADMW1001_CH_ID_ANLG_2_UNIVERSAL)
00174 
00175 #define ADMW1001_CHANNEL_IS_ADC_SENSOR(c)                               \
00176     ((c) >= ADMW1001_CH_ID_ANLG_1_UNIVERSAL && (c) <= ADMW1001_CH_ID_ANLG_2_UNIVERSAL)
00177 
00178 #define ADMW1001_CHANNEL_IS_ADC_VOLTAGE(c)                              \
00179     ((c) == ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL || ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL)
00180 
00181 #define ADMW1001_CHANNEL_IS_ADC_CURRENT(c)                              \
00182     ((c) == ADMW1001_CH_ID_ANLG_1_UNIVERSAL || (c) == ADMW1001_CH_ID_ANLG_2_UNIVERSAL)
00183 
00184 #define ADMW1001_CHANNEL_IS_VIRTUAL(c)                                  \
00185     ((c) == ADMW1001_CH_ID_DIG_SPI_1 || (c) == ADMW1001_CH_ID_DIG_SPI_2)
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     ADMW_CORE_Alert_Status_2_t alert2Reg;
00316     READ_REG_U16(hDevice, alert2Reg.VALUE16, CORE_ALERT_STATUS_2);
00317 
00318     memset(pStatus, 0, sizeof(*pStatus));
00319 
00320     if (!statusReg.Cmd_Running) /* Active-low, so invert it */
00321         pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_BUSY ;
00322     if (statusReg.Drdy)
00323         pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_DATAREADY ;
00324     if (statusReg.FIFO_Error)
00325         pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_FIFO_ERROR ;
00326     if (statusReg.Alert_Active) {
00327         pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_ALERT ;
00328 
00329         ADMW_CORE_Alert_Code_t alertCodeReg;
00330         READ_REG_U16(hDevice, alertCodeReg.VALUE16, CORE_ALERT_CODE);
00331         pStatus->alertCode  = alertCodeReg.Alert_Code;
00332 
00333         ADMW_CORE_Channel_Alert_Status_t channelAlertStatusReg;
00334         READ_REG_U16(hDevice, channelAlertStatusReg.VALUE16,
00335                      CORE_CHANNEL_ALERT_STATUS);
00336 
00337         for (unsigned i = 0; i < ADMW1001_MAX_CHANNELS ; i++) {
00338             if (channelAlertStatusReg.VALUE16 & (1 << i)) {
00339                 ADMW_CORE_Alert_Code_Ch_t channelAlertCodeReg;
00340                 READ_REG_U16(hDevice, channelAlertCodeReg.VALUE16, CORE_ALERT_CODE_CHn(i));
00341                 pStatus->channelAlertCodes [i] = channelAlertCodeReg.Alert_Code_Ch;
00342 
00343                 ADMW_CORE_Alert_Detail_Ch_t alertDetailReg;
00344                 READ_REG_U16(hDevice, alertDetailReg.VALUE16,
00345                              CORE_ALERT_DETAIL_CHn(i));
00346 
00347                 if (alertDetailReg.Time_Out)
00348                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_TIMEOUT ;
00349                 if (alertDetailReg.Under_Range)
00350                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_UNDER_RANGE ;
00351                 if (alertDetailReg.Over_Range)
00352                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_OVER_RANGE ;
00353                 if (alertDetailReg.Low_Limit)
00354                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LOW_LIMIT ;
00355                 if (alertDetailReg.High_Limit)
00356                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_HIGH_LIMIT ;
00357                 if (alertDetailReg.Sensor_Open)
00358                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_SENSOR_OPEN ;
00359                 if (alertDetailReg.Ref_Detect)
00360                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_REF_DETECT ;
00361                 if (alertDetailReg.Config_Err)
00362                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_CONFIG_ERR ;
00363                 if (alertDetailReg.LUT_Error_Ch)
00364                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LUT_ERR ;
00365                 if (alertDetailReg.Sensor_Not_Ready)
00366                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_SENSOR_NOT_READY ;
00367                 if (alertDetailReg.Comp_Not_Ready)
00368                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_COMP_NOT_READY ;
00369                 if (alertDetailReg.Correction_UnderRange)
00370                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LUT_UNDER_RANGE ;
00371                 if (alertDetailReg.Correction_OverRange)
00372                     pStatus->channelAlerts [i] |= ADMW_CHANNEL_ALERT_LUT_OVER_RANGE ;
00373             }
00374         }
00375 
00376         if (alert2Reg.Configuration_Error)
00377             pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_CONFIG_ERROR ;
00378         if (alert2Reg.LUT_Error)
00379             pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_LUT_ERROR ;
00380     }
00381 
00382     if (statusReg.Error) {
00383         pStatus->deviceStatus  |= ADMW_DEVICE_STATUS_ERROR ;
00384 
00385         ADMW_CORE_Error_Code_t errorCodeReg;
00386         READ_REG_U16(hDevice, errorCodeReg.VALUE16, CORE_ERROR_CODE);
00387         pStatus->errorCode  = errorCodeReg.Error_Code;
00388 
00389         ADMW_CORE_Diagnostics_Status_t diagStatusReg;
00390         READ_REG_U16(hDevice, diagStatusReg.VALUE16, CORE_DIAGNOSTICS_STATUS);
00391 
00392         if (diagStatusReg.Diag_Checksum_Error)
00393             pStatus->diagnosticsStatus  |= ADMW_DIAGNOSTICS_STATUS_CHECKSUM_ERROR ;
00394         if (diagStatusReg.Diag_Conversion_Error)
00395             pStatus->diagnosticsStatus  |= ADMW_DIAGNOSTICS_STATUS_CONVERSION_ERROR ;
00396         if (diagStatusReg.Diag_Calibration_Error)
00397             pStatus->diagnosticsStatus  |= ADMW_DIAGNOSTICS_STATUS_CALIBRATION_ERROR ;
00398     }
00399 
00400     if (statusReg.Alert_Active || statusReg.Error) {
00401         ADMW_CORE_Debug_Code_t debugCodeReg;
00402         READ_REG_U32(hDevice, debugCodeReg.VALUE32, CORE_DEBUG_CODE);
00403         pStatus->debugCode  = debugCodeReg.Debug_Code;
00404     }
00405 
00406     return ADMW_SUCCESS ;
00407 }
00408 
00409 ADMW_RESULT  admw_GetCommandRunningState(
00410     ADMW_DEVICE_HANDLE  hDevice,
00411     bool *pbCommandRunning)
00412 {
00413     ADMW_CORE_Status_t statusReg;
00414 
00415     READ_REG_U8(hDevice, statusReg.VALUE8, CORE_STATUS);
00416 
00417     /* We should never normally see 0xFF here if the module is operational */
00418     if (statusReg.VALUE8 == 0xFF)
00419         return ADMW_ERR_NOT_INITIALIZED ;
00420 
00421     *pbCommandRunning = !statusReg.Cmd_Running; /* Active-low, so invert it */
00422 
00423     return ADMW_SUCCESS ;
00424 }
00425 
00426 static ADMW_RESULT  executeCommand(
00427     ADMW_DEVICE_HANDLE  const hDevice,
00428     ADMW_CORE_Command_Special_Command  const command,
00429     bool const bWaitForCompletion)
00430 {
00431     ADMW_CORE_Command_t commandReg;
00432     bool bCommandRunning;
00433     ADMW_RESULT  eRet;
00434 
00435     /*
00436      * Don't allow another command to be issued if one is already running, but
00437      * make an exception for ENUM_CORE_COMMAND_NOP which can be used to
00438      * request a running command to be stopped (e.g. continuous measurement)
00439      */
00440     if (command != ENUM_CORE_COMMAND_NOP) {
00441         eRet = admw_GetCommandRunningState(hDevice, &bCommandRunning);
00442         if (eRet)
00443             return eRet;
00444 
00445         if (bCommandRunning)
00446             return ADMW_IN_USE ;
00447     }
00448 
00449     commandReg.Special_Command = command;
00450     WRITE_REG_U8(hDevice, commandReg.VALUE8, CORE_COMMAND);
00451 
00452     if (bWaitForCompletion) {
00453         do {
00454             /* Allow a minimum 50usec delay for status update before checking */
00455             admw_TimeDelayUsec(50);
00456 
00457             eRet = admw_GetCommandRunningState(hDevice, &bCommandRunning);
00458             if (eRet)
00459                 return eRet;
00460         } while (bCommandRunning);
00461     }
00462 
00463     return ADMW_SUCCESS ;
00464 }
00465 
00466 ADMW_RESULT  admw_Shutdown(
00467     ADMW_DEVICE_HANDLE  const hDevice)
00468 {
00469     return executeCommand(hDevice, CORE_COMMAND_POWER_DOWN, false);
00470 }
00471 
00472 
00473 ADMW_RESULT  admw_ApplyConfigUpdates(
00474     ADMW_DEVICE_HANDLE  const hDevice)
00475 {
00476     return executeCommand(hDevice, CORE_COMMAND_LATCH_CONFIG, true);
00477 }
00478 
00479 /*!
00480  * @brief Start a measurement cycle.
00481  *
00482  * @param[out]
00483  *
00484  * @return Status
00485  *         - #ADMW_SUCCESS Call completed successfully.
00486  *         - #ADMW_FAILURE
00487  *
00488  * @details Sends the latch config command. Configuration for channels in
00489  *          conversion cycle should be completed before this function.
00490  *          Channel enabled bit should be set before this function.
00491  *          Starts a conversion and configures the format of the sample.
00492  *
00493  */
00494 ADMW_RESULT  admw_StartMeasurement(
00495     ADMW_DEVICE_HANDLE     const hDevice,
00496     ADMW_MEASUREMENT_MODE  const eMeasurementMode)
00497 {
00498     switch (eMeasurementMode) {
00499         case ADMW_MEASUREMENT_MODE_NORMAL :
00500             return executeCommand(hDevice, CORE_COMMAND_CONVERT_WITH_RAW, false);
00501         case ADMW_MEASUREMENT_MODE_OMIT_RAW :
00502             return executeCommand(hDevice, CORE_COMMAND_CONVERT, false);
00503         default:
00504             ADMW_LOG_ERROR("Invalid measurement mode %d specified",
00505                            eMeasurementMode);
00506             return ADMW_INVALID_PARAM ;
00507     }
00508 }
00509 
00510 /*
00511  * Store the configuration settings to persistent memory on the device.
00512  * The settings can be saved to 4 different flash memory areas (slots).
00513  * No other command must be running when this is called.
00514  * Do not power down the device while this command is running.
00515  */
00516 ADMW_RESULT  admw_SaveConfig(
00517     ADMW_DEVICE_HANDLE     const hDevice,
00518     ADMW_USER_CONFIG_SLOT  const eSlotId)
00519 {
00520     switch (eSlotId) {
00521         case ADMW_FLASH_CONFIG_1:
00522             return executeCommand(hDevice, CORE_COMMAND_SAVE_CONFIG_1, true);
00523         default:
00524             ADMW_LOG_ERROR("Invalid user config target slot %d specified",
00525                            eSlotId);
00526             return ADMW_INVALID_PARAM ;
00527     }
00528 }
00529 
00530 /*
00531  * Restore the configuration settings from persistent memory on the device.
00532  * No other command must be running when this is called.
00533  */
00534 ADMW_RESULT  admw_RestoreConfig(
00535     ADMW_DEVICE_HANDLE     const hDevice,
00536     ADMW_USER_CONFIG_SLOT  const eSlotId)
00537 {
00538     switch (eSlotId) {
00539         case ADMW_FLASH_CONFIG_1:
00540             return executeCommand(hDevice, CORE_COMMAND_LOAD_CONFIG_1, true);
00541         default:
00542             ADMW_LOG_ERROR("Invalid user config source slot %d specified",
00543                            eSlotId);
00544             return ADMW_INVALID_PARAM ;
00545     }
00546 }
00547 
00548 /*
00549  * Store the LUT data to persistent memory on the device.
00550  * No other command must be running when this is called.
00551  * Do not power down the device while this command is running.
00552  */
00553 ADMW_RESULT  admw_SaveLutData(
00554     ADMW_DEVICE_HANDLE     const hDevice)
00555 {
00556     return executeCommand(hDevice, CORE_COMMAND_SAVE_LUT, true);
00557 }
00558 
00559 /*
00560  * Restore the LUT data from persistent memory on the device.
00561  * No other command must be running when this is called.
00562  */
00563 ADMW_RESULT  admw_RestoreLutData(
00564     ADMW_DEVICE_HANDLE     const hDevice)
00565 {
00566     return executeCommand(hDevice, CORE_COMMAND_LOAD_LUT, true);
00567 }
00568 
00569 /*
00570  * Stop the measurement cycles on the device.
00571  * To be used only if a measurement command is currently running.
00572  */
00573 ADMW_RESULT  admw_StopMeasurement(
00574     ADMW_DEVICE_HANDLE     const hDevice)
00575 {
00576     return executeCommand(hDevice, CORE_COMMAND_NOP, true);
00577 }
00578 
00579 /*
00580  * Read a set of data samples from the device.
00581  * This may be called at any time.
00582  */
00583 ADMW_RESULT  admw_GetData(
00584     ADMW_DEVICE_HANDLE     const hDevice,
00585     ADMW_MEASUREMENT_MODE  const eMeasurementMode,
00586     ADMW_DATA_SAMPLE     * const pSamples,
00587     uint8_t                    const nBytesPerSample,
00588     uint32_t                   const nRequested,
00589     uint32_t                 * const pnReturned)
00590 {
00591     ADMW1001_Sensor_Result_t  sensorResult;
00592     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00593     uint16_t command = ADMW1001_HOST_COMMS_READ_CMD |
00594                        (REG_CORE_DATA_FIFO & ADMW1001_HOST_COMMS_ADR_MASK);
00595     uint8_t commandData[2] = {
00596         command >> 8,
00597         command & 0xFF
00598     };
00599     uint8_t commandResponse[2];
00600     unsigned nValidSamples = 0;
00601     ADMW_RESULT  eRet = ADMW_SUCCESS ;
00602 
00603     do {
00604         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00605                                 sizeof(command), false);
00606         if (eRet) {
00607             ADMW_LOG_ERROR("Failed to send read command for FIFO register");
00608             return eRet;
00609         }
00610         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00611     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00612              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00613 
00614     for (unsigned i = 0; i < nRequested; i++) {
00615         bool bHoldCs = true;
00616 
00617         /* Keep the CS signal asserted for all but the last sample */
00618         if ((i + 1) == nRequested)
00619             bHoldCs = false;
00620 
00621         getDataCnt++;
00622 
00623         eRet = admw_SpiTransfer(pCtx->hSpi, NULL, &sensorResult,
00624                                 nBytesPerSample, bHoldCs);
00625         if (eRet) {
00626             ADMW_LOG_ERROR("Failed to read data from FIFO register");
00627             return eRet;
00628         }
00629 
00630         if (! sensorResult.Ch_Valid) {
00631             /*
00632              * Reading an invalid sample indicates that there are no
00633              * more samples available or we've lost sync with the device.
00634              * In the latter case, it might be recoverable, but return here
00635              * to let the application check the device status and decide itself.
00636              */
00637             eRet = ADMW_INCOMPLETE ;
00638             break;
00639         }
00640 
00641         ADMW_DATA_SAMPLE  *pSample = &pSamples[nValidSamples];
00642 
00643         pSample->status  = (ADMW_DEVICE_STATUS_FLAGS )0;
00644         if (sensorResult.Ch_Error)
00645             pSample->status  |= ADMW_DEVICE_STATUS_ERROR ;
00646         if (sensorResult.Ch_Alert)
00647             pSample->status  |= ADMW_DEVICE_STATUS_ALERT ;
00648 
00649         if (sensorResult.Ch_Raw)
00650             pSample->rawValue  = sensorResult.Raw_Sample;
00651         else
00652             pSample->rawValue  = 0;
00653 
00654         pSample->channelId  = sensorResult.Channel_ID;
00655         pSample->processedValue  = sensorResult.Sensor_Result;
00656 
00657         nValidSamples++;
00658 
00659         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00660     }
00661     *pnReturned = nValidSamples;
00662 
00663     return eRet;
00664 }
00665 
00666 /*
00667  * Close the given ADMW device.
00668  */
00669 ADMW_RESULT  admw_Close(
00670     ADMW_DEVICE_HANDLE     const hDevice)
00671 {
00672     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00673 
00674     admw_GpioClose(pCtx->hGpio);
00675     admw_SpiClose(pCtx->hSpi);
00676     admw_LogClose();
00677 
00678     return ADMW_SUCCESS ;
00679 }
00680 
00681 ADMW_RESULT  admw1001_WriteRegister(
00682     ADMW_DEVICE_HANDLE  hDevice,
00683     uint16_t nAddress,
00684     void *pData,
00685     unsigned nLength)
00686 {
00687     ADMW_RESULT  eRet;
00688     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00689     uint16_t command = ADMW1001_HOST_COMMS_WRITE_CMD |
00690                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00691     uint8_t commandData[2] = {
00692         command >> 8,
00693         command & 0xFF
00694     };
00695     uint8_t commandResponse[2];
00696 
00697     do {
00698         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00699                                 sizeof(command), false);
00700         if (eRet) {
00701             ADMW_LOG_ERROR("Failed to send write command for register %u",
00702                            nAddress);
00703             return eRet;
00704         }
00705 
00706         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00707     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00708              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00709 
00710     eRet = admw_SpiTransfer(pCtx->hSpi, pData, NULL, nLength, false);
00711     if (eRet) {
00712         ADMW_LOG_ERROR("Failed to write data (%dB) to register %u",
00713                        nLength, nAddress);
00714         return eRet;
00715     }
00716 
00717     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00718 
00719     return ADMW_SUCCESS ;
00720 }
00721 
00722 ADMW_RESULT  admw1001_Write_Debug_Register(
00723     ADMW_DEVICE_HANDLE  hDevice,
00724     uint16_t nAddress,
00725     void *pData,
00726     unsigned nLength)
00727 {
00728     ADMW_RESULT  eRet;
00729     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00730     uint16_t command = ADMW1001_HOST_COMMS_DEBUG_WRITE_CMD |
00731                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00732     uint8_t commandData[2] = {
00733         command >> 8,
00734         command & 0xFF
00735     };
00736     uint8_t commandResponse[2];
00737 
00738     do {
00739         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00740                                 sizeof(command), false);
00741         if (eRet) {
00742             ADMW_LOG_ERROR("Failed to send write command for register %u",
00743                            nAddress);
00744             return eRet;
00745         }
00746 
00747         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00748     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00749              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00750 
00751     eRet = admw_SpiTransfer(pCtx->hSpi, pData, NULL, nLength, false);
00752     if (eRet) {
00753         ADMW_LOG_ERROR("Failed to write data (%dB) to register %u",
00754                        nLength, nAddress);
00755         return eRet;
00756     }
00757 
00758     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00759 
00760     return ADMW_SUCCESS ;
00761 }
00762 ADMW_RESULT  admw1001_ReadRegister(
00763     ADMW_DEVICE_HANDLE  hDevice,
00764     uint16_t nAddress,
00765     void *pData,
00766     unsigned nLength)
00767 {
00768     ADMW_RESULT  eRet;
00769     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00770     uint16_t command = ADMW1001_HOST_COMMS_READ_CMD |
00771                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00772     uint8_t commandData[2] = {
00773         command >> 8,
00774         command & 0xFF
00775     };
00776     uint8_t commandResponse[2];
00777 
00778     do {
00779         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00780                                 sizeof(command), false);
00781         if (eRet) {
00782             ADMW_LOG_ERROR("Failed to send read command for register %u",
00783                            nAddress);
00784             return eRet;
00785         }
00786 
00787         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00788     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00789              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00790 
00791     eRet = admw_SpiTransfer(pCtx->hSpi, NULL, pData, nLength, false);
00792     if (eRet) {
00793         ADMW_LOG_ERROR("Failed to read data (%uB) from register %u",
00794                        nLength, nAddress);
00795         return eRet;
00796     }
00797 
00798     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00799 
00800     return ADMW_SUCCESS ;
00801 }
00802 
00803 ADMW_RESULT  admw1001_Read_Debug_Register(
00804     ADMW_DEVICE_HANDLE  hDevice,
00805     uint16_t nAddress,
00806     void *pData,
00807     unsigned nLength)
00808 {
00809     ADMW_RESULT  eRet;
00810     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00811     uint16_t command = ADMW1001_HOST_COMMS_DEBUG_READ_CMD |
00812                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00813     uint8_t commandData[2] = {
00814         command >> 8,
00815         command & 0xFF
00816     };
00817     uint8_t commandResponse[2];
00818 
00819     do {
00820         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00821                                 sizeof(command), false);
00822         if (eRet) {
00823             ADMW_LOG_ERROR("Failed to send read command for register %u",
00824                            nAddress);
00825             return eRet;
00826         }
00827 
00828         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00829     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00830              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00831 
00832     eRet = admw_SpiTransfer(pCtx->hSpi, NULL, pData, nLength, false);
00833     if (eRet) {
00834         ADMW_LOG_ERROR("Failed to read data (%uB) from register %u",
00835                        nLength, nAddress);
00836         return eRet;
00837     }
00838 
00839     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00840 
00841     return ADMW_SUCCESS ;
00842 }
00843 ADMW_RESULT  admw_GetDeviceReadyState(
00844     ADMW_DEVICE_HANDLE    const hDevice,
00845     bool                  * const bReady)
00846 {
00847     ADMW_SPI_Chip_Type_t chipTypeReg;
00848 
00849     READ_REG_U8(hDevice, chipTypeReg.VALUE8, SPI_CHIP_TYPE);
00850     /* If we read this register successfully, assume the device is ready */
00851     *bReady = (chipTypeReg.VALUE8 == REG_SPI_CHIP_TYPE_RESET);
00852 
00853     return ADMW_SUCCESS ;
00854 }
00855 
00856 ADMW_RESULT  admw1001_GetDataReadyModeInfo(
00857     ADMW_DEVICE_HANDLE         const hDevice,
00858     ADMW_MEASUREMENT_MODE      const eMeasurementMode,
00859     ADMW1001_OPERATING_MODE  * const peOperatingMode,
00860     ADMW1001_DATAREADY_MODE  * const peDataReadyMode,
00861     uint32_t                * const pnSamplesPerDataready,
00862     uint32_t                * const pnSamplesPerCycle,
00863     uint8_t                 * const pnBytesPerSample)
00864 {
00865     unsigned nChannelsEnabled = 0;
00866     unsigned nSamplesPerCycle = 0;
00867 
00868     ADMW_CORE_Mode_t modeReg;
00869     READ_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE);
00870 
00871     if (eMeasurementMode == (modeReg.Conversion_Mode == CORE_MODE_SINGLECYCLE))
00872         *peOperatingMode = ADMW1001_OPERATING_MODE_SINGLECYCLE ;
00873     else
00874         *peOperatingMode = ADMW1001_OPERATING_MODE_CONTINUOUS ;
00875 
00876     if (eMeasurementMode == ADMW_MEASUREMENT_MODE_OMIT_RAW ) {
00877         *pnBytesPerSample = 5;
00878     } else {
00879         *pnBytesPerSample = 8;
00880     }
00881 
00882     for (ADMW1001_CH_ID  chId = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
00883             chId < ADMW1001_MAX_CHANNELS ;
00884             chId++) {
00885         ADMW_CORE_Sensor_Details_t sensorDetailsReg;
00886         ADMW_CORE_Channel_Count_t channelCountReg;
00887 
00888         if (ADMW1001_CHANNEL_IS_VIRTUAL(chId))
00889             continue;
00890 
00891         READ_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(chId));
00892         READ_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(chId));
00893 
00894         if (channelCountReg.Channel_Enable && !sensorDetailsReg.Do_Not_Publish) {
00895             ADMW_CORE_Sensor_Type_t sensorTypeReg;
00896             unsigned nActualChannels = 1;
00897 
00898             READ_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(chId));
00899 
00900             if (chId == ADMW1001_CH_ID_DIG_SPI_0 ) {
00901                 /* Some sensors automatically generate samples on additional
00902                  * "virtual" channels so these channels must be counted as
00903                  * active when those sensors are selected and we use the count
00904                  * from the corresponding "physical" channel
00905                  */
00906                 if ((sensorTypeReg.Sensor_Type >=
00907                         CORE_SENSOR_TYPE_SPI_ACCELEROMETER_A) &&
00908                         (sensorTypeReg.Sensor_Type <=
00909                          CORE_SENSOR_TYPE_SPI_ACCELEROMETER_B)) {
00910                     nActualChannels += 2;
00911                 }
00912             }
00913 
00914             nChannelsEnabled += nActualChannels;
00915 
00916             nSamplesPerCycle += nActualChannels *
00917                                 (channelCountReg.Channel_Count + 1);
00918         }
00919     }
00920 
00921     if (nChannelsEnabled == 0) {
00922         *pnSamplesPerDataready = 0;
00923         *pnSamplesPerCycle = 0;
00924         return ADMW_SUCCESS ;
00925     }
00926 
00927     *pnSamplesPerCycle = nSamplesPerCycle;
00928 
00929     if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) {
00930         *pnSamplesPerDataready = 1;
00931     } else {
00932         *pnSamplesPerDataready = nSamplesPerCycle;
00933     }
00934 
00935     if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) {
00936         *peDataReadyMode = ADMW1001_DATAREADY_PER_CONVERSION ;
00937     } else {
00938         *peDataReadyMode = ADMW1001_DATAREADY_PER_CYCLE ;
00939     }
00940 
00941     return ADMW_SUCCESS ;
00942 }
00943 
00944 ADMW_RESULT  admw_GetProductID(
00945     ADMW_DEVICE_HANDLE  hDevice,
00946     ADMW_PRODUCT_ID  *pProductId)
00947 {
00948     ADMW_SPI_Product_ID_L_t productIdLoReg;
00949     ADMW_SPI_Product_ID_H_t productIdHiReg;
00950 
00951     READ_REG_U8(hDevice, productIdLoReg.VALUE8, SPI_PRODUCT_ID_L);
00952     READ_REG_U8(hDevice, productIdHiReg.VALUE8, SPI_PRODUCT_ID_H);
00953 
00954     *pProductId = (ADMW_PRODUCT_ID )((productIdHiReg.VALUE8 << 8) |
00955                                     productIdLoReg.VALUE8);
00956     return ADMW_SUCCESS ;
00957 }
00958 
00959 static ADMW_RESULT  admw_SetPowerMode(
00960     ADMW_DEVICE_HANDLE  hDevice,
00961     ADMW1001_POWER_MODE  powerMode)
00962 {
00963     ADMW_CORE_Power_Config_t powerConfigReg;
00964 
00965     if (powerMode == ADMW1001_POWER_MODE_HIBERNATION ) {
00966         powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_HIBERNATION;
00967     } else if (powerMode == ADMW1001_POWER_MODE_ACTIVE ) {
00968         powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_ACTIVE_MODE;
00969     } else {
00970         ADMW_LOG_ERROR("Invalid power mode %d specified", powerMode);
00971         return ADMW_INVALID_PARAM ;
00972     }
00973 
00974     WRITE_REG_U8(hDevice, powerConfigReg.VALUE8, CORE_POWER_CONFIG);
00975 
00976     return ADMW_SUCCESS ;
00977 }
00978 
00979 ADMW_RESULT  admw1001_SetPowerConfig(
00980     ADMW_DEVICE_HANDLE  hDevice,
00981     ADMW1001_POWER_CONFIG  *pPowerConfig)
00982 {
00983     ADMW_RESULT  eRet;
00984 
00985     eRet = admw_SetPowerMode(hDevice, pPowerConfig->powerMode );
00986     if (eRet != ADMW_SUCCESS ) {
00987         ADMW_LOG_ERROR("Failed to set power mode");
00988         return eRet;
00989     }
00990 
00991     return ADMW_SUCCESS ;
00992 }
00993 
00994 static ADMW_RESULT  admw_SetRSenseValue(
00995     ADMW_DEVICE_HANDLE  hDevice,
00996     float32_t RSenseValue)
00997 {
00998    ADMW_CORE_External_Reference_Resistor_t RefResistorConfigReg;
00999   
01000    RefResistorConfigReg.Ext_Refin1_Value = RSenseValue;
01001    
01002    WRITE_REG_FLOAT(hDevice, RefResistorConfigReg.VALUE32, CORE_EXTERNAL_REFERENCE_RESISTOR);
01003    
01004    return ADMW_SUCCESS ;
01005 
01006 }
01007 
01008 static ADMW_RESULT  admw_SetMode(
01009     ADMW_DEVICE_HANDLE  hDevice,
01010     ADMW1001_OPERATING_MODE  eOperatingMode,
01011     ADMW1001_DATAREADY_MODE  eDataReadyMode)
01012 {
01013     ADMW_CORE_Mode_t modeReg;
01014 
01015     modeReg.VALUE8 = REG_RESET_VAL(CORE_MODE);
01016 
01017     if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) {
01018         modeReg.Conversion_Mode = CORE_MODE_SINGLECYCLE;
01019     } else if (eOperatingMode == ADMW1001_OPERATING_MODE_CONTINUOUS ) {
01020         modeReg.Conversion_Mode = CORE_MODE_CONTINUOUS;
01021     } else {
01022         ADMW_LOG_ERROR("Invalid operating mode %d specified",
01023                        eOperatingMode);
01024         return ADMW_INVALID_PARAM ;
01025     }
01026 
01027     if (eDataReadyMode == ADMW1001_DATAREADY_PER_CONVERSION ) {
01028         modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CONVERSION;
01029     } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_CYCLE ) {
01030         modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CYCLE;
01031     } else {
01032         ADMW_LOG_ERROR("Invalid data-ready mode %d specified", eDataReadyMode);
01033         return ADMW_INVALID_PARAM ;
01034     }
01035 
01036     WRITE_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE);
01037 
01038     return ADMW_SUCCESS ;
01039 }
01040 
01041 ADMW_RESULT  admw_SetCycleControl(ADMW_DEVICE_HANDLE  hDevice,
01042                                  uint32_t           nCycleInterval,
01043                                  bool               vBiasEnable)
01044 {
01045     ADMW_CORE_Cycle_Control_t cycleControlReg;
01046 
01047     cycleControlReg.VALUE16 = REG_RESET_VAL(CORE_CYCLE_CONTROL);
01048 
01049     if (nCycleInterval < (1000 * (1 << 12))) {
01050         cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_MILLISECONDS;
01051         nCycleInterval /= 1000;
01052     } else {
01053         cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_SECONDS;
01054         nCycleInterval /= 1000000;
01055     }
01056 
01057     if (vBiasEnable == true) {
01058         cycleControlReg.Vbias = 1;
01059     }
01060     CHECK_REG_FIELD_VAL(CORE_CYCLE_CONTROL_CYCLE_TIME, nCycleInterval);
01061     cycleControlReg.Cycle_Time = nCycleInterval;
01062 
01063     WRITE_REG_U16(hDevice, cycleControlReg.VALUE16, CORE_CYCLE_CONTROL);
01064 
01065     return ADMW_SUCCESS ;
01066 }
01067 
01068 static ADMW_RESULT  admw_SetExternalReferenceValues(
01069     ADMW_DEVICE_HANDLE  hDevice,
01070     float32_t externalRef1Value)
01071 {
01072     WRITE_REG_FLOAT(hDevice, externalRef1Value, CORE_EXTERNAL_REFERENCE_RESISTOR);
01073 
01074     return ADMW_SUCCESS ;
01075 }
01076 
01077 ADMW_RESULT  admw1001_SetMeasurementConfig(
01078     ADMW_DEVICE_HANDLE  hDevice,
01079     ADMW1001_MEASUREMENT_CONFIG  *pMeasConfig)
01080 {
01081     ADMW_RESULT  eRet;
01082 
01083     eRet = admw_SetMode(hDevice,
01084                         pMeasConfig->operatingMode ,
01085                         pMeasConfig->dataReadyMode );
01086     if (eRet != ADMW_SUCCESS ) {
01087         ADMW_LOG_ERROR("Failed to set operating mode");
01088         return eRet;
01089     }
01090 
01091     eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval ,
01092                                 pMeasConfig->vBiasEnable );
01093     if (eRet != ADMW_SUCCESS ) {
01094         ADMW_LOG_ERROR("Failed to set cycle control");
01095         return eRet;
01096     }
01097 
01098     if(pMeasConfig->externalRef1Value >0) {
01099         eRet = admw_SetExternalReferenceValues(hDevice,
01100                                                pMeasConfig->externalRef1Value );
01101     }
01102 
01103     if (eRet != ADMW_SUCCESS ) {
01104         ADMW_LOG_ERROR("Failed to set external reference values");
01105         return eRet;
01106     }
01107 
01108     eRet = admw_SetRSenseValue(hDevice, pMeasConfig->RSenseValue );
01109     if (eRet != ADMW_SUCCESS )
01110     {
01111         ADMW_LOG_ERROR("Failed to set RSenseValue");
01112         return eRet;
01113     }
01114     return ADMW_SUCCESS ;
01115 }
01116 
01117 ADMW_RESULT  admw1001_SetDiagnosticsConfig(
01118     ADMW_DEVICE_HANDLE  hDevice,
01119     ADMW1001_DIAGNOSTICS_CONFIG  *pDiagnosticsConfig)
01120 {
01121     ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg;
01122 
01123     diagnosticsControlReg.VALUE16 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL);
01124 
01125     if (pDiagnosticsConfig->disableGlobalDiag )
01126         diagnosticsControlReg.Diag_Global_En = 0;
01127     else
01128         diagnosticsControlReg.Diag_Global_En = 1;
01129 
01130     if (pDiagnosticsConfig->disableMeasurementDiag )
01131         diagnosticsControlReg.Diag_Meas_En = 0;
01132     else
01133         diagnosticsControlReg.Diag_Meas_En = 1;
01134 
01135     switch (pDiagnosticsConfig->osdFrequency ) {
01136         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_DISABLED :
01137             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_OFF;
01138             break;
01139         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_CYCLE :
01140             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1_CYCLE;
01141             break;
01142         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_100_CYCLES :
01143             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_100_CYCLES;
01144             break;
01145         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_1000_CYCLES :
01146             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1000_CYCLES;
01147             break;
01148         default:
01149             ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified",
01150                            pDiagnosticsConfig->osdFrequency );
01151             return ADMW_INVALID_PARAM ;
01152     }
01153 
01154     WRITE_REG_U16(hDevice, diagnosticsControlReg.VALUE16, CORE_DIAGNOSTICS_CONTROL);
01155 
01156     return ADMW_SUCCESS ;
01157 }
01158 
01159 ADMW_RESULT  admw1001_SetChannelCount(
01160     ADMW_DEVICE_HANDLE  hDevice,
01161     ADMW1001_CH_ID  eChannelId,
01162     uint32_t nMeasurementsPerCycle)
01163 {
01164     ADMW_CORE_Channel_Count_t channelCountReg;
01165 
01166     channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn);
01167 
01168     if (nMeasurementsPerCycle > 0) {
01169         nMeasurementsPerCycle -= 1;
01170 
01171         CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT,
01172                             nMeasurementsPerCycle);
01173 
01174         channelCountReg.Channel_Enable = 1;
01175         channelCountReg.Channel_Count = nMeasurementsPerCycle;
01176     } else {
01177         channelCountReg.Channel_Enable = 0;
01178     }
01179 
01180     WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId));
01181 
01182     return ADMW_SUCCESS ;
01183 }
01184 
01185 ADMW_RESULT  admw1001_SetChannelOptions(
01186     ADMW_DEVICE_HANDLE  hDevice,
01187     ADMW1001_CH_ID  eChannelId,
01188     ADMW1001_CHANNEL_PRIORITY  ePriority)
01189 {
01190     ADMW_CORE_Channel_Options_t channelOptionsReg;
01191 
01192     channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn);
01193 
01194     CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority);
01195     channelOptionsReg.Channel_Priority = ePriority;
01196 
01197     WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId));
01198 
01199     return ADMW_SUCCESS ;
01200 }
01201 
01202 ADMW_RESULT  admw1001_SetChannelSkipCount(
01203     ADMW_DEVICE_HANDLE  hDevice,
01204     ADMW1001_CH_ID  eChannelId,
01205     uint32_t nCycleSkipCount)
01206 {
01207     ADMW_CORE_Channel_Skip_t channelSkipReg;
01208 
01209     channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn);
01210 
01211     CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount);
01212 
01213     channelSkipReg.Channel_Skip = nCycleSkipCount;
01214 
01215     WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId));
01216 
01217     return ADMW_SUCCESS ;
01218 }
01219 
01220 static ADMW_RESULT  admw_SetChannelAdcSensorType(
01221     ADMW_DEVICE_HANDLE           hDevice,
01222     ADMW1001_CH_ID               eChannelId,
01223     ADMW1001_ADC_SENSOR_TYPE     sensorType)
01224 {
01225     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01226 
01227     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01228 
01229     /* Ensure that the sensor type is valid for this channel */
01230     switch(sensorType) {
01231         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 :
01232         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 :
01233         case ADMW1001_ADC_SENSOR_RTD_3WIRE_1 :
01234         case ADMW1001_ADC_SENSOR_RTD_3WIRE_2 :
01235         case ADMW1001_ADC_SENSOR_RTD_3WIRE_3 :
01236         case ADMW1001_ADC_SENSOR_RTD_3WIRE_4 :
01237         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 :
01238         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 :
01239         case ADMW1001_ADC_SENSOR_RTD_4WIRE_1 :
01240         case ADMW1001_ADC_SENSOR_RTD_4WIRE_2 :
01241         case ADMW1001_ADC_SENSOR_RTD_4WIRE_3 :
01242         case ADMW1001_ADC_SENSOR_RTD_4WIRE_4 :
01243         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_1 :
01244         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_2 :
01245         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_3 :
01246         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_4 :
01247         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_1 :
01248         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_2 :
01249         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_3 :
01250         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_4 :
01251         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 :
01252         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 :
01253         case ADMW1001_ADC_SENSOR_RTD_2WIRE_1 :
01254         case ADMW1001_ADC_SENSOR_RTD_2WIRE_2 :
01255         case ADMW1001_ADC_SENSOR_RTD_2WIRE_3 :
01256         case ADMW1001_ADC_SENSOR_RTD_2WIRE_4 :
01257         case ADMW1001_ADC_SENSOR_DIODE_2C_TYPEA :
01258         case ADMW1001_ADC_SENSOR_DIODE_3C_TYPEA :
01259         case ADMW1001_ADC_SENSOR_DIODE_2C_1 :
01260         case ADMW1001_ADC_SENSOR_DIODE_3C_1 :
01261         case ADMW1001_ADC_SENSOR_THERMISTOR_A_10K :
01262         case ADMW1001_ADC_SENSOR_THERMISTOR_B_10K :
01263         case ADMW1001_ADC_SENSOR_THERMISTOR_1 :
01264         case ADMW1001_ADC_SENSOR_THERMISTOR_2 :
01265         case ADMW1001_ADC_SENSOR_THERMISTOR_3 :
01266         case ADMW1001_ADC_SENSOR_THERMISTOR_4 :
01267             if (! (ADMW1001_CHANNEL_IS_ADC_SENSOR(eChannelId) ||
01268                     ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId))) {
01269                 ADMW_LOG_ERROR(
01270                     "Invalid ADC sensor type %d specified for channel %d",
01271                     sensorType, eChannelId);
01272                 return ADMW_INVALID_PARAM ;
01273             }
01274             break;
01275         case ADMW1001_ADC_SENSOR_VOLTAGE :
01276         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_A :
01277         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_B :
01278         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_1 :
01279         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_2 :
01280         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J :
01281         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K :
01282         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T :
01283         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_1 :
01284         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_2 :
01285         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_3 :
01286         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_4 :
01287             if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) {
01288                 ADMW_LOG_ERROR(
01289                     "Invalid ADC sensor type %d specified for channel %d",
01290                     sensorType, eChannelId);
01291                 return ADMW_INVALID_PARAM ;
01292             }
01293             break;
01294         case ADMW1001_ADC_SENSOR_CURRENT :
01295         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_A :
01296         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_1 :
01297         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_2 :
01298             if (! ADMW1001_CHANNEL_IS_ADC_CURRENT(eChannelId)) {
01299                 ADMW_LOG_ERROR(
01300                     "Invalid ADC sensor type %d specified for channel %d",
01301                     sensorType, eChannelId);
01302                 return ADMW_INVALID_PARAM ;
01303             }
01304             break;
01305         default:
01306             ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified",
01307                            sensorType);
01308             return ADMW_INVALID_PARAM ;
01309     }
01310 
01311     sensorTypeReg.Sensor_Type = sensorType;
01312 
01313     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01314 
01315     return ADMW_SUCCESS ;
01316 }
01317 
01318 static ADMW_RESULT  admw_SetChannelAdcSensorDetails(
01319     ADMW_DEVICE_HANDLE       hDevice,
01320     ADMW1001_CH_ID           eChannelId,
01321     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01322 /*
01323  * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers
01324  * General details:
01325  * - Measurement_Units
01326  * - Compensation_Channel
01327  * - CJC_Publish (if "CJC" was removed from the name)
01328  * ADC-specific details:
01329  * - PGA_Gain
01330  * - Reference_Select
01331  * - Reference_Buffer_Disable
01332  */
01333 {
01334     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ;
01335     ADMW1001_ADC_REFERENCE_TYPE  refType            = pAdcChannelConfig->reference;
01336     ADMW_CORE_Sensor_Details_t  sensorDetailsReg;
01337 
01338     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01339 
01340     switch(pChannelConfig->measurementUnit ) {
01341         case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT :
01342             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF;
01343             break;
01344         case ADMW1001_MEASUREMENT_UNIT_CELSIUS :
01345             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC;
01346             break;
01347         case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED :
01348             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01349             break;
01350         default:
01351             ADMW_LOG_ERROR("Invalid measurement unit %d specified",
01352                            pChannelConfig->measurementUnit );
01353             return ADMW_INVALID_PARAM ;
01354     }
01355 
01356     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01357         sensorDetailsReg.Compensation_Disable = 1;
01358         sensorDetailsReg.Compensation_Channel = 0;
01359     } else {
01360         sensorDetailsReg.Compensation_Disable = 0;
01361         sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ;
01362     }
01363 
01364     switch(refType) {
01365         case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL :
01366             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT;
01367             break;
01368         case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 :
01369             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1;
01370             break;
01371         case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD :
01372             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD;
01373             break;
01374         default:
01375             ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType);
01376             return ADMW_INVALID_PARAM ;
01377     }
01378 
01379     switch(pAdcChannelConfig->gain ) {
01380         case ADMW1001_ADC_GAIN_1X :
01381             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1;
01382             break;
01383         case ADMW1001_ADC_GAIN_2X :
01384             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2;
01385             break;
01386         case ADMW1001_ADC_GAIN_4X :
01387             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4;
01388             break;
01389         case ADMW1001_ADC_GAIN_8X :
01390             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8;
01391             break;
01392         case ADMW1001_ADC_GAIN_16X :
01393             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16;
01394             break;
01395         case ADMW1001_ADC_GAIN_32X :
01396             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32;
01397             break;
01398         case ADMW1001_ADC_GAIN_64X :
01399             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64;
01400             break;
01401         case ADMW1001_ADC_GAIN_128X :
01402             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128;
01403             break;
01404         default:
01405             ADMW_LOG_ERROR("Invalid ADC gain %d specified",
01406                            pAdcChannelConfig->gain );
01407             return ADMW_INVALID_PARAM ;
01408     }
01409 
01410     switch(pAdcChannelConfig->rtdCurve ) {
01411         case ADMW1001_ADC_RTD_CURVE_EUROPEAN :
01412             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE;
01413             break;
01414         case ADMW1001_ADC_RTD_CURVE_AMERICAN :
01415             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE;
01416             break;
01417         case ADMW1001_ADC_RTD_CURVE_JAPANESE :
01418             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE;
01419             break;
01420         case ADMW1001_ADC_RTD_CURVE_ITS90 :
01421             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE;
01422             break;
01423         default:
01424             ADMW_LOG_ERROR("Invalid RTD Curve %d specified",
01425                            pAdcChannelConfig->rtdCurve );
01426             return ADMW_INVALID_PARAM ;
01427     }
01428 
01429     if (pChannelConfig->disablePublishing ) {
01430         sensorDetailsReg.Do_Not_Publish = 1;
01431     } else {
01432         sensorDetailsReg.Do_Not_Publish = 0;
01433     }
01434 
01435     switch (pChannelConfig->lutSelect ) {
01436         case ADMW1001_LUT_DEFAULT :
01437         case ADMW1001_LUT_UNITY :
01438         case ADMW1001_LUT_CUSTOM :
01439             sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ;
01440             break;
01441         default:
01442             ADMW_LOG_ERROR("Invalid LUT selection %d specified",
01443                            pChannelConfig->lutSelect );
01444             return ADMW_INVALID_PARAM ;
01445     }
01446 
01447     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01448 
01449     return ADMW_SUCCESS ;
01450 }
01451 
01452 static ADMW_RESULT  admw_SetChannelAdcMeasurementSetup(
01453     ADMW_DEVICE_HANDLE  hDevice,
01454     ADMW1001_CH_ID  eChannelId,
01455     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig)
01456 {
01457     ADMW_CORE_Measurement_Setup_t MeasSetupReg;
01458     ADMW1001_ADC_FILTER_CONFIG  *pFilterConfig = &pAdcChannelConfig->filter ;    
01459     MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn);
01460 
01461     MeasSetupReg.PST_MEAS_EXC_CTRL = pAdcChannelConfig->current .excitationState ;
01462     MeasSetupReg.Buffer_Bypass = pAdcChannelConfig->bufferBypass ;
01463     
01464     if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC4 ) {
01465         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4;
01466         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01467     } else if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC3 ) {
01468         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3;
01469         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01470     } else {
01471         ADMW_LOG_ERROR("Invalid ADC filter type %d specified",
01472                        pFilterConfig->type );
01473         return ADMW_INVALID_PARAM ;
01474     }
01475 
01476     /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */
01477     MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ;
01478 
01479     if(pFilterConfig->notch1p2 )
01480         MeasSetupReg.NOTCH_EN_2 = 1;
01481     else
01482         MeasSetupReg.NOTCH_EN_2 = 0;
01483 
01484     switch(pFilterConfig->groundSwitch ) {
01485         case ADMW1001_ADC_GND_SW_OPEN :
01486             MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_OPEN;
01487             break;
01488         case ADMW1001_ADC_GND_SW_CLOSED :
01489             MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_CLOSED;
01490             break;
01491         default:
01492             ADMW_LOG_ERROR("Invalid ground switch state %d specified",
01493                            pFilterConfig->groundSwitch );
01494             return ADMW_INVALID_PARAM ;
01495     }
01496 
01497     WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId));
01498 
01499     return ADMW_SUCCESS ;
01500 }
01501 
01502 static ADMW_RESULT  admw_SetChannelAdcCurrentConfig(
01503     ADMW_DEVICE_HANDLE  hDevice,
01504     ADMW1001_CH_ID  eChannelId,
01505     ADMW1001_ADC_EXC_CURRENT_CONFIG  *pCurrentConfig)
01506 {
01507     ADMW_CORE_Channel_Excitation_t channelExcitationReg;
01508 
01509     channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn);
01510 
01511     if (pCurrentConfig->outputLevel  == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT )
01512         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE;
01513     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_EXTERNAL )
01514         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL;
01515     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_50uA )
01516         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA;
01517     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_100uA )
01518         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA;
01519     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_250uA )
01520         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA;
01521     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_500uA )
01522         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA;
01523     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_1000uA )
01524         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA;
01525     else {
01526         ADMW_LOG_ERROR("Invalid ADC excitation current %d specified",
01527                        pCurrentConfig->outputLevel );
01528         return ADMW_INVALID_PARAM ;
01529     }
01530 
01531 
01532 
01533     switch(pCurrentConfig->diodeRatio ) {
01534         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_100UA:
01535             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_10UA_100UA;
01536             break;
01537         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_160UA:
01538             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_20UA_160UA;
01539             break;
01540         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_300UA:
01541             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_50UA_300UA;
01542             break;
01543         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_600UA:
01544             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_100UA_600UA;
01545             break;
01546         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_50UA_100UA:
01547             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_10UA_50UA_100UA;
01548             break;
01549         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_100UA_160UA:
01550             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_20UA_100UA_160UA;
01551             break;
01552         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_150UA_300UA:
01553             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_50UA_150UA_300UA;
01554             break;
01555         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_300UA_600UA:
01556             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_100UA_300UA_600UA;
01557             break;
01558         default:
01559             ADMW_LOG_ERROR("Invalid diode ratio %d specified",
01560                            pCurrentConfig->diodeRatio );
01561             return ADMW_INVALID_PARAM ;
01562     }
01563 
01564     WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId));
01565 
01566     return ADMW_SUCCESS ;
01567 }
01568 
01569 ADMW_RESULT  admw_SetAdcChannelConfig(
01570     ADMW_DEVICE_HANDLE  hDevice,
01571     ADMW1001_CH_ID  eChannelId,
01572     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01573 {
01574     ADMW_RESULT  eRet;
01575     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig =
01576         &pChannelConfig->adcChannelConfig ;
01577 
01578     eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId,
01579                                         pAdcChannelConfig->sensor );
01580     if (eRet != ADMW_SUCCESS ) {
01581         ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d",
01582                        eChannelId);
01583         return eRet;
01584     }
01585 
01586     eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId,
01587                                            pChannelConfig);
01588     if (eRet != ADMW_SUCCESS ) {
01589         ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d",
01590                        eChannelId);
01591         return eRet;
01592     }
01593 
01594     eRet = admw_SetChannelAdcMeasurementSetup(hDevice, eChannelId,
01595                                     pAdcChannelConfig);
01596     if (eRet != ADMW_SUCCESS ) {
01597         ADMW_LOG_ERROR("Failed to set ADC filter for channel %d",
01598                        eChannelId);
01599         return eRet;
01600     }
01601 
01602     eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId,
01603                                            &pAdcChannelConfig->current );
01604     if (eRet != ADMW_SUCCESS ) {
01605         ADMW_LOG_ERROR("Failed to set ADC current for channel %d",
01606                        eChannelId);
01607         return eRet;
01608     }
01609 
01610     return ADMW_SUCCESS ;
01611 }
01612 
01613 static ADMW_RESULT  admw_SetChannelDigitalSensorDetails(
01614     ADMW_DEVICE_HANDLE  hDevice,
01615     ADMW1001_CH_ID  eChannelId,
01616     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01617 {
01618     ADMW_CORE_Sensor_Details_t sensorDetailsReg;
01619 
01620     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01621 
01622     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01623         sensorDetailsReg.Compensation_Disable = 1;
01624         sensorDetailsReg.Compensation_Channel = 0;
01625     } else {
01626         ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor");
01627         return ADMW_INVALID_PARAM ;
01628     }
01629 
01630     if (pChannelConfig->measurementUnit  == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) {
01631         sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01632     } else {
01633         ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel");
01634         return ADMW_INVALID_PARAM ;
01635     }
01636 
01637     if (pChannelConfig->disablePublishing )
01638         sensorDetailsReg.Do_Not_Publish = 1;
01639     else
01640         sensorDetailsReg.Do_Not_Publish = 0;
01641 
01642     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01643 
01644     return ADMW_SUCCESS ;
01645 }
01646 
01647 static ADMW_RESULT  admw_SetDigitalSensorCommands(
01648     ADMW_DEVICE_HANDLE  hDevice,
01649     ADMW1001_CH_ID  eChannelId,
01650     ADMW1001_DIGITAL_SENSOR_COMMAND  *pConfigCommand,
01651     ADMW1001_DIGITAL_SENSOR_COMMAND  *pDataRequestCommand)
01652 {
01653     ADMW_CORE_Digital_Sensor_Num_Cmds_t numCmdsReg;
01654 
01655     numCmdsReg.VALUE8 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_NUM_CMDSn);
01656 
01657     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_CFG_CMDS,
01658                         pConfigCommand->commandLength );
01659     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_READ_CMDS,
01660                         pDataRequestCommand->commandLength );
01661 
01662     numCmdsReg.Digital_Sensor_Num_Cfg_Cmds = pConfigCommand->commandLength ;
01663     numCmdsReg.Digital_Sensor_Num_Read_Cmds = pDataRequestCommand->commandLength ;
01664 
01665     WRITE_REG_U8(hDevice, numCmdsReg.VALUE8,
01666                  CORE_DIGITAL_SENSOR_NUM_CMDSn(eChannelId));
01667 
01668     /*
01669      * NOTE - the fall-through cases in the switch statement below are
01670      * intentional.
01671      */
01672     switch (pConfigCommand->commandLength ) {
01673         case 7:
01674             WRITE_REG_U8(hDevice, pConfigCommand->command [6],
01675                          CORE_DIGITAL_SENSOR_COMMAND7n(eChannelId));
01676         case 6:
01677             WRITE_REG_U8(hDevice, pConfigCommand->command [5],
01678                          CORE_DIGITAL_SENSOR_COMMAND6n(eChannelId));
01679         case 5:
01680             WRITE_REG_U8(hDevice, pConfigCommand->command [4],
01681                          CORE_DIGITAL_SENSOR_COMMAND5n(eChannelId));
01682         case 4:
01683             WRITE_REG_U8(hDevice, pConfigCommand->command [3],
01684                          CORE_DIGITAL_SENSOR_COMMAND4n(eChannelId));
01685         case 3:
01686             WRITE_REG_U8(hDevice, pConfigCommand->command [2],
01687                          CORE_DIGITAL_SENSOR_COMMAND3n(eChannelId));
01688         case 2:
01689             WRITE_REG_U8(hDevice, pConfigCommand->command [1],
01690                          CORE_DIGITAL_SENSOR_COMMAND2n(eChannelId));
01691         case 1:
01692             WRITE_REG_U8(hDevice, pConfigCommand->command [0],
01693                          CORE_DIGITAL_SENSOR_COMMAND1n(eChannelId));
01694         case 0:
01695         default:
01696             break;
01697     };
01698 
01699     switch (pDataRequestCommand->commandLength ) {
01700         case 7:
01701             WRITE_REG_U8(hDevice, pDataRequestCommand->command [6],
01702                          CORE_DIGITAL_SENSOR_READ_CMD7n(eChannelId));
01703         case 6:
01704             WRITE_REG_U8(hDevice, pDataRequestCommand->command [5],
01705                          CORE_DIGITAL_SENSOR_READ_CMD6n(eChannelId));
01706         case 5:
01707             WRITE_REG_U8(hDevice, pDataRequestCommand->command [4],
01708                          CORE_DIGITAL_SENSOR_READ_CMD5n(eChannelId));
01709         case 4:
01710             WRITE_REG_U8(hDevice, pDataRequestCommand->command [3],
01711                          CORE_DIGITAL_SENSOR_READ_CMD4n(eChannelId));
01712         case 3:
01713             WRITE_REG_U8(hDevice, pDataRequestCommand->command [2],
01714                          CORE_DIGITAL_SENSOR_READ_CMD3n(eChannelId));
01715         case 2:
01716             WRITE_REG_U8(hDevice, pDataRequestCommand->command [1],
01717                          CORE_DIGITAL_SENSOR_READ_CMD2n(eChannelId));
01718         case 1:
01719             WRITE_REG_U8(hDevice, pDataRequestCommand->command [0],
01720                          CORE_DIGITAL_SENSOR_READ_CMD1n(eChannelId));
01721         case 0:
01722         default:
01723             break;
01724     };
01725 
01726     return ADMW_SUCCESS ;
01727 }
01728 
01729 static ADMW_RESULT  admw_SetDigitalSensorFormat(
01730     ADMW_DEVICE_HANDLE  hDevice,
01731     ADMW1001_CH_ID  eChannelId,
01732     ADMW1001_DIGITAL_SENSOR_DATA_FORMAT  *pDataFormat)
01733 {
01734     ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg;
01735 
01736     sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn);
01737 
01738     if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) {
01739         if (pDataFormat->frameLength == 0) {
01740             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01741             return ADMW_INVALID_PARAM ;
01742         }
01743         if (pDataFormat->numDataBits == 0) {
01744             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01745             return ADMW_INVALID_PARAM ;
01746         }
01747 
01748         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES,
01749                             pDataFormat->frameLength - 1);
01750         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS,
01751                             pDataFormat->numDataBits - 1);
01752         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET,
01753                             pDataFormat->bitOffset);
01754 
01755         sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1;
01756         sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1;
01757         sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset;
01758         sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0;
01759         sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0;
01760 
01761         switch (pDataFormat->coding) {
01762             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR:
01763                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR;
01764                 break;
01765             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT:
01766                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL;
01767                 break;
01768             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY:
01769                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY;
01770                 break;
01771             default:
01772                 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format");
01773                 return ADMW_INVALID_PARAM ;
01774         }
01775     } else {
01776         sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE;
01777     }
01778 
01779     WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16,
01780                   CORE_DIGITAL_SENSOR_CONFIGn(eChannelId));
01781 
01782 
01783     return ADMW_SUCCESS ;
01784 }
01785 
01786 static ADMW_RESULT  admw_SetDigitalCalibrationParam(
01787     ADMW_DEVICE_HANDLE  hDevice,
01788     ADMW1001_CH_ID  eChannelId,
01789     ADMW1001_DIGITAL_CALIBRATION_COMMAND  *pCalibrationParam)
01790 {
01791     ADMW_CORE_Calibration_Parameter_t calibrationParamReg;
01792 
01793     calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn);
01794 
01795     if (pCalibrationParam->enableCalibrationParam  == false)
01796         calibrationParamReg.Calibration_Parameter_Enable = 0;
01797     else
01798         calibrationParamReg.Calibration_Parameter_Enable = 1;
01799 
01800     CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER,
01801                         pCalibrationParam->calibrationParam );
01802 
01803     calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam ;
01804 
01805     WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32,
01806                   CORE_CALIBRATION_PARAMETERn(eChannelId));
01807 
01808     return ADMW_SUCCESS ;
01809 }
01810 
01811 static ADMW_RESULT  admw_SetChannelI2cSensorType(
01812     ADMW_DEVICE_HANDLE  hDevice,
01813     ADMW1001_CH_ID  eChannelId,
01814     ADMW1001_I2C_SENSOR_TYPE  sensorType)
01815 {
01816     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01817 
01818     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01819 
01820     /* Ensure that the sensor type is valid for this channel */
01821     switch(sensorType) {
01822         case ADMW1001_I2C_SENSOR_HUMIDITY_A :
01823         case ADMW1001_I2C_SENSOR_HUMIDITY_B :
01824             sensorTypeReg.Sensor_Type = sensorType;
01825             break;
01826         default:
01827             ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType);
01828             return ADMW_INVALID_PARAM ;
01829     }
01830 
01831     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01832 
01833     return ADMW_SUCCESS ;
01834 }
01835 
01836 static ADMW_RESULT  admw_SetChannelI2cSensorAddress(
01837     ADMW_DEVICE_HANDLE  hDevice,
01838     ADMW1001_CH_ID  eChannelId,
01839     uint32_t deviceAddress)
01840 {
01841     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress);
01842     WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId));
01843 
01844     return ADMW_SUCCESS ;
01845 }
01846 
01847 static ADMW_RESULT  admw_SetDigitalChannelComms(
01848     ADMW_DEVICE_HANDLE  hDevice,
01849     ADMW1001_CH_ID  eChannelId,
01850     ADMW1001_DIGITAL_SENSOR_COMMS  *pDigitalComms)
01851 {
01852     ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms;
01853 
01854     digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn);
01855 
01856     if(pDigitalComms->useCustomCommsConfig ) {
01857         digitalSensorComms.Digital_Sensor_Comms_En = 1;
01858 
01859         if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) {
01860             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K;
01861         } else if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) {
01862             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K;
01863         } else {
01864             ADMW_LOG_ERROR("Invalid I2C clock speed %d specified",
01865                            pDigitalComms->i2cClockSpeed );
01866             return ADMW_INVALID_PARAM ;
01867         }
01868 
01869         if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) {
01870             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0;
01871         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) {
01872             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1;
01873         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) {
01874             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2;
01875         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) {
01876             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3;
01877         } else {
01878             ADMW_LOG_ERROR("Invalid SPI mode %d specified",
01879                            pDigitalComms->spiMode );
01880             return ADMW_INVALID_PARAM ;
01881         }
01882 
01883         switch (pDigitalComms->spiClock ) {
01884             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ :
01885                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ;
01886                 break;
01887             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ :
01888                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ;
01889                 break;
01890             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ :
01891                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ;
01892                 break;
01893             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ :
01894                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ;
01895                 break;
01896             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ :
01897                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ;
01898                 break;
01899             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ :
01900                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ;
01901                 break;
01902             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ :
01903                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ;
01904                 break;
01905             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ :
01906                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ;
01907                 break;
01908             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ :
01909                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ;
01910                 break;
01911             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ :
01912                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ;
01913                 break;
01914             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ :
01915                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ;
01916                 break;
01917             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ :
01918                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ;
01919                 break;
01920             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ :
01921                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ;
01922                 break;
01923             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ :
01924                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ;
01925                 break;
01926             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ :
01927                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ;
01928                 break;
01929             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ :
01930                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ;
01931                 break;
01932             default:
01933                 ADMW_LOG_ERROR("Invalid SPI clock %d specified",
01934                                pDigitalComms->spiClock );
01935                 return ADMW_INVALID_PARAM ;
01936         }
01937     } else {
01938         digitalSensorComms.Digital_Sensor_Comms_En = 0;
01939     }
01940 
01941     WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId));
01942 
01943     return ADMW_SUCCESS ;
01944 }
01945 
01946 ADMW_RESULT  admw_SetI2cChannelConfig(
01947     ADMW_DEVICE_HANDLE  hDevice,
01948     ADMW1001_CH_ID  eChannelId,
01949     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01950 {
01951     ADMW_RESULT  eRet;
01952     ADMW1001_I2C_CHANNEL_CONFIG  *pI2cChannelConfig =
01953         &pChannelConfig->i2cChannelConfig ;
01954 
01955     eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId,
01956                                         pI2cChannelConfig->sensor );
01957     if (eRet != ADMW_SUCCESS ) {
01958         ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d",
01959                        eChannelId);
01960         return eRet;
01961     }
01962 
01963     eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId,
01964                                            pI2cChannelConfig->deviceAddress );
01965     if (eRet != ADMW_SUCCESS ) {
01966         ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d",
01967                        eChannelId);
01968         return eRet;
01969     }
01970 
01971     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
01972             pChannelConfig);
01973     if (eRet != ADMW_SUCCESS ) {
01974         ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d",
01975                        eChannelId);
01976         return eRet;
01977     }
01978 
01979     eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId,
01980                                          &pI2cChannelConfig->configurationCommand ,
01981                                          &pI2cChannelConfig->dataRequestCommand );
01982     if (eRet != ADMW_SUCCESS ) {
01983         ADMW_LOG_ERROR("Failed to set I2C sensor commands for channel %d",
01984                        eChannelId);
01985         return eRet;
01986     }
01987 
01988     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
01989                                        &pI2cChannelConfig->dataFormat );
01990     if (eRet != ADMW_SUCCESS ) {
01991         ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d",
01992                        eChannelId);
01993         return eRet;
01994     }
01995 
01996     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
01997                                            &pI2cChannelConfig->digitalCalibrationParam );
01998     if (eRet != ADMW_SUCCESS ) {
01999         ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d",
02000                        eChannelId);
02001         return eRet;
02002     }
02003 
02004     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
02005                                        &pI2cChannelConfig->configureComms );
02006     if (eRet != ADMW_SUCCESS ) {
02007         ADMW_LOG_ERROR("Failed to set I2C comms for channel %d",
02008                        eChannelId);
02009         return eRet;
02010     }
02011 
02012     return ADMW_SUCCESS ;
02013 }
02014 
02015 static ADMW_RESULT  admw_SetChannelSpiSensorType(
02016     ADMW_DEVICE_HANDLE  hDevice,
02017     ADMW1001_CH_ID  eChannelId,
02018     ADMW1001_SPI_SENSOR_TYPE  sensorType)
02019 {
02020     ADMW_CORE_Sensor_Type_t sensorTypeReg;
02021 
02022     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
02023 
02024     /* Ensure that the sensor type is valid for this channel */
02025     switch(sensorType) {
02026         case ADMW1001_SPI_SENSOR_PRESSURE_A :
02027         case ADMW1001_SPI_SENSOR_ACCELEROMETER_A :
02028         case ADMW1001_SPI_SENSOR_ACCELEROMETER_B :
02029 
02030             sensorTypeReg.Sensor_Type = sensorType;
02031             break;
02032         default:
02033             ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType);
02034             return ADMW_INVALID_PARAM ;
02035     }
02036 
02037     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
02038 
02039     return ADMW_SUCCESS ;
02040 }
02041 
02042 ADMW_RESULT  admw_SetSpiChannelConfig(
02043     ADMW_DEVICE_HANDLE  hDevice,
02044     ADMW1001_CH_ID  eChannelId,
02045     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
02046 {
02047     ADMW_RESULT  eRet;
02048     ADMW1001_SPI_CHANNEL_CONFIG  *pSpiChannelConfig =
02049         &pChannelConfig->spiChannelConfig ;
02050 
02051     eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId,
02052                                         pSpiChannelConfig->sensor );
02053     if (eRet != ADMW_SUCCESS ) {
02054         ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d",
02055                        eChannelId);
02056         return eRet;
02057     }
02058 
02059     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
02060             pChannelConfig);
02061     if (eRet != ADMW_SUCCESS ) {
02062         ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d",
02063                        eChannelId);
02064         return eRet;
02065     }
02066 
02067     eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId,
02068                                          &pSpiChannelConfig->configurationCommand ,
02069                                          &pSpiChannelConfig->dataRequestCommand );
02070     if (eRet != ADMW_SUCCESS ) {
02071         ADMW_LOG_ERROR("Failed to set SPI sensor commands for channel %d",
02072                        eChannelId);
02073         return eRet;
02074     }
02075 
02076     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
02077                                        &pSpiChannelConfig->dataFormat );
02078     if (eRet != ADMW_SUCCESS ) {
02079         ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d",
02080                        eChannelId);
02081         return eRet;
02082     }
02083 
02084     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
02085                                            &pSpiChannelConfig->digitalCalibrationParam );
02086     if (eRet != ADMW_SUCCESS ) {
02087         ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d",
02088                        eChannelId);
02089         return eRet;
02090     }
02091 
02092     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
02093                                        &pSpiChannelConfig->configureComms );
02094     if (eRet != ADMW_SUCCESS ) {
02095         ADMW_LOG_ERROR("Failed to set SPI comms for channel %d",
02096                        eChannelId);
02097         return eRet;
02098     }
02099 
02100     return ADMW_SUCCESS ;
02101 }
02102 
02103 ADMW_RESULT  admw1001_SetChannelThresholdLimits(
02104     ADMW_DEVICE_HANDLE  hDevice,
02105     ADMW1001_CH_ID  eChannelId,
02106     float32_t fHighThresholdLimit,
02107     float32_t fLowThresholdLimit)
02108 {
02109     /*
02110      * If the low/high limits are *both* set to 0 in memory, or NaNs, assume
02111      * that they are unset, or not required, and use infinity defaults instead
02112      */
02113     if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) {
02114         fHighThresholdLimit = INFINITY;
02115         fLowThresholdLimit = -INFINITY;
02116     } else {
02117         if (isnan(fHighThresholdLimit))
02118             fHighThresholdLimit = INFINITY;
02119         if (isnan(fLowThresholdLimit))
02120             fLowThresholdLimit = -INFINITY;
02121     }
02122 
02123     WRITE_REG_FLOAT(hDevice, fHighThresholdLimit,
02124                     CORE_HIGH_THRESHOLD_LIMITn(eChannelId));
02125     WRITE_REG_FLOAT(hDevice, fLowThresholdLimit,
02126                     CORE_LOW_THRESHOLD_LIMITn(eChannelId));
02127 
02128     return ADMW_SUCCESS ;
02129 }
02130 
02131 ADMW_RESULT  admw1001_SetOffsetGain(
02132     ADMW_DEVICE_HANDLE  hDevice,
02133     ADMW1001_CH_ID  eChannelId,
02134     float32_t fOffsetAdjustment,
02135     float32_t fGainAdjustment)
02136 {
02137     /* Replace with default values if NaNs are specified (or 0.0 for gain) */
02138     if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f))
02139         fGainAdjustment = 1.0f;
02140     if (isnan(fOffsetAdjustment))
02141         fOffsetAdjustment = 0.0f;
02142 
02143     WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId));
02144     WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId));
02145 
02146     return ADMW_SUCCESS ;
02147 }
02148 
02149 ADMW_RESULT  admw1001_SetSensorParameter(
02150     ADMW_DEVICE_HANDLE  hDevice,
02151     ADMW1001_CH_ID  eChannelId,
02152     float32_t fSensorParam)
02153 {
02154     if (fSensorParam == 0.0f)
02155         fSensorParam = NAN;
02156 
02157     WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId));
02158 
02159     return ADMW_SUCCESS ;
02160 }
02161 
02162 ADMW_RESULT  admw1001_SetChannelSettlingTime(
02163     ADMW_DEVICE_HANDLE  hDevice,
02164     ADMW1001_CH_ID  eChannelId,
02165     uint32_t nSettlingTime)
02166 {
02167     ADMW_CORE_Settling_Time_t settlingTimeReg;
02168 
02169     if (nSettlingTime < (1 << 12)) {
02170         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MICROSECONDS;
02171     } else if (nSettlingTime < (1000 * (1 << 12))) {
02172         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MILLISECONDS;
02173         nSettlingTime /= 1000;
02174     } else {
02175         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_SECONDS;
02176         nSettlingTime /= 1000000;
02177     }
02178 
02179     CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime);
02180     settlingTimeReg.Settling_Time = nSettlingTime;
02181 
02182     WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId));
02183 
02184     return ADMW_SUCCESS ;
02185 }
02186 
02187 ADMW_RESULT  admw1001_SetChannelConfig(
02188     ADMW_DEVICE_HANDLE  hDevice,
02189     ADMW1001_CH_ID  eChannelId,
02190     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
02191 {
02192     ADMW_RESULT  eRet;
02193 
02194     if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) {
02195         eRet = admw1001_SetChannelCount(hDevice, eChannelId,
02196                                         pChannelConfig->enableChannel  ?
02197                                         pChannelConfig->measurementsPerCycle  : 0);
02198         if (eRet != ADMW_SUCCESS ) {
02199             ADMW_LOG_ERROR("Failed to set measurement count for channel %d",
02200                            eChannelId);
02201             return eRet;
02202         }
02203 
02204         eRet = admw1001_SetChannelOptions(hDevice, eChannelId,
02205                                           pChannelConfig->priority );
02206         if (eRet != ADMW_SUCCESS ) {
02207             ADMW_LOG_ERROR("Failed to set priority for channel %d",
02208                            eChannelId);
02209             return eRet;
02210         }
02211 
02212         /* If the channel is not enabled, we can skip the following steps */
02213         if (pChannelConfig->enableChannel ) {
02214             eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId,
02215                                                 pChannelConfig->cycleSkipCount );
02216             if (eRet != ADMW_SUCCESS ) {
02217                 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d",
02218                                eChannelId);
02219                 return eRet;
02220             }
02221 
02222             switch (eChannelId) {
02223                 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL :
02224                 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL :
02225                 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL :
02226                 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL :
02227                     eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig);
02228                     break;
02229                 case ADMW1001_CH_ID_DIG_I2C_0 :
02230                 case ADMW1001_CH_ID_DIG_I2C_1 :
02231                     eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig);
02232                     break;
02233                 case ADMW1001_CH_ID_DIG_SPI_0 :
02234                     eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig);
02235                     break;
02236                 default:
02237                     ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId);
02238                     return ADMW_INVALID_PARAM ;
02239             }
02240 
02241             eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId,
02242                                                    pChannelConfig->extraSettlingTime );
02243             if (eRet != ADMW_SUCCESS ) {
02244                 ADMW_LOG_ERROR("Failed to set settling time for channel %d",
02245                                eChannelId);
02246                 return eRet;
02247             }
02248         }
02249     }
02250 
02251     if (pChannelConfig->enableChannel ) {
02252         /* Threshold limits can be configured individually for virtual channels */
02253         eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId,
02254                 pChannelConfig->highThreshold ,
02255                 pChannelConfig->lowThreshold );
02256         if (eRet != ADMW_SUCCESS ) {
02257             ADMW_LOG_ERROR("Failed to set threshold limits for channel %d",
02258                            eChannelId);
02259             return eRet;
02260         }
02261 
02262         /* Offset and gain can be configured individually for virtual channels */
02263         eRet = admw1001_SetOffsetGain(hDevice, eChannelId,
02264                                       pChannelConfig->offsetAdjustment ,
02265                                       pChannelConfig->gainAdjustment );
02266         if (eRet != ADMW_SUCCESS ) {
02267             ADMW_LOG_ERROR("Failed to set offset/gain for channel %d",
02268                            eChannelId);
02269             return eRet;
02270         }
02271 
02272         /* Set sensor specific parameter */
02273         eRet = admw1001_SetSensorParameter(hDevice, eChannelId,
02274                                            pChannelConfig->sensorParameter );
02275         if (eRet != ADMW_SUCCESS ) {
02276             ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d",
02277                            eChannelId);
02278             return eRet;
02279         }
02280     }
02281 
02282     return ADMW_SUCCESS ;
02283 }
02284 
02285 ADMW_RESULT  admw_SetConfig(
02286     ADMW_DEVICE_HANDLE     const hDevice,
02287     ADMW_CONFIG          * const pConfig)
02288 {
02289     ADMW1001_CONFIG  *pDeviceConfig;
02290     ADMW_PRODUCT_ID  productId;
02291     ADMW_RESULT  eRet;
02292 
02293     if (pConfig->productId  != ADMW_PRODUCT_ID_ADMW1001 ) {
02294         ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)",
02295                        pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 );
02296         return ADMW_INVALID_PARAM ;
02297     }
02298 
02299     if (!((pConfig->versionId .major ==VERSIONID_MAJOR) &&
02300             (pConfig->versionId .minor ==VERSIONID_MINOR))) {
02301         ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported",
02302                        pConfig->versionId );
02303         return ADMW_INVALID_PARAM ;
02304     }
02305 
02306 
02307     /* Check that the actual Product ID is a match? */
02308     eRet = admw_GetProductID(hDevice, &productId);
02309     if (eRet) {
02310         ADMW_LOG_ERROR("Failed to read device Product ID register");
02311         return eRet;
02312     }
02313     if (pConfig->productId  != productId) {
02314         ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)",
02315                        pConfig->productId , productId);
02316         return ADMW_INVALID_PARAM ;
02317     }
02318 
02319     pDeviceConfig = &pConfig->admw1001 ;
02320 
02321     eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power );
02322     if (eRet) {
02323         ADMW_LOG_ERROR("Failed to set power configuration");
02324         return eRet;
02325     }
02326 
02327     eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement );
02328     if (eRet) {
02329         ADMW_LOG_ERROR("Failed to set measurement configuration");
02330         return eRet;
02331     }
02332 
02333     eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics );
02334     if (eRet) {
02335         ADMW_LOG_ERROR("Failed to set diagnostics configuration");
02336         return eRet;
02337     }
02338 
02339     for (ADMW1001_CH_ID  id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
02340             id < ADMW1001_MAX_CHANNELS ;
02341             id++) {
02342         eRet = admw1001_SetChannelConfig(hDevice, id,
02343                                          &pDeviceConfig->channels [id]);
02344         if (eRet) {
02345             ADMW_LOG_ERROR("Failed to set channel %d configuration", id);
02346             return eRet;
02347         }
02348     }
02349 
02350     return ADMW_SUCCESS ;
02351 }
02352 
02353 ADMW_RESULT  admw1001_SetLutData(
02354     ADMW_DEVICE_HANDLE    const hDevice,
02355     ADMW1001_LUT       * const pLutData)
02356 {
02357     ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header;
02358     ADMW1001_LUT_TABLE  *pLutTable = pLutData->tables;
02359     unsigned actualLength = 0;
02360 
02361     if (pLutData->header.signature != ADMW_LUT_SIGNATURE) {
02362         ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)",
02363                        ADMW_LUT_SIGNATURE, pLutHeader->signature);
02364         return ADMW_INVALID_SIGNATURE ;
02365     }
02366 
02367     for (unsigned i = 0; i < pLutHeader->numTables; i++) {
02368         ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor;
02369         ADMW1001_LUT_TABLE_DATA  *pData = &pLutTable->data;
02370         unsigned short calculatedCrc;
02371 
02372         switch (pDesc->geometry) {
02373             case ADMW1001_LUT_GEOMETRY_COEFFS:
02374                 switch (pDesc->equation) {
02375                     case ADMW1001_LUT_EQUATION_POLYN:
02376                     case ADMW1001_LUT_EQUATION_POLYNEXP:
02377                     case ADMW1001_LUT_EQUATION_QUADRATIC:
02378                     case ADMW1001_LUT_EQUATION_STEINHART:
02379                     case ADMW1001_LUT_EQUATION_LOGARITHMIC:
02380                     case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN:
02381                         break;
02382                     default:
02383                         ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02384                                        pDesc->equation, i);
02385                         return ADMW_INVALID_PARAM ;
02386                 }
02387                 break;
02388             case ADMW1001_LUT_GEOMETRY_NES_1D:
02389             case ADMW1001_LUT_GEOMETRY_NES_2D:
02390             case ADMW1001_LUT_GEOMETRY_ES_1D:
02391             case ADMW1001_LUT_GEOMETRY_ES_2D:
02392                 if (pDesc->equation != ADMW1001_LUT_EQUATION_LUT) {
02393                     ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02394                                    pDesc->equation, i);
02395                     return ADMW_INVALID_PARAM ;
02396                 }
02397                 break;
02398             default:
02399                 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u",
02400                                pDesc->geometry, i);
02401                 return ADMW_INVALID_PARAM ;
02402         }
02403 
02404         switch (pDesc->dataType) {
02405             case ADMW1001_LUT_DATA_TYPE_FLOAT32:
02406             case ADMW1001_LUT_DATA_TYPE_FLOAT64:
02407                 break;
02408             default:
02409                 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u",
02410                                pDesc->dataType, i);
02411                 return ADMW_INVALID_PARAM ;
02412         }
02413 
02414         calculatedCrc = admw_crc16_ccitt(pData, pDesc->length);
02415         if (calculatedCrc != pDesc->crc16) {
02416             ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)",
02417                            i, pDesc->crc16, calculatedCrc);
02418             return ADMW_CRC_ERROR ;
02419         }
02420 
02421         actualLength += sizeof(*pDesc) + pDesc->length;
02422 
02423         /* Move to the next look-up table */
02424         pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length);
02425     }
02426 
02427     if (actualLength != pLutHeader->totalLength) {
02428         ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)",
02429                        pLutHeader->totalLength, actualLength);
02430         return ADMW_WRONG_SIZE ;
02431     }
02432 
02433     if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) {
02434         ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded",
02435                        ADMW_LUT_MAX_SIZE);
02436         return ADMW_WRONG_SIZE ;
02437     }
02438 
02439     /* Write the LUT data to the device */
02440     unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength;
02441     WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET);
02442     WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA);
02443 
02444     return ADMW_SUCCESS ;
02445 }
02446 
02447 ADMW_RESULT  admw1001_SetLutDataRaw(
02448     ADMW_DEVICE_HANDLE     const hDevice,
02449     ADMW1001_LUT_RAW   * const pLutData)
02450 {
02451     return admw1001_SetLutData(hDevice,
02452                                (ADMW1001_LUT *)pLutData);
02453 }
02454 
02455 static ADMW_RESULT  getLutTableSize(
02456     ADMW1001_LUT_DESCRIPTOR * const pDesc,
02457     ADMW1001_LUT_TABLE_DATA  * const pData,
02458     unsigned *pLength)
02459 {
02460     switch (pDesc->geometry) {
02461         case ADMW1001_LUT_GEOMETRY_COEFFS:
02462             if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN)
02463                 *pLength = ADMW1001_LUT_2D_POLYN_COEFF_LIST_SIZE(pData->coeffList2d);
02464             else
02465                 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList);
02466             break;
02467         case ADMW1001_LUT_GEOMETRY_NES_1D:
02468             *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes);
02469             break;
02470         case ADMW1001_LUT_GEOMETRY_NES_2D:
02471             *pLength = ADMW1001_LUT_2D_NES_SIZE(pData->lut2dNes);
02472             break;
02473         case ADMW1001_LUT_GEOMETRY_ES_1D:
02474             *pLength = ADMW1001_LUT_1D_ES_SIZE(pData->lut1dEs);
02475             break;
02476         case ADMW1001_LUT_GEOMETRY_ES_2D:
02477             *pLength = ADMW1001_LUT_2D_ES_SIZE(pData->lut2dEs);
02478             break;
02479         default:
02480             ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n",
02481                            pDesc->geometry);
02482             return ADMW_INVALID_PARAM ;
02483     }
02484 
02485     return ADMW_SUCCESS ;
02486 }
02487 
02488 ADMW_RESULT  admw1001_AssembleLutData(
02489     ADMW1001_LUT                  * pLutBuffer,
02490     unsigned                              nLutBufferSize,
02491     unsigned                        const nNumTables,
02492     ADMW1001_LUT_DESCRIPTOR * const ppDesc[],
02493     ADMW1001_LUT_TABLE_DATA  * const ppData[])
02494 {
02495     ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header;
02496     uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr);
02497 
02498     if (sizeof(*pHdr) > nLutBufferSize) {
02499         ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02500         return ADMW_INVALID_PARAM ;
02501     }
02502 
02503     /* First initialise the top-level header */
02504     pHdr->signature = ADMW_LUT_SIGNATURE;
02505     pHdr->version.major = 1;
02506     pHdr->version.minor = 0;
02507     pHdr->numTables = 0;
02508     pHdr->totalLength = 0;
02509 
02510     /*
02511      * Walk through the list of table pointers provided, appending the table
02512      * descriptor+data from each one to the provided LUT buffer
02513      */
02514     for (unsigned i = 0; i < nNumTables; i++) {
02515         ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i];
02516         ADMW1001_LUT_TABLE_DATA  * const pData = ppData[i];
02517         ADMW_RESULT  res;
02518         unsigned dataLength = 0;
02519 
02520         /* Calculate the length of the table data */
02521         res = getLutTableSize(pDesc, pData, &dataLength);
02522         if (res != ADMW_SUCCESS )
02523             return res;
02524 
02525         /* Fill in the table descriptor length and CRC fields */
02526         pDesc->length = dataLength;
02527         pDesc->crc16 = admw_crc16_ccitt(pData, dataLength);
02528 
02529         if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) {
02530             ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02531             return ADMW_INVALID_PARAM ;
02532         }
02533 
02534         /* Append the table to the LUT buffer (desc + data) */
02535         memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc));
02536         pHdr->totalLength += sizeof(*pDesc);
02537         memcpy(pLutTableData + pHdr->totalLength, pData, dataLength);
02538         pHdr->totalLength += dataLength;
02539 
02540         pHdr->numTables++;
02541     }
02542 
02543     return ADMW_SUCCESS ;
02544 }
02545 
02546 ADMW_RESULT  deviceInformation(ADMW_DEVICE_HANDLE  hDevice)
02547 {
02548     uint16_t nAddress = REG_CORE_REVISION;
02549     char nData[ADMW_VERSION_REG_VAL_SIZE];  //4 Bytes of version register data
02550     ADMW_RESULT  res;
02551     res=admw1001_ReadRegister(hDevice,nAddress,nData,sizeof(nData));
02552     if(res != ADMW_SUCCESS ) {
02553         //if reading version register failed, sending 00.00.0000 as ADMW1001 firmware version
02554         //strcat(nData, ADMW1001_FIRMWARE_VERSION_DEFAULT);
02555         ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]);
02556     } else {
02557         char buffer[ADMW_FORMATTED_VERSION_SIZE]; //00.00.0000  8 digits + 2 Bytes "." + one null character at the end
02558         strcat(nData, buffer);
02559         ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]);
02560     }
02561     return ADMW_SUCCESS ;
02562 }
02563 
02564 ADMW_RESULT  admw1001_getFirmwareStatus(
02565     ADMW_DEVICE_HANDLE    const hDevice,
02566     bool                  * const bFirmwareStatus)
02567 {
02568     bool bitCommand;
02569     ADMW_RESULT  eRet;
02570     uint8_t pinreg = 0x1;
02571 
02572     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
02573     static uint8_t DataBuffer[SPI_BUFFER_SIZE] = {0};
02574     uint16_t nSize;
02575 
02576     //Construct Read Status command
02577     DataBuffer[0] = 0x07;
02578     DataBuffer[1] = 0x0E;   //Packet ID
02579 
02580     DataBuffer[2] = 0x00;
02581     DataBuffer[3] = 0x00;   //Data words
02582 
02583     DataBuffer[4] = 0x53;
02584     DataBuffer[5] = 0x00;   //Command ID
02585 
02586     DataBuffer[6] = 0x00;
02587     DataBuffer[7] = 0x00;
02588     DataBuffer[8] = 0x00;
02589     DataBuffer[9] = 0x00;   //Address
02590 
02591     DataBuffer[10] = 0x53;
02592     DataBuffer[11] = 0x00;
02593     DataBuffer[12] = 0x00;
02594     DataBuffer[13] = 0x00;  //Checksum
02595 
02596     nSize = SFL_READ_STATUS_HDR_SIZE;
02597 
02598     do {
02599         // Get the SFL command irq pin to check if SFL is ready to receive commands
02600         // Status pin is not checked since SFL is just booted, there should not be any issue with SFL
02601         eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand );
02602         if( eRet != ADMW_SUCCESS ) {
02603             return eRet;
02604         }
02605 
02606         // 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
02607         // pinreg == '0x00' - Error occured in SFL
02608         // pinreg == '0x01' - SFL is ready to recieve commands
02609         // pinreg == '0x02' - Error occured in handling any commands in SFL
02610         // pinreg == '0x03' - SFL not booted
02611 
02612         pinreg = (bitCommand);
02613 
02614     } while(pinreg != 0x0u);
02615 
02616     eRet = admw_SpiTransfer(pCtx->hSpi, DataBuffer, NULL,
02617                             nSize, false);
02618     if (eRet) {
02619         return eRet;
02620     }
02621 
02622     //wait for command irq line to go low after sending read status header
02623     wait_ms( 100 );
02624 
02625     do {
02626         // Get the SFL command irq pin to check if SFL is ready to receive commands
02627         // Status pin is not checked since SFL is just booted, there should not be any issue with SFL
02628         eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand );
02629         if( eRet != ADMW_SUCCESS ) {
02630             return eRet;
02631         }
02632 
02633         // 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
02634         // pinreg == '0x00' - Error occured in SFL
02635         // pinreg == '0x01' - SFL is ready to recieve commands
02636         // pinreg == '0x02' - Error occured in handling any commands in SFL
02637         // pinreg == '0x03' - SFL not booted
02638 
02639         pinreg = (bitCommand);
02640 
02641     } while(pinreg != 0x0u);
02642 
02643     nSize = SFL_READ_STATUS_RESPONSE_SIZE;
02644 
02645     eRet = admw_SpiReceive(pCtx->hSpi, NULL, DataBuffer,
02646                            nSize, false);
02647 
02648     if (eRet) {
02649         return eRet;
02650     }
02651 
02652     //Verifying the application version from the response to check if firmware is present or not
02653     /*
02654         Flash Memory description
02655         ______________
02656        |  Secure      | 0x0000 0000
02657        |  Flashloader |
02658        |______________| 0x0000 3BFF
02659        |  Security    |------------------
02660        |  Page        | 0x0000 3C00
02661        |              |
02662        |______________| 0x0000 3FFF
02663        |              |------------------
02664        |  App Info    | 0x0000 4000
02665        |   Page       |
02666        |______________| 0x0000 4800
02667        |              |------------------
02668        | Application  |
02669        |   Image      |  Application resides only in this region
02670        |______________|------------------
02671        |  Reserved    | 0x0003 FFF8
02672        |     for      | Reserved memory region
02673        |  Signature   | 0x0003 FFFF
02674        |______________|------------------
02675 
02676        Application version is stored in the App Info Page, the app version is updated in this region everytime the new application firmware is downloaded.
02677        Here we verify if Application version is present in the Read Status response
02678        If the app version bytes value is 0xFFFFFFFF then there is no firmware else there exist a firmware
02679 
02680        Read Status Response:
02681         ____________________________________________________________________________________________________________________________________
02682        |                             |                  |                              |                              |                     |
02683        |uint16_t nFlashLoaderVersion | uint16_t nStatus | uint32_t nApplicationVersion | uint32_t nApplicationHash[8] | uint16_t nChecksum  |
02684        |_____________________________|__________________|______________________________|______________________________|_____________________|
02685 
02686      */
02687 
02688     if( ((DataBuffer[4] == 0xFF) &&
02689             (DataBuffer[5] == 0xFF) &&
02690             (DataBuffer[6] == 0xFF) &&
02691             (DataBuffer[7] == 0xFF)) ||
02692             ((DataBuffer[4] == 0x00) &&
02693              (DataBuffer[5] == 0x00) &&
02694              (DataBuffer[6] == 0x00) &&
02695              (DataBuffer[7] == 0x00))) {
02696         *bFirmwareStatus = false;
02697     } else {
02698         *bFirmwareStatus = true;
02699     }
02700 
02701     return eRet;
02702 }