Diaz George / Mbed OS EV-PRO-MW1001_EXTVLTG-Dec18
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers admw_1001.c Source File

admw_1001.c

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