# RGB Controller Technical Manual
> This document is intended for host-side (Host) development and integration personnel. It describes the I2C communication interface, register model, and business behavior provided by this chip.
> This document describes only the **externally visible interface and business logic**.
- Author: DXL
- Document version: v1.0
- Date: 2026-08-25
---
## 1. Overview
This chip acts as an **I2C slave** and drives a chain of single-wire, daisy-chained RGB LEDs. The host sends LED color data and configuration commands to the chip over the I2C bus; the chip maintains a color buffer internally and automatically, continuously refreshes the data onto the LED strip.
Core capabilities:
| Capability | Description |
|------|------|
| Color setting | Set the RGB888 color value of each LED individually |
| Index management | Supports setting a start index, automatic index increment, and index locking |
| One-command lights off | Turn off all LEDs with a single command |
| Controllable blink | Hardware-timed on/off flashing, freeing the host CPU |
| Firmware version | Reads the firmware major/minor version for compatibility adaptation |
---
## 2. I2C Communication Interface
### 2.1 Slave Address
The chip supports selecting the slave address via the level state of an **address-select pin**:
| Address-select pin state | 7-bit slave address | Remarks |
|----------------|--------------|------|
| High level (tied to VCC) | `0x48` | Currently available |
| Low level (tied to GND) | `0x49` | Currently available |
| Tied to SCL | `0x68` | Reserved, not yet enabled |
| Tied to SDA | `0x69` | Reserved, not yet enabled |
> Note: the address-select pin performs a level detection with debounce during the **power-on initialization phase**; a high level uses `0x48`, a low level uses `0x49`.
> The two dynamic-detection schemes "tied to SCL / tied to SDA" in the table are currently reserved designs that are not yet enabled in the actual firmware — do not rely on them.
### 2.2 Register Addressing Method (Register Pointer)
The chip uses the "register pointer" addressing method: **before every operation, one byte of register address must be written first**. Once the chip remembers this address, subsequent reads and writes target that register.
- **Write operation**: when writing the data body, byte 1 is the register address, and the subsequent bytes are that register's data.
- **Read operation**: you must **first perform a write operation** (writing only 1 byte of register address) to set the target register, then initiate the read operation.
> Key point: the register address is **retained across transactions**. The register address set by the previous write operation remains valid in subsequent read transactions until the next write operation writes a new register address.
### 2.3 Read/Write Operation Timing
**Write register:**
```
START → 7-bit address + W(0) → ACK → [register address] → [data bytes…] → STOP
```
**Read register:**
```
Step 1 (set pointer): START → 7-bit address + W(0) → ACK → [register address] → STOP
Step 2 (read data) : START → 7-bit address + R(1) → ACK → [data bytes…] → host NACK → STOP
```
### 2.4 Recommended Communication Rate
It is recommended to use a communication clock rate of **around 10 kHz**; an excessively high rate may cause communication failures.
### 2.5 Abnormal Acknowledge (NACK) Behavior
The chip replies NACK and terminates the current communication in the following cases:
| Case | Description |
|------|------|
| Address mismatch | The received 7-bit address differs from the configured slave address |
| Reading an invalid address | A read operation is initiated when no register address has been set (default `0x00`) |
| Reading a write-only register | Reading the lights-off register (`0x04`) |
| Writing a read-only register | Writing the firmware version register (`0xFF`) |
| Writing an invalid address | The register address is `0x00` |
| Index out of range | The written index value ≥ the current valid LED count |
---
## 3. Register Map
### 3.1 Register Overview Table
| Address | Name | Access | Data Length | Description |
|------|------|------|----------|------|
| `0x00` | Invalid address | — | — | Power-on default address; not readable or writable |
| `0x01` | Count register | Read / Write | 1 byte | Number of LEDs actually mounted on the hardware |
| `0x02` | Index register | Read / Write | 1 byte | Index of the LED currently being operated on |
| `0x03` | Data register | Read / Write | 3×N bytes | LED color value (RGB888) |
| `0x04` | Lights-off register | Write-only | No data body | Turn off all LEDs |
| `0x05` | Index lock register | Read / Write | 1 byte | Whether to lock the operation index |
| `0x06` | Blink enable register | Read / Write | 1 byte | Whether to enable controllable blink |
| `0x07` | Blink duration register | Read / Write | 2 bytes | On duration + off duration |
| `0xFF` | Firmware version register | Read-only | 2 bytes | Major version + minor version |
### 3.2 Register Detailed Descriptions
#### 0x00 — Invalid Address (Reserved)
Power-on default value. No read operation can be performed at this address; writing this address causes NACK and terminates the communication.
#### 0x01 — Count Register (Read/Write)
Indicates the number of LEDs actually mounted on the current hardware.
- **Write**: writes 1 byte. If multiple bytes are written, the **last byte** takes effect. If the written value exceeds the chip's supported upper limit, it is **clamped** to the upper limit.
- **Read**: returns the current valid LED count.
- **Default**: the chip's supported upper-limit count after power-on.
#### 0x02 — Index Register (Read/Write)
Indicates the LED index to be operated on (starting from 0).
- **Write**: writes 1 byte. If multiple bytes are written, the last byte takes effect. If the written value ≥ the current valid LED count, it is an illegal operation; the chip replies NACK and terminates the communication.
- **Read**: returns the current operation index.
- **Side effect**: writing **triggers blink disable**.
- **Constraint**: the legal index range is `0 ~ (valid count - 1)`.
#### 0x03 — Data Register (Read/Write)
LED color data. **Every 3 bytes is the RGB888 color value of one LED**, in the byte order **R, G, B**.
- **Write**: writes a multiple of 3 bytes consecutively. Each time 3 bytes (one complete LED) are written, the index auto-increments by 1 (unless locked, see `0x05`).
- **Read**: reads consecutively; every 3 bytes returns one LED's R, G, B, and the index auto-increments by 1.
- **Index wraparound**: when the index increments to the valid count, it resets to zero, enabling circular read/write of the buffer.
- **Persistence**: the index does **not** reset to zero after communication ends; the next operation continues from the current index.
- **Side effect**: both read and write **trigger blink disable**.
> Example: after setting count = 8 and index = 0, writing 24 bytes (8 LEDs) each time covers the entire LED strip.
#### 0x04 — Lights-off Register (Write-only)
Turns off all LEDs (all colors set to R0-G0-B0).
- **Write**: no data body required; writing triggers it.
- **Read**: not supported; reading causes NACK.
- **Deferred effect**: the lights-off action actually executes after the current I2C communication **ends (STOP)**.
- **Side effect**: also disables blink.
- **Note**: after writing, allow about **10ms** to ensure the lights-off completes; if the data or index register is written again during this period, the lights-off may fail (color disorder or some LEDs not properly turned off).
#### 0x05 — Index Lock Register (Read/Write)
Controls whether the index auto-increments when writing the data register.
- **Write**: writing `0` means unlocked (index auto-increments when writing data); writing a non-`0` value means locked (index does not increment when writing data).
- **Read**: returns the current lock state (`0` / `1`).
- **Purpose**: when locked, it is suitable for repeatedly writing data commands to **refresh a single LED** (index unchanged).
- **Note**: locking affects only the index auto-increment of **write** operations; the index of **read** operations still increments.
#### 0x06 — Blink Enable Register (Read/Write)
Controls the controllable blink function.
- **Write**: writing a non-`0` value enables blink (blink applies to the LED selected by the current index); writing `0` disables blink.
- **Read**: returns the current enable state (`0` / `1`).
- **Blink behavior**: once enabled, the selected LED automatically cycles through "on duration → off duration → on duration…".
- **Mutual exclusion**: see Section 4.
#### 0x07 — Blink Duration Register (Read/Write)
Sets the on and off durations of the blink.
- **Write**: byte 1 is the **on duration**, byte 2 is the **off duration**.
- **Read**: returns the on duration and off duration bytes in sequence.
- **Unit**: both are 10ms; a single byte ranges from 0 to 255, i.e., up to 2.55 seconds can be set.
- **Default**: 500ms each for on and off.
#### 0xFF — Firmware Version Register (Read-only)
- **Read**: byte 1 is the major version, byte 2 is the minor version.
- **Write**: not supported; writing causes NACK.
- **Purpose**: it is recommended that the host read the firmware version during specific flows, so that when compatibility issues arise they can be adapted and fixed accordingly.
---
## 4. Register Mutual Exclusion Conditions
Controllable blink (after `0x06` is enabled) is **mutually exclusive** with the following operations; performing these operations **automatically disables blink**:
| Triggering operation | Register | Disables blink? |
|----------|--------|--------------|
| Write index | `0x02` | ✅ Yes |
| Write data | `0x03` | ✅ Yes |
| Read data | `0x03` | ✅ Yes |
| Write lights-off | `0x04` | ✅ Yes (and turns off all LEDs) |
| Write blink enable (value 0) | `0x06` | ✅ Yes |
> Design rationale: blink applies to the "LED selected by the current index", while index, data, and lights-off operations all change that LED's state, conflicting with blink. Therefore blink must be disabled first before performing these operations.
**Other read/write restrictions (mutual exclusion / constraints)**:
| Restriction | Description |
|------|------|
| `0x04` write-only | Reading causes NACK |
| `0xFF` read-only | Writing causes NACK |
| `0x00` invalid | Both reading and writing cause NACK |
| Index out of range | Writing an index ≥ valid count causes NACK |
| Count clamping | Writing a count above the upper limit is clamped to the upper limit |
---
## 5. Business Flowcharts
### 5.1 Power-on Initialization Flow
```mermaid
flowchart TD
A([Power-on reset]) --> B[Controller internal initialization]
B --> C[RGB initialization
clear color buffer
turn off all LEDs by default]
C --> D[Blink timer initialization
default on/off 500ms each]
D --> E[I2C slave initialization]
E --> F{Address-select pin
level detection and debounce}
F -->|High level| G[Slave address = 0x48]
F -->|Low level| H[Slave address = 0x49]
G --> I[Enter main loop]
H --> I
```
### 5.2 Main Loop Overall Flow
```mermaid
flowchart TD
A([Main loop entry]) --> B[Sample I2C bus
detect SCL / SDA transitions]
B --> C{SCL transition?}
C -->|Yes| D[I2C state machine handling]
C -->|No| E{SDA transition?}
E -->|Yes| F[START / STOP signal handling]
E -->|No| G[Cache bus state]
D --> G
F --> G
G --> H{10ms timer reached?}
H -->|Yes| I[Blink timing accumulation +1]
H -->|No| K{I2C communication in progress?}
I --> K
K -->|Yes| A
K -->|No| L{Waiting for strip reset?}
L -->|Yes| A
L -->|No| M[Blink on / off switching decision]
M --> N{Data updated?}
N -->|No| A
N -->|Yes| O[Refresh LED colors]
O --> A
```
### 5.3 I2C Communication State Machine
```mermaid
stateDiagram-v2
[*] --> IDLE
IDLE --> ADDR: START received
ADDR --> OP: 7-bit address matches
ADDR --> IDLE: address mismatch
OP --> IACK1: parse read/write bit and prepare response
IACK1 --> IACK2: SCL falling edge
IACK2 --> WRITEDATA: write operation
IACK2 --> READDATA: read operation
WRITEDATA --> WACK1: 8 bits received
WACK1 --> WACK2: SCL falling edge
WACK2 --> WRITEDATA: continue receiving
READDATA --> RACK: 8 bits sent
RACK --> READDATA: host ACK received
RACK --> IDLE: host NACK received
WRITEDATA --> IDLE: STOP received
READDATA --> IDLE: STOP received
```
### 5.4 Write Operation Data Flow
```mermaid
flowchart TD
A([Host write operation]) --> B[START + address + write bit]
B --> C[Slave replies ACK]
C --> D[Receive byte 1 = register address]
D --> E{Address valid?}
E -->|Invalid 0x00| F[Reply NACK to terminate]
E -->|Valid| G[Save register address]
G --> H[Receive subsequent data bytes]
H --> I[Write by register type
count / index / data / lock / blink …]
I --> J[STOP]
J --> K[Execute deferred actions
lights off / disable blink]
K --> L([Done])
```
### 5.5 Read Operation Data Flow
```mermaid
flowchart TD
A([Read operation preamble]) --> B[First write 1 byte to set register address]
B --> C[START + address + read bit]
C --> D{Register readable?}
D -->|0x00 or 0x04| E[Reply NACK to terminate]
D -->|Readable| F[Slave ACK]
F --> G[Return data per current register
multi-byte registers auto-advance]
G --> H{Host continues reading?}
H -->|ACK| G
H -->|NACK + STOP| I([End])
```
### 5.6 Blink On/Off Logic
```mermaid
flowchart TD
A[Blink enabled
refreshed to target LED] --> B{Currently in on phase?}
B -->|Yes| C{On duration reached?}
C -->|Yes| D[Switch to off
set color to 0
restart timing]
C -->|No| E[Keep waiting]
B -->|No| F{Off duration reached?}
F -->|Yes| G[Switch to on
take color from buffer
restart timing]
F -->|No| H[Keep waiting]
D --> A
G --> A
```
---
## 6. Key Business Feature Summary
1. **Deferred effect of changes**: actions such as lights-off and blink-disable are not executed immediately when the command arrives; instead they are processed uniformly **after the I2C communication ends (STOP)**, avoiding refresh operations interfering with bus communication stability.
2. **Index management**:
- When writing data, the index auto-increments after every 3 bytes (lockable).
- When reading data, the index always auto-increments.
- The index wraps around to 0 after reaching the valid count.
- The index is retained across transactions and does not reset when communication ends.
3. **Data refresh mechanism**: when data changes, a refresh-enable flag is set, and the main loop refreshes all LEDs once in a **full pass**; when there is no change, it refreshes only once, avoiding unnecessary refresh overhead.
4. **Blink frees the host**: blink is driven by the chip's internal timer; the host only needs to set the on/off durations and enable it, without continuously sending commands, thereby freeing the host CPU.
5. **Safety protection**:
- Out-of-range protection: a count above the upper limit is automatically clamped; an out-of-range index returns NACK.
- Communication priority: while I2C communication is in progress, LED refresh is skipped, reducing the probability of communication failure.
---
## 7. Usage Notes
1. It is recommended that the host first read the firmware version register (`0xFF`) after power-on, to adapt when compatibility issues arise.
2. After executing lights-off (`0x04`), allow about 10ms; do not write the data/index register during this period.
3. After setting the count (`0x01`), the legal range of the index (`0x02`) changes accordingly; be careful to avoid out-of-range writes.
4. Before using the blink function, confirm that the current index points to the target LED; index/data/lights-off operations disable blink.
5. It is recommended to keep the communication rate at around 10 kHz; an excessively high rate may cause communication failures.
6. The current slave address supports only two static selections, `0x48` (high level) and `0x49` (low level); `0x68`/`0x69` are reserved.