com.qualcomm.robotcore.hardware

## Interface I2cDeviceSynch

- All Superinterfaces:
    Engagable, HardwareDevice, HardwareDeviceHealth, I2cAddrConfig, I2cAddressableDevice, I2cDeviceSynchSimple, RobotConfigNameable
  All Known Implementing Classes:
    I2cDeviceSynchImpl, I2cDeviceSynchImplOnSimple

      public interface I2cDeviceSynch
      extends I2cDeviceSynchSimple, Engagable

  `I2cDeviceSynch` is an interface that exposes functionality for interacting with I2c devices. Its methods are synchronous, in that they complete their action before returning to the caller.

  Methods are provided to read and write data simply and straightforwardly. Singleton bytes or larger quantities of data can be read or written using `read8()` and `write8()` or `read()` and `write()` respectively. No attention to 'read mode' or 'write mode' is required. Simply call reads and writes as you need them, and the right thing happens.

  For devices that automatically shutdown if no communication is received within a certain duration, a heartbeat facility is optionally provided.

  On causality: regarding the sequencing of reads and writes, two important points are worthy of mention. First, reads and writes are ultimately issued to the controller in the same chronological order they were received by the device client instance. Second, even more importantly, reads *always* see the effect of preceding writes on the controller. That is, a read that follows a write will ensure that, first, the write gets issued to the controller, and then, second, a read from the controller is subsequently issued. By contrast, absent such constraints, a read might quickly return freshly-read data already present without having to interact with the controller. Which brings us to...

  Reading data. The simplest way to read data is to call one of the variations of the `read()` method. This is always correct, and will return data as accessed from the I2c device. However, in many situations, reads can be significantly optimized by use of a read window. With a read window, a larger chunk of the device's I2c register space can be automatically read even if only a portion of it is needed to service a particular read() call; this can make subsequent read()s significantly faster. Further, depending on the mode of `ReadWindow` used, read operations will occur in the background, and read()s will be serviced (subject to causality) out of cached data updated and maintained by the background processing without any synchronous communication with the I2c device itself. For sensors in particular, this mode of operation can be particularly advantageous.

  Three modes of `ReadWindow` are available:

  1. `REPEAT`. In this mode, background reads are always scheduled and cached data updated whenever there's no other (writing) work to do. This is the mode commonly used by sensors, who mostly execute reads and only issue a write relatively infrequently.
  2. `BALANCED`. In this mode, background reads are also performed, but only if the user initiates a manual read first after a write operation. The object does not automatically start background reads on its own, as the transition from writing to reading can be a relatively expensive one. This mode can be useful for objects like motor and servo controllers which exhibit a balanced mix of both write and read operations
  3. `ONLY_ONCE`. In this mode, no background reading is performed; data is always retrieved with a synchronous communication to the i2c device.

  An `I2cDeviceSynch` has only one read window in effect at any particular time. This can be updated with `setReadWindow(ReadWindow)` or `ensureReadWindow()`. When a read() is made, if the registers requested therein are contained within the current read window, then that whole window of data is read from the i2c device (if the cache is out of date) and the appropriate portion thereof returned. In contrast, if the requested registers are not so contained, then, in effect, a one-off `ONLY_ONCE` is used without disturbing the window maintained by `setReadWindow(ReadWindow)`.

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Interface and Description
    --- | ---
    `static class` | `I2cDeviceSynch.HeartbeatAction` Instances of HeartBeatAction indicate what action to carry out to perform a heartbeat should that become necessary.
    `static class` | `I2cDeviceSynch.ReadMode` `I2cDeviceSynch.ReadMode` controls whether when asked to read we read only once or read multiple times.
    `static class` | `I2cDeviceSynch.ReadWindow` RegWindow is a utility class for managing the window of I2C register bytes that are read from our I2C device on every hardware cycle

    - ### Nested classes/interfaces inherited from interface com.qualcomm.robotcore.hardware.HardwareDeviceHealth

      `HardwareDeviceHealth.HealthStatus`

    - ### Nested classes/interfaces inherited from interface com.qualcomm.robotcore.hardware.HardwareDevice

      `HardwareDevice.Manufacturer`

  - ### Method Summary

    All Methods Instance Methods Abstract Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `ensureReadWindow(I2cDeviceSynch.ReadWindow windowNeeded, I2cDeviceSynch.ReadWindow windowToSet)` Ensure that the current register window covers the indicated set of registers.
    `I2cDeviceSynch.HeartbeatAction` | `getHeartbeatAction()` Returns the current action, if any, to take upon expiration of the heartbeat interval.
    `int` | `getHeartbeatInterval()` Returns the interval within which communication must be received by the I2C device lest a timeout occur.
    `I2cDeviceSynch.ReadWindow` | `getReadWindow()` Returns the current register window used for reading.
    `TimestampedData` | `readTimeStamped(int ireg, int creg, I2cDeviceSynch.ReadWindow readWindowNeeded, I2cDeviceSynch.ReadWindow readWindowSet)` Advanced: Atomically calls ensureReadWindow() with the last two parameters and then readTimeStamped() with the first two without the possibility of a concurrent client interrupting in the middle.
    `void` | `setHeartbeatAction(I2cDeviceSynch.HeartbeatAction action)` Sets the action to take when the current heartbeat interval expires.
    `void` | `setHeartbeatInterval(int ms)` Sets the interval within which communication must be received by the I2C device lest a timeout may occur.
    `void` | `setReadWindow(I2cDeviceSynch.ReadWindow window)` Set the set of registers that we will read and read and read again on every hardware cycle

    - ### Methods inherited from interface com.qualcomm.robotcore.hardware.I2cDeviceSynchSimple

      `enableWriteCoalescing, getI2cAddr, getLogging, getLoggingTag, isArmed, isWriteCoalescingEnabled, read, read8, readTimeStamped, setI2cAddr, setLogging, setLoggingTag, waitForWriteCompletions, write, write, write8, write8`

    - ### Methods inherited from interface com.qualcomm.robotcore.hardware.HardwareDeviceHealth

      `getHealthStatus, setHealthStatus`

    - ### Methods inherited from interface com.qualcomm.robotcore.hardware.I2cAddrConfig

      `setI2cAddress`

    - ### Methods inherited from interface com.qualcomm.robotcore.hardware.I2cAddressableDevice

      `getI2cAddress`

    - ### Methods inherited from interface com.qualcomm.robotcore.hardware.RobotConfigNameable

      `getUserConfiguredName, setUserConfiguredName`

    - ### Methods inherited from interface com.qualcomm.robotcore.hardware.HardwareDevice

      `close, getConnectionInfo, getDeviceName, getManufacturer, getVersion, resetDeviceConfigurationForOpMode`

    - ### Methods inherited from interface com.qualcomm.robotcore.hardware.Engagable

      `disengage, engage, isEngaged`

- - ### Method Detail

    - #### setReadWindow

          void setReadWindow(I2cDeviceSynch.ReadWindow window)

      Set the set of registers that we will read and read and read again on every hardware cycle
      Parameters:
        `window` - the register window to read. May be null, indicating that no reads are to occur.
      See Also:
        `getReadWindow()`

    - #### getReadWindow

          I2cDeviceSynch.ReadWindow getReadWindow()

      Returns the current register window used for reading.
      Returns:
        the current read window
      See Also:
        `setReadWindow(ReadWindow)`

    - #### ensureReadWindow

          void ensureReadWindow(I2cDeviceSynch.ReadWindow windowNeeded,
                                I2cDeviceSynch.ReadWindow windowToSet)

      Ensure that the current register window covers the indicated set of registers. If there is currently a non-null register window, and windowNeeded is non-null, and the current register window entirely contains windowNeeded, then do nothing. Otherwise, set the current register window to windowToSet.
      Parameters:
        `windowNeeded` - Test the current register window, if any, against this window to see if an update to the current register window is needed in order to cover it. May be null, indicating that an update to the current register window is always needed
        `windowToSet` - If an update to the current register window is needed, then this is the window to which it will be set. May be null.
      See Also:
        `setReadWindow(ReadWindow)`, `I2cDeviceSynchSimple.read8(int)`

    - #### readTimeStamped

          TimestampedData readTimeStamped(int ireg,
                                          int creg,
                                          I2cDeviceSynch.ReadWindow readWindowNeeded,
                                          I2cDeviceSynch.ReadWindow readWindowSet)

      Advanced: Atomically calls ensureReadWindow() with the last two parameters and then readTimeStamped() with the first two without the possibility of a concurrent client interrupting in the middle.
      Parameters:
        `ireg` - the register number of the first byte register to read
        `creg` - the number of bytes / registers to read
        `readWindowNeeded` - the read window we require
        `readWindowSet` - the read window to set if the required read window is not current
      Returns:
        the data that was read, together with the timestamp
      See Also:
        `ensureReadWindow(ReadWindow, ReadWindow)`, `I2cDeviceSynchSimple.readTimeStamped(int, int)`

    - #### setHeartbeatInterval

          void setHeartbeatInterval(int ms)

      Sets the interval within which communication must be received by the I2C device lest a timeout may occur. The default heartbeat interval is zero, signifying that no heartbeat is maintained.
      Parameters:
        `ms` - the new hearbeat interval, in milliseconds
      See Also:
        `getHeartbeatInterval()`

    - #### getHeartbeatInterval

          int getHeartbeatInterval()

      Returns the interval within which communication must be received by the I2C device lest a timeout occur.
      Returns:
        the current heartbeat interval, in milliseconds
      See Also:
        `setHeartbeatInterval(int)`

    - #### setHeartbeatAction

          void setHeartbeatAction(I2cDeviceSynch.HeartbeatAction action)

      Sets the action to take when the current heartbeat interval expires. The default action is null; thus, to be useful, an action must always be explicitly specified.
      Parameters:
        `action` - the action to take at each heartbeat.
      See Also:
        `getHeartbeatAction()`, `setHeartbeatInterval(int)`

    - #### getHeartbeatAction

          I2cDeviceSynch.HeartbeatAction getHeartbeatAction()

      Returns the current action, if any, to take upon expiration of the heartbeat interval.
      Returns:
        the current heartbeat action. May be null
      See Also:
        `setHeartbeatAction(HeartbeatAction)`