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