ICM-456xx FIFO and Interupt Configuration and Usage

By admin , 17 February 2026

# Purpose and Context

This document shows how to configure the ICM-456xx to assert an interrupt when 2 samples are stored in the FIFO. This procedure has been tested with ICM-45686-S, and should also work for ICM-45605(-S) and ICM-45686, and other ICM-456xx variants.

# Hardware Setup

In this example, the MCU 4-wire SPI bus is wired to the ICM-456xx, and the **INT1** interrupt pin will be configured as push-pull. The code below is written in Micropython v1.25.0.

# Initialize the SPI Bus, Interrupt Line, and Sensor

We configure our MCU's SPI bus and interrupt as follows:

``` python
MCU_config_interrupts(MCU_INT_PIN=28) # configure our MCU to watch pin#28 for falling-edge interrupt
icm456xx = instantiate_icm456xx_spi(csv_logfile) # create icm456xx object on SPI bus
icm456xx.reset()
icm456xx.ireg_write(IPREG_TOP1+0x67, 0x02) # set big endian format to match datasheet - see register SREG_CTRL
```

SPI transactions:

```         
SPI-Write,addr: 0x7F,data: 0x02
SPI-Write,addr: 0x7C,data: 0xA2 0x67 0x02
```

# Configure Sensor Before Enabling

### ODR and FSR

First we configure the sensor FSR and ODR for 4g and 500dps at 12.5Hz:

``` python
icm456xx.gyro_setup(ODR=12.5, FSR=500)
icm456xx.accel_setup(ODR=12.5, FSR=4)
```

SPI transactions:

```         
SPI-Write,addr: 0x1C,data: 0x3C
SPI-Write,addr: 0x1B,data: 0x3C
```

### FIFO Config and IMU Timestamp

Next we configure the FIFO to store accel/gyro data, STOP-ON-FULL mode (FIFO stops storing samples once full) and we enable the IMU timestamp

``` python
icm456xx.write(0x21, 0b111) # Configure FIFO_CONFIG3 register so FIFO stores accel and gyro data
icm456xx.write(0x1D, 0b10000111) # FIFO_CONFIG0 - set FIFO to STOP-ON-FULL mode, 2kByte depth
icm456xx.ireg_write(IPREG_TOP1+0x58, 0x60|0b1) # SMC_CONTROL_0 - enable timestamp via TMST_FSYNC_EN=1 (bit 1)
```

SPI Transactions:

```         
SPI-Write,addr: 0x21,data: 0x07
SPI-Write,addr: 0x1D,data: 0x87
SPI-Write,addr: 0x7C,data: 0xA2 0x58 0x61
```

### INT1 Behavior and FIFO Interrupt Conditions

Set the FIFO to assert an interupt on **INT1** if the FIFO watermark is tripped after **FIFO_WM_TH**=2 samples, and configure **INT1** as push-pull/active low.

``` python
FIFO_WM_TH=2 # FIFO watermark = 2 samples

icm456xx.write(0x16, 0b010) # INT1_CONFIG0 - INT1_STATUS_EN_FIFO_THS - interrupt on FIFO watermark
icm456xx.write(0x18, 0b010) # INT1_CONFIG2 - push-pull, latch mode, active low
icm456xx.ireg_write(IPREG_TOP1+0x69, 0x00) # INT_PULSE_MIN_ON_INTF0 - set interrupt pulse 100us
       
icm456xx.write(0x1E, FIFO_WM_TH&0xFF) # FIFO_CONFIG1_0 - FIFO_WM_TH[7:0]
icm456xx.write(0x1F, (FIFO_WM_TH>>8) ) # FIFO_CONFIG1_1 - FIFO_WM_TH[15:8]
icm456xx.write(0x20, 0x20 | 0b1000) # FIFO_CONFIG2 - interrupt when FIFO_WM <= FIFO_COUNT by setting FIFO_WR_WM_GT_TH=1
icm456xx.write(0x22, 0b00000010) # FIFO_CONFIG4 - enable timestamp via FIFO_TMST_FSYNC_EN (bit 2)
```

SPI Transactions:

```         
SPI-Write,addr: 0x16,data: 0x02
SPI-Write,addr: 0x18,data: 0x02
SPI-Write,addr: 0x7C,data: 0xA2 0x69 0x00
SPI-Write,addr: 0x1E,data: 0x02
SPI-Write,addr: 0x1F,data: 0x00
SPI-Write,addr: 0x20,data: 0x28
SPI-Write,addr: 0x22,data: 0x02
```

# Enable Sensor and Read Data

Now we enable the accel/gyro ADCs, and read \~2 seconds worth of data

``` python
icm456xx.write(0x10, 0b1111) # PWR_MGMT0 - enable
sleep(0.1) # accel/gyro warmup time
icm456xx.FIFO_flush() # clear all samples in FIFO
```

SPI transactions:

```         
SPI-Write,addr: 0x10,data: 0x0F
SPI-Write,addr: 0x20,data: 0xA8
```

### Main Read Loop

The following block of code outputs two seconds of sensor data. The code waits for an interrupt on INT1, reads two samples from the FIFO, then waits for the next interrupt.

``` python
T_STOPPING = INT1_time+2e6 # stopping time = 2 seconds (2e6 microseconds) from "now" (time of most revent INT1 event)
while(INT1_time<T_STOPPING):
   if (INT1_event==False):
       # INT1_event hasn't happened yet, so skip code below
       continue

   # INT1_event just happened, so read from FIFO
   FIFO_READ_SINGLE_SAMPLE = icm456xx.read(0x12, 18, MCU_timestamp=INT1_time)
   IMU_data_parsed = parse_IMU_FIFO_packet(FIFO_READ_SINGLE_SAMPLE, FIFO_COUNT=True)
   FIFO_READ_SINGLE_SAMPLE = icm456xx.read(0x12, 18, MCU_timestamp=INT1_time)
   IMU_data_parsed = parse_IMU_FIFO_packet(FIFO_READ_SINGLE_SAMPLE, FIFO_COUNT=True)
   
   INT1_event=False # set INT1_event flag=False, to indicate this interrupt has been serviced.  now: wait for next INT1
```

SPI transactions:

```         
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x84 0xFF 0x10 0x20 0x2B 0x00 0x0F 0xFF 0xFC 0x00 0x01 0xFE 0x78 0xEE,MCU_time_us=303193933
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x7D 0xFF 0x10 0x20 0x34 0x00 0x0F 0xFF 0xFD 0x00 0x01 0xFE 0xB1 0x6E,MCU_time_us=303193933
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x83 0xFF 0x0F 0x20 0x33 0x00 0x0F 0xFF 0xFC 0x00 0x03 0xFE 0xE9 0xEE,MCU_time_us=303353304
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x80 0xFF 0x11 0x20 0x34 0x00 0x10 0xFF 0xFC 0x00 0x02 0xFE 0x22 0x6E,MCU_time_us=303353304
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x81 0xFF 0x10 0x20 0x33 0x00 0x0F 0xFF 0xFC 0x00 0x02 0xFE 0x5A 0xEE,MCU_time_us=303512621
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x80 0xFF 0x10 0x20 0x34 0x00 0x10 0xFF 0xFC 0x00 0x01 0xFE 0x93 0x6E,MCU_time_us=303512621
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x82 0xFF 0x0D 0x20 0x36 0x00 0x0F 0xFF 0xFC 0x00 0x02 0xFE 0xCB 0xEE,MCU_time_us=303671964
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x81 0xFF 0x0F 0x20 0x36 0x00 0x10 0xFF 0xFD 0x00 0x03 0xFE 0x04 0x6E,MCU_time_us=303671964
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x81 0xFF 0x0F 0x20 0x35 0x00 0x0F 0xFF 0xFA 0x00 0x02 0xFE 0x3C 0xEE,MCU_time_us=303831255
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x81 0xFF 0x0F 0x20 0x35 0x00 0x0E 0xFF 0xFB 0x00 0x02 0xFE 0x75 0x6E,MCU_time_us=303831255
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x7F 0xFF 0x0F 0x20 0x37 0x00 0x0F 0xFF 0xFB 0x00 0x02 0xFE 0xAD 0xEE,MCU_time_us=303990588
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x80 0xFF 0x0F 0x20 0x35 0x00 0x0F 0xFF 0xFB 0x00 0x03 0xFE 0xE6 0x6E,MCU_time_us=303990588
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x7D 0xFF 0x0C 0x20 0x37 0x00 0x0F 0xFF 0xFC 0x00 0x02 0xFD 0x1E 0xEE,MCU_time_us=304150035
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x85 0xFF 0x0F 0x20 0x36 0x00 0x10 0xFF 0xFB 0x00 0x03 0xFE 0x57 0x6E,MCU_time_us=304150035
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x7F 0xFF 0x0F 0x20 0x38 0x00 0x10 0xFF 0xFB 0x00 0x03 0xFE 0x8F 0xEE,MCU_time_us=304309241
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x83 0xFF 0x11 0x20 0x32 0x00 0x0F 0xFF 0xFC 0x00 0x02 0xFD 0xC8 0x6E,MCU_time_us=304309241
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x80 0xFF 0x0E 0x20 0x3A 0x00 0x0E 0xFF 0xFC 0x00 0x03 0xFE 0x00 0xEE,MCU_time_us=304468562
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x81 0xFF 0x0D 0x20 0x35 0x00 0x0E 0xFF 0xFB 0x00 0x03 0xFE 0x39 0x6E,MCU_time_us=304468562
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x81 0xFF 0x11 0x20 0x3A 0x00 0x0F 0xFF 0xFC 0x00 0x03 0xFE 0x71 0xEE,MCU_time_us=304627865
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x83 0xFF 0x11 0x20 0x35 0x00 0x0F 0xFF 0xFB 0x00 0x02 0xFE 0xAA 0x6E,MCU_time_us=304627865
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x7F 0xFF 0x0A 0x20 0x37 0x00 0x10 0xFF 0xFC 0x00 0x02 0xFE 0xE2 0xEE,MCU_time_us=304787234
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x7F 0xFF 0x0F 0x20 0x3A 0x00 0x0E 0xFF 0xFB 0x00 0x03 0xFE 0x1B 0x6E,MCU_time_us=304787234
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x80 0xFF 0x0D 0x20 0x37 0x00 0x10 0xFF 0xFC 0x00 0x02 0xFE 0x53 0xEE,MCU_time_us=304946517
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x81 0xFF 0x0F 0x20 0x3A 0x00 0x0F 0xFF 0xFB 0x00 0x03 0xFE 0x8C 0x6E,MCU_time_us=304946517
SPI-Read ,addr: 0x12,data: 0x00 0x02 0x68 0x03 0x85 0xFF 0x0D 0x20 0x35 0x00 0x0F 0xFF 0xFB 0x00 0x03 0xFE 0xC4 0xEE,MCU_time_us=305105818
SPI-Read ,addr: 0x12,data: 0x00 0x01 0x68 0x03 0x7E 0xFF 0x11 0x20 0x39 0x00 0x0F 0xFF 0xFB 0x00 0x02 0xFE 0xFD 0x6E,MCU_time_us=305105818
```

# Parsing FIFO Data

A FIFO packet can be a variety of sizes (search datasheet for "Packet Structure" to see every combination). This code configures the sensor to use a 16-byte packet, and can be parsed as follows:

``` python
def unsigned_to_signed(unsigned_int, bit_depth=20):
   """ converts 2's complement unsigned integers to signed integers """
   
   N = 2**bit_depth
   
   if unsigned_int >= N:
       raise ValueError(f"input={unsigned_int} is larger than 2**{bit_depth}={N}")
   elif unsigned_int >= (N/2):
       output = unsigned_int-N
   else:
       output = unsigned_int

   return output


def parse_IMU_FIFO_packet(x, FIFO_COUNT=False):
   """ See 'packet structure' section in ICM-456xx datasheet """
   output = {}
   
   if FIFO_COUNT: # if the read starts at address 0x12, then the first 2 bytes contain...
       output["FIFO count"] = (x[0]<<8) + x[1] # ...FIFO_COUNT
       x = x[2:]
   
   if len(x)==16:
       output["header"] = x[0]
       output["accel"] = [unsigned_to_signed((x[2*i-1]<<8)+x[2*i], bit_depth=16) for i in range(1, 4)]
       output["gyro"] = [unsigned_to_signed((x[2*i-1]<<8)+x[2*i], bit_depth=16) for i in range(4, 7)]
       output["IMU temperature"] = unsigned_to_signed(x[13], bit_depth=8)
       output["IMU timestamp"] = (x[14]<<8)+x[15]
   else:
       raise ValueError("FIFO packet not expected length") # other packet sizes are supported by ICM-456xx, but not implemented in this example code
  
   return output
```

Here is an example FIFO packet in its raw form, and parsed form:

``` python
>>> FIFO_READ_SINGLE_SAMPLE=icm456xx.read(0x12, 18)
[0, 1, 104, 3, 126, 255, 17, 32, 57, 0, 15, 255, 251, 0, 2, 254, 253, 110]
>>> # first two bytes above ([0, 1]) are the FIFO_COUNT, and the remaining 16 bytes are the FIFO packet with sensor data
>>>
>>> parse_IMU_FIFO_packet(FIFO_READ_SINGLE_SAMPLE, FIFO_COUNT=True)
{'IMU timestamp': 64878, 'accel': [894, -239, 8249], 'FIFO count': 1, 'IMU temperature': -2, 'header': 104, 'gyro': [15, -5, 2]}
```

For more information on the FIFO and its usage, please see the ICM-456xx product family appnotes and reference drivers.


# Revision History

-   2026-02-02 - initial release

Pinned
Off