# Hardware synchronization (FSYNC)

FSYNC hardware synchronization aligns sensor capture through a shared electrical trigger instead of matching messages later in
software. It remains the most direct way to minimize capture skew between supported cameras and devices.

### Principles and theory

FSYNC hardware synchronization aligns capture from a shared electrical trigger instead of aligning frames later in software. This
is real frame synchronization: participating sensors use the same trigger event as the basis for exposure timing, so FSYNC aligns
start of exposure by default.

### When to use it

Use FSYNC when:

 * the deployment needs the tightest possible frame alignment
 * cameras or devices can share a physical trigger connection
 * hardware wiring is acceptable and more important than network flexibility

### Support and constraints

Continuous FSYNC expects a stable trigger cadence that matches the configured sensor FPS, while snapshot triggering is
sensor-dependent. Rolling shutter sensors can participate in continuous synchronization, but their exposure timing still needs to
be interpreted using the [timing fundamentals](https://docs.luxonis.com/hardware/platform/deploy/data-sync.md) rather than assumed
to behave like global shutter capture.

FSYNC is the highest-accuracy synchronization option. Use the [PTP
synchronization](https://docs.luxonis.com/hardware/platform/deploy/data-sync/ptp-sync.md) page instead when the deployment needs
Ethernet-based clock distribution and shared trigger wiring is impractical.

#### RVC2

### RVC2 implementation

Series 2 / RVC2 hardware sync uses the FSYNC or FSIN signal and allows precise synchronization, typically below 10 microseconds,
across multiple camera sensors and potentially with other hardware such as flash LEDs, external IMUs, or other cameras. Classic
Series 2 FSYNC operates at 1.8V sensor logic, while some newer M8-equipped variants expose a 5V-triggered external interface.

### FSYNC signal

FSYNC/FSIN (frame sync) is a pulse driven high at the start of each frame capture. Its pulse width is not proportional to exposure
time. It can operate as either an input or an output.

On stereo cameras such as OAK-D, the stereo pair is kept in sync by configuring one monochrome sensor as FSYNC `INPUT` and the
other as FSYNC `OUTPUT`, so one sensor drives the other directly.

> **FSYNC signal output**
> At the moment, only OV9282 and OV9782 can output FSYNC. IMX378, IMX477, IMX577, and similar sensors are currently supported only as FSYNC inputs, even though the hardware should also be capable of output in the future. AR0234 supports input-only FSYNC triggering.

#### Synchronizing frames externally

To drive Series 2 cameras from an outside signal source, configure the participating sensors to use FSIN as `INPUT`.

All Series 2 OAK PoE models expose FSIN and STROBE through the M8 I/O connector. The [FSYNC Y-Adapter](hw-catalog://FSYNC
Y-Adapter) can be used to daisy-chain multiple cameras together.

```py
# Example: we have 3 cameras on ports A, B, and C
cam_A.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
cam_B.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
cam_C.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
```

You can also control the FSIN line via GPIO from within the
[Script](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/script.md) node; see [this
example](https://gist.github.com/Erol444/a9189a8215371ff9f4cf4472960e1d66).

#### Sensor FSYNC support

Only some sensors support FSYNC-based synchronization. There are two relevant operating modes:

 * Continuous streaming with external syncing, configured with `CameraControl.setFrameSyncMode()`. In this mode, the FSIN signal
   is expected to arrive continuously at a rate matching the configured sensor FPS. It can only correct for small amounts of drift
   over time.
 * Snapshot mode with external syncing, configured with `CameraControl.setExternalTrigger()`. In this mode, triggers can arrive at
   arbitrary times and the sensor captures a photo or snapshot when triggered.

| Sensor | Shutter | Support |
| --- | --- | --- |
| [OV9282](sensor://OV9282), [OV9782](sensor://OV9782) | Global | FSYNC input/output, both continuous mode and snapshot triggering
are supported |
| [OV7251](sensor://OV7251) | Global | Expected to have the same hardware support as OV9*82, but not implemented in firmware yet |
| [AR0234](sensor://AR0234) | Global | FSYNC input, continuous mode, and snapshot triggering are supported |
| [IMX378](sensor://IMX378), [IMX477](sensor://IMX477), [IMX577](sensor://IMX577), IMX380 | Rolling | FSYNC input; only continuous
mode is supported for rolling shutter sensors. Hardware FSYNC output is not implemented in firmware yet |
| [IMX582](sensor://IMX582) | Rolling | Similar to IMX378, but not yet tested |
| IMX296 (RPi GS Camera) | Global | Arbitrary external trigger is supported on XTR or XTRIG, and pulse length determines exposure
time |

#### External FSYNC example

#### Older devices

Here is an example of using an external FSYNC signal to trigger camera sensors. Any Series 2 OAK-D PoE model can be used to
generate the trigger; the example setup uses an M8 breakout board to expose GND and FSYNC.

In [this example](https://gist.github.com/Erol444/0138af63378dc8de5b3f7d80db1ea1a5), sensors were configured in `Snapshot mode`,
because the signal was triggered with a switch button. Only the stereo cameras (2x OV9282) were triggered by the button, since
IMX378 color does not support snapshot mode. If the color sensor were OV9782 instead, it could also be triggered this way.

#### Newer devices

Devices that use the newer M8 connector, such as [OAK-D ToF](hw-catalog://OAK-D ToF), expect a 5V trigger signal.

By default, pin 2 on the M8 connector (FSYNC) is pulled high internally. When the pin remains high, frames stream continuously
while the camera is in either `INPUT` or `OUTPUT` mode. To trigger frames externally, pull the pin low, for example to pin 8
`GND`, to stop streaming, then pull it high again to restart streaming.

This lets you send 5V pulses to the FSYNC pin to trigger frame capture.

> **FSYNC triggering**
> Only global shutter sensors such as OV9282, OV9782, and AR0234 support FSYNC photo or snapshot triggering. Rolling shutter sensors such as IMX378, IMX477, and IMX577 do not support snapshot triggering.

### STROBE signal

STROBE is an output from the image sensor that remains high during exposure. It can be used to drive external illumination so that
lights are only active during exposure rather than continuously, which reduces power consumption and heating.

Luxonis uses STROBE on Pro variants of OAK cameras to drive the onboard IR LED and IR laser dot projector.

### STROBE demo

Cameras with the M8 connector can drive external lighting from STROBE, as demonstrated here:

### OAK-FFC hardware syncing

On [OAK-FFC-4P](hw-catalog://OAK-FFC 4P), there are four camera ports: A (RGB), B (left), C (right), and D (`cam_d`). A and D are
4-lane MIPI, while B and C are 2-lane MIPI. Each pair shares an I2C bus, and the B/C bus is configured for left-right hardware
sync by default.

For A and D ports, hardware syncing needs to be enabled explicitly:

```py
cam_A.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.OUTPUT)
cam_D.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
```

### Arducam FFC camera syncing

Arducam FFC cameras use a 22-pin connector, which does not carry FSIN or STROBE. To connect them to the OAK-FFC baseboard, a
26-to-22 pin converter is needed, and that adapter exposes FSIN/STROBE only through test pads. To sync these cameras, either
solder a wire from the test pad to the module FSIN header pin, or tie the FSIN header pins together, as shown in [this forum
discussion](https://discuss.luxonis.com/d/934-ffc-4p-hardware-synchronization/3).

### Connecting FSIN and STROBE

As noted above, Series 2 OAK PoE models expose FSYNC and STROBE through the M8 I/O connector. If you are not using that connector,
you will likely need to solder to the device PCB directly. Most board designs are open-source in the external `oak-hardware`
repository: https://github.com/luxonis/oak-hardware

### OAK-FFC-4P FSIN

On [OAK-FFC-4P](hw-catalog://OAK-FFC 4P), `FSIN_4LANE` and `FSIN_2LANE` can be connected through `MXIO6`. The script below
synchronizes all four attached cameras.

```python
# CAM_A will drive FSIN signal for all other cameras:
cam_A.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT) # 4LANE
cam_B.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.OUTPUT) # 2LANE
cam_C.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT) # 2LANE
cam_D.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT) # 4LANE

# AND importantly to tie the FSIN signals of A+D and B+C pairs, by setting a GPIO:
# OAK-FFC-4P requires driving MXIO6 high (FSIN_MODE_SELECT) to connect together
# the A+D FSIN group (4-lane pair) with the B+C group (2-lane pair)
config = dai.Device.Config()
config.board.gpio[6] = dai.BoardConfig.GPIO(dai.BoardConfig.GPIO.OUTPUT,
                                            dai.BoardConfig.GPIO.Level.HIGH)

with dai.Device(config) as device:
    device.startPipeline(pipeline)
```

Additional background is available in [the same forum
discussion](https://discuss.luxonis.com/d/934-ffc-4p-hardware-synchronization/3).

> **CAM_B and CAM_C**
> CAM_B and CAM_C share the same 2-lane MIPI I2C bus. If both ports have the same FFC sensor connected, they stay in sync regardless of additional settings because the `start exposure` I2C command reaches both sensors at the same time. This is the same mechanism used to keep the stereo pair in sync on OAK-D devices.

### Series 2 USB OAKs

FSIN lines on the DM9098 board used by [OAK-D S2](hw-catalog://OAK-D S2), [OAK-D W](hw-catalog://OAK-D W), [OAK-D
Pro](hw-catalog://OAK-D Pro), and [OAK-D Pro W](hw-catalog://OAK-D Pro W):

### USB OAK-1* FSIN

FSIN test pad on the NG9093 board used by [OAK-1](hw-catalog://OAK-1), [OAK-1 W](hw-catalog://OAK-1 W), [OAK-1
Lite](hw-catalog://OAK-1 Lite), [OAK-1 Lite W](hw-catalog://OAK-1 Lite W), and [OAK-1 Max](hw-catalog://OAK-1 Max):

### OAK-D-Lite FSIN

Note that the stereo pair and color camera are not connected together on OAK-D-Lite.

#### RVC4

### RVC4 implementation

OAK4 hardware sync uses the FSYNC line on supported devices and is the most accurate way to align frame capture across multiple
cameras. This is real frame sync: devices capture from a shared electrical trigger rather than being aligned later in software.

Use hardware FSYNC when:

 * you need the tightest synchronization accuracy
 * devices are close enough to share a physical sync line
 * the deployment is small enough that FSYNC daisy-chaining remains practical

For supported M8-equipped devices, the [FSYNC Y-Adapter](hw-catalog://FSYNC Y-Adapter) is the simplest way to distribute the
trigger signal between devices. For connector details, see [OAK4 M8
interface](https://docs.luxonis.com/hardware/platform/deploy/oak4-m8-interface.md).

On RVC4, only the continuous streaming FSYNC workflow is currently enabled. Unlike RVC2, which supports both continuous streaming
and snapshot mode on supported sensors, RVC4 does not currently expose snapshot-triggered FSYNC operation.

There are two ways to trigger external FSYNC on OAK4 devices:

### External FSYNC signal from another OAK device

Daisy-chain the devices so one OAK acts as the FSYNC Master while the others run in FSYNC Slave mode. For the full wiring and
setup details, see the [FSYNC Y-Adapter guide](hw-catalog://FSYNC Y-Adapter).

### External FSYNC Signal from Function Generator

Drive FSYNC from an external signal source. OAK4 devices require a 5V trigger signal. For the full wiring and setup details, see
the [FSYNC Y-Adapter guide](hw-catalog://FSYNC Y-Adapter).

### Minimal examples

PTP sync and external FSYNC use the same `depthai-core` examples. For external FSYNC, run them with the `--external-sync` flag:

 * [Python multi-device frame sync
   example](https://github.com/luxonis/depthai-core/blob/main/examples/python/Misc/MultiDevice/multi_device_frame_sync.py)
 * [C++ multi-device frame sync
   example](https://github.com/luxonis/depthai-core/blob/main/examples/cpp/Misc/MultiDevice/multi_device_frame_sync.cpp)
