Skip to main content

I2C

The I2C (Inter-Integrated Circuit) interface provides two-wire synchronous serial communication. Supports standard (100 kHz), fast (400 kHz), and fast-plus (1 MHz) modes with configurable voltage levels from 1.6V to 5.0V.

Only master mode

Please note that the AT1000 device only supports master mode for I2C communication. This means that it can initiate communication with slave devices, but it cannot act as a slave itself.

Multiplexing

Some interfaces share the same GPIO pins, so only one can be used at a time. Check out the multiplexing tables in the introduction for more details.

Quick Start​

The example code below shows how to enable the I2C bus, set the baud rate, and transmit/receive data.

import AT1000 from '@ikalogic/at1000';
let devices = await AT1000.findDevices(500); // Find devices with a 500ms timeout
let tester = devices[0]; // Target the first detected device
let i2c = tester.com.i2c(0); // Select the first I2C bus

await i2c.enable({ vcc: 3.3, baud_rate: 100000 }); // Enable I2C bus with 3.3V and 100kHz

// Define an I2C transaction
let i2c_transaction = {
address: 0x50, // I2C address of the slave device
start: true, // Start condition
stop: true, // Stop condition
nack_last_byte: false, // NACK the last byte
};

// Write request to the slave device, registers 0x10 and 0x20
await i2c.tx({ ...i2c_transaction, data: [0x10, 0x20] });

i2c_transaction.nack_last_byte = true;
// Read 4 bytes from the slave device
let data = await i2c.rx({ ...i2c_transaction, length: 4 });

// Disable I2C bus on AT1000 master
await i2c.disable();

API Reference​

Accessing I2C​

const i2c = tester.com.i2c(id);

Parameters:

  • id (number): The I2C interface identifier (0-based index)

Returns: I2c instance


Methods​

configure(config)​

Configures the I2C interface parameters without changing the enabled state.

await i2c.configure({ 
baud_rate: 400000,
vcc: 3.3
});

Parameters:

  • config (I2cConfigPatch): Configuration object with optional properties:
    • enabled (boolean, optional): Enable or disable the interface
    • baud_rate (number, optional): I2C clock frequency - 100000, 400000, or 1000000
    • vcc (number, optional): Logic level voltage in volts (1.6 to 5.0)

Valid baud rates:

  • 100000 (100 kHz): Standard mode
  • 400000 (400 kHz): Fast mode
  • 1000000 (1 MHz): Fast-plus mode

Returns: Promise<I2cConfig> - The updated configuration

Exceptions:

  • Throws validation error if baud_rate is not one of the valid values
  • Throws validation error if vcc is outside the range [1.6, 5.0]

enable([config])​

Enables the I2C interface and optionally applies configuration.

await i2c.enable({ 
baud_rate: 400000,
vcc: 3.3
});

Parameters:

  • config (I2cEnableConfig, optional): Optional configuration to apply:
    • baud_rate (number, optional): I2C clock frequency (100000, 400000, or 1000000)
    • vcc (number, optional): Logic level voltage (1.6 to 5.0)

Returns: Promise<I2cConfig> - The updated configuration with enabled: true

Exceptions:

  • Throws validation error if parameters are outside valid ranges

disable()​

Disables the I2C interface.

await i2c.disable();

Returns: Promise<I2cConfig> - The updated configuration with enabled: false


tx(transaction)​

Writes data to an I2C device.

// Write to device at address 0x50
await i2c.tx({
address: 0x50,
data: [0x00, 0x10, 0xAA, 0xBB]
});

// Write with custom start/stop conditions
await i2c.tx({
address: 0x3C,
start: true,
stop: false, // No stop - for repeated start
data: [0x40, 0xFF]
});

Parameters:

  • transaction (I2cTransactionWrite): Write transaction configuration:
    • address (number, required): 7-bit I2C device address
    • data (string | number[], required): Data to write (max 1024 bytes)
    • start (boolean, optional, default: true): Generate START condition
    • stop (boolean, optional, default: true): Generate STOP condition
    • nack_last_byte (boolean, optional, default: false): Send NACK on last byte

Returns: Promise<number> - Number of bytes written

Exceptions:

  • Throws validation error if data exceeds 1024 bytes
  • Throws error if device doesn't acknowledge (NACK)

rx(transaction)​

Reads data from an I2C device.

// Read 16 bytes from device at address 0x50
const data = await i2c.rx({
address: 0x50,
length: 16
});

// Read with custom conditions
const data2 = await i2c.rx({
address: 0x3C,
length: 8,
start: true,
stop: true,
nack_last_byte: true
});

Parameters:

  • transaction (I2cTransactionRead): Read transaction configuration:
    • address (number, required): 7-bit I2C device address
    • length (number, required): Number of bytes to read (1 to 1024)
    • start (boolean, optional, default: true): Generate START condition
    • stop (boolean, optional, default: true): Generate STOP condition
    • nack_last_byte (boolean, optional, default: true): Send NACK on last byte

Returns: Promise<SerialData> - Received data as byte array (number[])

Exceptions:

  • Throws validation error if length is outside the range [1, 1024]
  • Throws error if device doesn't acknowledge (NACK)

Types​

I2cConfig​

Complete configuration object returned by configuration methods.

{
enabled: boolean,
baud_rate: number, // 100000, 400000, or 1000000
vcc: number // 1.6 to 5.0
}

I2cConfigPatch​

Partial configuration for the configure() method. All properties are optional.

{
enabled?: boolean,
baud_rate?: number, // 100000, 400000, or 1000000
vcc?: number // 1.6 to 5.0
}

I2cEnableConfig​

Optional configuration for the enable() method.

{
baud_rate?: number, // 100000, 400000, or 1000000
vcc?: number // 1.6 to 5.0
}

I2cTransactionWrite​

Write transaction parameters.

{
address: number, // 7-bit I2C address
data: string | number[], // Data to write (max 1024 bytes)
start?: boolean, // Generate START (default: true)
stop?: boolean, // Generate STOP (default: true)
nack_last_byte?: boolean // NACK last byte (default: false)
}

I2cTransactionRead​

Read transaction parameters.

{
address: number, // 7-bit I2C address
length: number, // Number of bytes to read (1-1024)
start?: boolean, // Generate START (default: true)
stop?: boolean, // Generate STOP (default: true)
nack_last_byte?: boolean // NACK last byte (default: true)
}

SerialData​

Output data type, always returned as a byte array.

number[]  // Array of bytes (0-255)

Usage Example​

import AT1000 from '@ikalogic/at1000';

// Find and connect to device
const devices = await AT1000.findDevices(500);
const tester = devices[0];

// Access I2C interface 0
const i2c = tester.com.i2c(0);

// Enable with 400 kHz clock and 3.3V logic
await i2c.enable({
baud_rate: 400000,
vcc: 3.3
});

// Write to EEPROM at address 0x50
await i2c.tx({
address: 0x50,
data: [0x00, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F] // "Hello" at address 0x0000
});

// Wait for write cycle to complete
await new Promise(resolve => setTimeout(resolve, 10));

// Read back from EEPROM
// First, set read address
await i2c.tx({
address: 0x50,
data: [0x00, 0x00],
stop: false // No stop for repeated start
});

// Then read data
const data = await i2c.rx({
address: 0x50,
length: 5
});

console.log("Read:", Buffer.from(data).toString()); // "Hello"

// Disable interface
await i2c.disable();

Common Patterns​

Register Read (Single Byte)​

// Read register 0x75 from device at 0x68 (e.g., IMU WHO_AM_I register)
await i2c.tx({
address: 0x68,
data: [0x75],
stop: false
});

const whoAmI = await i2c.rx({
address: 0x68,
length: 1
});

console.log("WHO_AM_I:", whoAmI[0].toString(16));

Register Write​

// Write 0x80 to register 0x6B (e.g., PWR_MGMT_1 register)
await i2c.tx({
address: 0x68,
data: [0x6B, 0x80]
});

Multi-Byte Register Read​

// Read 6 bytes starting from register 0x3B (e.g., accelerometer data)
await i2c.tx({
address: 0x68,
data: [0x3B],
stop: false
});

const accelData = await i2c.rx({
address: 0x68,
length: 6
});

// Parse as 16-bit signed integers
const accelX = (accelData[0] << 8) | accelData[1];
const accelY = (accelData[2] << 8) | accelData[3];
const accelZ = (accelData[4] << 8) | accelData[5];

EEPROM Operations​

// Write to EEPROM (24C256 example)
const eepromAddr = 0x50;
const memAddr = [0x00, 0x10]; // Address 0x0010
const writeData = [0xAA, 0xBB, 0xCC, 0xDD];

await i2c.tx({
address: eepromAddr,
data: [...memAddr, ...writeData]
});

// Wait for write cycle (5ms typical)
await new Promise(resolve => setTimeout(resolve, 10));

// Read back
await i2c.tx({
address: eepromAddr,
data: memAddr,
stop: false
});

const readData = await i2c.rx({
address: eepromAddr,
length: 4
});

Scanning I2C Bus​

console.log("Scanning I2C bus...");
const foundDevices = [];

for (let addr = 0x08; addr < 0x78; addr++) {
try {
await i2c.tx({
address: addr,
data: []
});
foundDevices.push(addr);
console.log(`Found device at 0x${addr.toString(16).padStart(2, '0')}`);
} catch (e) {
// Device not found at this address
}
}

console.log(`Found ${foundDevices.length} device(s)`);

Repeated Start Transaction​

// Combined write-read transaction with repeated start
// (More efficient than separate transactions)

// Write register address
await i2c.tx({
address: 0x3C,
data: [0x00],
stop: false // Keep bus active for repeated start
});

// Immediately read without releasing bus
const data = await i2c.rx({
address: 0x3C,
length: 16,
start: true, // Repeated START
stop: true
});

Notes​

  • I2C addresses are 7-bit values (0x08 to 0x77)
  • The interface handles 10-bit addressing internally if needed
  • Pull-up resistors are typically required on SDA and SCL lines (often integrated)
  • Clock stretching is supported automatically
  • Use nack_last_byte: true when reading to signal end of transaction
  • Maximum transfer length is 1024 bytes per transaction