Vybhav Kadaba / Mbed OS EV-PRO-MW1001_test2
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  admw_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 100usec delay for status update before checking */
00437             admw_TimeDelayUsec(100);
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         /* Keep the CS signal asserted for all but the last sample */
00652         if ((i + 1) == nRequested)
00653             bHoldCs = false;
00654 
00655         getDataCnt++;
00656 
00657         eRet = admw_SpiTransfer(pCtx->hSpi, NULL, &sensorResult,
00658                                 nBytesPerSample, bHoldCs);
00659         if (eRet) {
00660             ADMW_LOG_ERROR("Failed to read data from FIFO register");
00661             return eRet;
00662         }
00663 
00664         if (! sensorResult.Ch_Valid) {
00665             /*
00666              * Reading an invalid sample indicates that there are no
00667              * more samples available or we've lost sync with the device.
00668              * In the latter case, it might be recoverable, but return here
00669              * to let the application check the device status and decide itself.
00670              */
00671             eRet = ADMW_INCOMPLETE ;
00672             break;
00673         }
00674 
00675         ADMW_DATA_SAMPLE  *pSample = &pSamples[nValidSamples];
00676 
00677         pSample->status  = (ADMW_DEVICE_STATUS_FLAGS )0;
00678         if (sensorResult.Ch_Error)
00679             pSample->status  |= ADMW_DEVICE_STATUS_ERROR ;
00680         if (sensorResult.Ch_Alert)
00681             pSample->status  |= ADMW_DEVICE_STATUS_ALERT ;
00682 
00683         if (sensorResult.Ch_Raw)
00684             pSample->rawValue  = sensorResult.Raw_Sample;
00685         else
00686             pSample->rawValue  = 0;
00687 
00688         pSample->channelId  = sensorResult.Channel_ID;
00689         pSample->processedValue  = sensorResult.Sensor_Result;
00690 
00691         nValidSamples++;
00692 
00693         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00694     }
00695     *pnReturned = nValidSamples;
00696 
00697     return eRet;
00698 }
00699 
00700 /*
00701  * Close the given ADMW device.
00702  */
00703 ADMW_RESULT  admw_Close(
00704     ADMW_DEVICE_HANDLE     const hDevice)
00705 {
00706     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00707 
00708     admw_GpioClose(pCtx->hGpio);
00709     admw_SpiClose(pCtx->hSpi);
00710     admw_LogClose();
00711 
00712     return ADMW_SUCCESS ;
00713 }
00714 
00715 ADMW_RESULT  admw1001_WriteRegister(
00716     ADMW_DEVICE_HANDLE  hDevice,
00717     uint16_t nAddress,
00718     void *pData,
00719     unsigned nLength)
00720 {
00721     ADMW_RESULT  eRet;
00722     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00723     uint16_t command = ADMW1001_HOST_COMMS_WRITE_CMD |
00724                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00725     uint8_t commandData[2] = {
00726         command >> 8,
00727         command & 0xFF
00728     };
00729     uint8_t commandResponse[2];
00730 
00731     do {
00732         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00733                                 sizeof(command), false);
00734         if (eRet) {
00735             ADMW_LOG_ERROR("Failed to send write command for register %u",
00736                            nAddress);
00737             return eRet;
00738         }
00739 
00740         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00741     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00742              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00743 
00744     eRet = admw_SpiTransfer(pCtx->hSpi, pData, NULL, nLength, false);
00745     if (eRet) {
00746         ADMW_LOG_ERROR("Failed to write data (%dB) to register %u",
00747                        nLength, nAddress);
00748         return eRet;
00749     }
00750 
00751     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00752 
00753     return ADMW_SUCCESS ;
00754 }
00755 
00756 ADMW_RESULT  admw1001_Write_Debug_Register(
00757     ADMW_DEVICE_HANDLE  hDevice,
00758     uint16_t nAddress,
00759     void *pData,
00760     unsigned nLength)
00761 {
00762     ADMW_RESULT  eRet;
00763     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00764     uint16_t command = ADMW1001_HOST_COMMS_DEBUG_WRITE_CMD |
00765                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00766     uint8_t commandData[2] = {
00767         command >> 8,
00768         command & 0xFF
00769     };
00770     uint8_t commandResponse[2];
00771 
00772     do {
00773         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00774                                 sizeof(command), false);
00775         if (eRet) {
00776             ADMW_LOG_ERROR("Failed to send write command for register %u",
00777                            nAddress);
00778             return eRet;
00779         }
00780         wait_ms(100);
00781         //admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00782     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00783              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00784 
00785     eRet = admw_SpiTransfer(pCtx->hSpi, pData, NULL, nLength, false);
00786     if (eRet) {
00787         ADMW_LOG_ERROR("Failed to write data (%dB) to register %u",
00788                        nLength, nAddress);
00789         return eRet;
00790     }
00791 
00792     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00793 
00794     return ADMW_SUCCESS ;
00795 }
00796 ADMW_RESULT  admw1001_ReadRegister(
00797     ADMW_DEVICE_HANDLE  hDevice,
00798     uint16_t nAddress,
00799     void *pData,
00800     unsigned nLength)
00801 {
00802     ADMW_RESULT  eRet;
00803     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00804     uint16_t command = ADMW1001_HOST_COMMS_READ_CMD |
00805                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00806     uint8_t commandData[2] = {
00807         command >> 8,
00808         command & 0xFF
00809     };
00810     uint8_t commandResponse[2];
00811 
00812     do {
00813         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00814                                 sizeof(command), false);
00815         if (eRet) {
00816             ADMW_LOG_ERROR("Failed to send read command for register %u",
00817                            nAddress);
00818             return eRet;
00819         }
00820 
00821         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00822     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00823              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00824 
00825     eRet = admw_SpiTransfer(pCtx->hSpi, NULL, pData, nLength, false);
00826     if (eRet) {
00827         ADMW_LOG_ERROR("Failed to read data (%uB) from register %u",
00828                        nLength, nAddress);
00829         return eRet;
00830     }
00831 
00832     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00833 
00834     return ADMW_SUCCESS ;
00835 }
00836 
00837 ADMW_RESULT  admw1001_Read_Debug_Register(
00838     ADMW_DEVICE_HANDLE  hDevice,
00839     uint16_t nAddress,
00840     void *pData,
00841     unsigned nLength)
00842 {
00843     ADMW_RESULT  eRet;
00844     ADMW_DEVICE_CONTEXT *pCtx = hDevice;
00845     uint16_t command = ADMW1001_HOST_COMMS_DEBUG_READ_CMD |
00846                        (nAddress & ADMW1001_HOST_COMMS_ADR_MASK);
00847     uint8_t commandData[2] = {
00848         command >> 8,
00849         command & 0xFF
00850     };
00851     uint8_t commandResponse[2];
00852 
00853     do {
00854         eRet = admw_SpiTransfer(pCtx->hSpi, commandData, commandResponse,
00855                                 sizeof(command), false);
00856         if (eRet) {
00857             ADMW_LOG_ERROR("Failed to send read command for register %u",
00858                            nAddress);
00859             return eRet;
00860         }
00861 
00862         admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00863     } while ((commandResponse[0] != ADMW1001_HOST_COMMS_CMD_RESP_0) ||
00864              (commandResponse[1] != ADMW1001_HOST_COMMS_CMD_RESP_1));
00865 
00866     eRet = admw_SpiTransfer(pCtx->hSpi, NULL, pData, nLength, false);
00867     if (eRet) {
00868         ADMW_LOG_ERROR("Failed to read data (%uB) from register %u",
00869                        nLength, nAddress);
00870         return eRet;
00871     }
00872 
00873     admw_TimeDelayUsec(ADMW1001_HOST_COMMS_XFER_DELAY);
00874 
00875     return ADMW_SUCCESS ;
00876 }
00877 ADMW_RESULT  admw_GetDeviceReadyState(
00878     ADMW_DEVICE_HANDLE    const hDevice,
00879     bool                  * const bReady)
00880 {
00881     ADMW_SPI_Chip_Type_t chipTypeReg;
00882 
00883     READ_REG_U8(hDevice, chipTypeReg.VALUE8, SPI_CHIP_TYPE);
00884     /* If we read this register successfully, assume the device is ready */
00885     *bReady = (chipTypeReg.VALUE8 == REG_SPI_CHIP_TYPE_RESET);
00886 
00887     return ADMW_SUCCESS ;
00888 }
00889 
00890 ADMW_RESULT  admw1001_GetDataReadyModeInfo(
00891     ADMW_DEVICE_HANDLE         const hDevice,
00892     ADMW_MEASUREMENT_MODE      const eMeasurementMode,
00893     ADMW1001_OPERATING_MODE  * const peOperatingMode,
00894     ADMW1001_DATAREADY_MODE  * const peDataReadyMode,
00895     uint32_t                * const pnSamplesPerDataready,
00896     uint32_t                * const pnSamplesPerCycle,
00897     uint8_t                 * const pnBytesPerSample)
00898 {
00899     unsigned nChannelsEnabled = 0;
00900     unsigned nSamplesPerCycle = 0;
00901 
00902     ADMW_CORE_Mode_t modeReg;
00903     READ_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE);
00904 
00905     if (eMeasurementMode == (modeReg.Conversion_Mode == CORE_MODE_SINGLECYCLE))
00906         *peOperatingMode = ADMW1001_OPERATING_MODE_SINGLECYCLE ;
00907     else
00908         *peOperatingMode = ADMW1001_OPERATING_MODE_CONTINUOUS ;
00909 
00910     if (eMeasurementMode == ADMW_MEASUREMENT_MODE_OMIT_RAW ) {
00911         *pnBytesPerSample = 8;
00912     } else {
00913         *pnBytesPerSample = 12;
00914     }
00915 
00916     for (ADMW1001_CH_ID  chId = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
00917             chId < ADMW1001_MAX_CHANNELS ;
00918             chId++) {
00919         ADMW_CORE_Sensor_Details_t sensorDetailsReg;
00920         ADMW_CORE_Channel_Count_t channelCountReg;
00921 
00922         if (ADMW1001_CHANNEL_IS_VIRTUAL(chId))
00923             continue;
00924 
00925         READ_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(chId));
00926         READ_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(chId));
00927 
00928         if (channelCountReg.Channel_Enable && !sensorDetailsReg.Do_Not_Publish) {
00929             unsigned nActualChannels = 1;
00930 
00931             if (chId == ADMW1001_CH_ID_DIG_SPI_0 ) {
00932                 /* Some sensors automatically generate samples on additional
00933                  * "virtual" channels so these channels must be counted as
00934                  * active when those sensors are selected and we use the count
00935                  * from the corresponding "physical" channel
00936                  */
00937 #if 0 /* SPI sensors arent supported at present to be added back once there is
00938        * support for these sensors
00939        */
00940                 ADMW_CORE_Sensor_Type_t sensorTypeReg;
00941 
00942                 READ_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(chId));
00943 
00944                 if ((sensorTypeReg.Sensor_Type >=
00945                         CORE_SENSOR_TYPE_SPI_ACCELEROMETER_A) &&
00946                         (sensorTypeReg.Sensor_Type <=
00947                          CORE_SENSOR_TYPE_SPI_ACCELEROMETER_B)) {
00948                     nActualChannels += 2;
00949                 }
00950 #endif
00951             }
00952 
00953             nChannelsEnabled += nActualChannels;
00954 
00955             nSamplesPerCycle += nActualChannels *
00956                                 (channelCountReg.Channel_Count + 1);
00957         }
00958     }
00959 
00960     if (nChannelsEnabled == 0) {
00961         *pnSamplesPerDataready = 0;
00962         *pnSamplesPerCycle = 0;
00963         return ADMW_SUCCESS ;
00964     }
00965 
00966     *pnSamplesPerCycle = nSamplesPerCycle;
00967 
00968     if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) {
00969         *pnSamplesPerDataready = 1;
00970     } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CYCLE) {
00971         *pnSamplesPerDataready = nSamplesPerCycle;
00972     } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_FIFO_FILL) {
00973         ADMW_CORE_Fifo_Num_Cycles_t fifoNumCyclesReg;
00974 
00975         READ_REG_U8(hDevice, fifoNumCyclesReg.VALUE8, CORE_FIFO_NUM_CYCLES);
00976 
00977         *pnSamplesPerDataready = nSamplesPerCycle * fifoNumCyclesReg.Fifo_Num_Cycles;
00978     } else {
00979         ADMW_LOG_ERROR("Invalid DRDY mode %d specified",
00980                        modeReg.Drdy_Mode);
00981         return ADMW_INVALID_PARAM ;
00982     }
00983 
00984     if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CONVERSION) {
00985         *peDataReadyMode = ADMW1001_DATAREADY_PER_CONVERSION ;
00986     } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_CYCLE) {
00987         *peDataReadyMode = ADMW1001_DATAREADY_PER_CYCLE ;
00988     } else if (modeReg.Drdy_Mode == CORE_MODE_DRDY_PER_FIFO_FILL) {
00989         *peDataReadyMode = ADMW1001_DATAREADY_PER_FIFO_FILL ;
00990     } else {
00991         ADMW_LOG_ERROR("Invalid DRDY mode %d specified",
00992                        modeReg.Drdy_Mode);
00993         return ADMW_INVALID_PARAM ;
00994     }
00995 
00996     return ADMW_SUCCESS ;
00997 }
00998 
00999 ADMW_RESULT  admw_GetProductID(
01000     ADMW_DEVICE_HANDLE  hDevice,
01001     ADMW_PRODUCT_ID  *pProductId)
01002 {
01003     ADMW_SPI_Product_ID_L_t productIdLoReg;
01004     ADMW_SPI_Product_ID_H_t productIdHiReg;
01005 
01006     READ_REG_U8(hDevice, productIdLoReg.VALUE8, SPI_PRODUCT_ID_L);
01007     READ_REG_U8(hDevice, productIdHiReg.VALUE8, SPI_PRODUCT_ID_H);
01008 
01009     *pProductId = (ADMW_PRODUCT_ID )((productIdHiReg.VALUE8 << 8) |
01010                                     productIdLoReg.VALUE8);
01011     return ADMW_SUCCESS ;
01012 }
01013 
01014 static ADMW_RESULT  admw_SetPowerMode(
01015     ADMW_DEVICE_HANDLE  hDevice,
01016     ADMW1001_POWER_MODE  powerMode)
01017 {
01018     ADMW_CORE_Power_Config_t powerConfigReg = { 0 };
01019 
01020     if (powerMode == ADMW1001_POWER_MODE_HIBERNATION ) {
01021         powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_HIBERNATION;
01022     } else if (powerMode == ADMW1001_POWER_MODE_ACTIVE ) {
01023         powerConfigReg.Power_Mode_MCU = CORE_POWER_CONFIG_ACTIVE_MODE;
01024     } else {
01025         ADMW_LOG_ERROR("Invalid power mode %d specified", powerMode);
01026         return ADMW_INVALID_PARAM ;
01027     }
01028 
01029     WRITE_REG_U8(hDevice, powerConfigReg.VALUE8, CORE_POWER_CONFIG);
01030 
01031     return ADMW_SUCCESS ;
01032 }
01033 
01034 ADMW_RESULT  admw1001_SetPowerConfig(
01035     ADMW_DEVICE_HANDLE  hDevice,
01036     ADMW1001_POWER_CONFIG  *pPowerConfig)
01037 {
01038     ADMW_RESULT  eRet;
01039 
01040     eRet = admw_SetPowerMode(hDevice, pPowerConfig->powerMode );
01041     if (eRet != ADMW_SUCCESS ) {
01042         ADMW_LOG_ERROR("Failed to set power mode");
01043         return eRet;
01044     }
01045 
01046     return ADMW_SUCCESS ;
01047 }
01048 
01049 static ADMW_RESULT  admw_SetRSenseValue(
01050     ADMW_DEVICE_HANDLE  hDevice,
01051     float32_t RSenseValue)
01052 {
01053     ADMW_CORE_External_Reference_Resistor_t RefResistorConfigReg;
01054 
01055     RefResistorConfigReg.Ext_Refin1_Value = RSenseValue;
01056 
01057     WRITE_REG_FLOAT(hDevice, RefResistorConfigReg.VALUE32, CORE_EXTERNAL_REFERENCE_RESISTOR);
01058 
01059     return ADMW_SUCCESS ;
01060 
01061 }
01062 static ADMW_RESULT  admw_SetMode(
01063     ADMW_DEVICE_HANDLE  hDevice,
01064     ADMW1001_OPERATING_MODE  eOperatingMode,
01065     ADMW1001_DATAREADY_MODE  eDataReadyMode)
01066 {
01067     ADMW_CORE_Mode_t modeReg;
01068 
01069     modeReg.VALUE8 = REG_RESET_VAL(CORE_MODE);
01070 
01071     if (eOperatingMode == ADMW1001_OPERATING_MODE_SINGLECYCLE ) {
01072         modeReg.Conversion_Mode = CORE_MODE_SINGLECYCLE;
01073     } else if (eOperatingMode == ADMW1001_OPERATING_MODE_CONTINUOUS ) {
01074         modeReg.Conversion_Mode = CORE_MODE_CONTINUOUS;
01075     } else {
01076         ADMW_LOG_ERROR("Invalid operating mode %d specified",
01077                        eOperatingMode);
01078         return ADMW_INVALID_PARAM ;
01079     }
01080 
01081     if (eDataReadyMode == ADMW1001_DATAREADY_PER_CONVERSION ) {
01082         modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CONVERSION;
01083     } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_CYCLE ) {
01084         modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_CYCLE;
01085     } else if (eDataReadyMode == ADMW1001_DATAREADY_PER_FIFO_FILL ) {
01086         modeReg.Drdy_Mode = CORE_MODE_DRDY_PER_FIFO_FILL;
01087     } else {
01088         ADMW_LOG_ERROR("Invalid data-ready mode %d specified", eDataReadyMode);
01089         return ADMW_INVALID_PARAM ;
01090     }
01091 
01092     WRITE_REG_U8(hDevice, modeReg.VALUE8, CORE_MODE);
01093 
01094     return ADMW_SUCCESS ;
01095 }
01096 
01097 ADMW_RESULT  admw_SetCycleControl(ADMW_DEVICE_HANDLE  hDevice,
01098                                  uint32_t           nCycleInterval,
01099                                  bool               vBiasEnable,
01100                                  bool           vPostExecCurrentState,
01101                                  bool               vGroundSwitch)
01102 {
01103     ADMW_CORE_Cycle_Control_t cycleControlReg;
01104 
01105     cycleControlReg.VALUE16 = REG_RESET_VAL(CORE_CYCLE_CONTROL);
01106 
01107     if (nCycleInterval < (1 << 12)) {
01108         cycleControlReg.Cycle_Time_Units = CORE_CYCLE_CONTROL_SECONDS;
01109     } else {
01110         ADMW_LOG_ERROR("Invalid nCycleInterval %d specified", nCycleInterval);
01111         return ADMW_INVALID_PARAM ;
01112     }
01113 
01114     if (vBiasEnable == true) {
01115         cycleControlReg.Vbias = 1;
01116     }
01117     CHECK_REG_FIELD_VAL(CORE_CYCLE_CONTROL_CYCLE_TIME, nCycleInterval);
01118     cycleControlReg.Cycle_Time = nCycleInterval;
01119 
01120     switch(vPostExecCurrentState) {
01121         case ADMW1001_ADC_EXC_STATE_CYCLE_POWER :
01122             cycleControlReg.PST_MEAS_EXC_CTRL = CORE_CYCLE_CONTROL_POWERCYCLE;
01123             break;
01124         case ADMW1001_ADC_EXC_STATE_ALWAYS_ON :
01125             cycleControlReg.PST_MEAS_EXC_CTRL = CORE_CYCLE_CONTROL_ALWAYSON;
01126             break;
01127         default:
01128             ADMW_LOG_ERROR("Invalid Post measurement Excitation Current state %d specified",
01129                            vPostExecCurrentState);
01130             return ADMW_INVALID_PARAM ;
01131     }
01132 
01133     switch(vGroundSwitch) {
01134         case ADMW1001_ADC_GND_SW_OPEN :
01135             cycleControlReg.GND_SW_CTRL = CORE_CYCLE_CONTROL_OPEN_SW;
01136             break;
01137         case ADMW1001_ADC_GND_SW_CLOSED :
01138             cycleControlReg.GND_SW_CTRL = CORE_CYCLE_CONTROL_CLOSE_SW;
01139             break;
01140         default:
01141             ADMW_LOG_ERROR("Invalid ground switch state %d specified",
01142                            vGroundSwitch);
01143             return ADMW_INVALID_PARAM ;
01144     }
01145 
01146     WRITE_REG_U16(hDevice, cycleControlReg.VALUE16, CORE_CYCLE_CONTROL);
01147 
01148     return ADMW_SUCCESS ;
01149 }
01150 static ADMW_RESULT  admw_SetExternalReferenceVoltage(
01151     ADMW_DEVICE_HANDLE  hDevice,
01152     float32_t externalRefVoltage)
01153 {
01154     WRITE_REG_FLOAT(hDevice, externalRefVoltage, CORE_EXTERNAL_VOLTAGE_REFERENCE);
01155 
01156     return ADMW_SUCCESS ;
01157 }
01158 static ADMW_RESULT  admw_SetFifoNumCycles(
01159     ADMW_DEVICE_HANDLE  hDevice,
01160     uint8_t fifoNumCycles)
01161 {
01162     WRITE_REG_U8(hDevice, fifoNumCycles, CORE_FIFO_NUM_CYCLES);
01163 
01164     return ADMW_SUCCESS ;
01165 }
01166 
01167 static ADMW_RESULT  admw_SetExternalReferenceValues(
01168     ADMW_DEVICE_HANDLE  hDevice,
01169     float32_t externalRef1Value)
01170 {
01171     WRITE_REG_FLOAT(hDevice, externalRef1Value, CORE_EXTERNAL_REFERENCE_RESISTOR);
01172 
01173     return ADMW_SUCCESS ;
01174 }
01175 static ADMW_RESULT  admw_SetAVDDVoltage(
01176     ADMW_DEVICE_HANDLE  hDevice,
01177     float32_t AVDDVoltage)
01178 {
01179 
01180     WRITE_REG_FLOAT(hDevice, AVDDVoltage, CORE_AVDD_VOLTAGE);
01181 
01182     return ADMW_SUCCESS ;
01183 }
01184 
01185 ADMW_RESULT  admw1001_SetMeasurementConfig(
01186     ADMW_DEVICE_HANDLE  hDevice,
01187     ADMW1001_MEASUREMENT_CONFIG  *pMeasConfig)
01188 {
01189     ADMW_RESULT  eRet;
01190 
01191     eRet = admw_SetMode(hDevice,
01192                         pMeasConfig->operatingMode ,
01193                         pMeasConfig->dataReadyMode );
01194     if (eRet != ADMW_SUCCESS ) {
01195         ADMW_LOG_ERROR("Failed to set operating mode");
01196         return eRet;
01197     }
01198 
01199     eRet = admw_SetCycleControl(hDevice, pMeasConfig->cycleInterval ,
01200                                 pMeasConfig->vBiasEnable ,
01201                                 pMeasConfig->excitationState ,
01202                                 pMeasConfig->groundSwitch  );
01203     if (eRet != ADMW_SUCCESS ) {
01204         ADMW_LOG_ERROR("Failed to set cycle control");
01205         return eRet;
01206     }
01207 
01208     if (pMeasConfig->fifoNumCycles  > 0) {
01209         eRet = admw_SetFifoNumCycles(hDevice,
01210                                      pMeasConfig->fifoNumCycles );
01211     }
01212 
01213     if (eRet != ADMW_SUCCESS ) {
01214         ADMW_LOG_ERROR("Failed to set the FIFO number of cycles.");
01215         return eRet;
01216     }
01217 
01218     if(pMeasConfig->externalRef1Value  > 0) {
01219         eRet = admw_SetExternalReferenceValues(hDevice,
01220                                                pMeasConfig->externalRef1Value );
01221     }
01222 
01223     if (eRet != ADMW_SUCCESS ) {
01224         ADMW_LOG_ERROR("Failed to set external reference values");
01225         return eRet;
01226     }
01227 
01228     if((pMeasConfig->AVDDVoltage  >= 3.0) && (pMeasConfig->AVDDVoltage  <= 3.6)) {
01229         eRet = admw_SetAVDDVoltage(hDevice,
01230                                    pMeasConfig->AVDDVoltage );
01231     }
01232 
01233     if (eRet != ADMW_SUCCESS ) {
01234         ADMW_LOG_ERROR("Failed to set AVDD Voltge");
01235         return eRet;
01236     }
01237 
01238     eRet = admw_SetRSenseValue(hDevice, pMeasConfig->RSenseValue );
01239     if (eRet != ADMW_SUCCESS ) {
01240         ADMW_LOG_ERROR("Failed to set RSenseValue");
01241         return eRet;
01242     }
01243 
01244     eRet = admw_SetExternalReferenceVoltage(hDevice, pMeasConfig->externalRefVoltage );
01245     if (eRet != ADMW_SUCCESS ) {
01246         ADMW_LOG_ERROR("Failed to set External reference Voltage");
01247         return eRet;
01248     }
01249 
01250     return ADMW_SUCCESS ;
01251 }
01252 ADMW_RESULT  admw1001_SetDiagnosticsConfig(
01253     ADMW_DEVICE_HANDLE  hDevice,
01254     ADMW1001_DIAGNOSTICS_CONFIG  *pDiagnosticsConfig)
01255 {
01256     ADMW_CORE_Diagnostics_Control_t diagnosticsControlReg;
01257 
01258     diagnosticsControlReg.VALUE8 = REG_RESET_VAL(CORE_DIAGNOSTICS_CONTROL);
01259 
01260     if (pDiagnosticsConfig->disableMeasurementDiag )
01261         diagnosticsControlReg.Diag_Meas_En = 0;
01262     else
01263         diagnosticsControlReg.Diag_Meas_En = 1;
01264 
01265     if(pDiagnosticsConfig->osdFrequency  <= 0x7F)
01266     {
01267       diagnosticsControlReg.Diag_OSD_Freq = pDiagnosticsConfig->osdFrequency ;
01268     }
01269     else
01270     {
01271         ADMW_LOG_ERROR("Invalid open-sensor diagnostic frequency %d specified",
01272                         pDiagnosticsConfig->osdFrequency );
01273         return ADMW_INVALID_PARAM ;
01274     }
01275     WRITE_REG_U8(hDevice, diagnosticsControlReg.VALUE8, CORE_DIAGNOSTICS_CONTROL);
01276 
01277     return ADMW_SUCCESS ;
01278 }
01279 
01280 ADMW_RESULT  admw1001_SetChannelCount(
01281     ADMW_DEVICE_HANDLE  hDevice,
01282     ADMW1001_CH_ID  eChannelId,
01283     uint32_t nMeasurementsPerCycle)
01284 {
01285     ADMW_CORE_Channel_Count_t channelCountReg;
01286 
01287     channelCountReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_COUNTn);
01288 
01289     if (nMeasurementsPerCycle > 0) {
01290         nMeasurementsPerCycle -= 1;
01291 
01292         CHECK_REG_FIELD_VAL(CORE_CHANNEL_COUNT_CHANNEL_COUNT,
01293                             nMeasurementsPerCycle);
01294 
01295         channelCountReg.Channel_Enable = 1;
01296         channelCountReg.Channel_Count = nMeasurementsPerCycle;
01297     } else {
01298         channelCountReg.Channel_Enable = 0;
01299     }
01300 
01301     WRITE_REG_U8(hDevice, channelCountReg.VALUE8, CORE_CHANNEL_COUNTn(eChannelId));
01302 
01303     return ADMW_SUCCESS ;
01304 }
01305 
01306 ADMW_RESULT  admw1001_SetChannelOptions(
01307     ADMW_DEVICE_HANDLE  hDevice,
01308     ADMW1001_CH_ID  eChannelId,
01309     ADMW1001_CHANNEL_PRIORITY  ePriority)
01310 {
01311     ADMW_CORE_Channel_Options_t channelOptionsReg;
01312 
01313     channelOptionsReg.VALUE8 = REG_RESET_VAL(CORE_CHANNEL_OPTIONSn);
01314 
01315     CHECK_REG_FIELD_VAL(CORE_CHANNEL_OPTIONS_CHANNEL_PRIORITY, ePriority);
01316     channelOptionsReg.Channel_Priority = ePriority;
01317 
01318     WRITE_REG_U8(hDevice, channelOptionsReg.VALUE8, CORE_CHANNEL_OPTIONSn(eChannelId));
01319 
01320     return ADMW_SUCCESS ;
01321 }
01322 
01323 ADMW_RESULT  admw1001_SetChannelSkipCount(
01324     ADMW_DEVICE_HANDLE  hDevice,
01325     ADMW1001_CH_ID  eChannelId,
01326     uint32_t nCycleSkipCount)
01327 {
01328     ADMW_CORE_Channel_Skip_t channelSkipReg;
01329 
01330     channelSkipReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_SKIPn);
01331 
01332     CHECK_REG_FIELD_VAL(CORE_CHANNEL_SKIP_CHANNEL_SKIP, nCycleSkipCount);
01333 
01334     channelSkipReg.Channel_Skip = nCycleSkipCount;
01335 
01336     WRITE_REG_U16(hDevice, channelSkipReg.VALUE16, CORE_CHANNEL_SKIPn(eChannelId));
01337 
01338     return ADMW_SUCCESS ;
01339 }
01340 
01341 static ADMW_RESULT  admw_SetChannelAdcSensorType(
01342     ADMW_DEVICE_HANDLE           hDevice,
01343     ADMW1001_CH_ID               eChannelId,
01344     ADMW1001_ADC_SENSOR_TYPE     sensorType)
01345 {
01346     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01347 
01348     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01349 
01350     /* Ensure that the sensor type is valid for this channel */
01351     switch(sensorType) {
01352         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT10 :
01353 
01354         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT50 :
01355         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT100 :
01356         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT200 :
01357         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT500 :
01358         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000 :
01359         case ADMW1001_ADC_SENSOR_RTD_2WIRE_PT1000_0P00375 :
01360         case ADMW1001_ADC_SENSOR_RTD_2WIRE_NI120 :
01361         case ADMW1001_ADC_SENSOR_RTD_2WIRE_CUSTOM :
01362         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT10 :
01363 
01364         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT50 :
01365         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT100 :
01366         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT200 :
01367         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT500 :
01368         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000 :
01369         case ADMW1001_ADC_SENSOR_RTD_4WIRE_PT1000_0P00375 :
01370         case ADMW1001_ADC_SENSOR_RTD_4WIRE_NI120 :
01371         case ADMW1001_ADC_SENSOR_RTD_4WIRE_CUSTOM :
01372         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT10 :
01373 
01374         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT50 :
01375         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT100 :
01376         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT200 :
01377         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT500 :
01378         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000 :
01379         case ADMW1001_ADC_SENSOR_RTD_3WIRE_PT1000_0P00375  :
01380 
01381         case ADMW1001_ADC_SENSOR_RTD_3WIRE_NI120 :
01382         case ADMW1001_ADC_SENSOR_RTD_3WIRE_CUSTOM :
01383         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_1 :
01384         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_2 :
01385         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_3 :
01386         case ADMW1001_ADC_SENSOR_BRIDGE_4WIRE_4 :
01387         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_1 :
01388         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_2 :
01389         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_3 :
01390         case ADMW1001_ADC_SENSOR_BRIDGE_6WIRE_4 :
01391         case ADMW1001_ADC_SENSOR_DIODE :
01392         case ADMW1001_ADC_SENSOR_THERMISTOR_44004_44033_2P252K_AT_25C :
01393         case ADMW1001_ADC_SENSOR_THERMISTOR_44005_44030_3K_AT_25C :
01394         case ADMW1001_ADC_SENSOR_THERMISTOR_44007_44034_5K_AT_25C :
01395         case ADMW1001_ADC_SENSOR_THERMISTOR_44006_44031_10K_AT_25C :
01396         case ADMW1001_ADC_SENSOR_THERMISTOR_44008_44032_30K_AT_25C :
01397         case ADMW1001_ADC_SENSOR_THERMISTOR_YSI_400 :
01398         case ADMW1001_ADC_SENSOR_THERMISTOR_SPECTRUM_1003K_1K :
01399         case ADMW1001_ADC_SENSOR_THERMISTOR_CUSTOM_STEINHART_HART :
01400         case ADMW1001_ADC_SENSOR_THERMISTOR_CUSTOM_TABLE :
01401         case ADMW1001_ADC_SENSOR_SINGLE_ENDED_ABSOLUTE :
01402         case ADMW1001_ADC_SENSOR_DIFFERENTIAL_ABSOLUTE :
01403         case ADMW1001_ADC_SENSOR_SINGLE_ENDED_RATIO :
01404         case ADMW1001_ADC_SENSOR_DIFFERENTIAL_RATIO :
01405 
01406             if (! (ADMW1001_CHANNEL_IS_ADC_CJC(eChannelId) ||
01407                     ADMW1001_CHANNEL_IS_ADC(eChannelId) )) {
01408                 ADMW_LOG_ERROR(
01409                     "Invalid ADC sensor type %d specified for channel %d",
01410                     sensorType, eChannelId);
01411                 return ADMW_INVALID_PARAM ;
01412             }
01413             break;
01414         case ADMW1001_ADC_SENSOR_VOLTAGE :
01415         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_A :
01416         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_B :
01417         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_1 :
01418         case ADMW1001_ADC_SENSOR_VOLTAGE_PRESSURE_2 :
01419         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_J :
01420         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_K :
01421         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_T :
01422         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_E :
01423         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_N :
01424         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_R :
01425         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_S :
01426         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_B :
01427         case ADMW1001_ADC_SENSOR_THERMOCOUPLE_CUSTOM :
01428             if (! ADMW1001_CHANNEL_IS_ADC_VOLTAGE(eChannelId)) {
01429                 ADMW_LOG_ERROR(
01430                     "Invalid ADC sensor type %d specified for channel %d",
01431                     sensorType, eChannelId);
01432                 return ADMW_INVALID_PARAM ;
01433             }
01434             break;
01435         case ADMW1001_ADC_SENSOR_CURRENT :
01436         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_A :
01437         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_1 :
01438         case ADMW1001_ADC_SENSOR_CURRENT_PRESSURE_2 :
01439             if (! ADMW1001_CHANNEL_IS_ADC_CURRENT(eChannelId)) {
01440                 ADMW_LOG_ERROR(
01441                     "Invalid ADC sensor type %d specified for channel %d",
01442                     sensorType, eChannelId);
01443                 return ADMW_INVALID_PARAM ;
01444             }
01445             break;
01446         default:
01447             ADMW_LOG_ERROR("Invalid/unsupported ADC sensor type %d specified",
01448                            sensorType);
01449             return ADMW_INVALID_PARAM ;
01450     }
01451 
01452     sensorTypeReg.Sensor_Type = sensorType;
01453 
01454     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01455 
01456     return ADMW_SUCCESS ;
01457 }
01458 
01459 static ADMW_RESULT  admw_SetChannelAdcSensorDetails(
01460     ADMW_DEVICE_HANDLE       hDevice,
01461     ADMW1001_CH_ID           eChannelId,
01462     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01463 /*
01464  * TODO - it would be nice if the general- vs. ADC-specific sensor details could be split into separate registers
01465  * General details:
01466  * - Measurement_Units
01467  * - Compensation_Channel
01468  * - CJC_Publish (if "CJC" was removed from the name)
01469  * ADC-specific details:
01470  * - PGA_Gain
01471  * - Reference_Select
01472  * - Reference_Buffer_Disable
01473  */
01474 {
01475     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig = &pChannelConfig->adcChannelConfig ;
01476     ADMW1001_ADC_REFERENCE_TYPE  refType            = pAdcChannelConfig->reference ;
01477     ADMW_CORE_Sensor_Details_t  sensorDetailsReg;
01478 
01479     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01480 
01481     switch(pChannelConfig->measurementUnit ) {
01482         case ADMW1001_MEASUREMENT_UNIT_FAHRENHEIT :
01483             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGF;
01484             break;
01485         case ADMW1001_MEASUREMENT_UNIT_CELSIUS :
01486             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_DEGC;
01487             break;
01488         case ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED :
01489             sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01490             break;
01491         default:
01492             ADMW_LOG_ERROR("Invalid measurement unit %d specified",
01493                            pChannelConfig->measurementUnit );
01494             return ADMW_INVALID_PARAM ;
01495     }
01496 
01497     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01498         sensorDetailsReg.Compensation_Disable = 1;
01499         sensorDetailsReg.Compensation_Channel = 0;
01500     } else {
01501         sensorDetailsReg.Compensation_Disable = 0;
01502         sensorDetailsReg.Compensation_Channel = pChannelConfig->compensationChannel ;
01503     }
01504 
01505     switch(refType) {
01506         case ADMW1001_ADC_REFERENCE_VOLTAGE_INTERNAL :
01507             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VINT;
01508             break;
01509         case ADMW1001_ADC_REFERENCE_VOLTAGE_EXTERNAL_1 :
01510             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_VEXT1;
01511             break;
01512         case ADMW1001_ADC_REFERENCE_VOLTAGE_AVDD :
01513             sensorDetailsReg.Reference_Select = CORE_SENSOR_DETAILS_REF_AVDD;
01514             break;
01515         default:
01516             ADMW_LOG_ERROR("Invalid ADC reference type %d specified", refType);
01517             return ADMW_INVALID_PARAM ;
01518     }
01519 
01520     switch(pAdcChannelConfig->gain ) {
01521         case ADMW1001_ADC_GAIN_1X :
01522             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_1;
01523             break;
01524         case ADMW1001_ADC_GAIN_2X :
01525             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_2;
01526             break;
01527         case ADMW1001_ADC_GAIN_4X :
01528             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_4;
01529             break;
01530         case ADMW1001_ADC_GAIN_8X :
01531             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_8;
01532             break;
01533         case ADMW1001_ADC_GAIN_16X :
01534             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_16;
01535             break;
01536         case ADMW1001_ADC_GAIN_32X :
01537             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_32;
01538             break;
01539         case ADMW1001_ADC_GAIN_64X :
01540             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_64;
01541             break;
01542         case ADMW1001_ADC_GAIN_128X :
01543             sensorDetailsReg.PGA_Gain = CORE_SENSOR_DETAILS_PGA_GAIN_128;
01544             break;
01545         default:
01546             ADMW_LOG_ERROR("Invalid ADC gain %d specified",
01547                            pAdcChannelConfig->gain );
01548             return ADMW_INVALID_PARAM ;
01549     }
01550 
01551     switch(pAdcChannelConfig->rtdCurve ) {
01552         case ADMW1001_ADC_RTD_CURVE_EUROPEAN :
01553             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_EUROPEAN_CURVE;
01554             break;
01555         case ADMW1001_ADC_RTD_CURVE_AMERICAN :
01556             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_AMERICAN_CURVE;
01557             break;
01558         case ADMW1001_ADC_RTD_CURVE_JAPANESE :
01559             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_JAPANESE_CURVE;
01560             break;
01561         case ADMW1001_ADC_RTD_CURVE_ITS90 :
01562             sensorDetailsReg.RTD_Curve = CORE_SENSOR_DETAILS_ITS90_CURVE;
01563             break;
01564         default:
01565             ADMW_LOG_ERROR("Invalid RTD Curve %d specified",
01566                            pAdcChannelConfig->rtdCurve );
01567             return ADMW_INVALID_PARAM ;
01568     }
01569 
01570     if (pChannelConfig->disablePublishing ) {
01571         sensorDetailsReg.Do_Not_Publish = 1;
01572     } else {
01573         sensorDetailsReg.Do_Not_Publish = 0;
01574     }
01575 
01576     switch (pChannelConfig->lutSelect ) {
01577         case ADMW1001_LUT_DEFAULT :
01578         case ADMW1001_LUT_CUSTOM :
01579             sensorDetailsReg.LUT_Select = pChannelConfig->lutSelect ;
01580             break;
01581         default:
01582             ADMW_LOG_ERROR("Invalid LUT selection %d specified",
01583                            pChannelConfig->lutSelect );
01584             return ADMW_INVALID_PARAM ;
01585     }
01586 
01587     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01588 
01589     return ADMW_SUCCESS ;
01590 }
01591 
01592 static ADMW_RESULT  admw_SetChannelAdcMeasurementSetup(
01593     ADMW_DEVICE_HANDLE  hDevice,
01594     ADMW1001_CH_ID  eChannelId,
01595     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig)
01596 {
01597     ADMW_CORE_Measurement_Setup_t MeasSetupReg;
01598     ADMW1001_ADC_FILTER_CONFIG  *pFilterConfig = &pAdcChannelConfig->filter ;
01599     MeasSetupReg.VALUE32 = REG_RESET_VAL(CORE_MEASUREMENT_SETUPn);
01600     MeasSetupReg.Buffer_Bypass = pAdcChannelConfig->bufferBypass ;
01601 
01602     if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC4 ) {
01603         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC4;
01604         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01605     } else if (pFilterConfig->type  == ADMW1001_ADC_FILTER_SINC3 ) {
01606         MeasSetupReg.ADC_Filter_Type = CORE_MEASUREMENT_SETUP_ENABLE_SINC3;
01607         MeasSetupReg.ADC_SF = pFilterConfig->sf ;
01608     } else {
01609         ADMW_LOG_ERROR("Invalid ADC filter type %d specified",
01610                        pFilterConfig->type );
01611         return ADMW_INVALID_PARAM ;
01612     }
01613 
01614     /* chop mod ecan be 0 (none), 1 (HW, 2 (SW, 3 (HW+SW). */
01615     MeasSetupReg.Chop_Mode = pFilterConfig->chopMode ;
01616 
01617     if(pFilterConfig->notch1p2 )
01618         MeasSetupReg.NOTCH_EN_2 = 1;
01619     else
01620         MeasSetupReg.NOTCH_EN_2 = 0;
01621 
01622     WRITE_REG_U32(hDevice, MeasSetupReg.VALUE32, CORE_MEASUREMENT_SETUPn(eChannelId));
01623 
01624     return ADMW_SUCCESS ;
01625 }
01626 
01627 static ADMW_RESULT  admw_SetChannelAdcCurrentConfig(
01628     ADMW_DEVICE_HANDLE  hDevice,
01629     ADMW1001_CH_ID  eChannelId,
01630     ADMW1001_ADC_EXC_CURRENT_CONFIG  *pCurrentConfig)
01631 {
01632     ADMW_CORE_Channel_Excitation_t channelExcitationReg;
01633 
01634     channelExcitationReg.VALUE16 = REG_RESET_VAL(CORE_CHANNEL_EXCITATIONn);
01635 
01636     if (pCurrentConfig->outputLevel  == ADMW1001_ADC_NO_EXTERNAL_EXC_CURRENT )
01637         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_NONE;
01638     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_EXTERNAL )
01639         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_EXTERNAL;
01640     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_50uA )
01641         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_50UA;
01642     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_100uA )
01643         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_100UA;
01644     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_250uA )
01645         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_250UA;
01646     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_500uA )
01647         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_500UA;
01648     else if (pCurrentConfig->outputLevel  == ADMW1001_ADC_EXC_CURRENT_1000uA )
01649         channelExcitationReg.IOUT_Excitation_Current = CORE_CHANNEL_EXCITATION_IEXC_1000UA;
01650     else {
01651         ADMW_LOG_ERROR("Invalid ADC excitation current %d specified",
01652                        pCurrentConfig->outputLevel );
01653         return ADMW_INVALID_PARAM ;
01654     }
01655 
01656     WRITE_REG_U16(hDevice, channelExcitationReg.VALUE16, CORE_CHANNEL_EXCITATIONn(eChannelId));
01657 
01658     return ADMW_SUCCESS ;
01659 }
01660 
01661 ADMW_RESULT  admw_SetAdcChannelConfig(
01662     ADMW_DEVICE_HANDLE  hDevice,
01663     ADMW1001_CH_ID  eChannelId,
01664     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01665 {
01666     ADMW_RESULT  eRet;
01667     ADMW1001_ADC_CHANNEL_CONFIG  *pAdcChannelConfig =
01668         &pChannelConfig->adcChannelConfig ;
01669 
01670     eRet = admw_SetChannelAdcSensorType(hDevice, eChannelId,
01671                                         pAdcChannelConfig->sensor );
01672     if (eRet != ADMW_SUCCESS ) {
01673         ADMW_LOG_ERROR("Failed to set ADC sensor type for channel %d",
01674                        eChannelId);
01675         return eRet;
01676     }
01677 
01678     eRet = admw_SetChannelAdcSensorDetails(hDevice, eChannelId,
01679                                            pChannelConfig);
01680     if (eRet != ADMW_SUCCESS ) {
01681         ADMW_LOG_ERROR("Failed to set ADC sensor details for channel %d",
01682                        eChannelId);
01683         return eRet;
01684     }
01685 
01686     eRet = admw_SetChannelAdcMeasurementSetup(hDevice, eChannelId,
01687             pAdcChannelConfig);
01688     if (eRet != ADMW_SUCCESS ) {
01689         ADMW_LOG_ERROR("Failed to set ADC filter for channel %d",
01690                        eChannelId);
01691         return eRet;
01692     }
01693 
01694     eRet = admw_SetChannelAdcCurrentConfig(hDevice, eChannelId,
01695                                            &pAdcChannelConfig->current );
01696     if (eRet != ADMW_SUCCESS ) {
01697         ADMW_LOG_ERROR("Failed to set ADC current for channel %d",
01698                        eChannelId);
01699         return eRet;
01700     }
01701 
01702     return ADMW_SUCCESS ;
01703 }
01704 
01705 static ADMW_RESULT  admw_SetChannelDigitalSensorDetails(
01706     ADMW_DEVICE_HANDLE  hDevice,
01707     ADMW1001_CH_ID  eChannelId,
01708     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01709 {
01710     ADMW_CORE_Sensor_Details_t sensorDetailsReg;
01711 
01712     sensorDetailsReg.VALUE32 = REG_RESET_VAL(CORE_SENSOR_DETAILSn);
01713 
01714     if (pChannelConfig->compensationChannel  == ADMW1001_CH_ID_NONE ) {
01715         sensorDetailsReg.Compensation_Disable = 1;
01716         sensorDetailsReg.Compensation_Channel = 0;
01717     } else {
01718         ADMW_LOG_ERROR("Invalid compensation channel specified for digital sensor");
01719         return ADMW_INVALID_PARAM ;
01720     }
01721 
01722     if (pChannelConfig->measurementUnit  == ADMW1001_MEASUREMENT_UNIT_UNSPECIFIED ) {
01723         sensorDetailsReg.Measurement_Units = CORE_SENSOR_DETAILS_UNITS_UNSPECIFIED;
01724     } else {
01725         ADMW_LOG_ERROR("Invalid measurement unit specified for digital channel");
01726         return ADMW_INVALID_PARAM ;
01727     }
01728 
01729     if (pChannelConfig->disablePublishing )
01730         sensorDetailsReg.Do_Not_Publish = 1;
01731     else
01732         sensorDetailsReg.Do_Not_Publish = 0;
01733 
01734     WRITE_REG_U32(hDevice, sensorDetailsReg.VALUE32, CORE_SENSOR_DETAILSn(eChannelId));
01735 
01736     return ADMW_SUCCESS ;
01737 }
01738 
01739 static ADMW_RESULT  admw_SetDigitalSensorFormat(
01740     ADMW_DEVICE_HANDLE  hDevice,
01741     ADMW1001_CH_ID  eChannelId,
01742     ADMW1001_DIGITAL_SENSOR_DATA_FORMAT  *pDataFormat)
01743 {
01744     ADMW_CORE_Digital_Sensor_Config_t sensorConfigReg;
01745 
01746     sensorConfigReg.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_CONFIGn);
01747 
01748     if (pDataFormat->coding != ADMW1001_DIGITAL_SENSOR_DATA_CODING_NONE) {
01749         if (pDataFormat->frameLength == 0) {
01750             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01751             return ADMW_INVALID_PARAM ;
01752         }
01753         if (pDataFormat->numDataBits == 0) {
01754             ADMW_LOG_ERROR("Invalid frame length specified for digital sensor data format");
01755             return ADMW_INVALID_PARAM ;
01756         }
01757 
01758         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_READ_BYTES,
01759                             pDataFormat->frameLength - 1);
01760         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_DATA_BITS,
01761                             pDataFormat->numDataBits - 1);
01762         CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_CONFIG_DIGITAL_SENSOR_BIT_OFFSET,
01763                             pDataFormat->bitOffset);
01764 
01765         sensorConfigReg.Digital_Sensor_Read_Bytes = pDataFormat->frameLength - 1;
01766         sensorConfigReg.Digital_Sensor_Data_Bits = pDataFormat->numDataBits - 1;
01767         sensorConfigReg.Digital_Sensor_Bit_Offset = pDataFormat->bitOffset;
01768         sensorConfigReg.Digital_Sensor_Left_Aligned = pDataFormat->leftJustified ? 1 : 0;
01769         sensorConfigReg.Digital_Sensor_Little_Endian = pDataFormat->littleEndian ? 1 : 0;
01770 
01771         switch (pDataFormat->coding) {
01772             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_UNIPOLAR:
01773                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_UNIPOLAR;
01774                 break;
01775             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_TWOS_COMPLEMENT:
01776                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_TWOS_COMPL;
01777                 break;
01778             case ADMW1001_DIGITAL_SENSOR_DATA_CODING_OFFSET_BINARY:
01779                 sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_OFFSET_BINARY;
01780                 break;
01781             default:
01782                 ADMW_LOG_ERROR("Invalid coding specified for digital sensor data format");
01783                 return ADMW_INVALID_PARAM ;
01784         }
01785     } else {
01786         sensorConfigReg.Digital_Sensor_Coding = CORE_DIGITAL_SENSOR_CONFIG_CODING_NONE;
01787     }
01788 
01789     WRITE_REG_U16(hDevice, sensorConfigReg.VALUE16,
01790                   CORE_DIGITAL_SENSOR_CONFIGn(eChannelId));
01791 
01792 
01793     return ADMW_SUCCESS ;
01794 }
01795 
01796 static ADMW_RESULT  admw_SetDigitalCalibrationParam(
01797     ADMW_DEVICE_HANDLE  hDevice,
01798     ADMW1001_CH_ID  eChannelId,
01799     ADMW1001_DIGITAL_CALIBRATION_COMMAND  *pCalibrationParam)
01800 {
01801 //    ADMW_CORE_Calibration_Parameter_t calibrationParamReg;
01802 //
01803 //    calibrationParamReg.VALUE32 = REG_RESET_VAL(CORE_CALIBRATION_PARAMETERn);
01804 //
01805 //    if (pCalibrationParam->enableCalibrationParam == false)
01806 //        calibrationParamReg.Calibration_Parameter_Enable = 0;
01807 //    else
01808 //        calibrationParamReg.Calibration_Parameter_Enable = 1;
01809 //
01810 //    CHECK_REG_FIELD_VAL(CORE_CALIBRATION_PARAMETER_CALIBRATION_PARAMETER,
01811 //        pCalibrationParam->calibrationParam);
01812 //
01813 //    calibrationParamReg.Calibration_Parameter = pCalibrationParam->calibrationParam;
01814 //
01815 //    WRITE_REG_U32(hDevice, calibrationParamReg.VALUE32,
01816 //                  CORE_CALIBRATION_PARAMETERn(eChannelId));
01817 //
01818     return ADMW_SUCCESS ;
01819 }
01820 
01821 static ADMW_RESULT  admw_SetChannelI2cSensorType(
01822     ADMW_DEVICE_HANDLE  hDevice,
01823     ADMW1001_CH_ID  eChannelId,
01824     ADMW1001_I2C_SENSOR_TYPE  sensorType)
01825 {
01826     ADMW_CORE_Sensor_Type_t sensorTypeReg;
01827 
01828     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
01829 
01830     /* Ensure that the sensor type is valid for this channel */
01831     switch(sensorType) {
01832         case ADMW1001_I2C_SENSOR_HUMIDITY_A :
01833         case ADMW1001_I2C_SENSOR_HUMIDITY_B :
01834         case ADMW1001_I2C_SENSOR_TEMPERATURE_ADT742X :
01835             sensorTypeReg.Sensor_Type = sensorType;
01836             break;
01837         default:
01838             ADMW_LOG_ERROR("Unsupported I2C sensor type %d specified", sensorType);
01839             return ADMW_INVALID_PARAM ;
01840     }
01841 
01842     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
01843 
01844     return ADMW_SUCCESS ;
01845 }
01846 
01847 static ADMW_RESULT  admw_SetChannelI2cSensorAddress(
01848     ADMW_DEVICE_HANDLE  hDevice,
01849     ADMW1001_CH_ID  eChannelId,
01850     uint32_t deviceAddress)
01851 {
01852     CHECK_REG_FIELD_VAL(CORE_DIGITAL_SENSOR_ADDRESS_DIGITAL_SENSOR_ADDRESS, deviceAddress);
01853     WRITE_REG_U8(hDevice, deviceAddress, CORE_DIGITAL_SENSOR_ADDRESSn(eChannelId));
01854 
01855     return ADMW_SUCCESS ;
01856 }
01857 
01858 static ADMW_RESULT  admw_SetDigitalChannelComms(
01859     ADMW_DEVICE_HANDLE  hDevice,
01860     ADMW1001_CH_ID  eChannelId,
01861     ADMW1001_DIGITAL_SENSOR_COMMS  *pDigitalComms)
01862 {
01863     ADMW_CORE_Digital_Sensor_Comms_t digitalSensorComms;
01864 
01865     digitalSensorComms.VALUE16 = REG_RESET_VAL(CORE_DIGITAL_SENSOR_COMMSn);
01866 
01867     if(pDigitalComms->useCustomCommsConfig ) {
01868 
01869         if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_100K ) {
01870             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_100K;
01871         } else if(pDigitalComms->i2cClockSpeed  == ADMW1001_DIGITAL_SENSOR_COMMS_I2C_CLOCK_SPEED_400K ) {
01872             digitalSensorComms.I2C_Clock = CORE_DIGITAL_SENSOR_COMMS_I2C_400K;
01873         } else {
01874             ADMW_LOG_ERROR("Invalid I2C clock speed %d specified",
01875                            pDigitalComms->i2cClockSpeed );
01876             return ADMW_INVALID_PARAM ;
01877         }
01878 
01879         if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_0 ) {
01880             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_0;
01881         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_1 ) {
01882             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_1;
01883         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_2 ) {
01884             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_2;
01885         } else if(pDigitalComms->spiMode  == ADMW1001_DIGITAL_SENSOR_COMMS_SPI_MODE_3 ) {
01886             digitalSensorComms.SPI_Mode = CORE_DIGITAL_SENSOR_COMMS_SPI_MODE_3;
01887         } else {
01888             ADMW_LOG_ERROR("Invalid SPI mode %d specified",
01889                            pDigitalComms->spiMode );
01890             return ADMW_INVALID_PARAM ;
01891         }
01892 
01893         switch (pDigitalComms->spiClock ) {
01894             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_8MHZ :
01895                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_8MHZ;
01896                 break;
01897             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_4MHZ :
01898                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_4MHZ;
01899                 break;
01900             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_2MHZ :
01901                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_2MHZ;
01902                 break;
01903             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1MHZ :
01904                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1MHZ;
01905                 break;
01906             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_500KHZ :
01907                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_500KHZ;
01908                 break;
01909             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_250KHZ :
01910                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_250KHZ;
01911                 break;
01912             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_125KHZ :
01913                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_125KHZ;
01914                 break;
01915             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_62P5KHZ :
01916                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_62P5KHZ;
01917                 break;
01918             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_31P3KHZ :
01919                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_31P3KHZ;
01920                 break;
01921             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_15P6KHZ :
01922                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_15P6KHZ;
01923                 break;
01924             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_7P8KHZ :
01925                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_7P8KHZ;
01926                 break;
01927             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_3P9KHZ :
01928                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_3P9KHZ;
01929                 break;
01930             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_1P9KHZ :
01931                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_1P9KHZ;
01932                 break;
01933             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_977HZ :
01934                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_977HZ;
01935                 break;
01936             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_488HZ :
01937                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_488HZ;
01938                 break;
01939             case ADMW1001_DIGITAL_SENSOR_COMMS_SPI_CLOCK_244HZ :
01940                 digitalSensorComms.SPI_Clock = CORE_DIGITAL_SENSOR_COMMS_SPI_244HZ;
01941                 break;
01942             default:
01943                 ADMW_LOG_ERROR("Invalid SPI clock %d specified",
01944                                pDigitalComms->spiClock );
01945                 return ADMW_INVALID_PARAM ;
01946         }
01947     }
01948 
01949 
01950     WRITE_REG_U16(hDevice, digitalSensorComms.VALUE16, CORE_DIGITAL_SENSOR_COMMSn(eChannelId));
01951 
01952     return ADMW_SUCCESS ;
01953 }
01954 
01955 ADMW_RESULT  admw_SetI2cChannelConfig(
01956     ADMW_DEVICE_HANDLE  hDevice,
01957     ADMW1001_CH_ID  eChannelId,
01958     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
01959 {
01960     ADMW_RESULT  eRet;
01961     ADMW1001_I2C_CHANNEL_CONFIG  *pI2cChannelConfig =
01962         &pChannelConfig->i2cChannelConfig ;
01963 
01964     eRet = admw_SetChannelI2cSensorType(hDevice, eChannelId,
01965                                         pI2cChannelConfig->sensor );
01966     if (eRet != ADMW_SUCCESS ) {
01967         ADMW_LOG_ERROR("Failed to set I2C sensor type for channel %d",
01968                        eChannelId);
01969         return eRet;
01970     }
01971 
01972     eRet = admw_SetChannelI2cSensorAddress(hDevice, eChannelId,
01973                                            pI2cChannelConfig->deviceAddress );
01974     if (eRet != ADMW_SUCCESS ) {
01975         ADMW_LOG_ERROR("Failed to set I2C sensor address for channel %d",
01976                        eChannelId);
01977         return eRet;
01978     }
01979 
01980     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
01981             pChannelConfig);
01982     if (eRet != ADMW_SUCCESS ) {
01983         ADMW_LOG_ERROR("Failed to set I2C sensor details for channel %d",
01984                        eChannelId);
01985         return eRet;
01986     }
01987 
01988     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
01989                                        &pI2cChannelConfig->dataFormat );
01990     if (eRet != ADMW_SUCCESS ) {
01991         ADMW_LOG_ERROR("Failed to set I2C sensor data format for channel %d",
01992                        eChannelId);
01993         return eRet;
01994     }
01995 
01996     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
01997                                            &pI2cChannelConfig->digitalCalibrationParam );
01998     if (eRet != ADMW_SUCCESS ) {
01999         ADMW_LOG_ERROR("Failed to set I2C digital calibration param for channel %d",
02000                        eChannelId);
02001         return eRet;
02002     }
02003 
02004     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
02005                                        &pI2cChannelConfig->configureComms );
02006     if (eRet != ADMW_SUCCESS ) {
02007         ADMW_LOG_ERROR("Failed to set I2C comms for channel %d",
02008                        eChannelId);
02009         return eRet;
02010     }
02011 
02012     return ADMW_SUCCESS ;
02013 }
02014 
02015 static ADMW_RESULT  admw_SetChannelSpiSensorType(
02016     ADMW_DEVICE_HANDLE  hDevice,
02017     ADMW1001_CH_ID  eChannelId,
02018     ADMW1001_SPI_SENSOR_TYPE  sensorType)
02019 {
02020     ADMW_CORE_Sensor_Type_t sensorTypeReg;
02021 
02022     sensorTypeReg.VALUE16 = REG_RESET_VAL(CORE_SENSOR_TYPEn);
02023 
02024     /* Ensure that the sensor type is valid for this channel */
02025     switch(sensorType) {
02026         case ADMW1001_SPI_SENSOR_PRESSURE_A :
02027         case ADMW1001_SPI_SENSOR_ACCELEROMETER_A :
02028         case ADMW1001_SPI_SENSOR_ACCELEROMETER_B :
02029 
02030             sensorTypeReg.Sensor_Type = sensorType;
02031             break;
02032         default:
02033             ADMW_LOG_ERROR("Unsupported SPI sensor type %d specified", sensorType);
02034             return ADMW_INVALID_PARAM ;
02035     }
02036 
02037     WRITE_REG_U16(hDevice, sensorTypeReg.VALUE16, CORE_SENSOR_TYPEn(eChannelId));
02038 
02039     return ADMW_SUCCESS ;
02040 }
02041 
02042 ADMW_RESULT  admw_SetSpiChannelConfig(
02043     ADMW_DEVICE_HANDLE  hDevice,
02044     ADMW1001_CH_ID  eChannelId,
02045     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
02046 {
02047     ADMW_RESULT  eRet;
02048     ADMW1001_SPI_CHANNEL_CONFIG  *pSpiChannelConfig =
02049         &pChannelConfig->spiChannelConfig ;
02050 
02051     eRet = admw_SetChannelSpiSensorType(hDevice, eChannelId,
02052                                         pSpiChannelConfig->sensor );
02053     if (eRet != ADMW_SUCCESS ) {
02054         ADMW_LOG_ERROR("Failed to set SPI sensor type for channel %d",
02055                        eChannelId);
02056         return eRet;
02057     }
02058 
02059     eRet = admw_SetChannelDigitalSensorDetails(hDevice, eChannelId,
02060             pChannelConfig);
02061     if (eRet != ADMW_SUCCESS ) {
02062         ADMW_LOG_ERROR("Failed to set SPI sensor details for channel %d",
02063                        eChannelId);
02064         return eRet;
02065     }
02066 
02067     eRet = admw_SetDigitalSensorFormat(hDevice, eChannelId,
02068                                        &pSpiChannelConfig->dataFormat );
02069     if (eRet != ADMW_SUCCESS ) {
02070         ADMW_LOG_ERROR("Failed to set SPI sensor data format for channel %d",
02071                        eChannelId);
02072         return eRet;
02073     }
02074 
02075     eRet = admw_SetDigitalCalibrationParam(hDevice, eChannelId,
02076                                            &pSpiChannelConfig->digitalCalibrationParam );
02077     if (eRet != ADMW_SUCCESS ) {
02078         ADMW_LOG_ERROR("Failed to set SPI digital calibration param for channel %d",
02079                        eChannelId);
02080         return eRet;
02081     }
02082 
02083     eRet = admw_SetDigitalChannelComms(hDevice, eChannelId,
02084                                        &pSpiChannelConfig->configureComms );
02085     if (eRet != ADMW_SUCCESS ) {
02086         ADMW_LOG_ERROR("Failed to set SPI comms for channel %d",
02087                        eChannelId);
02088         return eRet;
02089     }
02090 
02091     return ADMW_SUCCESS ;
02092 }
02093 
02094 ADMW_RESULT  admw1001_SetChannelThresholdLimits(
02095     ADMW_DEVICE_HANDLE  hDevice,
02096     ADMW1001_CH_ID  eChannelId,
02097     float32_t fHighThresholdLimit,
02098     float32_t fLowThresholdLimit)
02099 {
02100     /*
02101      * If the low/high limits are *both* set to 0 in memory, or NaNs, assume
02102      * that they are unset, or not required, and use infinity defaults instead
02103      */
02104     if (fHighThresholdLimit == 0.0f && fLowThresholdLimit == 0.0f) {
02105         fHighThresholdLimit = INFINITY;
02106         fLowThresholdLimit = -INFINITY;
02107     } else {
02108         if (isnan(fHighThresholdLimit))
02109             fHighThresholdLimit = INFINITY;
02110         if (isnan(fLowThresholdLimit))
02111             fLowThresholdLimit = -INFINITY;
02112     }
02113 
02114     WRITE_REG_FLOAT(hDevice, fHighThresholdLimit,
02115                     CORE_HIGH_THRESHOLD_LIMITn(eChannelId));
02116     WRITE_REG_FLOAT(hDevice, fLowThresholdLimit,
02117                     CORE_LOW_THRESHOLD_LIMITn(eChannelId));
02118 
02119     return ADMW_SUCCESS ;
02120 }
02121 
02122 ADMW_RESULT  admw1001_SetOffsetGain(
02123     ADMW_DEVICE_HANDLE  hDevice,
02124     ADMW1001_CH_ID  eChannelId,
02125     float32_t fOffsetAdjustment,
02126     float32_t fGainAdjustment)
02127 {
02128     /* Replace with default values if NaNs are specified (or 0.0 for gain) */
02129     if (isnan(fGainAdjustment) || (fGainAdjustment == 0.0f))
02130         fGainAdjustment = 1.0f;
02131     if (isnan(fOffsetAdjustment))
02132         fOffsetAdjustment = 0.0f;
02133 
02134     WRITE_REG_FLOAT(hDevice, fGainAdjustment, CORE_SENSOR_GAINn(eChannelId));
02135     WRITE_REG_FLOAT(hDevice, fOffsetAdjustment, CORE_SENSOR_OFFSETn(eChannelId));
02136 
02137     return ADMW_SUCCESS ;
02138 }
02139 
02140 ADMW_RESULT  admw1001_SetSensorParameter(
02141     ADMW_DEVICE_HANDLE  hDevice,
02142     ADMW1001_CH_ID  eChannelId,
02143     float32_t fSensorParam)
02144 {
02145     if (fSensorParam == 0.0f)
02146         fSensorParam = NAN;
02147 
02148     //WRITE_REG_FLOAT(hDevice, fSensorParam, CORE_SENSOR_PARAMETERn(eChannelId));
02149 
02150     return ADMW_SUCCESS ;
02151 }
02152 
02153 ADMW_RESULT  admw1001_SetChannelSettlingTime(
02154     ADMW_DEVICE_HANDLE  hDevice,
02155     ADMW1001_CH_ID  eChannelId,
02156     uint32_t nSettlingTime)
02157 {
02158     ADMW_CORE_Settling_Time_t settlingTimeReg;
02159 
02160     CHECK_REG_FIELD_VAL(CORE_SETTLING_TIME_SETTLING_TIME, nSettlingTime);
02161     settlingTimeReg.Settling_Time = nSettlingTime;
02162 
02163     WRITE_REG_U16(hDevice, settlingTimeReg.VALUE16, CORE_SETTLING_TIMEn(eChannelId));
02164 
02165     return ADMW_SUCCESS ;
02166 }
02167 
02168 ADMW_RESULT  admw1001_SetChannelConfig(
02169     ADMW_DEVICE_HANDLE  hDevice,
02170     ADMW1001_CH_ID  eChannelId,
02171     ADMW1001_CHANNEL_CONFIG  *pChannelConfig)
02172 {
02173     ADMW_RESULT  eRet;
02174 
02175     if (! ADMW1001_CHANNEL_IS_VIRTUAL(eChannelId)) {
02176         eRet = admw1001_SetChannelCount(hDevice, eChannelId,
02177                                         pChannelConfig->enableChannel  ?
02178                                         pChannelConfig->measurementsPerCycle  : 0);
02179         if (eRet != ADMW_SUCCESS ) {
02180             ADMW_LOG_ERROR("Failed to set measurement count for channel %d",
02181                            eChannelId);
02182             return eRet;
02183         }
02184 
02185         eRet = admw1001_SetChannelOptions(hDevice, eChannelId,
02186                                           pChannelConfig->priority );
02187         if (eRet != ADMW_SUCCESS ) {
02188             ADMW_LOG_ERROR("Failed to set priority for channel %d",
02189                            eChannelId);
02190             return eRet;
02191         }
02192 
02193         /* If the channel is not enabled, we can skip the following steps */
02194         if (pChannelConfig->enableChannel ) {
02195             eRet = admw1001_SetChannelSkipCount(hDevice, eChannelId,
02196                                                 pChannelConfig->cycleSkipCount );
02197             if (eRet != ADMW_SUCCESS ) {
02198                 ADMW_LOG_ERROR("Failed to set cycle skip count for channel %d",
02199                                eChannelId);
02200                 return eRet;
02201             }
02202 
02203             switch (eChannelId) {
02204                 case ADMW1001_CH_ID_ANLG_1_UNIVERSAL :
02205                 case ADMW1001_CH_ID_ANLG_2_UNIVERSAL :
02206                 case ADMW1001_CH_ID_ANLG_1_DIFFERENTIAL :
02207                 case ADMW1001_CH_ID_ANLG_2_DIFFERENTIAL :
02208                     eRet = admw_SetAdcChannelConfig(hDevice, eChannelId, pChannelConfig);
02209                     break;
02210                 case ADMW1001_CH_ID_DIG_I2C_0 :
02211                 case ADMW1001_CH_ID_DIG_I2C_1 :
02212                     eRet = admw_SetI2cChannelConfig(hDevice, eChannelId, pChannelConfig);
02213                     break;
02214                 case ADMW1001_CH_ID_DIG_SPI_0 :
02215                     eRet = admw_SetSpiChannelConfig(hDevice, eChannelId, pChannelConfig);
02216                     break;
02217                 default:
02218                     ADMW_LOG_ERROR("Invalid channel ID %d specified", eChannelId);
02219                     eRet = ADMW_INVALID_PARAM ;
02220 #if 0
02221                     /* when using i2c sensors there is an error ( dataformat->length=0)
02222                     the code below catches this error and this causes further problems.*/
02223                     break;
02224             }
02225             if (eRet != ADMW_SUCCESS ) {
02226                 ADMW_LOG_ERROR("Failed to set config for channel %d",
02227                                eChannelId);
02228                 return eRet;
02229 #endif
02230             }
02231 
02232             eRet = admw1001_SetChannelSettlingTime(hDevice, eChannelId,
02233                                                    pChannelConfig->extraSettlingTime );
02234             if (eRet != ADMW_SUCCESS ) {
02235                 ADMW_LOG_ERROR("Failed to set settling time for channel %d",
02236                                eChannelId);
02237                 return eRet;
02238             }
02239         }
02240     }
02241 
02242     if (pChannelConfig->enableChannel ) {
02243         /* Threshold limits can be configured individually for virtual channels */
02244         eRet = admw1001_SetChannelThresholdLimits(hDevice, eChannelId,
02245                 pChannelConfig->highThreshold ,
02246                 pChannelConfig->lowThreshold );
02247         if (eRet != ADMW_SUCCESS ) {
02248             ADMW_LOG_ERROR("Failed to set threshold limits for channel %d",
02249                            eChannelId);
02250             return eRet;
02251         }
02252 
02253         /* Offset and gain can be configured individually for virtual channels */
02254         eRet = admw1001_SetOffsetGain(hDevice, eChannelId,
02255                                       pChannelConfig->offsetAdjustment ,
02256                                       pChannelConfig->gainAdjustment );
02257         if (eRet != ADMW_SUCCESS ) {
02258             ADMW_LOG_ERROR("Failed to set offset/gain for channel %d",
02259                            eChannelId);
02260             return eRet;
02261         }
02262 
02263         /* Set sensor specific parameter */
02264         eRet = admw1001_SetSensorParameter(hDevice, eChannelId,
02265                                            pChannelConfig->sensorParameter );
02266         if (eRet != ADMW_SUCCESS ) {
02267             ADMW_LOG_ERROR("Failed to set sensor parameter for channel %d",
02268                            eChannelId);
02269             return eRet;
02270         }
02271     }
02272 
02273     return ADMW_SUCCESS ;
02274 }
02275 
02276 ADMW_RESULT  admw_SetConfig(
02277     ADMW_DEVICE_HANDLE     const hDevice,
02278     ADMW_CONFIG          * const pConfig)
02279 {
02280     ADMW1001_CONFIG  *pDeviceConfig;
02281     ADMW_PRODUCT_ID  productId;
02282     ADMW_RESULT  eRet;
02283 
02284     if (pConfig->productId  != ADMW_PRODUCT_ID_ADMW1001 ) {
02285         ADMW_LOG_ERROR("Configuration Product ID (0x%X) is not supported (0x%0X)",
02286                        pConfig->productId , ADMW_PRODUCT_ID_ADMW1001 );
02287         return ADMW_INVALID_PARAM ;
02288     }
02289 
02290     if (!((pConfig->versionId .major ==VERSIONID_MAJOR) &&
02291             (pConfig->versionId .minor ==VERSIONID_MINOR))) {
02292         ADMW_LOG_ERROR("Configuration Version ID (0x%X) is not supported",
02293                        pConfig->versionId );
02294         return ADMW_INVALID_PARAM ;
02295     }
02296 
02297 
02298     /* Check that the actual Product ID is a match? */
02299     eRet = admw_GetProductID(hDevice, &productId);
02300     if (eRet) {
02301         ADMW_LOG_ERROR("Failed to read device Product ID register");
02302         return eRet;
02303     }
02304     if (pConfig->productId  != productId) {
02305         ADMW_LOG_ERROR("Configuration Product ID (0x%X) does not match device (0x%0X)",
02306                        pConfig->productId , productId);
02307         return ADMW_INVALID_PARAM ;
02308     }
02309 
02310     pDeviceConfig = &pConfig->admw1001 ;
02311 
02312     eRet = admw1001_SetPowerConfig(hDevice, &pDeviceConfig->power );
02313     if (eRet) {
02314         ADMW_LOG_ERROR("Failed to set power configuration");
02315         return eRet;
02316     }
02317 
02318     eRet = admw1001_SetMeasurementConfig(hDevice, &pDeviceConfig->measurement );
02319     if (eRet) {
02320         ADMW_LOG_ERROR("Failed to set measurement configuration");
02321         return eRet;
02322     }
02323 
02324     eRet = admw1001_SetDiagnosticsConfig(hDevice, &pDeviceConfig->diagnostics );
02325     if (eRet) {
02326         ADMW_LOG_ERROR("Failed to set diagnostics configuration");
02327         return eRet;
02328     }
02329 
02330     for (ADMW1001_CH_ID  id = ADMW1001_CH_ID_ANLG_1_UNIVERSAL ;
02331             id < ADMW1001_MAX_CHANNELS ;
02332             id++) {
02333         eRet = admw1001_SetChannelConfig(hDevice, id,
02334                                          &pDeviceConfig->channels [id]);
02335         if (eRet) {
02336             ADMW_LOG_ERROR("Failed to set channel %d configuration", id);
02337             return eRet;
02338         }
02339     }
02340 
02341     return ADMW_SUCCESS ;
02342 }
02343 
02344 ADMW_RESULT  admw1001_SetLutData(
02345     ADMW_DEVICE_HANDLE    const hDevice,
02346     ADMW1001_LUT       * const pLutData)
02347 {
02348     ADMW1001_LUT_HEADER *pLutHeader = &pLutData->header;
02349     ADMW1001_LUT_TABLE  *pLutTable = pLutData->tables;
02350 
02351     unsigned actualLength = 0;
02352 
02353     if (pLutData->header.signature != ADMW_LUT_SIGNATURE) {
02354         ADMW_LOG_ERROR("LUT signature incorrect (expected 0x%X, actual 0x%X)",
02355                        ADMW_LUT_SIGNATURE, pLutHeader->signature);
02356         return ADMW_INVALID_SIGNATURE ;
02357     }
02358     if ((pLutData->tables->descriptor.geometry!= ADMW1001_LUT_GEOMETRY_NES_1D) &&
02359             (pLutData->tables->data.lut1dNes.nElements > MAX_LUT_NUM_ENTRIES)) {
02360         return ADMW_INVALID_PARAM ;
02361     }
02362     for (unsigned i = 0; i < pLutHeader->numTables; i++) {
02363         ADMW1001_LUT_DESCRIPTOR *pDesc = &pLutTable->descriptor;
02364         ADMW1001_LUT_TABLE_DATA  *pData = &pLutTable->data;
02365         unsigned short calculatedCrc;
02366 
02367         switch (pDesc->geometry) {
02368             case ADMW1001_LUT_GEOMETRY_COEFFS:
02369                 switch (pDesc->equation) {
02370                     case ADMW1001_LUT_EQUATION_POLYN:
02371                     case ADMW1001_LUT_EQUATION_POLYNEXP:
02372                     case ADMW1001_LUT_EQUATION_QUADRATIC:
02373                     case ADMW1001_LUT_EQUATION_STEINHART:
02374                     case ADMW1001_LUT_EQUATION_LOGARITHMIC:
02375                     case ADMW1001_LUT_EQUATION_BIVARIATE_POLYN:
02376                         break;
02377                     default:
02378                         ADMW_LOG_ERROR("Invalid equation %u specified for LUT table %u",
02379                                        pDesc->equation, i);
02380                         return ADMW_INVALID_PARAM ;
02381                 }
02382                 break;
02383             case ADMW1001_LUT_GEOMETRY_NES_1D:
02384                 break;
02385             default:
02386                 ADMW_LOG_ERROR("Invalid geometry %u specified for LUT table %u",
02387                                pDesc->geometry, i);
02388                 return ADMW_INVALID_PARAM ;
02389         }
02390 
02391         switch (pDesc->dataType) {
02392             case ADMW1001_LUT_DATA_TYPE_FLOAT32:
02393             case ADMW1001_LUT_DATA_TYPE_FLOAT64:
02394                 break;
02395             default:
02396                 ADMW_LOG_ERROR("Invalid vector format %u specified for LUT table %u",
02397                                pDesc->dataType, i);
02398                 return ADMW_INVALID_PARAM ;
02399         }
02400 
02401         calculatedCrc = admw_crc16_ccitt(pData, pDesc->length);
02402         if (calculatedCrc != pDesc->crc16) {
02403             ADMW_LOG_ERROR("CRC validation failed on LUT table %u (expected 0x%04X, actual 0x%04X)",
02404                            i, pDesc->crc16, calculatedCrc);
02405             return ADMW_CRC_ERROR ;
02406         }
02407 
02408         actualLength += sizeof(*pDesc) + pDesc->length;
02409 
02410         /* Move to the next look-up table */
02411         pLutTable = (ADMW1001_LUT_TABLE *)((uint8_t *)pLutTable + sizeof(*pDesc) + pDesc->length);
02412     }
02413 
02414     if (actualLength != pLutHeader->totalLength) {
02415         ADMW_LOG_ERROR("LUT table length mismatch (expected %u, actual %u)",
02416                        pLutHeader->totalLength, actualLength);
02417         return ADMW_WRONG_SIZE ;
02418     }
02419 
02420     if (sizeof(*pLutHeader) + pLutHeader->totalLength > ADMW_LUT_MAX_SIZE) {
02421         ADMW_LOG_ERROR("Maximum LUT table length (%u bytes) exceeded",
02422                        ADMW_LUT_MAX_SIZE);
02423         return ADMW_WRONG_SIZE ;
02424     }
02425 
02426     /* Write the LUT data to the device */
02427     unsigned lutSize = sizeof(*pLutHeader) + pLutHeader->totalLength;
02428     WRITE_REG_U16(hDevice, 0, CORE_LUT_OFFSET);
02429     WRITE_REG_U8_ARRAY(hDevice, (uint8_t *)pLutData, lutSize, CORE_LUT_DATA);
02430 
02431     return ADMW_SUCCESS ;
02432 }
02433 ADMW_RESULT  admw1001_SetLutDataRaw(
02434     ADMW_DEVICE_HANDLE     const hDevice,
02435     ADMW1001_LUT_RAW   * const pLutData)
02436 {
02437     return admw1001_SetLutData(hDevice,
02438                                (ADMW1001_LUT *)pLutData);
02439 }
02440 
02441 static ADMW_RESULT  getLutTableSize(
02442     ADMW1001_LUT_DESCRIPTOR * const pDesc,
02443     ADMW1001_LUT_TABLE_DATA  * const pData,
02444     unsigned *pLength)
02445 {
02446     switch (pDesc->geometry) {
02447         case ADMW1001_LUT_GEOMETRY_COEFFS:
02448             if (pDesc->equation == ADMW1001_LUT_EQUATION_BIVARIATE_POLYN)
02449                 *pLength = ADMW1001_LUT_COEFF_LIST_SIZE(pData->coeffList);
02450             break;
02451         case ADMW1001_LUT_GEOMETRY_NES_1D:
02452             *pLength = ADMW1001_LUT_1D_NES_SIZE(pData->lut1dNes);
02453             break;
02454         default:
02455             ADMW_LOG_ERROR("Invalid LUT table geometry %d specified\r\n",
02456                            pDesc->geometry);
02457             return ADMW_INVALID_PARAM ;
02458     }
02459 
02460     return ADMW_SUCCESS ;
02461 }
02462 
02463 ADMW_RESULT  admw1001_AssembleLutData(
02464     ADMW1001_LUT                  * pLutBuffer,
02465     unsigned                              nLutBufferSize,
02466     unsigned                        const nNumTables,
02467     ADMW1001_LUT_DESCRIPTOR * const ppDesc[],
02468     ADMW1001_LUT_TABLE_DATA  * const ppData[])
02469 {
02470     ADMW1001_LUT_HEADER *pHdr = &pLutBuffer->header;
02471     uint8_t *pLutTableData = (uint8_t *)pLutBuffer + sizeof(*pHdr);
02472 
02473     if (sizeof(*pHdr) > nLutBufferSize) {
02474         ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02475         return ADMW_INVALID_PARAM ;
02476     }
02477 
02478     /* First initialise the top-level header */
02479     pHdr->signature = ADMW_LUT_SIGNATURE;
02480     pHdr->version.major = 1;
02481     pHdr->version.minor = 0;
02482     pHdr->numTables = 0;
02483     pHdr->totalLength = 0;
02484 
02485     /*
02486      * Walk through the list of table pointers provided, appending the table
02487      * descriptor+data from each one to the provided LUT buffer
02488      */
02489     for (unsigned i = 0; i < nNumTables; i++) {
02490         ADMW1001_LUT_DESCRIPTOR * const pDesc = ppDesc[i];
02491         ADMW1001_LUT_TABLE_DATA  * const pData = ppData[i];
02492         ADMW_RESULT  res;
02493         unsigned dataLength = 0;
02494 
02495         /* Calculate the length of the table data */
02496         res = getLutTableSize(pDesc, pData, &dataLength);
02497         if (res != ADMW_SUCCESS )
02498             return res;
02499 
02500         /* Fill in the table descriptor length and CRC fields */
02501         pDesc->length = dataLength;
02502         pDesc->crc16 = admw_crc16_ccitt(pData, dataLength);
02503 
02504         if ((sizeof(*pHdr) + pHdr->totalLength + sizeof(*pDesc) + dataLength) > nLutBufferSize) {
02505             ADMW_LOG_ERROR("Insufficient LUT buffer size provided");
02506             return ADMW_INVALID_PARAM ;
02507         }
02508 
02509         /* Append the table to the LUT buffer (desc + data) */
02510         memcpy(pLutTableData + pHdr->totalLength, pDesc, sizeof(*pDesc));
02511         pHdr->totalLength += sizeof(*pDesc);
02512         memcpy(pLutTableData + pHdr->totalLength, pData, dataLength);
02513         pHdr->totalLength += dataLength;
02514 
02515         pHdr->numTables++;
02516     }
02517 
02518     return ADMW_SUCCESS ;
02519 }