ADISense1000 Version 2.1 code base

Fork of AdiSense1000_V21 by Sean Wilson

doc/key_topics.md

Committer:
RGurav
Date:
2018-09-18
Revision:
33:640b6bebda17
Parent:
28:4eb837cd71df

File content as of revision 33:640b6bebda17:

Key Topics
==========

[TOC]

# Register Interface {#registerinterface}
The ADSNS1000 module provides a register-style interface for the purpose
of exchanging configuration, status, and data with the host application
processor.

## Overview {#registerinterface_overview}
The registers can be divided broadly into the following categories:
* Command input register
  - This special register is used to issue commands to the module.
  - Commands are issued to tell the ADSNS1000 what operation is required.
  - New commands are typically ignored until the running command has completed
    (as indicated via the Status registers).
* Configuration input registers
  - Configuration registers are used to specify the required configuration
    parameters for use by the module, typically specifying details such as
    operating mode, sensor information, measurement thresholds, and many other
    options.
  - Changes to configuration input registers are typically ignored until a
    command is issued to "apply" the configuration on the device.
* Status output registers
  - Status information is provided by the ADSNS1000 module via these read-only
    registers.
  - Dedicated output signals (e.g. ERROR and ALERT) are linked with this status
    information.
  - The host application processor may acknowledge and reset/clear the status
    indicators by reading the relevant status registers.  The status indicators
    will be set again if the underlying condition is present.
* Data output registers
  - Measurement data samples produced by the ADSNS1000 are accessed via a
    FIFO-style register which may be read repeatedly until all available data
    has been consumed.
  - Data samples are provided in a pre-determined format according to the
    measurement command selected.
  - When a CONVERT command is issued the output spans 5 bytes and is comprised
    of the 32 bit floating point measurement result and a byte of status
    information.
  - When a CONVERT\_WITH\_RAW command is issued the output spans 8 bytes and is
    comprised of the 32 bit floating point measurement result, a byte of status
    information and 3 bytes of raw uncompensated data sample retrieved from the
    sensor input channel.
  - Status information provided with the measurement result indicate the channel
    number and indicate ALERT or ERROR conditions.
* Keyhole access registers
  - Access to large internal memory regions within the module is typically
    provided via a pair of "keyhole" registers, consisting of an address
    register and a data register.
  - An address (i.e. a starting offset within the region) must first be written
    to the address register, then the companion data register may be accessed
    repeatedly to read/write data to the corresponding region.  The address is
    automatically incremented with each access to the data register, so that
    data can be transferred in a single burst for efficiency.

# Configuration {#configuration}
The ADSNS1000 module is a flexible measurement module which must be configured
via the [register interface](@ref registerinterface) before it can be used to
acquire and process data from external sensor inputs.

## Overview {#configuration_overview}
A configuration consists of the following elements:
* Global configuration register settings, such as:
  - Operating modes
  - Power modes
  - Measurement cycle times
  - External reference options
* Channel-specific register settings, such as:
  - measurement count
  - sensor type
  - sensor configuration details
  - settling time
  - filter options
  - threshold limits
  - calibration adjustments
* Measurement Correction data
  - used to compensate for the non-linear characteristics of analog
    sensors/transducers
  - supplied via a Look-Up Table data structure with a specific format
  - ADSNS1000 provides the complete sensor measurement solution for custom
    sensors - excitation, measurement and correction

## Configuration data structure {#configuration_data}
Although the module can be configured and managed directly via the
[register interface](@ref registerinterface), the ADISENSE Host Library
provides a level of abstraction above this which allows a more simplified
programming paradigm between the Host processor and the ADSNS1000 module.

A single C-language configuration data structure can be used to define all
configuration values for the ADSNS1000 module. This can be passed to the
relevant ADISENSE Host Library API functions, which will do the work of
translating the configuration details into the appropriate register values and
sending them to the ADSNS1000 module via its host SPI communication interface.

Individual configurations are stored and compiled as .c files and a
configuration may be selected and loaded by the application code.  Note that
only the essential configuration fields are filled, depending on the specific
sensor configuration and operating mode required.

## Loading and Applying a configuration {#configuration_loading}
Configuration data must first be loaded via the @ref adi_sense_SetConfig API
function. This function updates the registers on the ADSNS1000 module according
to the supplied configuration details. The new configuration is then activated
by calling the @ref adi_sense_ApplyConfigUpdates function. This function issues
a special command to instruct the module to apply the new configuration.  If
user-defined linearisation data is also required, this must also be loaded via
the @ref adi_sense_1000_SetLutData function _before_ applying the new
configuration.

To avoid loading the configuration details to the module every time it is
powered on, it is possible to save the configuration to non-volatile memory
on the module using @ref adi_sense_SaveConfig and @ref adi_sense_SaveLutData.
The saved configuration is automatically restored by default when the module is
subsequently reset or power cycled. This configuration can be reloaded on demand
if required using the @ref adi_sense_RestoreConfig and @ref
adi_sense_RestoreLutData functions.  Note that, in all cases, @ref
adi_sense_ApplyConfigUpdates _must_ be called to instruct the module to
apply/activate the configuration before it will be used.

Once a valid configuration has been loaded and applied, the user may issue
commands to the ADSNS1000 module to initiate measurement cycles, internal
calibration, or diagnostic routines (all of which depend on a valid
configuration being applied in advance).

## Configuration errors {#configuration_errors}
Attempts to load invalid configuration details will be flagged via the relevant
status registers and signals.  After calling @ref adi_sense_ApplyConfigUpdates,
it is advisable to check the status of the module by calling @ref
adi_sense_GetStatus and examining the relevant status information returned from
the module.  Subsequent commands issued to the module may not execute correctly
in the presence of unresolved configuration errors.

# Measurement Cycles {#measurementcycles}
## Overview {#measurementcycles_overview}
Conversions are carried out sequentially across each of the enabled channels in
a predictable pattern which has a defined order and user-specified number of
conversions per channel.  This is typically referred to as the _Measurement
Sequence_.

A _Measurement Cycle_ essentially consists of a single _Measurement Sequence_
which may be repeated at specified time intervals.

The configuration parameters required to define the Measurement Cycle and
Sequence are as follows:
* Cycle interval time (specified in microseconds/milliseconds/seconds)
* For each enabled sensor input channel:
  - Number of conversions-per-cycle
  - Extra settling time (specified in microseconds)

In addition to the cycle time, the following operating modes dictate when and
how many cycles should be executed:
* **Single-Cycle Mode**
  - Executes a single Measurement Cycle and stops
* **Continuous Mode**
  - Executes Measurement Cycles continuously until stopped by the host
    application processor
* **Multi-Cycle Mode**
  - Executes a specified number (burst) of Measurement Cycles and stores the
    results in a buffer for retrieval by the host.
  - Repeats this indefinitely at specified intervals (multi-cycle burst
    interval) until stopped by the host application processor.

## Executing Measurement Cycles {#measurementcycles_executing}
Once a valid configuration is loaded (see @ref configuration),
Measurement Cycles are initiated by the host application processor via @ref
adi_sense_StartMeasurement, and may be stopped if necessary via @ref
adi_sense_StopMeasurement.  These functions issue the relevant commands to the
ADSNS1000 module via its dedicate command register.

Certain auxiliary tasks may also be carried out internally by the module on a
per-cycle basis, such as Calibration and Diagnostics.  These are discussed in
in later sections below.

## Sequence Order {#measurementcycles_sequence}
The sequence is constructed according to a number of configurable parameters:
- which channels are enabled
- number of measurements to be performed per channel
- channel priorities
- cycle type selection

When the selected cycle type is @ref ADI_SENSE_1000_CYCLE_TYPE_FULL,
the full number of requested measurements is carried out on a channel before
advancing to the next channel in the sequence.  Channels are visited in
priority/ascending order.

When the selected cycle type is @ref ADI_SENSE_1000_CYCLE_TYPE_SWITCH,
the arrangement is similar to round-robin scheduling - a measurement is carried
out on each enabled channel, in priority/ascending channel order, and then the
loop is repeated until the requested number of measurements on each channel has
been satisfied.

By default, channels are arranged in the measurement sequence based on ascending
order of channel ID.  However, a priority-level may be specified per channel to
force a different ordering of the channels, with higher-priority channels
appearing before lower-priority channels. Channels with equal priority are
ordered by ascending order of channel ID.  Lower numbers indicate higher
priority, with 0 being the highest.

For example, lets say channels [0, 3, 4, 5] are enabled, with cycleType as @ref
ADI_SENSE_1000_CYCLE_TYPE_SWITCH, and measurementsPerCycle and priority
(0=highest) set as follows:

channelId | priority | measurementsPerCycle
--------- | -------- | --------------------
    CJC_1 | 1        | 4
 SENSOR_0 | 2        | 2
    I2C_1 | 0        | 3
    SPI_0 | 2        | 1

The length of the sequence would be 10 measurements in total, and the order in
which the channel measurements appear in the sequence would look like this:

| **I2C_1** | **CJC_1** | **SENSOR_0** | **SPI_0** | **I2C_1** | **CJC_1** | **SENSOR_0** | **I2C_1** | **CJC_1** | **CJC_1** |

When measurement data samples are retrieved from the ADISENSE by the host
application, this is the order in which those data samples will appear.

Changing the cycleType to @ref ADI_SENSE_1000_CYCLE_TYPE_FULL in the example above
would generate the following sequence:

| **I2C_1** | **I2C_1** | **I2C_1** | **CJC_1** | **CJC_1** | **CJC_1** | **CJC_1** | **SENSOR_0** | **SENSOR_0** | **SPI_0** |

The ADSNS1000 module has 11 measurement ports; however, when ADXL used on the
SPI port this equates to 3 measurements. The ADSNS1000 allows for a maximum of
128 measurementsPerCycle. Therefore a single cycle can produce a maximum of 1664
measurements. In other words, the maximum length of the sequence is 1664.

## Sequence Timing {#measurementcycles_timing}
The timing of each measurement within the sequence depends on a number of
factors:
* **Settling time**
  - A settling time is applied when switching between each channel (unless there
    is only a single channel in the sequence), particularly to allow the analog
    front-end circuit to settle before a conversion is performed.
  - Each channel is subject to a minimum settling time (as specified in the
    ADSNS1000 datasheet)
  - Additional settling time can be configured per-channel if required
  - As the analog sensor channels are multiplexed into the ADC, with each
    channel potentially having a different front-end circuit depending on the
    sensor type selected, the settling and conversion of the analog channels
    must be done one-at-a-time in series.  Their settling time starts only when
    the channel is reached in the sequence.
  - Digital sensors operate independently, and so are activated in parallel to
    other sensors.  Consequently, their settling time may start at the start of
    a cycle, or immediately after a previous conversion result has been obtained
    from the digital sensor.
* **Conversion time**
  - Once the settling time has passed, a conversion is initiated to obtain a raw
    measurement value from the sensor input.
  - The time required for the conversion may be influenced by factors such as
    filter configuration (in the case of analog channels) or specific digital
    sensor performance characteristics and configuration options.
* **Processing time**
  - Once the raw conversion result is obtained, it is subjected to further
    processing to apply correction for non-linear sensors, calibration
    adjustments, and conversion into final measurement units
  - The processing time varies depending on the sensor type and correction
    algorithms to be applied, but a standard budget of processing time (as
    specified in the ADSNS1000 datasheet) is allocated to each channel to
    produce consistent and predictable time separation between the channel
    measurement results.

So, to summarise, the distinct phases for each measurement on each channel
typically look like this:

**settling** > **conversion** > **processing** > **publishing**

Taking the sequence example in the previous section, let's assume a base
settling time (_Ts_) and processing time (_Tp_) of 500 microseconds for each
channel and the following variable timing parameters _Te_ and _Tc_ (in units of
microseconds):

channelId | extraSettlingTime (_Te_) | conversionTime (_Tc_) | sum (_Ts_ + _Te_ + _Tc_ + _Tp_) | measurementsPerCycle | total
--------- | ------------------------ | --------------------- | ------------------------------- | -------------------- | -----
    CJC_1 | 4000                     | 50000                 | 55000                           | 4                    | 220000
 SENSOR_0 | 1000                     | 50000                 | 52000                           | 2                    | 104000
    I2C_1 | 20000                    | 1000                  | 22000                           | 3                    | 66000
    SPI_0 | 0                        | 800                   | 1800                            | 1                    | 1800

To clarify: _Te_ above comes directly from the channel configuration.  _Tc_,
however, is dictated by the sensor and its configuration.

The minimum time required for the cycle to complete is, in the above example,
391800 microseconds.

If the selected operating mode is Continuous or Multi-Cycle mode, the
configuration must also specify the interval between successive cycles
(cycleInterval).   If this is less than the actual time required to
complete the cycle, the next cycle will start immediately after the
completion of the previous one; if it is more, there will be a delay
until the next cycle is started.

## Measurement Results storage and retrieval {#measurementcycles_publishing}
As part of module configuration, a data-ready mode must be selected to indicate
how measurements results are made available and retained for consumption by the
host application processor:

* **Per-Conversion**
  - In this mode, each measurement result is made available as soon as it is
    ready.
  - Only a single result is stored, and it is overwritten when the next
    measurement result becomes ready.  Only the latest result is retained.
  - The host application processor must consume each  measurement result (by
    reading the DATA_FIFO register) as soon as the result becomes available. The
    availability of each result is identified by a DRDY rising edge.
* **Per-Cycle**
  - In this mode, the measurement results from a full cycle (10 data samples, in
    the example above) are made available only when the measurement cycle is
    complete.
  - The results are overwritten when the next measurement cycle (if any) is
    completed.
  - The host application processor must consume the measurement results in a
    batch as soon as they become available.
* **Per-Multicycle-Burst**
  - In this mode, the measurement results from a burst of measurement cycles are
    made available only when the measurement cycles are completed.
  - The results are overwritten when the next burst of measurement cycles are
    completed.
  - The host application processor must consume the measurement results in a
    batch as soon as they become available.
  - Note that this data-ready mode is only available when the Multi-Cycle
    operating mode is also selected.

When new measurement results are ready for retrieval, the DRDY output signal
is asserted.  The host application may check this signal continuously, or attach
an interrupt notification to this signal, to ensure that measurement results are
retrieved in a timely fashion before they are subsequently overwritten by the
next conversion/cycle.  Alternatively, the host application may also read the
STATUS register to check the DRDY status indicator.

The ADISENSE Host Library API provides the following functions which are
relevant for data retrieval:
* @ref adi_sense_RegisterGpioCallback for receiving DRDY interrupt notifications
* @ref adi_sense_GetGpioState for polling the state of the DRDY signal
* @ref adi_sense_GetStatus for reading the module status registers
* @ref adi_sense_GetData for retrieving the measurement results from the module

The @ref adi_sense_1000_GetDataReadyModeInfo API function, specific to the
ADSNS1000, is useful for obtaining information on the number of measurement
results to expect when the DRDY indicator is asserted, based on the operating
and data-ready mode configuration settings currently set in the ADSNS1000 module
registers.

# Calibration {#calibration}
The ADSNS1000 module incorporates a number of calibration measures to ensure
the accuracy of measurement results, described in the following sections.  These
mostly pertain to the analog measurement channels, but some provisions are also
included for calibration of digital sensors.

## Factory calibration {#calibration_factory}
Calibration is performed during factory production for removal of errors
introduced by components (e.g. resistors, switches) present on the signal paths
of the module's analog front-end.  Calibration offset and gain values are
calculated and stored in non-volatile memory within the module as part of the
production process.  These are applied automatically without intervention from
the host application.

## Internal auto-calibration {#calibration_internal}
The high-accuracy ADC incorporated within the ADSNS1000 module includes internal
calibration functions to assist in removing offset or gain errors internal to
that ADC.  As this is a time-consuming process, it is invoked only in the
following circumstances:
* The host application issues a self-calibration command (@ref
  adi_sense_RunCalibration)
* The host application updates the module configuration and the module
  determines, based on the configuration changes, that re-calibration is
  required.  In this case, the calibration is carried out at the point where the
  new configuration settings are applied (@ref adi_sense_ApplyConfigUpdates)

In all cases, a valid configuration must be set and is used as part of the
calibration process.  External sensors and reference circuits must be
connected for calibration to work correctly.

## User calibration {#calibration_user}
Additional gain and offset correction parameters may be specified per-channel as
part of the module configuration.  These are applied as a final step to each
measurement result from the channel during the final stages of processing before
the data sample is made available to the host processor.

# Diagnostics {#diagnostics}
The ADC within the ADSNS1000 module includes a range of sophisticated diagnostic
features to automatically detect error conditions such as under-/over-voltage on
analog input signals, supply voltage errors, reference detection errors and more
as detailed in the ADSNS1000 Datasheet.  These diagnostics are enabled by
default and, if triggered, will result in an ERROR or ALERT signal being
asserted by the module.  Diagnostic status can be queried via the module status
registers (@ref adi_sense_GetStatus).

Additional diagnostic tests may be executed by the module to detect additional
error conditions such as a disconnected or mis-wired sensor.  These tests can be
time-consuming, and so are carried out only if selected by the user:
* Sensor diagnostics may be requested by executing a dedicated diagnostics
  command (@ref adi_sense_RunDiagnostics)
* Sensor diagnostics may be optionally executed at the start of each measurement
  cycle, at a frequency determined by the user through the configuration
  parameters (see @ref ADI_SENSE_1000_DIAGNOSTICS_CONFIG)

# Sensor Linearisation {#linearisation}
Analog sensors can produce an output which may not be completely linear or
directly proportional with respect to their input.  Different sensor types
generally have different linearity characteristics, each requiring different
correction methods or coefficients for accurate translation of the sensor output
back to the corresponding input.  Typical methods include use of linearisation
formulae (e.g. polynomial equations with variable coefficients), or tables of
sample input values and their corresponding outputs which can be used with
interpolation to perform the translation.

The ADSNS1000 module performs linearisation and calibration correction of the
analog sensor measurements, and incorporates the linearisation functions
complete with coefficients or translation tables for a range of supported sensor
types.  On the ADSNS1000 module, for example, measurement results from any
[sensor types](@ref ADI_SENSE_1000_ADC_SENSOR_TYPE) named with the "_L1" suffix
will be automatically linearised using built-in linearisation functions and
coefficients or translation tables.

It is also possible to have ADSNS1000 perform linearisation on other custom
sensor types.  A range of [sensor type IDs](@ref ADI_SENSE_1000_ADC_SENSOR_TYPE)
named with an "_L2" suffix are reserved for this purpose.  By specifying one of
these sensor types, and by providing the necessary linearisation information for
that sensor type as part of a "look-up table" data structure loaded via the @ref
adi_sense_1000_SetLutData API function, the ADSNS1000 module can be extended to
work with sensor variants which require a different linearisation than what is
already provided through built-in methods. Linearisation data may be provided
in the form of a coefficient list for a polynomial equation, or as a translation
table, depending on what is most appropriate for that sensor.

Translation tables can be expressed in a number of formats, such as 1- or
2-Dimensional tables, with equally- or non-equally-spaced vectors.  2-D tables
are used where the sensor output is affected by both the sensor input and
another factor such as the operating temperature of the sensor itself.  If the
sensor output values can be captured for an equally-spaced set of input values
(i.e. values separated by a constant increment, such as 3,6,9,12,etc.), the
equally-spaced table formats allow for a more compact representation as only the
output values need to be listed individually.

Multiple coefficient lists can be specified for a given sensor type, along with
an applicable range of input values, as it may be necessary to apply different
equations depending on the input range.  For example, RTD sensors feature a
different linearity curve for input ranges above/below 0 degrees Celsius.

The ADSNS1000 module allows a flexible look-up table (LUT) data structure up to
a [maximum size](@ref ADI_SENSE_LUT_MAX_SIZE) to be loaded by the user for use
with custom "L2" sensor types.  The LUT data structure format, defined as @ref
ADI_SENSE_1000_LUT, allows for a variable set of tables of different formats
to be included as part of the overall data structure.  Each table is preceeded
by a descriptor which specifies the format of the following table.  A single
top-level header at the start of the LUT specifies how many tables are contained
within.  The LUT structure basically looks like this:

    |---------------------|
    | top-level header    |
    |---------------------|
    | table #0 descriptor |
    | table #0 data       |
    |---------------------|
    | table #1 descriptor |
    | table #1 data       |
    |---------------------|
             ~~~
    |---------------------|
    | table #N descriptor |
    | table #N data       |
    |---------------------|

To cater for this flexibility, the data structure definition can appear to be
complex. To absorb some of this complexity, a supplementary API function named
@ref adi_sense_1000_AssembleLutData is provided. By providing a list of
pointers to descriptors and data elements for each table to be included in the
LUT structure, along with buffer of allocated memory, this function constructs
the top-level header and appends each table and also fills some fields within
the table descriptors (e.g. length, CRC).  Please refer to the "user_lut_data"
application example for an illustration of how this function can be used.