Host API Example for the ADMW1001

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_SetMode(
00995     ADMW_DEVICE_HANDLE  hDevice,
00996     ADMW1001_OPERATING_MODE  eOperatingMode,
00997     ADMW1001_DATAREADY_MODE  eDataReadyMode)
00998 {
00999     ADMW_CORE_Mode_t modeReg;
01000 
01001     modeReg.VALUE8 = REG_RESET_VAL(CORE_MODE);
01002 
01003     if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) {
01004         modeReg.Conversion_Mode = CORE_MODE_SINGLECYCLE;
01005     } else if (eOperatingMode == ADMW1001_OPERATING_MODE_CONTINUOUS ) {
01006         modeReg.Conversion_Mode = CORE_MODE_CONTINUOUS;
01007     } else {
01008         ADMW_LOG_ERROR("Invalid operating mode %d specified",
01009                        eOperatingMode);
01010         return ADMW_INVALID_PARAM ;
01011     }
01012 
01013     if (eDataReadyMode == ADMW1001_DATAREADY_PER_CONVERSION ) {
01014         modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CONVERSION;
01015     } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_CYCLE ) {
01016         modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CYCLE;
01017     } else {
01018         ADMW_LOG_ERROR("Invalid data-ready mode %d specified", eDataReadyMode);
01019         return ADMW_INVALID_PARAM ;
01020     }
01021 
01022     WRITE_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE);
01023 
01024     return ADMW_SUCCESS ;
01025 }
01026 
01027 ADMW_RESULT  admw_SetCycleControl(ADMW_DEVICE_HANDLE  hDevice,
01028                                  uint32_t           nCycleInterval,
01029                                  bool               vBiasEnable)
01030 {
01031     ADMW_CORE_Cycle_Control_t cycleControlReg;
01032 
01033     cycleControlReg.VALUE16 = REG_RESET_VAL(CORE_CYCLE_CONTROL);
01034 
01035     if (nCycleInterval < (1000 * (1 << 12))) {
01036         cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_MILLISECONDS;
01037         nCycleInterval /= 1000;
01038     } else {
01039         cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_SECONDS;
01040         nCycleInterval /= 1000000;
01041     }
01042 
01043     if (vBiasEnable == true) {
01044         cycleControlReg.Vbias = 1;
01045     }
01046     CHECK_REG_FIELD_VAL(CORE_CYCLE_CONTROL_CYCLE_TIME, nCycleInterval);
01047     cycleControlReg.Cycle_Time = nCycleInterval;
01048 
01049     WRITE_REG_U16(hDevice, cycleControlReg.VALUE16, CORE_CYCLE_CONTROL);
01050 
01051     return ADMW_SUCCESS ;
01052 }
01053 
01054 static ADMW_RESULT  admw_SetExternalReferenceValues(
01055     ADMW_DEVICE_HANDLE  hDevice,
01056     float32_t externalRef1Value)
01057 {
01058     WRITE_REG_FLOAT(hDevice, externalRef1Value, CORE_EXTERNAL_REFERENCE_RESISTOR);
01059 
01060     return ADMW_SUCCESS ;
01061 }
01062 
01063 ADMW_RESULT  admw1001_SetMeasurementConfig(
01064     ADMW_DEVICE_HANDLE  hDevice,
01065     ADMW1001_MEASUREMENT_CONFIG  *pMeasConfig)
01066 {
01067     ADMW_RESULT  eRet;
01068 
01069     eRet = admw_SetMode(hDevice,
01070                         pMeasConfig->operatingMode ,
01071                         pMeasConfig->dataReadyMode );
01072     if (eRet != ADMW_SUCCESS ) {
01073         ADMW_LOG_ERROR("Failed to set operating mode");
01074         return eRet;
01075     }
01076 
01077     eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval ,
01078                                 pMeasConfig->vBiasEnable );
01079     if (eRet != ADMW_SUCCESS ) {
01080         ADMW_LOG_ERROR("Failed to set cycle control");
01081         return eRet;
01082     }
01083 
01084     if(pMeasConfig->externalRef1Value >0) {
01085         eRet = admw_SetExternalReferenceValues(hDevice,
01086                                                pMeasConfig->externalRef1Value );
01087     }
01088 
01089     if (eRet != ADMW_SUCCESS ) {
01090         ADMW_LOG_ERROR("Failed to set external reference values");
01091         return eRet;
01092     }
01093 
01094     return ADMW_SUCCESS ;
01095 }
01096 
01097 ADMW_RESULT  admw1001_SetDiagnosticsConfig(
01098     ADMW_DEVICE_HANDLE  hDevice,
01099     ADMW1001_DIAGNOSTICS_CONFIG  *pDiagnosticsConfig)
01100 {
01101     ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg;
01102 
01103     diagnosticsControlReg.VALUE16 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL);
01104 
01105     if (pDiagnosticsConfig->disableGlobalDiag )
01106         diagnosticsControlReg.Diag_Global_En = 0;
01107     else
01108         diagnosticsControlReg.Diag_Global_En = 1;
01109 
01110     if (pDiagnosticsConfig->disableMeasurementDiag )
01111         diagnosticsControlReg.Diag_Meas_En = 0;
01112     else
01113         diagnosticsControlReg.Diag_Meas_En = 1;
01114 
01115     switch (pDiagnosticsConfig->osdFrequency ) {
01116         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_DISABLED :
01117             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_OFF;
01118             break;
01119         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_CYCLE :
01120             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1_CYCLE;
01121             break;
01122         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_100_CYCLES :
01123             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_100_CYCLES;
01124             break;
01125         case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_1000_CYCLES :
01126             diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1000_CYCLES;
01127             break;
01128         default:
01129             ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified",
01130                            pDiagnosticsConfig->osdFrequency );
01131             return ADMW_INVALID_PARAM ;
01132     }
01133 
01134     WRITE_REG_U16(hDevice, diagnosticsControlReg.VALUE16, CORE_DIAGNOSTICS_CONTROL);
01135 
01136     return ADMW_SUCCESS ;
01137 }
01138 
01139 ADMW_RESULT  admw1001_SetChannelCount(
01140     ADMW_DEVICE_HANDLE  hDevice,
01141     ADMW1001_CH_ID  eChannelId,
01142     uint32_t nMeasurementsPerCycle)
01143 {
01144     ADMW_CORE_Channel_Count_t channelCountReg;
01145 
01146     channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn);
01147 
01148     if (nMeasurementsPerCycle > 0) {
01149         nMeasurementsPerCycle -= 1;
01150 
01151         CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT,
01152                             nMeasurementsPerCycle);
01153 
01154         channelCountReg.Channel_Enable = 1;
01155         channelCountReg.Channel_Count = nMeasurementsPerCycle;
01156     } else {
01157         channelCountReg.Channel_Enable = 0;
01158     }
01159 
01160     WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId));
01161 
01162     return ADMW_SUCCESS ;
01163 }
01164 
01165 ADMW_RESULT  admw1001_SetChannelOptions(
01166     ADMW_DEVICE_HANDLE  hDevice,
01167     ADMW1001_CH_ID  eChannelId,
01168     ADMW1001_CHANNEL_PRIORITY  ePriority)
01169 {
01170     ADMW_CORE_Channel_Options_t channelOptionsReg;
01171 
01172     channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn);
01173 
01174     CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority);
01175     channelOptionsReg.Channel_Priority = ePriority;
01176 
01177     WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId));
01178 
01179     return ADMW_SUCCESS ;
01180 }
01181 
01182 ADMW_RESULT  admw1001_SetChannelSkipCount(
01183     ADMW_DEVICE_HANDLE  hDevice,
01184     ADMW1001_CH_ID  eChannelId,
01185     uint32_t nCycleSkipCount)
01186 {
01187     ADMW_CORE_Channel_Skip_t channelSkipReg;
01188 
01189     channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn);
01190 
01191     CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount);
01192 
01193     channelSkipReg.Channel_Skip = nCycleSkipCount;
01194 
01195     WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId));
01196 
01197     return ADMW_SUCCESS ;
01198 }
01199 
01200 static ADMW_RESULT  admw_SetChannelAdcSensorType(
01201     ADMW_DEVICE_HANDLE           hDevice,
01202     ADMW1001_CH_ID               eChannelId,
01203     ADMW1001_ADC_SENSOR_TYPE     sensorType)
01204 {
01205     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01206 
01207     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01208 
01209     /* Ensure that the sensor type is valid for this channel */
01210     switch(sensorType) {
01211         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 :
01212         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 :
01213         case ADMW1001_ADC_SENSOR_RTD_3WIRE_1 :
01214         case ADMW1001_ADC_SENSOR_RTD_3WIRE_2 :
01215         case ADMW1001_ADC_SENSOR_RTD_3WIRE_3 :
01216         case ADMW1001_ADC_SENSOR_RTD_3WIRE_4 :
01217         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 :
01218         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 :
01219         case ADMW1001_ADC_SENSOR_RTD_4WIRE_1 :
01220         case ADMW1001_ADC_SENSOR_RTD_4WIRE_2 :
01221         case ADMW1001_ADC_SENSOR_RTD_4WIRE_3 :
01222         case ADMW1001_ADC_SENSOR_RTD_4WIRE_4 :
01223         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_1 :
01224         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_2 :
01225         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_3 :
01226         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_4 :
01227         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_1 :
01228         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_2 :
01229         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_3 :
01230         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_4 :
01231         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 :
01232         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 :
01233         case ADMW1001_ADC_SENSOR_RTD_2WIRE_1 :
01234         case ADMW1001_ADC_SENSOR_RTD_2WIRE_2 :
01235         case ADMW1001_ADC_SENSOR_RTD_2WIRE_3 :
01236         case ADMW1001_ADC_SENSOR_RTD_2WIRE_4 :
01237         case ADMW1001_ADC_SENSOR_DIODE_2C_TYPEA :
01238         case ADMW1001_ADC_SENSOR_DIODE_3C_TYPEA :
01239         case ADMW1001_ADC_SENSOR_DIODE_2C_1 :
01240         case ADMW1001_ADC_SENSOR_DIODE_3C_1 :
01241         case ADMW1001_ADC_SENSOR_THERMISTOR_A_10K :
01242         case ADMW1001_ADC_SENSOR_THERMISTOR_B_10K :
01243         case ADMW1001_ADC_SENSOR_THERMISTOR_1 :
01244         case ADMW1001_ADC_SENSOR_THERMISTOR_2 :
01245         case ADMW1001_ADC_SENSOR_THERMISTOR_3 :
01246         case ADMW1001_ADC_SENSOR_THERMISTOR_4 :
01247             if (! (ADMW1001_CHANNEL_IS_ADC_SENSOR(eChannelId) ||
01248                     ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId))) {
01249                 ADMW_LOG_ERROR(
01250                     "Invalid ADC sensor type %d specified for channel %d",
01251                     sensorType, eChannelId);
01252                 return ADMW_INVALID_PARAM ;
01253             }
01254             break;
01255         case ADMW1001_ADC_SENSOR_VOLTAGE :
01256         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_A :
01257         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_B :
01258         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_1 :
01259         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_2 :
01260         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J :
01261         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K :
01262         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T :
01263         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_1 :
01264         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_2 :
01265         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_3 :
01266         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_4 :
01267             if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) {
01268                 ADMW_LOG_ERROR(
01269                     "Invalid ADC sensor type %d specified for channel %d",
01270                     sensorType, eChannelId);
01271                 return ADMW_INVALID_PARAM ;
01272             }
01273             break;
01274         case ADMW1001_ADC_SENSOR_CURRENT :
01275         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_A :
01276         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_1 :
01277         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_2 :
01278             if (! ADMW1001_CHANNEL_IS_ADC_CURRENT(eChannelId)) {
01279                 ADMW_LOG_ERROR(
01280                     "Invalid ADC sensor type %d specified for channel %d",
01281                     sensorType, eChannelId);
01282                 return ADMW_INVALID_PARAM ;
01283             }
01284             break;
01285         default:
01286             ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified",
01287                            sensorType);
01288             return ADMW_INVALID_PARAM ;
01289     }
01290 
01291     sensorTypeReg.Sensor_Type = sensorType;
01292 
01293     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01294 
01295     return ADMW_SUCCESS ;
01296 }
01297 
01298 static ADMW_RESULT  admw_SetChannelAdcSensorDetails(
01299     ADMW_DEVICE_HANDLE       hDevice,
01300     ADMW1001_CH_ID           eChannelId,
01301     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01302 /*
01303  * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers
01304  * General details:
01305  * - Measurement_Units
01306  * - Compensation_Channel
01307  * - CJC_Publish (if "CJC" was removed from the name)
01308  * ADC-specific details:
01309  * - PGA_Gain
01310  * - Reference_Select
01311  * - Reference_Buffer_Disable
01312  */
01313 {
01314     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ;
01315     ADMW1001_ADC_REFERENCE_TYPE  refType            = pAdcChannelConfig->reference;
01316     ADMW_CORE_Sensor_Details_t  sensorDetailsReg;
01317 
01318     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01319 
01320     switch(pChannelConfig->measurementUnit ) {
01321         case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT :
01322             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF;
01323             break;
01324         case ADMW1001_MEASUREMENT_UNIT_CELSIUS :
01325             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC;
01326             break;
01327         case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED :
01328             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01329             break;
01330         default:
01331             ADMW_LOG_ERROR("Invalid measurement unit %d specified",
01332                            pChannelConfig->measurementUnit );
01333             return ADMW_INVALID_PARAM ;
01334     }
01335 
01336     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01337         sensorDetailsReg.Compensation_Disable = 1;
01338         sensorDetailsReg.Compensation_Channel = 0;
01339     } else {
01340         sensorDetailsReg.Compensation_Disable = 0;
01341         sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ;
01342     }
01343 
01344     switch(refType) {
01345         case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL :
01346             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT;
01347             break;
01348         case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 :
01349             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1;
01350             break;
01351         case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD :
01352             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD;
01353             break;
01354         default:
01355             ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType);
01356             return ADMW_INVALID_PARAM ;
01357     }
01358 
01359     switch(pAdcChannelConfig->gain ) {
01360         case ADMW1001_ADC_GAIN_1X :
01361             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1;
01362             break;
01363         case ADMW1001_ADC_GAIN_2X :
01364             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2;
01365             break;
01366         case ADMW1001_ADC_GAIN_4X :
01367             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4;
01368             break;
01369         case ADMW1001_ADC_GAIN_8X :
01370             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8;
01371             break;
01372         case ADMW1001_ADC_GAIN_16X :
01373             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16;
01374             break;
01375         case ADMW1001_ADC_GAIN_32X :
01376             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32;
01377             break;
01378         case ADMW1001_ADC_GAIN_64X :
01379             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64;
01380             break;
01381         case ADMW1001_ADC_GAIN_128X :
01382             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128;
01383             break;
01384         default:
01385             ADMW_LOG_ERROR("Invalid ADC gain %d specified",
01386                            pAdcChannelConfig->gain );
01387             return ADMW_INVALID_PARAM ;
01388     }
01389 
01390     switch(pAdcChannelConfig->rtdCurve ) {
01391         case ADMW1001_ADC_RTD_CURVE_EUROPEAN :
01392             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE;
01393             break;
01394         case ADMW1001_ADC_RTD_CURVE_AMERICAN :
01395             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE;
01396             break;
01397         case ADMW1001_ADC_RTD_CURVE_JAPANESE :
01398             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE;
01399             break;
01400         case ADMW1001_ADC_RTD_CURVE_ITS90 :
01401             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE;
01402             break;
01403         default:
01404             ADMW_LOG_ERROR("Invalid RTD Curve %d specified",
01405                            pAdcChannelConfig->rtdCurve );
01406             return ADMW_INVALID_PARAM ;
01407     }
01408 
01409     if (pChannelConfig->disablePublishing ) {
01410         sensorDetailsReg.Do_Not_Publish = 1;
01411     } else {
01412         sensorDetailsReg.Do_Not_Publish = 0;
01413     }
01414 
01415     switch (pChannelConfig->lutSelect ) {
01416         case ADMW1001_LUT_DEFAULT :
01417         case ADMW1001_LUT_UNITY :
01418         case ADMW1001_LUT_CUSTOM :
01419             sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ;
01420             break;
01421         default:
01422             ADMW_LOG_ERROR("Invalid LUT selection %d specified",
01423                            pChannelConfig->lutSelect );
01424             return ADMW_INVALID_PARAM ;
01425     }
01426 
01427     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01428 
01429     return ADMW_SUCCESS ;
01430 }
01431 
01432 static ADMW_RESULT  admw_SetChannelAdcFilter(
01433     ADMW_DEVICE_HANDLE  hDevice,
01434     ADMW1001_CH_ID  eChannelId,
01435     ADMW1001_ADC_FILTER_CONFIG  *pFilterConfig)
01436 {
01437     ADMW_CORE_Measurement_Setup_t MeasSetupReg;
01438     MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn);
01439 
01440     if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC4 ) {
01441         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4;
01442         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01443     } else if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC3 ) {
01444         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3;
01445         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01446     } else {
01447         ADMW_LOG_ERROR("Invalid ADC filter type %d specified",
01448                        pFilterConfig->type );
01449         return ADMW_INVALID_PARAM ;
01450     }
01451 
01452     /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */
01453     MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ;
01454 
01455     if(pFilterConfig->notch1p2 )
01456         MeasSetupReg.NOTCH_EN_2 = 1;
01457     else
01458         MeasSetupReg.NOTCH_EN_2 = 0;
01459 
01460     switch(pFilterConfig->groundSwitch ) {
01461         case ADMW1001_ADC_GND_SW_OPEN :
01462             MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_OPEN;
01463             break;
01464         case ADMW1001_ADC_GND_SW_CLOSED :
01465             MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_CLOSED;
01466             break;
01467         default:
01468             ADMW_LOG_ERROR("Invalid ground switch state %d specified",
01469                            pFilterConfig->groundSwitch );
01470             return ADMW_INVALID_PARAM ;
01471     }
01472 
01473     WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId));
01474 
01475     return ADMW_SUCCESS ;
01476 }
01477 
01478 static ADMW_RESULT  admw_SetChannelAdcCurrentConfig(
01479     ADMW_DEVICE_HANDLE  hDevice,
01480     ADMW1001_CH_ID  eChannelId,
01481     ADMW1001_ADC_EXC_CURRENT_CONFIG  *pCurrentConfig)
01482 {
01483     ADMW_CORE_Channel_Excitation_t channelExcitationReg;
01484 
01485     channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn);
01486 
01487     if (pCurrentConfig->outputLevel  == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT )
01488         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE;
01489     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_EXTERNAL )
01490         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL;
01491     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_50uA )
01492         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA;
01493     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_100uA )
01494         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA;
01495     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_250uA )
01496         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA;
01497     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_500uA )
01498         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA;
01499     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_1000uA )
01500         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA;
01501     else {
01502         ADMW_LOG_ERROR("Invalid ADC excitation current %d specified",
01503                        pCurrentConfig->outputLevel );
01504         return ADMW_INVALID_PARAM ;
01505     }
01506 
01507 
01508 
01509     switch(pCurrentConfig->diodeRatio ) {
01510         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_100UA:
01511             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_10UA_100UA;
01512             break;
01513         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_160UA:
01514             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_20UA_160UA;
01515             break;
01516         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_300UA:
01517             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_50UA_300UA;
01518             break;
01519         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_600UA:
01520             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_2PT_100UA_600UA;
01521             break;
01522         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_10UA_50UA_100UA:
01523             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_10UA_50UA_100UA;
01524             break;
01525         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_20UA_100UA_160UA:
01526             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_20UA_100UA_160UA;
01527             break;
01528         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_50UA_150UA_300UA:
01529             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_50UA_150UA_300UA;
01530             break;
01531         case ADMW1001_ADC_EXC_CURRENT_IOUT_DIODE_100UA_300UA_600UA:
01532             channelExcitationReg.IOUT_Diode_Ratio = CORE_CHANNEL_EXCITATION_DIODE_3PT_100UA_300UA_600UA;
01533             break;
01534         default:
01535             ADMW_LOG_ERROR("Invalid diode ratio %d specified",
01536                            pCurrentConfig->diodeRatio );
01537             return ADMW_INVALID_PARAM ;
01538     }
01539 
01540     WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId));
01541 
01542     return ADMW_SUCCESS ;
01543 }
01544 
01545 ADMW_RESULT  admw_SetAdcChannelConfig(
01546     ADMW_DEVICE_HANDLE  hDevice,
01547     ADMW1001_CH_ID  eChannelId,
01548     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01549 {
01550     ADMW_RESULT  eRet;
01551     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig =
01552         &pChannelConfig->adcChannelConfig ;
01553 
01554     eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId,
01555                                         pAdcChannelConfig->sensor );
01556     if (eRet != ADMW_SUCCESS ) {
01557         ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d",
01558                        eChannelId);
01559         return eRet;
01560     }
01561 
01562     eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId,
01563                                            pChannelConfig);
01564     if (eRet != ADMW_SUCCESS ) {
01565         ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d",
01566                        eChannelId);
01567         return eRet;
01568     }
01569 
01570     eRet = admw_SetChannelAdcFilter(hDevice, eChannelId,
01571                                     &pAdcChannelConfig->filter );
01572     if (eRet != ADMW_SUCCESS ) {
01573         ADMW_LOG_ERROR("Failed to set ADC filter for channel %d",
01574                        eChannelId);
01575         return eRet;
01576     }
01577 
01578     eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId,
01579                                            &pAdcChannelConfig->current );
01580     if (eRet != ADMW_SUCCESS ) {
01581         ADMW_LOG_ERROR("Failed to set ADC current for channel %d",
01582                        eChannelId);
01583         return eRet;
01584     }
01585 
01586     return ADMW_SUCCESS ;
01587 }
01588 
01589 static ADMW_RESULT  admw_SetChannelDigitalSensorDetails(
01590     ADMW_DEVICE_HANDLE  hDevice,
01591     ADMW1001_CH_ID  eChannelId,
01592     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01593 {
01594     ADMW_CORE_Sensor_Details_t sensorDetailsReg;
01595 
01596     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01597 
01598     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01599         sensorDetailsReg.Compensation_Disable = 1;
01600         sensorDetailsReg.Compensation_Channel = 0;
01601     } else {
01602         ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor");
01603         return ADMW_INVALID_PARAM ;
01604     }
01605 
01606     if (pChannelConfig->measurementUnit  == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) {
01607         sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01608     } else {
01609         ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel");
01610         return ADMW_INVALID_PARAM ;
01611     }
01612 
01613     if (pChannelConfig->disablePublishing )
01614         sensorDetailsReg.Do_Not_Publish = 1;
01615     else
01616         sensorDetailsReg.Do_Not_Publish = 0;
01617 
01618     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01619 
01620     return ADMW_SUCCESS ;
01621 }
01622 
01623 static ADMW_RESULT  admw_SetDigitalSensorCommands(
01624     ADMW_DEVICE_HANDLE  hDevice,
01625     ADMW1001_CH_ID  eChannelId,
01626     ADMW1001_DIGITAL_SENSOR_COMMAND  *pConfigCommand,
01627     ADMW1001_DIGITAL_SENSOR_COMMAND  *pDataRequestCommand)
01628 {
01629     ADMW_CORE_Digital_Sensor_Num_Cmds_t numCmdsReg;
01630 
01631     numCmdsReg.VALUE8 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_NUM_CMDSn);
01632 
01633     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_CFG_CMDS,
01634                         pConfigCommand->commandLength );
01635     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_NUM_CMDS_DIGITAL_SENSOR_NUM_READ_CMDS,
01636                         pDataRequestCommand->commandLength );
01637 
01638     numCmdsReg.Digital_Sensor_Num_Cfg_Cmds = pConfigCommand->commandLength ;
01639     numCmdsReg.Digital_Sensor_Num_Read_Cmds = pDataRequestCommand->commandLength ;
01640 
01641     WRITE_REG_U8(hDevice, numCmdsReg.VALUE8,
01642                  CORE_DIGITAL_SENSOR_NUM_CMDSn(eChannelId));
01643 
01644     /*
01645      * NOTE - the fall-through cases in the switch statement below are
01646      * intentional.
01647      */
01648     switch (pConfigCommand->commandLength ) {
01649         case 7:
01650             WRITE_REG_U8(hDevice, pConfigCommand->command [6],
01651                          CORE_DIGITAL_SENSOR_COMMAND7n(eChannelId));
01652         case 6:
01653             WRITE_REG_U8(hDevice, pConfigCommand->command [5],
01654                          CORE_DIGITAL_SENSOR_COMMAND6n(eChannelId));
01655         case 5:
01656             WRITE_REG_U8(hDevice, pConfigCommand->command [4],
01657                          CORE_DIGITAL_SENSOR_COMMAND5n(eChannelId));
01658         case 4:
01659             WRITE_REG_U8(hDevice, pConfigCommand->command [3],
01660                          CORE_DIGITAL_SENSOR_COMMAND4n(eChannelId));
01661         case 3:
01662             WRITE_REG_U8(hDevice, pConfigCommand->command [2],
01663                          CORE_DIGITAL_SENSOR_COMMAND3n(eChannelId));
01664         case 2:
01665             WRITE_REG_U8(hDevice, pConfigCommand->command [1],
01666                          CORE_DIGITAL_SENSOR_COMMAND2n(eChannelId));
01667         case 1:
01668             WRITE_REG_U8(hDevice, pConfigCommand->command [0],
01669                          CORE_DIGITAL_SENSOR_COMMAND1n(eChannelId));
01670         case 0:
01671         default:
01672             break;
01673     };
01674 
01675     switch (pDataRequestCommand->commandLength ) {
01676         case 7:
01677             WRITE_REG_U8(hDevice, pDataRequestCommand->command [6],
01678                          CORE_DIGITAL_SENSOR_READ_CMD7n(eChannelId));
01679         case 6:
01680             WRITE_REG_U8(hDevice, pDataRequestCommand->command [5],
01681                          CORE_DIGITAL_SENSOR_READ_CMD6n(eChannelId));
01682         case 5:
01683             WRITE_REG_U8(hDevice, pDataRequestCommand->command [4],
01684                          CORE_DIGITAL_SENSOR_READ_CMD5n(eChannelId));
01685         case 4:
01686             WRITE_REG_U8(hDevice, pDataRequestCommand->command [3],
01687                          CORE_DIGITAL_SENSOR_READ_CMD4n(eChannelId));
01688         case 3:
01689             WRITE_REG_U8(hDevice, pDataRequestCommand->command [2],
01690                          CORE_DIGITAL_SENSOR_READ_CMD3n(eChannelId));
01691         case 2:
01692             WRITE_REG_U8(hDevice, pDataRequestCommand->command [1],
01693                          CORE_DIGITAL_SENSOR_READ_CMD2n(eChannelId));
01694         case 1:
01695             WRITE_REG_U8(hDevice, pDataRequestCommand->command [0],
01696                          CORE_DIGITAL_SENSOR_READ_CMD1n(eChannelId));
01697         case 0:
01698         default:
01699             break;
01700     };
01701 
01702     return ADMW_SUCCESS ;
01703 }
01704 
01705 static ADMW_RESULT  admw_SetDigitalSensorFormat(
01706     ADMW_DEVICE_HANDLE  hDevice,
01707     ADMW1001_CH_ID  eChannelId,
01708     ADMW1001_DIGITAL_SENSOR_DATA_FORMAT  *pDataFormat)
01709 {
01710     ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg;
01711 
01712     sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn);
01713 
01714     if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) {
01715         if (pDataFormat->frameLength == 0) {
01716             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01717             return ADMW_INVALID_PARAM ;
01718         }
01719         if (pDataFormat->numDataBits == 0) {
01720             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01721             return ADMW_INVALID_PARAM ;
01722         }
01723 
01724         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES,
01725                             pDataFormat->frameLength - 1);
01726         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS,
01727                             pDataFormat->numDataBits - 1);
01728         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET,
01729                             pDataFormat->bitOffset);
01730 
01731         sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1;
01732         sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1;
01733         sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset;
01734         sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0;
01735         sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0;
01736 
01737         switch (pDataFormat->coding) {
01738             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR:
01739                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR;
01740                 break;
01741             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT:
01742                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL;
01743                 break;
01744             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY:
01745                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY;
01746                 break;
01747             default:
01748                 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format");
01749                 return ADMW_INVALID_PARAM ;
01750         }
01751     } else {
01752         sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE;
01753     }
01754 
01755     WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16,
01756                   CORE_DIGITAL_SENSOR_CONFIGn(eChannelId));
01757 
01758 
01759     return ADMW_SUCCESS ;
01760 }
01761 
01762 static ADMW_RESULT  admw_SetDigitalCalibrationParam(
01763     ADMW_DEVICE_HANDLE  hDevice,
01764     ADMW1001_CH_ID  eChannelId,
01765     ADMW1001_DIGITAL_CALIBRATION_COMMAND  *pCalibrationParam)
01766 {
01767     ADMW_CORE_Calibration_Parameter_t calibrationParamReg;
01768 
01769     calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn);
01770 
01771     if (pCalibrationParam->enableCalibrationParam  == false)
01772         calibrationParamReg.Calibration_Parameter_Enable = 0;
01773     else
01774         calibrationParamReg.Calibration_Parameter_Enable = 1;
01775 
01776     CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER,
01777                         pCalibrationParam->calibrationParam );
01778 
01779     calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam ;
01780 
01781     WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32,
01782                   CORE_CALIBRATION_PARAMETERn(eChannelId));
01783 
01784     return ADMW_SUCCESS ;
01785 }
01786 
01787 static ADMW_RESULT  admw_SetChannelI2cSensorType(
01788     ADMW_DEVICE_HANDLE  hDevice,
01789     ADMW1001_CH_ID  eChannelId,
01790     ADMW1001_I2C_SENSOR_TYPE  sensorType)
01791 {
01792     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01793 
01794     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01795 
01796     /* Ensure that the sensor type is valid for this channel */
01797     switch(sensorType) {
01798         case ADMW1001_I2C_SENSOR_HUMIDITY_A :
01799         case ADMW1001_I2C_SENSOR_HUMIDITY_B :
01800             sensorTypeReg.Sensor_Type = sensorType;
01801             break;
01802         default:
01803             ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType);
01804             return ADMW_INVALID_PARAM ;
01805     }
01806 
01807     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01808 
01809     return ADMW_SUCCESS ;
01810 }
01811 
01812 static ADMW_RESULT  admw_SetChannelI2cSensorAddress(
01813     ADMW_DEVICE_HANDLE  hDevice,
01814     ADMW1001_CH_ID  eChannelId,
01815     uint32_t deviceAddress)
01816 {
01817     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress);
01818     WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId));
01819 
01820     return ADMW_SUCCESS ;
01821 }
01822 
01823 static ADMW_RESULT  admw_SetDigitalChannelComms(
01824     ADMW_DEVICE_HANDLE  hDevice,
01825     ADMW1001_CH_ID  eChannelId,
01826     ADMW1001_DIGITAL_SENSOR_COMMS  *pDigitalComms)
01827 {
01828     ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms;
01829 
01830     digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn);
01831 
01832     if(pDigitalComms->useCustomCommsConfig ) {
01833         digitalSensorComms.Digital_Sensor_Comms_En = 1;
01834 
01835         if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) {
01836             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K;
01837         } else if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) {
01838             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K;
01839         } else {
01840             ADMW_LOG_ERROR("Invalid I2C clock speed %d specified",
01841                            pDigitalComms->i2cClockSpeed );
01842             return ADMW_INVALID_PARAM ;
01843         }
01844 
01845         if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) {
01846             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0;
01847         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) {
01848             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1;
01849         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) {
01850             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2;
01851         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) {
01852             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3;
01853         } else {
01854             ADMW_LOG_ERROR("Invalid SPI mode %d specified",
01855                            pDigitalComms->spiMode );
01856             return ADMW_INVALID_PARAM ;
01857         }
01858 
01859         switch (pDigitalComms->spiClock ) {
01860             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ :
01861                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ;
01862                 break;
01863             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ :
01864                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ;
01865                 break;
01866             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ :
01867                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ;
01868                 break;
01869             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ :
01870                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ;
01871                 break;
01872             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ :
01873                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ;
01874                 break;
01875             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ :
01876                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ;
01877                 break;
01878             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ :
01879                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ;
01880                 break;
01881             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ :
01882                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ;
01883                 break;
01884             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ :
01885                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ;
01886                 break;
01887             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ :
01888                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ;
01889                 break;
01890             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ :
01891                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ;
01892                 break;
01893             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ :
01894                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ;
01895                 break;
01896             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ :
01897                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ;
01898                 break;
01899             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ :
01900                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ;
01901                 break;
01902             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ :
01903                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ;
01904                 break;
01905             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ :
01906                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ;
01907                 break;
01908             default:
01909                 ADMW_LOG_ERROR("Invalid SPI clock %d specified",
01910                                pDigitalComms->spiClock );
01911                 return ADMW_INVALID_PARAM ;
01912         }
01913     } else {
01914         digitalSensorComms.Digital_Sensor_Comms_En = 0;
01915     }
01916 
01917     WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId));
01918 
01919     return ADMW_SUCCESS ;
01920 }
01921 
01922 ADMW_RESULT  admw_SetI2cChannelConfig(
01923     ADMW_DEVICE_HANDLE  hDevice,
01924     ADMW1001_CH_ID  eChannelId,
01925     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01926 {
01927     ADMW_RESULT  eRet;
01928     ADMW1001_I2C_CHANNEL_CONFIG  *pI2cChannelConfig =
01929         &pChannelConfig->i2cChannelConfig ;
01930 
01931     eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId,
01932                                         pI2cChannelConfig->sensor );
01933     if (eRet != ADMW_SUCCESS ) {
01934         ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d",
01935                        eChannelId);
01936         return eRet;
01937     }
01938 
01939     eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId,
01940                                            pI2cChannelConfig->deviceAddress );
01941     if (eRet != ADMW_SUCCESS ) {
01942         ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d",
01943                        eChannelId);
01944         return eRet;
01945     }
01946 
01947     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
01948             pChannelConfig);
01949     if (eRet != ADMW_SUCCESS ) {
01950         ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d",
01951                        eChannelId);
01952         return eRet;
01953     }
01954 
01955     eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId,
01956                                          &pI2cChannelConfig->configurationCommand ,
01957                                          &pI2cChannelConfig->dataRequestCommand );
01958     if (eRet != ADMW_SUCCESS ) {
01959         ADMW_LOG_ERROR("Failed to set I2C sensor commands for channel %d",
01960                        eChannelId);
01961         return eRet;
01962     }
01963 
01964     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
01965                                        &pI2cChannelConfig->dataFormat );
01966     if (eRet != ADMW_SUCCESS ) {
01967         ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d",
01968                        eChannelId);
01969         return eRet;
01970     }
01971 
01972     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
01973                                            &pI2cChannelConfig->digitalCalibrationParam );
01974     if (eRet != ADMW_SUCCESS ) {
01975         ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d",
01976                        eChannelId);
01977         return eRet;
01978     }
01979 
01980     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
01981                                        &pI2cChannelConfig->configureComms );
01982     if (eRet != ADMW_SUCCESS ) {
01983         ADMW_LOG_ERROR("Failed to set I2C comms for channel %d",
01984                        eChannelId);
01985         return eRet;
01986     }
01987 
01988     return ADMW_SUCCESS ;
01989 }
01990 
01991 static ADMW_RESULT  admw_SetChannelSpiSensorType(
01992     ADMW_DEVICE_HANDLE  hDevice,
01993     ADMW1001_CH_ID  eChannelId,
01994     ADMW1001_SPI_SENSOR_TYPE  sensorType)
01995 {
01996     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01997 
01998     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01999 
02000     /* Ensure that the sensor type is valid for this channel */
02001     switch(sensorType) {
02002         case ADMW1001_SPI_SENSOR_PRESSURE_A :
02003         case ADMW1001_SPI_SENSOR_ACCELEROMETER_A :
02004         case ADMW1001_SPI_SENSOR_ACCELEROMETER_B :
02005 
02006             sensorTypeReg.Sensor_Type = sensorType;
02007             break;
02008         default:
02009             ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType);
02010             return ADMW_INVALID_PARAM ;
02011     }
02012 
02013     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
02014 
02015     return ADMW_SUCCESS ;
02016 }
02017 
02018 ADMW_RESULT  admw_SetSpiChannelConfig(
02019     ADMW_DEVICE_HANDLE  hDevice,
02020     ADMW1001_CH_ID  eChannelId,
02021     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
02022 {
02023     ADMW_RESULT  eRet;
02024     ADMW1001_SPI_CHANNEL_CONFIG  *pSpiChannelConfig =
02025         &pChannelConfig->spiChannelConfig ;
02026 
02027     eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId,
02028                                         pSpiChannelConfig->sensor );
02029     if (eRet != ADMW_SUCCESS ) {
02030         ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d",
02031                        eChannelId);
02032         return eRet;
02033     }
02034 
02035     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
02036             pChannelConfig);
02037     if (eRet != ADMW_SUCCESS ) {
02038         ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d",
02039                        eChannelId);
02040         return eRet;
02041     }
02042 
02043     eRet = admw_SetDigitalSensorCommands(hDevice, eChannelId,
02044                                          &pSpiChannelConfig->configurationCommand ,
02045                                          &pSpiChannelConfig->dataRequestCommand );
02046     if (eRet != ADMW_SUCCESS ) {
02047         ADMW_LOG_ERROR("Failed to set SPI sensor commands for channel %d",
02048                        eChannelId);
02049         return eRet;
02050     }
02051 
02052     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
02053                                        &pSpiChannelConfig->dataFormat );
02054     if (eRet != ADMW_SUCCESS ) {
02055         ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d",
02056                        eChannelId);
02057         return eRet;
02058     }
02059 
02060     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
02061                                            &pSpiChannelConfig->digitalCalibrationParam );
02062     if (eRet != ADMW_SUCCESS ) {
02063         ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d",
02064                        eChannelId);
02065         return eRet;
02066     }
02067 
02068     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
02069                                        &pSpiChannelConfig->configureComms );
02070     if (eRet != ADMW_SUCCESS ) {
02071         ADMW_LOG_ERROR("Failed to set SPI comms for channel %d",
02072                        eChannelId);
02073         return eRet;
02074     }
02075 
02076     return ADMW_SUCCESS ;
02077 }
02078 
02079 ADMW_RESULT  admw1001_SetChannelThresholdLimits(
02080     ADMW_DEVICE_HANDLE  hDevice,
02081     ADMW1001_CH_ID  eChannelId,
02082     float32_t fHighThresholdLimit,
02083     float32_t fLowThresholdLimit)
02084 {
02085     /*
02086      * If the low/high limits are *both* set to 0 in memory, or NaNs, assume
02087      * that they are unset, or not required, and use infinity defaults instead
02088      */
02089     if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) {
02090         fHighThresholdLimit = INFINITY;
02091         fLowThresholdLimit = -INFINITY;
02092     } else {
02093         if (isnan(fHighThresholdLimit))
02094             fHighThresholdLimit = INFINITY;
02095         if (isnan(fLowThresholdLimit))
02096             fLowThresholdLimit = -INFINITY;
02097     }
02098 
02099     WRITE_REG_FLOAT(hDevice, fHighThresholdLimit,
02100                     CORE_HIGH_THRESHOLD_LIMITn(eChannelId));
02101     WRITE_REG_FLOAT(hDevice, fLowThresholdLimit,
02102                     CORE_LOW_THRESHOLD_LIMITn(eChannelId));
02103 
02104     return ADMW_SUCCESS ;
02105 }
02106 
02107 ADMW_RESULT  admw1001_SetOffsetGain(
02108     ADMW_DEVICE_HANDLE  hDevice,
02109     ADMW1001_CH_ID  eChannelId,
02110     float32_t fOffsetAdjustment,
02111     float32_t fGainAdjustment)
02112 {
02113     /* Replace with default values if NaNs are specified (or 0.0 for gain) */
02114     if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f))
02115         fGainAdjustment = 1.0f;
02116     if (isnan(fOffsetAdjustment))
02117         fOffsetAdjustment = 0.0f;
02118 
02119     WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId));
02120     WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId));
02121 
02122     return ADMW_SUCCESS ;
02123 }
02124 
02125 ADMW_RESULT  admw1001_SetSensorParameter(
02126     ADMW_DEVICE_HANDLE  hDevice,
02127     ADMW1001_CH_ID  eChannelId,
02128     float32_t fSensorParam)
02129 {
02130     if (fSensorParam == 0.0f)
02131         fSensorParam = NAN;
02132 
02133     WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId));
02134 
02135     return ADMW_SUCCESS ;
02136 }
02137 
02138 ADMW_RESULT  admw1001_SetChannelSettlingTime(
02139     ADMW_DEVICE_HANDLE  hDevice,
02140     ADMW1001_CH_ID  eChannelId,
02141     uint32_t nSettlingTime)
02142 {
02143     ADMW_CORE_Settling_Time_t settlingTimeReg;
02144 
02145     if (nSettlingTime < (1 << 12)) {
02146         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MICROSECONDS;
02147     } else if (nSettlingTime < (1000 * (1 << 12))) {
02148         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MILLISECONDS;
02149         nSettlingTime /= 1000;
02150     } else {
02151         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_SECONDS;
02152         nSettlingTime /= 1000000;
02153     }
02154 
02155     CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime);
02156     settlingTimeReg.Settling_Time = nSettlingTime;
02157 
02158     WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId));
02159 
02160     return ADMW_SUCCESS ;
02161 }
02162 
02163 ADMW_RESULT  admw1001_SetChannelConfig(
02164     ADMW_DEVICE_HANDLE  hDevice,
02165     ADMW1001_CH_ID  eChannelId,
02166     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
02167 {
02168     ADMW_RESULT  eRet;
02169 
02170     if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) {
02171         eRet = admw1001_SetChannelCount(hDevice, eChannelId,
02172                                         pChannelConfig->enableChannel  ?
02173                                         pChannelConfig->measurementsPerCycle  : 0);
02174         if (eRet != ADMW_SUCCESS ) {
02175             ADMW_LOG_ERROR("Failed to set measurement count for channel %d",
02176                            eChannelId);
02177             return eRet;
02178         }
02179 
02180         eRet = admw1001_SetChannelOptions(hDevice, eChannelId,
02181                                           pChannelConfig->priority );
02182         if (eRet != ADMW_SUCCESS ) {
02183             ADMW_LOG_ERROR("Failed to set priority for channel %d",
02184                            eChannelId);
02185             return eRet;
02186         }
02187 
02188         /* If the channel is not enabled, we can skip the following steps */
02189         if (pChannelConfig->enableChannel ) {
02190             eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId,
02191                                                 pChannelConfig->cycleSkipCount );
02192             if (eRet != ADMW_SUCCESS ) {
02193                 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d",
02194                                eChannelId);
02195                 return eRet;
02196             }
02197 
02198             switch (eChannelId) {
02199                 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL :
02200                 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL :
02201                 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL :
02202                 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL :
02203                     eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig);
02204                     break;
02205                 case ADMW1001_CH_ID_DIG_I2C_0 :
02206                 case ADMW1001_CH_ID_DIG_I2C_1 :
02207                     eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig);
02208                     break;
02209                 case ADMW1001_CH_ID_DIG_SPI_0 :
02210                     eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig);
02211                     break;
02212                 default:
02213                     ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId);
02214                     return ADMW_INVALID_PARAM ;
02215             }
02216 
02217             eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId,
02218                                                    pChannelConfig->extraSettlingTime );
02219             if (eRet != ADMW_SUCCESS ) {
02220                 ADMW_LOG_ERROR("Failed to set settling time for channel %d",
02221                                eChannelId);
02222                 return eRet;
02223             }
02224         }
02225     }
02226 
02227     if (pChannelConfig->enableChannel ) {
02228         /* Threshold limits can be configured individually for virtual channels */
02229         eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId,
02230                 pChannelConfig->highThreshold ,
02231                 pChannelConfig->lowThreshold );
02232         if (eRet != ADMW_SUCCESS ) {
02233             ADMW_LOG_ERROR("Failed to set threshold limits for channel %d",
02234                            eChannelId);
02235             return eRet;
02236         }
02237 
02238         /* Offset and gain can be configured individually for virtual channels */
02239         eRet = admw1001_SetOffsetGain(hDevice, eChannelId,
02240                                       pChannelConfig->offsetAdjustment ,
02241                                       pChannelConfig->gainAdjustment );
02242         if (eRet != ADMW_SUCCESS ) {
02243             ADMW_LOG_ERROR("Failed to set offset/gain for channel %d",
02244                            eChannelId);
02245             return eRet;
02246         }
02247 
02248         /* Set sensor specific parameter */
02249         eRet = admw1001_SetSensorParameter(hDevice, eChannelId,
02250                                            pChannelConfig->sensorParameter );
02251         if (eRet != ADMW_SUCCESS ) {
02252             ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d",
02253                            eChannelId);
02254             return eRet;
02255         }
02256     }
02257 
02258     return ADMW_SUCCESS ;
02259 }
02260 
02261 ADMW_RESULT  admw_SetConfig(
02262     ADMW_DEVICE_HANDLE     const hDevice,
02263     ADMW_CONFIG          * const pConfig)
02264 {
02265     ADMW1001_CONFIG  *pDeviceConfig;
02266     ADMW_PRODUCT_ID  productId;
02267     ADMW_RESULT  eRet;
02268 
02269     if (pConfig->productId  != ADMW_PRODUCT_ID_ADMW1001 ) {
02270         ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)",
02271                        pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 );
02272         return ADMW_INVALID_PARAM ;
02273     }
02274 
02275     if (!((pConfig->versionId .major ==VERSIONID_MAJOR) &&
02276             (pConfig->versionId .minor ==VERSIONID_MINOR))) {
02277         ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported",
02278                        pConfig->versionId );
02279         return ADMW_INVALID_PARAM ;
02280     }
02281 
02282 
02283     /* Check that the actual Product ID is a match? */
02284     eRet = admw_GetProductID(hDevice, &productId);
02285     if (eRet) {
02286         ADMW_LOG_ERROR("Failed to read device Product ID register");
02287         return eRet;
02288     }
02289     if (pConfig->productId  != productId) {
02290         ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)",
02291                        pConfig->productId , productId);
02292         return ADMW_INVALID_PARAM ;
02293     }
02294 
02295     pDeviceConfig = &pConfig->admw1001 ;
02296 
02297     eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power );
02298     if (eRet) {
02299         ADMW_LOG_ERROR("Failed to set power configuration");
02300         return eRet;
02301     }
02302 
02303     eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement );
02304     if (eRet) {
02305         ADMW_LOG_ERROR("Failed to set measurement configuration");
02306         return eRet;
02307     }
02308 
02309     eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics );
02310     if (eRet) {
02311         ADMW_LOG_ERROR("Failed to set diagnostics configuration");
02312         return eRet;
02313     }
02314 
02315     for (ADMW1001_CH_ID  id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
02316             id < ADMW1001_MAX_CHANNELS ;
02317             id++) {
02318         eRet = admw1001_SetChannelConfig(hDevice, id,
02319                                          &pDeviceConfig->channels [id]);
02320         if (eRet) {
02321             ADMW_LOG_ERROR("Failed to set channel %d configuration", id);
02322             return eRet;
02323         }
02324     }
02325 
02326     return ADMW_SUCCESS ;
02327 }
02328 
02329 ADMW_RESULT  admw1001_SetLutData(
02330     ADMW_DEVICE_HANDLE    const hDevice,
02331     ADMW1001_LUT       * const pLutData)
02332 {
02333     ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header;
02334     ADMW1001_LUT_TABLE  *pLutTable = pLutData->tables;
02335     unsigned actualLength = 0;
02336 
02337     if (pLutData->header.signature != ADMW_LUT_SIGNATURE) {
02338         ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)",
02339                        ADMW_LUT_SIGNATURE, pLutHeader->signature);
02340         return ADMW_INVALID_SIGNATURE ;
02341     }
02342 
02343     for (unsigned i = 0; i < pLutHeader->numTables; i++) {
02344         ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor;
02345         ADMW1001_LUT_TABLE_DATA  *pData = &pLutTable->data;
02346         unsigned short calculatedCrc;
02347 
02348         switch (pDesc->geometry) {
02349             case ADMW1001_LUT_GEOMETRY_COEFFS:
02350                 switch (pDesc->equation) {
02351                     case ADMW1001_LUT_EQUATION_POLYN:
02352                     case ADMW1001_LUT_EQUATION_POLYNEXP:
02353                     case ADMW1001_LUT_EQUATION_QUADRATIC:
02354                     case ADMW1001_LUT_EQUATION_STEINHART:
02355                     case ADMW1001_LUT_EQUATION_LOGARITHMIC:
02356                     case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN:
02357                         break;
02358                     default:
02359                         ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02360                                        pDesc->equation, i);
02361                         return ADMW_INVALID_PARAM ;
02362                 }
02363                 break;
02364             case ADMW1001_LUT_GEOMETRY_NES_1D:
02365             case ADMW1001_LUT_GEOMETRY_NES_2D:
02366             case ADMW1001_LUT_GEOMETRY_ES_1D:
02367             case ADMW1001_LUT_GEOMETRY_ES_2D:
02368                 if (pDesc->equation != ADMW1001_LUT_EQUATION_LUT) {
02369                     ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02370                                    pDesc->equation, i);
02371                     return ADMW_INVALID_PARAM ;
02372                 }
02373                 break;
02374             default:
02375                 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u",
02376                                pDesc->geometry, i);
02377                 return ADMW_INVALID_PARAM ;
02378         }
02379 
02380         switch (pDesc->dataType) {
02381             case ADMW1001_LUT_DATA_TYPE_FLOAT32:
02382             case ADMW1001_LUT_DATA_TYPE_FLOAT64:
02383                 break;
02384             default:
02385                 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u",
02386                                pDesc->dataType, i);
02387                 return ADMW_INVALID_PARAM ;
02388         }
02389 
02390         calculatedCrc = admw_crc16_ccitt(pData, pDesc->length);
02391         if (calculatedCrc != pDesc->crc16) {
02392             ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)",
02393                            i, pDesc->crc16, calculatedCrc);
02394             return ADMW_CRC_ERROR ;
02395         }
02396 
02397         actualLength += sizeof(*pDesc) + pDesc->length;
02398 
02399         /* Move to the next look-up table */
02400         pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length);
02401     }
02402 
02403     if (actualLength != pLutHeader->totalLength) {
02404         ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)",
02405                        pLutHeader->totalLength, actualLength);
02406         return ADMW_WRONG_SIZE ;
02407     }
02408 
02409     if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) {
02410         ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded",
02411                        ADMW_LUT_MAX_SIZE);
02412         return ADMW_WRONG_SIZE ;
02413     }
02414 
02415     /* Write the LUT data to the device */
02416     unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength;
02417     WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET);
02418     WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA);
02419 
02420     return ADMW_SUCCESS ;
02421 }
02422 
02423 ADMW_RESULT  admw1001_SetLutDataRaw(
02424     ADMW_DEVICE_HANDLE     const hDevice,
02425     ADMW1001_LUT_RAW   * const pLutData)
02426 {
02427     return admw1001_SetLutData(hDevice,
02428                                (ADMW1001_LUT *)pLutData);
02429 }
02430 
02431 static ADMW_RESULT  getLutTableSize(
02432     ADMW1001_LUT_DESCRIPTOR * const pDesc,
02433     ADMW1001_LUT_TABLE_DATA  * const pData,
02434     unsigned *pLength)
02435 {
02436     switch (pDesc->geometry) {
02437         case ADMW1001_LUT_GEOMETRY_COEFFS:
02438             if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN)
02439                 *pLength = ADMW1001_LUT_2D_POLYN_COEFF_LIST_SIZE(pData->coeffList2d);
02440             else
02441                 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList);
02442             break;
02443         case ADMW1001_LUT_GEOMETRY_NES_1D:
02444             *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes);
02445             break;
02446         case ADMW1001_LUT_GEOMETRY_NES_2D:
02447             *pLength = ADMW1001_LUT_2D_NES_SIZE(pData->lut2dNes);
02448             break;
02449         case ADMW1001_LUT_GEOMETRY_ES_1D:
02450             *pLength = ADMW1001_LUT_1D_ES_SIZE(pData->lut1dEs);
02451             break;
02452         case ADMW1001_LUT_GEOMETRY_ES_2D:
02453             *pLength = ADMW1001_LUT_2D_ES_SIZE(pData->lut2dEs);
02454             break;
02455         default:
02456             ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n",
02457                            pDesc->geometry);
02458             return ADMW_INVALID_PARAM ;
02459     }
02460 
02461     return ADMW_SUCCESS ;
02462 }
02463 
02464 ADMW_RESULT  admw1001_AssembleLutData(
02465     ADMW1001_LUT                  * pLutBuffer,
02466     unsigned                              nLutBufferSize,
02467     unsigned                        const nNumTables,
02468     ADMW1001_LUT_DESCRIPTOR * const ppDesc[],
02469     ADMW1001_LUT_TABLE_DATA  * const ppData[])
02470 {
02471     ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header;
02472     uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr);
02473 
02474     if (sizeof(*pHdr) > nLutBufferSize) {
02475         ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02476         return ADMW_INVALID_PARAM ;
02477     }
02478 
02479     /* First initialise the top-level header */
02480     pHdr->signature = ADMW_LUT_SIGNATURE;
02481     pHdr->version.major = 1;
02482     pHdr->version.minor = 0;
02483     pHdr->numTables = 0;
02484     pHdr->totalLength = 0;
02485 
02486     /*
02487      * Walk through the list of table pointers provided, appending the table
02488      * descriptor+data from each one to the provided LUT buffer
02489      */
02490     for (unsigned i = 0; i < nNumTables; i++) {
02491         ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i];
02492         ADMW1001_LUT_TABLE_DATA  * const pData = ppData[i];
02493         ADMW_RESULT  res;
02494         unsigned dataLength = 0;
02495 
02496         /* Calculate the length of the table data */
02497         res = getLutTableSize(pDesc, pData, &dataLength);
02498         if (res != ADMW_SUCCESS )
02499             return res;
02500 
02501         /* Fill in the table descriptor length and CRC fields */
02502         pDesc->length = dataLength;
02503         pDesc->crc16 = admw_crc16_ccitt(pData, dataLength);
02504 
02505         if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) {
02506             ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02507             return ADMW_INVALID_PARAM ;
02508         }
02509 
02510         /* Append the table to the LUT buffer (desc + data) */
02511         memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc));
02512         pHdr->totalLength += sizeof(*pDesc);
02513         memcpy(pLutTableData + pHdr->totalLength, pData, dataLength);
02514         pHdr->totalLength += dataLength;
02515 
02516         pHdr->numTables++;
02517     }
02518 
02519     return ADMW_SUCCESS ;
02520 }
02521 
02522 ADMW_RESULT  deviceInformation(ADMW_DEVICE_HANDLE  hDevice)
02523 {
02524     uint16_t nAddress = REG_CORE_REVISION;
02525     char nData[ADMW_VERSION_REG_VAL_SIZE];  //4 Bytes of version register data
02526     ADMW_RESULT  res;
02527     res=admw1001_ReadRegister(hDevice,nAddress,nData,sizeof(nData));
02528     if(res != ADMW_SUCCESS ) {
02529         //if reading version register failed, sending 00.00.0000 as ADMW1001 firmware version
02530         //strcat(nData, ADMW1001_FIRMWARE_VERSION_DEFAULT);
02531         ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]);
02532     } else {
02533         char buffer[ADMW_FORMATTED_VERSION_SIZE]; //00.00.0000  8 digits + 2 Bytes "." + one null character at the end
02534         strcat(nData, buffer);
02535         ADMW_LOG_INFO("Firmware Version Id is %X.%X",nData[2],nData[0]);
02536     }
02537     return ADMW_SUCCESS ;
02538 }
02539 
02540 ADMW_RESULT  admw1001_getFirmwareStatus(
02541     ADMW_DEVICE_HANDLE    const hDevice,
02542     bool                  * const bFirmwareStatus)
02543 {
02544     bool bitCommand;
02545     ADMW_RESULT  eRet;
02546     uint8_t pinreg = 0x1;
02547 
02548     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
02549     static uint8_t DataBuffer[SPI_BUFFER_SIZE] = {0};
02550     uint16_t nSize;
02551 
02552     //Construct Read Status command
02553     DataBuffer[0] = 0x07;
02554     DataBuffer[1] = 0x0E;   //Packet ID
02555 
02556     DataBuffer[2] = 0x00;
02557     DataBuffer[3] = 0x00;   //Data words
02558 
02559     DataBuffer[4] = 0x53;
02560     DataBuffer[5] = 0x00;   //Command ID
02561 
02562     DataBuffer[6] = 0x00;
02563     DataBuffer[7] = 0x00;
02564     DataBuffer[8] = 0x00;
02565     DataBuffer[9] = 0x00;   //Address
02566 
02567     DataBuffer[10] = 0x53;
02568     DataBuffer[11] = 0x00;
02569     DataBuffer[12] = 0x00;
02570     DataBuffer[13] = 0x00;  //Checksum
02571 
02572     nSize = SFL_READ_STATUS_HDR_SIZE;
02573 
02574     do {
02575         // Get the SFL command irq pin to check if SFL is ready to receive commands
02576         // Status pin is not checked since SFL is just booted, there should not be any issue with SFL
02577         eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand );
02578         if( eRet != ADMW_SUCCESS ) {
02579             return eRet;
02580         }
02581 
02582         // 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
02583         // pinreg == '0x00' - Error occured in SFL
02584         // pinreg == '0x01' - SFL is ready to recieve commands
02585         // pinreg == '0x02' - Error occured in handling any commands in SFL
02586         // pinreg == '0x03' - SFL not booted
02587 
02588         pinreg = (bitCommand);
02589 
02590     } while(pinreg != 0x0u);
02591 
02592     eRet = admw_SpiTransfer(pCtx->hSpi, DataBuffer, NULL,
02593                             nSize, false);
02594     if (eRet) {
02595         return eRet;
02596     }
02597 
02598     //wait for command irq line to go low after sending read status header
02599     wait_ms( 100 );
02600 
02601     do {
02602         // Get the SFL command irq pin to check if SFL is ready to receive commands
02603         // Status pin is not checked since SFL is just booted, there should not be any issue with SFL
02604         eRet = admw_GetGpioState( hDevice, ADMW_GPIO_PIN_DATAREADY , &bitCommand );
02605         if( eRet != ADMW_SUCCESS ) {
02606             return eRet;
02607         }
02608 
02609         // 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
02610         // pinreg == '0x00' - Error occured in SFL
02611         // pinreg == '0x01' - SFL is ready to recieve commands
02612         // pinreg == '0x02' - Error occured in handling any commands in SFL
02613         // pinreg == '0x03' - SFL not booted
02614 
02615         pinreg = (bitCommand);
02616 
02617     } while(pinreg != 0x0u);
02618 
02619     nSize = SFL_READ_STATUS_RESPONSE_SIZE;
02620 
02621     eRet = admw_SpiReceive(pCtx->hSpi, NULL, DataBuffer,
02622                            nSize, false);
02623 
02624     if (eRet) {
02625         return eRet;
02626     }
02627 
02628     //Verifying the application version from the response to check if firmware is present or not
02629     /*
02630         Flash Memory description
02631         ______________
02632        |  Secure      | 0x0000 0000
02633        |  Flashloader |
02634        |______________| 0x0000 3BFF
02635        |  Security    |------------------
02636        |  Page        | 0x0000 3C00
02637        |              |
02638        |______________| 0x0000 3FFF
02639        |              |------------------
02640        |  App Info    | 0x0000 4000
02641        |   Page       |
02642        |______________| 0x0000 4800
02643        |              |------------------
02644        | Application  |
02645        |   Image      |  Application resides only in this region
02646        |______________|------------------
02647        |  Reserved    | 0x0003 FFF8
02648        |     for      | Reserved memory region
02649        |  Signature   | 0x0003 FFFF
02650        |______________|------------------
02651 
02652        Application version is stored in the App Info Page, the app version is updated in this region everytime the new application firmware is downloaded.
02653        Here we verify if Application version is present in the Read Status response
02654        If the app version bytes value is 0xFFFFFFFF then there is no firmware else there exist a firmware
02655 
02656        Read Status Response:
02657         ____________________________________________________________________________________________________________________________________
02658        |                             |                  |                              |                              |                     |
02659        |uint16_t nFlashLoaderVersion | uint16_t nStatus | uint32_t nApplicationVersion | uint32_t nApplicationHash[8] | uint16_t nChecksum  |
02660        |_____________________________|__________________|______________________________|______________________________|_____________________|
02661 
02662      */
02663 
02664     if( ((DataBuffer[4] == 0xFF) &&
02665             (DataBuffer[5] == 0xFF) &&
02666             (DataBuffer[6] == 0xFF) &&
02667             (DataBuffer[7] == 0xFF)) ||
02668             ((DataBuffer[4] == 0x00) &&
02669              (DataBuffer[5] == 0x00) &&
02670              (DataBuffer[6] == 0x00) &&
02671              (DataBuffer[7] == 0x00))) {
02672         *bFirmwareStatus = false;
02673     } else {
02674         *bFirmwareStatus = true;
02675     }
02676 
02677     return eRet;
02678 }