Vybhav Kadaba / Mbed OS EV-PRO-MW1001_oct25
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",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 == (modeReg.Conversion_Mode == CORE_MODE_SINGLECYCLE))
00907         *peOperatingMode = ADMW1001_OPERATING_MODE_SINGLECYCLE ;
00908     else
00909         *peOperatingMode = ADMW1001_OPERATING_MODE_CONTINUOUS ;
00910 
00911     if (eMeasurementMode == ADMW_MEASUREMENT_MODE_OMIT_RAW ) {
00912         *pnBytesPerSample = 5;
00913     } else {
00914         *pnBytesPerSample = 8;
00915     }
00916 
00917     for (ADMW1001_CH_ID  chId = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
00918             chId < ADMW1001_MAX_CHANNELS ;
00919             chId++) {
00920         ADMW_CORE_Sensor_Details_t sensorDetailsReg;
00921         ADMW_CORE_Channel_Count_t channelCountReg;
00922 
00923         if (ADMW1001_CHANNEL_IS_VIRTUAL(chId))
00924             continue;
00925 
00926         READ_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(chId));
00927         READ_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(chId));
00928 
00929         if (channelCountReg.Channel_Enable && !sensorDetailsReg.Do_Not_Publish)
00930         {
00931             unsigned nActualChannels = 1;
00932 
00933             if (chId == ADMW1001_CH_ID_DIG_SPI_0 )
00934             {
00935                 /* Some sensors automatically generate samples on additional
00936                  * "virtual" channels so these channels must be counted as
00937                  * active when those sensors are selected and we use the count
00938                  * from the corresponding "physical" channel
00939                  */
00940 #if 0 /* SPI sensors arent supported at present to be added back once there is 
00941        * support for these sensors
00942        */
00943                 ADMW_CORE_Sensor_Type_t sensorTypeReg;
00944 
00945                 READ_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(chId));
00946       
00947                 if ((sensorTypeReg.Sensor_Type >=
00948                     CORE_SENSOR_TYPE_SPI_ACCELEROMETER_A) &&
00949                     (sensorTypeReg.Sensor_Type <=
00950                     CORE_SENSOR_TYPE_SPI_ACCELEROMETER_B))
00951                 {
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 {
01087     ADMW_CORE_Cycle_Control_t cycleControlReg;
01088 
01089     cycleControlReg.VALUE16 = REG_RESET_VAL(CORE_CYCLE_CONTROL);
01090 
01091     if (nCycleInterval < (1000 * (1 << 12))) {
01092         cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_MILLISECONDS;
01093         nCycleInterval /= 1000;
01094     } else {
01095         cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_SECONDS;
01096         nCycleInterval /= 1000000;
01097     }
01098 
01099     if (vBiasEnable == true) {
01100         cycleControlReg.Vbias = 1;
01101     }
01102     CHECK_REG_FIELD_VAL(CORE_CYCLE_CONTROL_CYCLE_TIME, nCycleInterval);
01103     cycleControlReg.Cycle_Time = nCycleInterval;
01104 
01105     WRITE_REG_U16(hDevice, cycleControlReg.VALUE16, CORE_CYCLE_CONTROL);
01106 
01107     return ADMW_SUCCESS ;
01108 }
01109 static ADMW_RESULT  admw_SetExternalReferenceVoltage(
01110     ADMW_DEVICE_HANDLE  hDevice,
01111     float32_t externalRefVoltage)
01112 {
01113     WRITE_REG_FLOAT(hDevice, externalRefVoltage, CORE_EXTERNAL_VOLTAGE_REFERENCE);
01114 
01115     return ADMW_SUCCESS ;
01116 }
01117 
01118 static ADMW_RESULT  admw_SetExternalReferenceValues(
01119     ADMW_DEVICE_HANDLE  hDevice,
01120     float32_t externalRef1Value)
01121 {
01122     WRITE_REG_FLOAT(hDevice, externalRef1Value, CORE_EXTERNAL_REFERENCE_RESISTOR);
01123 
01124     return ADMW_SUCCESS ;
01125 }
01126 
01127 ADMW_RESULT  admw1001_SetMeasurementConfig(
01128     ADMW_DEVICE_HANDLE  hDevice,
01129     ADMW1001_MEASUREMENT_CONFIG  *pMeasConfig)
01130 {
01131     ADMW_RESULT  eRet;
01132 
01133     eRet = admw_SetMode(hDevice,
01134                         pMeasConfig->operatingMode ,
01135                         pMeasConfig->dataReadyMode );
01136     if (eRet != ADMW_SUCCESS ) {
01137         ADMW_LOG_ERROR("Failed to set operating mode");
01138         return eRet;
01139     }
01140 
01141     eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval ,
01142                                 pMeasConfig->vBiasEnable );
01143     if (eRet != ADMW_SUCCESS ) {
01144         ADMW_LOG_ERROR("Failed to set cycle control");
01145         return eRet;
01146     }
01147 
01148     if(pMeasConfig->externalRef1Value >0) {
01149         eRet = admw_SetExternalReferenceValues(hDevice,
01150                                                pMeasConfig->externalRef1Value );
01151     }
01152 
01153     if (eRet != ADMW_SUCCESS ) {
01154         ADMW_LOG_ERROR("Failed to set external reference values");
01155         return eRet;
01156     }
01157 
01158     eRet = admw_SetRSenseValue(hDevice, pMeasConfig->RSenseValue );
01159     if (eRet != ADMW_SUCCESS )
01160     {
01161         ADMW_LOG_ERROR("Failed to set RSenseValue");
01162         return eRet;
01163     }
01164     
01165     eRet = admw_SetExternalReferenceVoltage(hDevice, pMeasConfig->externalRefVoltage );
01166     if (eRet != ADMW_SUCCESS )
01167     {
01168         ADMW_LOG_ERROR("Failed to set External reference Voltage");
01169         return eRet;
01170     }    
01171           
01172     return ADMW_SUCCESS ;
01173 }
01174 
01175 ADMW_RESULT  admw1001_SetDiagnosticsConfig(
01176     ADMW_DEVICE_HANDLE  hDevice,
01177     ADMW1001_DIAGNOSTICS_CONFIG  *pDiagnosticsConfig)
01178 {
01179     ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg;
01180 
01181     diagnosticsControlReg.VALUE8 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL);
01182 
01183     if (pDiagnosticsConfig->disableMeasurementDiag )
01184         diagnosticsControlReg.Diag_Meas_En = 0;
01185     else
01186         diagnosticsControlReg.Diag_Meas_En = 1;
01187 
01188     switch (pDiagnosticsConfig->osdFrequency )
01189     {
01190     case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_DISABLED :
01191         diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_OFF;
01192         break;
01193     case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_CYCLE :
01194         diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_1_CYCLE;
01195         break;
01196     case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_100_CYCLES :
01197         diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_10_CYCLES;
01198         break;
01199     case ADMW1001_OPEN_SENSOR_DIAGNOSTICS_PER_1000_CYCLES :
01200         diagnosticsControlReg.Diag_OSD_Freq = CORE_DIAGNOSTICS_CONTROL_OCD_PER_100_CYCLES;
01201         break;
01202     default:
01203         ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified",
01204                         pDiagnosticsConfig->osdFrequency );
01205         return ADMW_INVALID_PARAM ;
01206     }
01207 
01208     WRITE_REG_U8(hDevice, diagnosticsControlReg.VALUE8, CORE_DIAGNOSTICS_CONTROL);
01209 
01210     return ADMW_SUCCESS ;
01211 }
01212 
01213 ADMW_RESULT  admw1001_SetChannelCount(
01214     ADMW_DEVICE_HANDLE  hDevice,
01215     ADMW1001_CH_ID  eChannelId,
01216     uint32_t nMeasurementsPerCycle)
01217 {
01218     ADMW_CORE_Channel_Count_t channelCountReg;
01219 
01220     channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn);
01221 
01222     if (nMeasurementsPerCycle > 0) {
01223         nMeasurementsPerCycle -= 1;
01224 
01225         CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT,
01226                             nMeasurementsPerCycle);
01227 
01228         channelCountReg.Channel_Enable = 1;
01229         channelCountReg.Channel_Count = nMeasurementsPerCycle;
01230     } else {
01231         channelCountReg.Channel_Enable = 0;
01232     }
01233 
01234     WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId));
01235 
01236     return ADMW_SUCCESS ;
01237 }
01238 
01239 ADMW_RESULT  admw1001_SetChannelOptions(
01240     ADMW_DEVICE_HANDLE  hDevice,
01241     ADMW1001_CH_ID  eChannelId,
01242     ADMW1001_CHANNEL_PRIORITY  ePriority)
01243 {
01244     ADMW_CORE_Channel_Options_t channelOptionsReg;
01245 
01246     channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn);
01247 
01248     CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority);
01249     channelOptionsReg.Channel_Priority = ePriority;
01250 
01251     WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId));
01252 
01253     return ADMW_SUCCESS ;
01254 }
01255 
01256 ADMW_RESULT  admw1001_SetChannelSkipCount(
01257     ADMW_DEVICE_HANDLE  hDevice,
01258     ADMW1001_CH_ID  eChannelId,
01259     uint32_t nCycleSkipCount)
01260 {
01261     ADMW_CORE_Channel_Skip_t channelSkipReg;
01262 
01263     channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn);
01264 
01265     CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount);
01266 
01267     channelSkipReg.Channel_Skip = nCycleSkipCount;
01268 
01269     WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId));
01270 
01271     return ADMW_SUCCESS ;
01272 }
01273 
01274 static ADMW_RESULT  admw_SetChannelAdcSensorType(
01275     ADMW_DEVICE_HANDLE           hDevice,
01276     ADMW1001_CH_ID               eChannelId,
01277     ADMW1001_ADC_SENSOR_TYPE     sensorType)
01278 {
01279     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01280 
01281     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01282 
01283     /* Ensure that the sensor type is valid for this channel */
01284     switch(sensorType) {
01285         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 :
01286         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 :
01287         case ADMW1001_ADC_SENSOR_RTD_3WIRE_1 :
01288         case ADMW1001_ADC_SENSOR_RTD_3WIRE_2 :
01289         case ADMW1001_ADC_SENSOR_RTD_3WIRE_3 :
01290         case ADMW1001_ADC_SENSOR_RTD_3WIRE_4 :
01291         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 :
01292         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 :
01293         case ADMW1001_ADC_SENSOR_RTD_4WIRE_1 :
01294         case ADMW1001_ADC_SENSOR_RTD_4WIRE_2 :
01295         case ADMW1001_ADC_SENSOR_RTD_4WIRE_3 :
01296         case ADMW1001_ADC_SENSOR_RTD_4WIRE_4 :
01297         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_1 :
01298         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_2 :
01299         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_3 :
01300         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_4 :
01301         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_1 :
01302         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_2 :
01303         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_3 :
01304         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_4 :
01305         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 :
01306         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 :
01307         case ADMW1001_ADC_SENSOR_RTD_2WIRE_1 :
01308         case ADMW1001_ADC_SENSOR_RTD_2WIRE_2 :
01309         case ADMW1001_ADC_SENSOR_RTD_2WIRE_3 :
01310         case ADMW1001_ADC_SENSOR_RTD_2WIRE_4 :
01311         case ADMW1001_ADC_SENSOR_DIODE_2C_TYPEA :
01312         case ADMW1001_ADC_SENSOR_DIODE_3C_TYPEA :
01313         case ADMW1001_ADC_SENSOR_DIODE_2C_1 :
01314         case ADMW1001_ADC_SENSOR_DIODE_3C_1 :
01315         case ADMW1001_ADC_SENSOR_THERMISTOR_A_10K :
01316         case ADMW1001_ADC_SENSOR_THERMISTOR_B_10K :
01317         case ADMW1001_ADC_SENSOR_THERMISTOR_1 :
01318         case ADMW1001_ADC_SENSOR_THERMISTOR_2 :
01319         case ADMW1001_ADC_SENSOR_THERMISTOR_3 :
01320         case ADMW1001_ADC_SENSOR_THERMISTOR_4 :
01321         case ADMW1001_ADC_SENSOR_SINGLE_ENDED_ABSOLUTE :
01322         case ADMW1001_ADC_SENSOR_DIFFERENTIAL_ABSOLUTE :
01323         case ADMW1001_ADC_SENSOR_SINGLE_ENDED_RATIO :
01324         case ADMW1001_ADC_SENSOR_DIFFERENTIAL_RATIO :
01325             if (! (ADMW1001_CHANNEL_IS_ADC_SENSOR(eChannelId) ||
01326                    ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId) || ADMW1001_CHANNEL_IS_ADC(eChannelId) ))
01327             {
01328                 ADMW_LOG_ERROR(
01329                     "Invalid ADC sensor type %d specified for channel %d",
01330                     sensorType, eChannelId);
01331                 return ADMW_INVALID_PARAM ;
01332             }
01333             break;
01334         case ADMW1001_ADC_SENSOR_VOLTAGE :
01335         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_A :
01336         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_B :
01337         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_1 :
01338         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_2 :
01339         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J :
01340         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K :
01341         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T :
01342         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_1 :
01343         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_2 :
01344         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_3 :
01345         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_4 :
01346             if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) {
01347                 ADMW_LOG_ERROR(
01348                     "Invalid ADC sensor type %d specified for channel %d",
01349                     sensorType, eChannelId);
01350                 return ADMW_INVALID_PARAM ;
01351             }
01352             break;
01353         case ADMW1001_ADC_SENSOR_CURRENT :
01354         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_A :
01355         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_1 :
01356         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_2 :
01357             if (! ADMW1001_CHANNEL_IS_ADC_CURRENT(eChannelId)) {
01358                 ADMW_LOG_ERROR(
01359                     "Invalid ADC sensor type %d specified for channel %d",
01360                     sensorType, eChannelId);
01361                 return ADMW_INVALID_PARAM ;
01362             }
01363             break;
01364         default:
01365             ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified",
01366                            sensorType);
01367             return ADMW_INVALID_PARAM ;
01368     }
01369 
01370     sensorTypeReg.Sensor_Type = sensorType;
01371 
01372     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01373 
01374     return ADMW_SUCCESS ;
01375 }
01376 
01377 static ADMW_RESULT  admw_SetChannelAdcSensorDetails(
01378     ADMW_DEVICE_HANDLE       hDevice,
01379     ADMW1001_CH_ID           eChannelId,
01380     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01381 /*
01382  * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers
01383  * General details:
01384  * - Measurement_Units
01385  * - Compensation_Channel
01386  * - CJC_Publish (if "CJC" was removed from the name)
01387  * ADC-specific details:
01388  * - PGA_Gain
01389  * - Reference_Select
01390  * - Reference_Buffer_Disable
01391  */
01392 {
01393     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ;
01394     ADMW1001_ADC_REFERENCE_TYPE  refType            = pAdcChannelConfig->reference;
01395     ADMW_CORE_Sensor_Details_t  sensorDetailsReg;
01396 
01397     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01398 
01399     switch(pChannelConfig->measurementUnit ) {
01400         case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT :
01401             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF;
01402             break;
01403         case ADMW1001_MEASUREMENT_UNIT_CELSIUS :
01404             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC;
01405             break;
01406         case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED :
01407             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01408             break;
01409         default:
01410             ADMW_LOG_ERROR("Invalid measurement unit %d specified",
01411                            pChannelConfig->measurementUnit );
01412             return ADMW_INVALID_PARAM ;
01413     }
01414 
01415     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01416         sensorDetailsReg.Compensation_Disable = 1;
01417         sensorDetailsReg.Compensation_Channel = 0;
01418     } else {
01419         sensorDetailsReg.Compensation_Disable = 0;
01420         sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ;
01421     }
01422 
01423     switch(refType) {
01424         case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL :
01425             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT;
01426             break;
01427         case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 :
01428             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1;
01429             break;
01430         case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD :
01431             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD;
01432             break;
01433         default:
01434             ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType);
01435             return ADMW_INVALID_PARAM ;
01436     }
01437 
01438     switch(pAdcChannelConfig->gain ) {
01439         case ADMW1001_ADC_GAIN_1X :
01440             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1;
01441             break;
01442         case ADMW1001_ADC_GAIN_2X :
01443             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2;
01444             break;
01445         case ADMW1001_ADC_GAIN_4X :
01446             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4;
01447             break;
01448         case ADMW1001_ADC_GAIN_8X :
01449             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8;
01450             break;
01451         case ADMW1001_ADC_GAIN_16X :
01452             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16;
01453             break;
01454         case ADMW1001_ADC_GAIN_32X :
01455             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32;
01456             break;
01457         case ADMW1001_ADC_GAIN_64X :
01458             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64;
01459             break;
01460         case ADMW1001_ADC_GAIN_128X :
01461             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128;
01462             break;
01463         default:
01464             ADMW_LOG_ERROR("Invalid ADC gain %d specified",
01465                            pAdcChannelConfig->gain );
01466             return ADMW_INVALID_PARAM ;
01467     }
01468 
01469     switch(pAdcChannelConfig->rtdCurve ) {
01470         case ADMW1001_ADC_RTD_CURVE_EUROPEAN :
01471             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE;
01472             break;
01473         case ADMW1001_ADC_RTD_CURVE_AMERICAN :
01474             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE;
01475             break;
01476         case ADMW1001_ADC_RTD_CURVE_JAPANESE :
01477             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE;
01478             break;
01479         case ADMW1001_ADC_RTD_CURVE_ITS90 :
01480             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE;
01481             break;
01482         default:
01483             ADMW_LOG_ERROR("Invalid RTD Curve %d specified",
01484                            pAdcChannelConfig->rtdCurve );
01485             return ADMW_INVALID_PARAM ;
01486     }
01487 
01488     if (pChannelConfig->disablePublishing ) {
01489         sensorDetailsReg.Do_Not_Publish = 1;
01490     } else {
01491         sensorDetailsReg.Do_Not_Publish = 0;
01492     }
01493 
01494     switch (pChannelConfig->lutSelect ) {
01495         case ADMW1001_LUT_DEFAULT :
01496         case ADMW1001_LUT_UNITY :
01497         case ADMW1001_LUT_CUSTOM :
01498             sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ;
01499             break;
01500         default:
01501             ADMW_LOG_ERROR("Invalid LUT selection %d specified",
01502                            pChannelConfig->lutSelect );
01503             return ADMW_INVALID_PARAM ;
01504     }
01505 
01506     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01507 
01508     return ADMW_SUCCESS ;
01509 }
01510 
01511 static ADMW_RESULT  admw_SetChannelAdcMeasurementSetup(
01512     ADMW_DEVICE_HANDLE  hDevice,
01513     ADMW1001_CH_ID  eChannelId,
01514     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig)
01515 {
01516     ADMW_CORE_Measurement_Setup_t MeasSetupReg;
01517     ADMW1001_ADC_FILTER_CONFIG  *pFilterConfig = &pAdcChannelConfig->filter ;
01518     MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn);
01519     MeasSetupReg.PST_MEAS_EXC_CTRL = pAdcChannelConfig->current .excitationState ;
01520     MeasSetupReg.Buffer_Bypass = pAdcChannelConfig->bufferBypass ;
01521     
01522     if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC4 ) {
01523         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4;
01524         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01525     } else if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC3 ) {
01526         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3;
01527         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01528     } else {
01529         ADMW_LOG_ERROR("Invalid ADC filter type %d specified",
01530                        pFilterConfig->type );
01531         return ADMW_INVALID_PARAM ;
01532     }
01533 
01534     /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */
01535     MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ;
01536 
01537     if(pFilterConfig->notch1p2 )
01538         MeasSetupReg.NOTCH_EN_2 = 1;
01539     else
01540         MeasSetupReg.NOTCH_EN_2 = 0;
01541 
01542     switch(pFilterConfig->groundSwitch ) {
01543         case ADMW1001_ADC_GND_SW_OPEN :
01544             MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_OPEN;
01545             break;
01546         case ADMW1001_ADC_GND_SW_CLOSED :
01547             MeasSetupReg.GND_SW = CORE_MEASUREMENT_SETUP_GND_SW_CLOSED;
01548             break;
01549         default:
01550             ADMW_LOG_ERROR("Invalid ground switch state %d specified",
01551                            pFilterConfig->groundSwitch );
01552             return ADMW_INVALID_PARAM ;
01553     }
01554 
01555     WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId));
01556 
01557     return ADMW_SUCCESS ;
01558 }
01559 
01560 static ADMW_RESULT  admw_SetChannelAdcCurrentConfig(
01561     ADMW_DEVICE_HANDLE  hDevice,
01562     ADMW1001_CH_ID  eChannelId,
01563     ADMW1001_ADC_EXC_CURRENT_CONFIG  *pCurrentConfig)
01564 {
01565     ADMW_CORE_Channel_Excitation_t channelExcitationReg;
01566 
01567     channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn);
01568 
01569     if (pCurrentConfig->outputLevel  == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT )
01570         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE;
01571     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_EXTERNAL )
01572         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL;
01573     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_50uA )
01574         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA;
01575     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_100uA )
01576         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA;
01577     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_250uA )
01578         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA;
01579     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_500uA )
01580         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA;
01581     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_1000uA )
01582         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA;
01583     else {
01584         ADMW_LOG_ERROR("Invalid ADC excitation current %d specified",
01585                        pCurrentConfig->outputLevel );
01586         return ADMW_INVALID_PARAM ;
01587     }
01588 
01589     WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId));
01590 
01591     return ADMW_SUCCESS ;
01592 }
01593 
01594 ADMW_RESULT  admw_SetAdcChannelConfig(
01595     ADMW_DEVICE_HANDLE  hDevice,
01596     ADMW1001_CH_ID  eChannelId,
01597     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01598 {
01599     ADMW_RESULT  eRet;
01600     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig =
01601         &pChannelConfig->adcChannelConfig ;
01602 
01603     eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId,
01604                                         pAdcChannelConfig->sensor );
01605     if (eRet != ADMW_SUCCESS ) {
01606         ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d",
01607                        eChannelId);
01608         return eRet;
01609     }
01610 
01611     eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId,
01612                                            pChannelConfig);
01613     if (eRet != ADMW_SUCCESS ) {
01614         ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d",
01615                        eChannelId);
01616         return eRet;
01617     }
01618 
01619     eRet = admw_SetChannelAdcMeasurementSetup(hDevice, eChannelId,
01620                                          pAdcChannelConfig);
01621     if (eRet != ADMW_SUCCESS ) {
01622         ADMW_LOG_ERROR("Failed to set ADC filter for channel %d",
01623                        eChannelId);
01624         return eRet;
01625     }
01626 
01627     eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId,
01628                                            &pAdcChannelConfig->current );
01629     if (eRet != ADMW_SUCCESS ) {
01630         ADMW_LOG_ERROR("Failed to set ADC current for channel %d",
01631                        eChannelId);
01632         return eRet;
01633     }
01634 
01635     return ADMW_SUCCESS ;
01636 }
01637 
01638 static ADMW_RESULT  admw_SetChannelDigitalSensorDetails(
01639     ADMW_DEVICE_HANDLE  hDevice,
01640     ADMW1001_CH_ID  eChannelId,
01641     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01642 {
01643     ADMW_CORE_Sensor_Details_t sensorDetailsReg;
01644 
01645     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01646 
01647     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01648         sensorDetailsReg.Compensation_Disable = 1;
01649         sensorDetailsReg.Compensation_Channel = 0;
01650     } else {
01651         ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor");
01652         return ADMW_INVALID_PARAM ;
01653     }
01654 
01655     if (pChannelConfig->measurementUnit  == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) {
01656         sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01657     } else {
01658         ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel");
01659         return ADMW_INVALID_PARAM ;
01660     }
01661 
01662     if (pChannelConfig->disablePublishing )
01663         sensorDetailsReg.Do_Not_Publish = 1;
01664     else
01665         sensorDetailsReg.Do_Not_Publish = 0;
01666 
01667     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01668 
01669     return ADMW_SUCCESS ;
01670 }
01671 
01672 static ADMW_RESULT  admw_SetDigitalSensorFormat(
01673     ADMW_DEVICE_HANDLE  hDevice,
01674     ADMW1001_CH_ID  eChannelId,
01675     ADMW1001_DIGITAL_SENSOR_DATA_FORMAT  *pDataFormat)
01676 {
01677     ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg;
01678 
01679     sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn);
01680 
01681     if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) {
01682         if (pDataFormat->frameLength == 0) {
01683             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01684             return ADMW_INVALID_PARAM ;
01685         }
01686         if (pDataFormat->numDataBits == 0) {
01687             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01688             return ADMW_INVALID_PARAM ;
01689         }
01690 
01691         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES,
01692                             pDataFormat->frameLength - 1);
01693         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS,
01694                             pDataFormat->numDataBits - 1);
01695         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET,
01696                             pDataFormat->bitOffset);
01697 
01698         sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1;
01699         sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1;
01700         sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset;
01701         sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0;
01702         sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0;
01703 
01704         switch (pDataFormat->coding) {
01705             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR:
01706                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR;
01707                 break;
01708             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT:
01709                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL;
01710                 break;
01711             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY:
01712                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY;
01713                 break;
01714             default:
01715                 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format");
01716                 return ADMW_INVALID_PARAM ;
01717         }
01718     } else {
01719         sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE;
01720     }
01721 
01722     WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16,
01723                   CORE_DIGITAL_SENSOR_CONFIGn(eChannelId));
01724 
01725 
01726     return ADMW_SUCCESS ;
01727 }
01728 
01729 static ADMW_RESULT  admw_SetDigitalCalibrationParam(
01730     ADMW_DEVICE_HANDLE  hDevice,
01731     ADMW1001_CH_ID  eChannelId,
01732     ADMW1001_DIGITAL_CALIBRATION_COMMAND  *pCalibrationParam)
01733 {
01734 //    ADMW_CORE_Calibration_Parameter_t calibrationParamReg;
01735 //
01736 //    calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn);
01737 //
01738 //    if (pCalibrationParam->enableCalibrationParam == false)
01739 //        calibrationParamReg.Calibration_Parameter_Enable = 0;
01740 //    else
01741 //        calibrationParamReg.Calibration_Parameter_Enable = 1;
01742 //
01743 //    CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER,
01744 //        pCalibrationParam->calibrationParam);
01745 //
01746 //    calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam;
01747 //
01748 //    WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32,
01749 //                  CORE_CALIBRATION_PARAMETERn(eChannelId));
01750 //
01751     return ADMW_SUCCESS ;
01752 }
01753 
01754 static ADMW_RESULT  admw_SetChannelI2cSensorType(
01755     ADMW_DEVICE_HANDLE  hDevice,
01756     ADMW1001_CH_ID  eChannelId,
01757     ADMW1001_I2C_SENSOR_TYPE  sensorType)
01758 {
01759     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01760 
01761     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01762 
01763     /* Ensure that the sensor type is valid for this channel */
01764     switch(sensorType) {
01765         case ADMW1001_I2C_SENSOR_HUMIDITY_A :
01766         case ADMW1001_I2C_SENSOR_HUMIDITY_B :
01767             sensorTypeReg.Sensor_Type = sensorType;
01768             break;
01769         default:
01770             ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType);
01771             return ADMW_INVALID_PARAM ;
01772     }
01773 
01774     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01775 
01776     return ADMW_SUCCESS ;
01777 }
01778 
01779 static ADMW_RESULT  admw_SetChannelI2cSensorAddress(
01780     ADMW_DEVICE_HANDLE  hDevice,
01781     ADMW1001_CH_ID  eChannelId,
01782     uint32_t deviceAddress)
01783 {
01784     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress);
01785     WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId));
01786 
01787     return ADMW_SUCCESS ;
01788 }
01789 
01790 static ADMW_RESULT  admw_SetDigitalChannelComms(
01791     ADMW_DEVICE_HANDLE  hDevice,
01792     ADMW1001_CH_ID  eChannelId,
01793     ADMW1001_DIGITAL_SENSOR_COMMS  *pDigitalComms)
01794 {
01795     ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms;
01796 
01797     digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn);
01798 
01799     if(pDigitalComms->useCustomCommsConfig ) {
01800         digitalSensorComms.Digital_Sensor_Comms_En = 1;
01801 
01802         if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) {
01803             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K;
01804         } else if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) {
01805             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K;
01806         } else {
01807             ADMW_LOG_ERROR("Invalid I2C clock speed %d specified",
01808                            pDigitalComms->i2cClockSpeed );
01809             return ADMW_INVALID_PARAM ;
01810         }
01811 
01812         if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) {
01813             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0;
01814         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) {
01815             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1;
01816         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) {
01817             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2;
01818         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) {
01819             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3;
01820         } else {
01821             ADMW_LOG_ERROR("Invalid SPI mode %d specified",
01822                            pDigitalComms->spiMode );
01823             return ADMW_INVALID_PARAM ;
01824         }
01825 
01826         switch (pDigitalComms->spiClock ) {
01827             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ :
01828                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ;
01829                 break;
01830             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ :
01831                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ;
01832                 break;
01833             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ :
01834                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ;
01835                 break;
01836             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ :
01837                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ;
01838                 break;
01839             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ :
01840                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ;
01841                 break;
01842             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ :
01843                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ;
01844                 break;
01845             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ :
01846                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ;
01847                 break;
01848             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ :
01849                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ;
01850                 break;
01851             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ :
01852                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ;
01853                 break;
01854             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ :
01855                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ;
01856                 break;
01857             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ :
01858                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ;
01859                 break;
01860             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ :
01861                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ;
01862                 break;
01863             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ :
01864                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ;
01865                 break;
01866             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ :
01867                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ;
01868                 break;
01869             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ :
01870                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ;
01871                 break;
01872             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ :
01873                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ;
01874                 break;
01875             default:
01876                 ADMW_LOG_ERROR("Invalid SPI clock %d specified",
01877                                pDigitalComms->spiClock );
01878                 return ADMW_INVALID_PARAM ;
01879         }
01880     } else {
01881         digitalSensorComms.Digital_Sensor_Comms_En = 0;
01882     }
01883 
01884     WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId));
01885 
01886     return ADMW_SUCCESS ;
01887 }
01888 
01889 ADMW_RESULT  admw_SetI2cChannelConfig(
01890     ADMW_DEVICE_HANDLE  hDevice,
01891     ADMW1001_CH_ID  eChannelId,
01892     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01893 {
01894     ADMW_RESULT  eRet;
01895     ADMW1001_I2C_CHANNEL_CONFIG  *pI2cChannelConfig =
01896         &pChannelConfig->i2cChannelConfig ;
01897 
01898     eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId,
01899                                         pI2cChannelConfig->sensor );
01900     if (eRet != ADMW_SUCCESS ) {
01901         ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d",
01902                        eChannelId);
01903         return eRet;
01904     }
01905 
01906     eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId,
01907                                            pI2cChannelConfig->deviceAddress );
01908     if (eRet != ADMW_SUCCESS ) {
01909         ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d",
01910                        eChannelId);
01911         return eRet;
01912     }
01913 
01914     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
01915             pChannelConfig);
01916     if (eRet != ADMW_SUCCESS ) {
01917         ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d",
01918                        eChannelId);
01919         return eRet;
01920     }
01921 
01922     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
01923                                        &pI2cChannelConfig->dataFormat );
01924     if (eRet != ADMW_SUCCESS ) {
01925         ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d",
01926                        eChannelId);
01927         return eRet;
01928     }
01929 
01930     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
01931                                            &pI2cChannelConfig->digitalCalibrationParam );
01932     if (eRet != ADMW_SUCCESS ) {
01933         ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d",
01934                        eChannelId);
01935         return eRet;
01936     }
01937 
01938     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
01939                                        &pI2cChannelConfig->configureComms );
01940     if (eRet != ADMW_SUCCESS ) {
01941         ADMW_LOG_ERROR("Failed to set I2C comms for channel %d",
01942                        eChannelId);
01943         return eRet;
01944     }
01945 
01946     return ADMW_SUCCESS ;
01947 }
01948 
01949 static ADMW_RESULT  admw_SetChannelSpiSensorType(
01950     ADMW_DEVICE_HANDLE  hDevice,
01951     ADMW1001_CH_ID  eChannelId,
01952     ADMW1001_SPI_SENSOR_TYPE  sensorType)
01953 {
01954     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01955 
01956     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01957 
01958     /* Ensure that the sensor type is valid for this channel */
01959     switch(sensorType) {
01960         case ADMW1001_SPI_SENSOR_PRESSURE_A :
01961         case ADMW1001_SPI_SENSOR_ACCELEROMETER_A :
01962         case ADMW1001_SPI_SENSOR_ACCELEROMETER_B :
01963 
01964             sensorTypeReg.Sensor_Type = sensorType;
01965             break;
01966         default:
01967             ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType);
01968             return ADMW_INVALID_PARAM ;
01969     }
01970 
01971     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01972 
01973     return ADMW_SUCCESS ;
01974 }
01975 
01976 ADMW_RESULT  admw_SetSpiChannelConfig(
01977     ADMW_DEVICE_HANDLE  hDevice,
01978     ADMW1001_CH_ID  eChannelId,
01979     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01980 {
01981     ADMW_RESULT  eRet;
01982     ADMW1001_SPI_CHANNEL_CONFIG  *pSpiChannelConfig =
01983         &pChannelConfig->spiChannelConfig ;
01984 
01985     eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId,
01986                                         pSpiChannelConfig->sensor );
01987     if (eRet != ADMW_SUCCESS ) {
01988         ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d",
01989                        eChannelId);
01990         return eRet;
01991     }
01992 
01993     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
01994             pChannelConfig);
01995     if (eRet != ADMW_SUCCESS ) {
01996         ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d",
01997                        eChannelId);
01998         return eRet;
01999     }
02000 
02001     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
02002                                        &pSpiChannelConfig->dataFormat );
02003     if (eRet != ADMW_SUCCESS ) {
02004         ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d",
02005                        eChannelId);
02006         return eRet;
02007     }
02008 
02009     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
02010                                            &pSpiChannelConfig->digitalCalibrationParam );
02011     if (eRet != ADMW_SUCCESS ) {
02012         ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d",
02013                        eChannelId);
02014         return eRet;
02015     }
02016 
02017     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
02018                                        &pSpiChannelConfig->configureComms );
02019     if (eRet != ADMW_SUCCESS ) {
02020         ADMW_LOG_ERROR("Failed to set SPI comms for channel %d",
02021                        eChannelId);
02022         return eRet;
02023     }
02024 
02025     return ADMW_SUCCESS ;
02026 }
02027 
02028 ADMW_RESULT  admw1001_SetChannelThresholdLimits(
02029     ADMW_DEVICE_HANDLE  hDevice,
02030     ADMW1001_CH_ID  eChannelId,
02031     float32_t fHighThresholdLimit,
02032     float32_t fLowThresholdLimit)
02033 {
02034     /*
02035      * If the low/high limits are *both* set to 0 in memory, or NaNs, assume
02036      * that they are unset, or not required, and use infinity defaults instead
02037      */
02038     if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) {
02039         fHighThresholdLimit = INFINITY;
02040         fLowThresholdLimit = -INFINITY;
02041     } else {
02042         if (isnan(fHighThresholdLimit))
02043             fHighThresholdLimit = INFINITY;
02044         if (isnan(fLowThresholdLimit))
02045             fLowThresholdLimit = -INFINITY;
02046     }
02047 
02048     WRITE_REG_FLOAT(hDevice, fHighThresholdLimit,
02049                     CORE_HIGH_THRESHOLD_LIMITn(eChannelId));
02050     WRITE_REG_FLOAT(hDevice, fLowThresholdLimit,
02051                     CORE_LOW_THRESHOLD_LIMITn(eChannelId));
02052 
02053     return ADMW_SUCCESS ;
02054 }
02055 
02056 ADMW_RESULT  admw1001_SetOffsetGain(
02057     ADMW_DEVICE_HANDLE  hDevice,
02058     ADMW1001_CH_ID  eChannelId,
02059     float32_t fOffsetAdjustment,
02060     float32_t fGainAdjustment)
02061 {
02062     /* Replace with default values if NaNs are specified (or 0.0 for gain) */
02063     if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f))
02064         fGainAdjustment = 1.0f;
02065     if (isnan(fOffsetAdjustment))
02066         fOffsetAdjustment = 0.0f;
02067 
02068     WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId));
02069     WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId));
02070 
02071     return ADMW_SUCCESS ;
02072 }
02073 
02074 ADMW_RESULT  admw1001_SetSensorParameter(
02075     ADMW_DEVICE_HANDLE  hDevice,
02076     ADMW1001_CH_ID  eChannelId,
02077     float32_t fSensorParam)
02078 {
02079     if (fSensorParam == 0.0f)
02080         fSensorParam = NAN;
02081 
02082     //WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId));
02083 
02084     return ADMW_SUCCESS ;
02085 }
02086 
02087 ADMW_RESULT  admw1001_SetChannelSettlingTime(
02088     ADMW_DEVICE_HANDLE  hDevice,
02089     ADMW1001_CH_ID  eChannelId,
02090     uint32_t nSettlingTime)
02091 {
02092     ADMW_CORE_Settling_Time_t settlingTimeReg;
02093 
02094     if (nSettlingTime < (1 << 12)) {
02095         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MICROSECONDS;
02096     } else if (nSettlingTime < (1000 * (1 << 12))) {
02097         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_MILLISECONDS;
02098         nSettlingTime /= 1000;
02099     } else {
02100         settlingTimeReg.Settling_Time_Units = CORE_SETTLING_TIME_SECONDS;
02101         nSettlingTime /= 1000000;
02102     }
02103 
02104     CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime);
02105     settlingTimeReg.Settling_Time = nSettlingTime;
02106 
02107     WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId));
02108 
02109     return ADMW_SUCCESS ;
02110 }
02111 
02112 ADMW_RESULT  admw1001_SetChannelConfig(
02113     ADMW_DEVICE_HANDLE  hDevice,
02114     ADMW1001_CH_ID  eChannelId,
02115     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
02116 {
02117     ADMW_RESULT  eRet;
02118 
02119     if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) {
02120         eRet = admw1001_SetChannelCount(hDevice, eChannelId,
02121                                         pChannelConfig->enableChannel  ?
02122                                         pChannelConfig->measurementsPerCycle  : 0);
02123         if (eRet != ADMW_SUCCESS ) {
02124             ADMW_LOG_ERROR("Failed to set measurement count for channel %d",
02125                            eChannelId);
02126             return eRet;
02127         }
02128 
02129         eRet = admw1001_SetChannelOptions(hDevice, eChannelId,
02130                                           pChannelConfig->priority );
02131         if (eRet != ADMW_SUCCESS ) {
02132             ADMW_LOG_ERROR("Failed to set priority for channel %d",
02133                            eChannelId);
02134             return eRet;
02135         }
02136 
02137         /* If the channel is not enabled, we can skip the following steps */
02138         if (pChannelConfig->enableChannel ) {
02139             eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId,
02140                                                 pChannelConfig->cycleSkipCount );
02141             if (eRet != ADMW_SUCCESS ) {
02142                 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d",
02143                                eChannelId);
02144                 return eRet;
02145             }
02146 
02147             switch (eChannelId) {
02148                 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL :
02149                 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL :
02150                 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL :
02151                 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL :
02152                     eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig);
02153                     break;
02154                 case ADMW1001_CH_ID_DIG_I2C_0 :
02155                 case ADMW1001_CH_ID_DIG_I2C_1 :
02156                     eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig);
02157                     break;
02158                 case ADMW1001_CH_ID_DIG_SPI_0 :
02159                     eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig);
02160                     break;
02161                 default:
02162                     ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId);
02163                     eRet = ADMW_INVALID_PARAM ;
02164 #if 0
02165                     /* when using i2c sensors there is an error ( dataformat->length=0)
02166                     the code below catches this error and this causes further problems.*/
02167                     break;
02168             }
02169             if (eRet != ADMW_SUCCESS ) {
02170                 ADMW_LOG_ERROR("Failed to set config for channel %d",
02171                                eChannelId);
02172                 return eRet;
02173 #endif
02174             }
02175 
02176             eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId,
02177                                                    pChannelConfig->extraSettlingTime );
02178             if (eRet != ADMW_SUCCESS ) {
02179                 ADMW_LOG_ERROR("Failed to set settling time for channel %d",
02180                                eChannelId);
02181                 return eRet;
02182             }
02183         }
02184     }
02185 
02186     if (pChannelConfig->enableChannel ) {
02187         /* Threshold limits can be configured individually for virtual channels */
02188         eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId,
02189                 pChannelConfig->highThreshold ,
02190                 pChannelConfig->lowThreshold );
02191         if (eRet != ADMW_SUCCESS ) {
02192             ADMW_LOG_ERROR("Failed to set threshold limits for channel %d",
02193                            eChannelId);
02194             return eRet;
02195         }
02196 
02197         /* Offset and gain can be configured individually for virtual channels */
02198         eRet = admw1001_SetOffsetGain(hDevice, eChannelId,
02199                                       pChannelConfig->offsetAdjustment ,
02200                                       pChannelConfig->gainAdjustment );
02201         if (eRet != ADMW_SUCCESS ) {
02202             ADMW_LOG_ERROR("Failed to set offset/gain for channel %d",
02203                            eChannelId);
02204             return eRet;
02205         }
02206 
02207         /* Set sensor specific parameter */
02208         eRet = admw1001_SetSensorParameter(hDevice, eChannelId,
02209                                            pChannelConfig->sensorParameter );
02210         if (eRet != ADMW_SUCCESS ) {
02211             ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d",
02212                            eChannelId);
02213             return eRet;
02214         }
02215     }
02216 
02217     return ADMW_SUCCESS ;
02218 }
02219 
02220 ADMW_RESULT  admw_SetConfig(
02221     ADMW_DEVICE_HANDLE     const hDevice,
02222     ADMW_CONFIG          * const pConfig)
02223 {
02224     ADMW1001_CONFIG  *pDeviceConfig;
02225     ADMW_PRODUCT_ID  productId;
02226     ADMW_RESULT  eRet;
02227 
02228     if (pConfig->productId  != ADMW_PRODUCT_ID_ADMW1001 ) {
02229         ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)",
02230                        pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 );
02231         return ADMW_INVALID_PARAM ;
02232     }
02233 
02234     if (!((pConfig->versionId .major ==VERSIONID_MAJOR) &&
02235             (pConfig->versionId .minor ==VERSIONID_MINOR))) {
02236         ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported",
02237                        pConfig->versionId );
02238         return ADMW_INVALID_PARAM ;
02239     }
02240 
02241 
02242     /* Check that the actual Product ID is a match? */
02243     eRet = admw_GetProductID(hDevice, &productId);
02244     if (eRet) {
02245         ADMW_LOG_ERROR("Failed to read device Product ID register");
02246         return eRet;
02247     }
02248     if (pConfig->productId  != productId) {
02249         ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)",
02250                        pConfig->productId , productId);
02251         return ADMW_INVALID_PARAM ;
02252     }
02253 
02254     pDeviceConfig = &pConfig->admw1001 ;
02255 
02256     eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power );
02257     if (eRet) {
02258         ADMW_LOG_ERROR("Failed to set power configuration");
02259         return eRet;
02260     }
02261 
02262     eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement );
02263     if (eRet) {
02264         ADMW_LOG_ERROR("Failed to set measurement configuration");
02265         return eRet;
02266     }
02267 
02268     eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics );
02269     if (eRet)
02270     {
02271         ADMW_LOG_ERROR("Failed to set diagnostics configuration");
02272         return eRet;
02273     }
02274 
02275     for (ADMW1001_CH_ID  id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
02276             id < ADMW1001_MAX_CHANNELS ;
02277             id++) {
02278         eRet = admw1001_SetChannelConfig(hDevice, id,
02279                                          &pDeviceConfig->channels [id]);
02280         if (eRet) {
02281             ADMW_LOG_ERROR("Failed to set channel %d configuration", id);
02282             return eRet;
02283         }
02284     }
02285 
02286     return ADMW_SUCCESS ;
02287 }
02288 
02289 ADMW_RESULT  admw1001_SetLutData(
02290     ADMW_DEVICE_HANDLE    const hDevice,
02291     ADMW1001_LUT       * const pLutData)
02292 {
02293     ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header;
02294     ADMW1001_LUT_TABLE  *pLutTable = pLutData->tables;
02295     unsigned actualLength = 0;
02296 
02297     if (pLutData->header.signature != ADMW_LUT_SIGNATURE) {
02298         ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)",
02299                        ADMW_LUT_SIGNATURE, pLutHeader->signature);
02300         return ADMW_INVALID_SIGNATURE ;
02301     }
02302 
02303     for (unsigned i = 0; i < pLutHeader->numTables; i++) {
02304         ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor;
02305         ADMW1001_LUT_TABLE_DATA  *pData = &pLutTable->data;
02306         unsigned short calculatedCrc;
02307 
02308         switch (pDesc->geometry) {
02309             case ADMW1001_LUT_GEOMETRY_COEFFS:
02310                 switch (pDesc->equation) {
02311                     case ADMW1001_LUT_EQUATION_POLYN:
02312                     case ADMW1001_LUT_EQUATION_POLYNEXP:
02313                     case ADMW1001_LUT_EQUATION_QUADRATIC:
02314                     case ADMW1001_LUT_EQUATION_STEINHART:
02315                     case ADMW1001_LUT_EQUATION_LOGARITHMIC:
02316                     case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN:
02317                         break;
02318                     default:
02319                         ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02320                                        pDesc->equation, i);
02321                         return ADMW_INVALID_PARAM ;
02322                 }
02323                 break;
02324             case ADMW1001_LUT_GEOMETRY_NES_1D:
02325             case ADMW1001_LUT_GEOMETRY_NES_2D:
02326             case ADMW1001_LUT_GEOMETRY_ES_1D:
02327             case ADMW1001_LUT_GEOMETRY_ES_2D:
02328                 if (pDesc->equation != ADMW1001_LUT_EQUATION_LUT) {
02329                     ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02330                                    pDesc->equation, i);
02331                     return ADMW_INVALID_PARAM ;
02332                 }
02333                 break;
02334             default:
02335                 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u",
02336                                pDesc->geometry, i);
02337                 return ADMW_INVALID_PARAM ;
02338         }
02339 
02340         switch (pDesc->dataType) {
02341             case ADMW1001_LUT_DATA_TYPE_FLOAT32:
02342             case ADMW1001_LUT_DATA_TYPE_FLOAT64:
02343                 break;
02344             default:
02345                 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u",
02346                                pDesc->dataType, i);
02347                 return ADMW_INVALID_PARAM ;
02348         }
02349 
02350         calculatedCrc = admw_crc16_ccitt(pData, pDesc->length);
02351         if (calculatedCrc != pDesc->crc16) {
02352             ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)",
02353                            i, pDesc->crc16, calculatedCrc);
02354             return ADMW_CRC_ERROR ;
02355         }
02356 
02357         actualLength += sizeof(*pDesc) + pDesc->length;
02358 
02359         /* Move to the next look-up table */
02360         pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length);
02361     }
02362 
02363     if (actualLength != pLutHeader->totalLength) {
02364         ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)",
02365                        pLutHeader->totalLength, actualLength);
02366         return ADMW_WRONG_SIZE ;
02367     }
02368 
02369     if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) {
02370         ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded",
02371                        ADMW_LUT_MAX_SIZE);
02372         return ADMW_WRONG_SIZE ;
02373     }
02374 
02375     /* Write the LUT data to the device */
02376     unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength;
02377     WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET);
02378     WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA);
02379 
02380     return ADMW_SUCCESS ;
02381 }
02382 
02383 ADMW_RESULT  admw1001_SetLutDataRaw(
02384     ADMW_DEVICE_HANDLE     const hDevice,
02385     ADMW1001_LUT_RAW   * const pLutData)
02386 {
02387     return admw1001_SetLutData(hDevice,
02388                                (ADMW1001_LUT *)pLutData);
02389 }
02390 
02391 static ADMW_RESULT  getLutTableSize(
02392     ADMW1001_LUT_DESCRIPTOR * const pDesc,
02393     ADMW1001_LUT_TABLE_DATA  * const pData,
02394     unsigned *pLength)
02395 {
02396     switch (pDesc->geometry) {
02397         case ADMW1001_LUT_GEOMETRY_COEFFS:
02398             if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN)
02399                 *pLength = ADMW1001_LUT_2D_POLYN_COEFF_LIST_SIZE(pData->coeffList2d);
02400             else
02401                 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList);
02402             break;
02403         case ADMW1001_LUT_GEOMETRY_NES_1D:
02404             *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes);
02405             break;
02406         case ADMW1001_LUT_GEOMETRY_NES_2D:
02407             *pLength = ADMW1001_LUT_2D_NES_SIZE(pData->lut2dNes);
02408             break;
02409         case ADMW1001_LUT_GEOMETRY_ES_1D:
02410             *pLength = ADMW1001_LUT_1D_ES_SIZE(pData->lut1dEs);
02411             break;
02412         case ADMW1001_LUT_GEOMETRY_ES_2D:
02413             *pLength = ADMW1001_LUT_2D_ES_SIZE(pData->lut2dEs);
02414             break;
02415         default:
02416             ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n",
02417                            pDesc->geometry);
02418             return ADMW_INVALID_PARAM ;
02419     }
02420 
02421     return ADMW_SUCCESS ;
02422 }
02423 
02424 ADMW_RESULT  admw1001_AssembleLutData(
02425     ADMW1001_LUT                  * pLutBuffer,
02426     unsigned                              nLutBufferSize,
02427     unsigned                        const nNumTables,
02428     ADMW1001_LUT_DESCRIPTOR * const ppDesc[],
02429     ADMW1001_LUT_TABLE_DATA  * const ppData[])
02430 {
02431     ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header;
02432     uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr);
02433 
02434     if (sizeof(*pHdr) > nLutBufferSize) {
02435         ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02436         return ADMW_INVALID_PARAM ;
02437     }
02438 
02439     /* First initialise the top-level header */
02440     pHdr->signature = ADMW_LUT_SIGNATURE;
02441     pHdr->version.major = 1;
02442     pHdr->version.minor = 0;
02443     pHdr->numTables = 0;
02444     pHdr->totalLength = 0;
02445 
02446     /*
02447      * Walk through the list of table pointers provided, appending the table
02448      * descriptor+data from each one to the provided LUT buffer
02449      */
02450     for (unsigned i = 0; i < nNumTables; i++) {
02451         ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i];
02452         ADMW1001_LUT_TABLE_DATA  * const pData = ppData[i];
02453         ADMW_RESULT  res;
02454         unsigned dataLength = 0;
02455 
02456         /* Calculate the length of the table data */
02457         res = getLutTableSize(pDesc, pData, &dataLength);
02458         if (res != ADMW_SUCCESS )
02459             return res;
02460 
02461         /* Fill in the table descriptor length and CRC fields */
02462         pDesc->length = dataLength;
02463         pDesc->crc16 = admw_crc16_ccitt(pData, dataLength);
02464 
02465         if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) {
02466             ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02467             return ADMW_INVALID_PARAM ;
02468         }
02469 
02470         /* Append the table to the LUT buffer (desc + data) */
02471         memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc));
02472         pHdr->totalLength += sizeof(*pDesc);
02473         memcpy(pLutTableData + pHdr->totalLength, pData, dataLength);
02474         pHdr->totalLength += dataLength;
02475 
02476         pHdr->numTables++;
02477     }
02478 
02479     return ADMW_SUCCESS ;
02480 }