TECHNICAL SPEC · I²C PROTOCOL

I²Ccommunication specification

Inside FP01, the Arduino (I²C master) interprets commands received over RS485 and issues instructions over I²C to the PSoC 4 (output control), the EEPROM (settings storage) and the DMX drivers (on FP01 Rev1.6 the OLED is also on I²C). This page summarizes the communication settings, the PSoC 4 registers and the byte sequence of each command, based on an analysis of the FP01 firmware Rev13 and PSoC Creator project sources.

SPEC VERSION
I2C_Rev13
BUS SPEED
100 kHz
MASTER
Arduino (Wire)
ADDRESS
7-bit
FIRMWARE
Rev13 (0013)
BUS MAP

I²CBus configuration

FP01 has two I²C buses. The Arduino-side I²C connects the PSoC 4 and EEPROM on the FP01 board (and the OLED on FP01 Rev1.6) and is also routed to the main board through FFC pins 21 and 22. The PSoC-side I²C is routed to FFC pins 19 and 20; on DIMX4 it is assigned to the temperature sensor (TEMP/SDA, SCL).

FP01 board Main board (via 40-pin FFC) Arduino I²C · SDA/SCL · 100 kHz FFC 21 / 22 Arduino I²C master (Wire) RS485 command → I²C 0x08 PSoC 4 Output control 0x50 EEPROM AT24C256C · 32KB 0x3C OLED FP01 Rev1.6 only 0x0A – 0x0D DMX drivers 1–4 DMX main board PSoC I²C (PSoC 4 pins 11 / 12) FFC 19 / 20 DIMX4 temperature sensor The Arduino-side bus also connects to PSoC 4 pins 15 / 16 on the FP01 board (PSoC 4 = slave 0x08). The dashed OLED is the FP01 Rev1.6 configuration. On FP01 Rev2.1 the OLED is connected via SPI and is not on the I²C bus.

Pin numbers follow the FFC connector specification (FFC_Rev2). The DMX driver addresses are defined in the firmware; driver 1 is the board closest to the ribbon cable.

SETTINGS

Communication settings

The Arduino is the only master. Wire.begin() is called without arguments, so the Arduino joins the bus as master. No speed is specified, so it runs at the Arduino default of 100 kHz. The OLED library (U8x8) raises the clock to 400 kHz unless told otherwise, so setBusClock(100000) keeps it at 100 kHz.

SLAVE · OUTPUT CONTROL
0x08

PSoC 4

Register-type slave to which dimming levels, fade times and the module ID are written. Write only; the Arduino does not read from it.

i2cDIMMER.cpp · PSOC_SLAVE_ADDRESS

SLAVE · SETTINGS STORE
0x50

EEPROM (AT24C256C)

Stores the module address, per-circuit settings, groups and scenes. Addressed with a 2-byte memory address (high → low).

i2cEEPROM.cpp · SLAVE_ADDRESS_EEPROM

SLAVE · DISPLAY · FP01 Rev1.6
0x3C

OLED (SH1106)

U8X8_SH1106_128X64_NONAME_HW_I2C of the U8x8 library. The address is the library default. Enters power-save mode after about 5 minutes without operation.

On FP01 Rev2.1 the OLED is connected via SPI (SCK, MOSI, CS + DC, RST) and does not use this I²C address.

screen.cpp

SLAVE · DMX DRIVER
0x0A–0x0D

DMX drivers 1–4

Sends fixed 4-byte packets to the address of the driver number (1–4) set for each circuit.

Rev13.ino · I2C_SLAVEADDR_1–4

Settings list

ItemValueDefined inNotes
RoleArduino = masterWire.begin()No argument = master. It is called twice in setup(), with the same effect.
Clock100 kHzArduino defaultA comment in the DMX version reads “I²C speed 100 kbps (Arduino default, so not specified)”.
OLED clock100 kHzu8x8.setBusClock(100000)On FP01 Rev1.6 the OLED was on the same bus, so the speeds are matched.
Address format7-bit—All values in the table are 7-bit (the 8-bit value on write is doubled: 0x08 → 0x10).
Byte orderBig-endian—2-byte values (dimming level, EEPROM address, DMX channel) are sent high byte first.
Wait before PSoC transferdelay(5)i2cDIMMER.cppEach write waits 5 ms before endTransmission().
EEPROM write wait10–20 msi2cEEPROM.cpp1 byte: 5 ms + 10 ms; 2 bytes: 5 ms + 20 ms; multiple bytes: number of bytes × 5 ms.
PSoC 4 · 0x08

PSoC 4register map

The PSoC 4 is a register-type slave that takes the first byte as the register address and writes the following data to it. Only circuits with local addresses 0–7 are sent to the PSoC 4; addresses 8 and above are not.

RegisterNameSizeValueSend function
0x00Module ID1 byte1:IGBTX4 2:DIMX4 3:PWMX4 4:RELAYX8 5:RRX8 6:CTRL1 7:RS485Xi2c_psoc_write_reg_module_id()
0x01–0x09Unused—Not written in Rev13—
0x0A + LA
0x0A–0x11
Fade time1 byte × 80–255 (units of 0.1 s; 2 = 0.2 s)i2c_psoc_write_reg_fade_time()
0x12 + LA×2
0x12–0x21
Dimming level (DIRECT)2 byte × 80–1000 (actual % × 0.1%; 0 = off, 1000 = 100%), high byte firsti2c_psoc_write_reg_light()

LA = local address (circuit number within the module, 0–7). Earlier versions had MIN and MAX level registers (0x12, 0x22), but in Rev13 they are commented out, and MIN/MAX conversion is done with the conversion table on the Arduino side.

Transmit frames

Write dimming leveli2c_psoc_write_reg_light(LA, level)
S
0x08 WSlave
0x12+LA×2Register
level ≫ 8High byte
level & FFLow byte
P
Write fade timei2c_psoc_write_reg_fade_time(LA, time)
S
0x08 WSlave
0x0A+LARegister
time0–255 (× 0.1 s)
P
Write module IDi2c_psoc_write_reg_module_id(id)
S
0x08 WSlave
0x00Register
id1–7
P

Calculate the byte sequence

1. Fade time
2. Dimming level

The logical level (0–1000, specified in the RS485 command) is converted to actual % with a conversion table built from each circuit's MIN and MAX before it is sent. Logical 0 maps to 0, logical 1 to MIN, logical 1000 to MAX, and values in between are mapped linearly (when MIN = MAX it is treated as 1–1000).

EEPROM · 0x50

EEPROM read and write

All settings are stored in an external EEPROM (AT24C256C-SSHL-T, 256 Kbit = 32 KB, 64-byte pages) and read at startup. Memory addresses are 2 bytes (0x0000–0x7FFF), and each circuit has its own block at local address × 0x100 + offset. The 64 circuits LA0–63 (0x0000–0x3FFF, 16 KB) fit within the capacity, and the firmware page length EEPROM_PAGE_LENGTH = 64 matches the page size of this EEPROM.

Write (1 / 2 / N bytes)i2c_eeprom_write_byte / _2byte / _nbyte
S
0x50 WSlave
addr ≫ 8Memory address high
addr & FFMemory address low
data…1 / 2 (high → low) / up to 64 (1 page)
P

After writing, wait until the EEPROM's internal write completes (1 byte 10 ms, 2 bytes 20 ms, N bytes N × 5 ms).

Read (1 / 2 bytes)i2c_eeprom_read_byte / _2byte
S
0x50 WSlave
addr ≫ 8High
addr & FFLow
P
S
0x50 RSlave
data1 or 2 bytes (high → low)
P

The address is written, followed by a STOP, then the data is read with requestFrom() (no repeated start is used).

Main stored items

OffsetItemSizeValue
0x0000Module address20–255 (LA0 block only)
0x000EResponse mode1Reply type (LA0 block only)
0x000FOLED power10:OFF 1:ON (LA0 block only)
0x0011Module type ID11–7 (also written to PSoC register 0x00)
0x18Power-on level20–1000 (logical)
0x1C / 0x1EMIN / MAX level2 + 20–1000 (actual %)
0x22Stored level2Level before OFF (restored by on__)
0x24 / 0x25UP/DOWN step 1 / 21 + 1For wall switches / for HA (× 0.1%)
0x27Fade time10–255 (forwarded as is to PSoC and DMX)
0x29On-delay10–255 (× 0.1 s)
0x2BCircuit description16ASCII
0x3BCircuit address2Address specified over RS485
0x40Member groups ×1632Group n = 0x40 + n×2
0x7A / 0x7BDMX driver number / channel1 + 21–4 / 1–512
0x80Scene table ×32640–1000; -1 (0xFFFF) = no change

Offsets from 0x18 onward are per-circuit values; the actual address is LA × 0x100 + offset.

DMX DRIVER · 0x0A–0x0D

Packets to the DMX drivers

For circuits with a DMX channel set, a 4-byte packet is sent to the DMX driver at the same time as the transfer to the PSoC 4. The destination is determined by the “DMX driver number” in EEPROM: 1→0x0A, 2→0x0B, 3→0x0C, 4→0x0D.

Send DMX leveli2c_DMX(LA, level) → i2c_send_4byte_n()
S
0x0A–0D WDrivers 1–4
ch ≫ 8DMX channel high
ch & FFDMX channel low (1–512)
level ≫ 2Brightness 0–250
fadeFade time 0–255
P

Brightness is the actual % (0–1000) divided by 4. The maximum is 250 and does not reach the DMX maximum of 255. For UP/DOWN operations the fade time is fixed at 2 (0.2 s).

The firmware still contains a polling routine (Polling_Slave_1–4) that reads 12 bytes from a driver and relays them to RS485, but its call from loop() is commented out, so it does not run in Rev13.

COMMAND → I²C

RS485 commands and I²C transfers

RS485 commands are 12 ASCII characters (8 for the v command) in the form [1 mode character][3-digit address][4-character instruction][4-digit argument]. The table shows what is sent over I²C when each command is received.

CommandDescriptionPSoC 4 (0x08)DMXEEPROM
m dire / a sccc / g scccDirect level setting, scene recallLevelSendRead only
v on__ / v off_ / v toggGroup ON, OFF, toggleLevelSendWrites the stored level on OFF
v up__ / down / up_2 / dn_2Group UP, DOWNfade=2 levelSendReads the step value
a fade / g fadeTemporary fade timeFade—Not written
s wftt / x wfttSet fade timeFade—0x27
a idonStart identification blinkfade=15 → alternating 0 / 1000——
a idofStop identification blinklevel=0——
OLED type selectionChange module typeModule ID—0x0011
s wmin / wmax / wpol etc.Write setting values——Each item

When raising the level (sending a value greater than 0), the firmware waits for the on-delay (× 0.1 s) before sending.

Startup sequence

01

Read settings

Reads the module address, type ID, response mode and OLED power from EEPROM.

02

Fade time

Reads the fade times of LA0–7 from EEPROM and writes them to PSoC 0x0A+LA.

03

Power-on level

Reads the power-on levels and writes them to PSoC 0x12+LA×2 at 30 ms intervals to turn the circuits on.

04

Module ID

Reads MIN and MAX to build the conversion table, and finally writes the type ID to PSoC 0x00.

PSoC CREATOR PROJECTS

I²C settings of the PSoC projects

The PSoC 5LP projects of the switches (ROTARY03, ROTARY02N) still contain I²C component settings. However, in the current build the place-and-route report shows 0% I²C usage, and communication with FP01 uses RS485 (UART). This is left over from an earlier design that matched FP01's address 0x08 and 100 kbps.

ProjectComponentModeSpeedAddressStatus
ROTARY03 Rev1.1.5
CY8C5888LTQ-LP097
I2CMaster (UDB)100 kbps(0x08)Unused calls are commented out
I2C_1Multi-master100 kbps0x08Unused
ROTARY02N Rev1.3EZI2C_Slave / EZI2C_1EZI2C slave (8-bit sub-address)100 kbps0x08Unused

The firmware of the PSoC 4 (CY8C4245PVI-482) on FP01 is not included in this analysis. The PSoC 4 register map is derived from what the master (Arduino) sends.

NOTES

Implementation notes

Points to watch, found by reading the Rev13 source.