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