Skip to content

Instantly share code, notes, and snippets.

@marcelrv
Last active November 28, 2025 23:03
Show Gist options
  • Select an option

  • Save marcelrv/36f9d2c66a273289211cc5fa73b00018 to your computer and use it in GitHub Desktop.

Select an option

Save marcelrv/36f9d2c66a273289211cc5fa73b00018 to your computer and use it in GitHub Desktop.
Surplife smartcurtain - lednetwf message format and known commands

updated version: surplife_protocol_description.md

Commands to control the light

For the LED Curtain, the initialization sequence consists of setting the current device time and performing a handshake/keep-alive check.

Here is the deciphered protocol description.

🔌 LED Curtain Initialization Sequence

1. Time Synchronization (0x10)

Direction: App $\to$ Device
Sequence Nr: 1
Command: 0x0A (Application Layer Header) + Payload

The app immediately sends the current local time to the device. This is used for scheduled timers and alarms stored on the device.

Raw Payload: 10 14 19 0b 1c 13 20 26 05 00 0f d1

Byte Index Hex Value Decimal Meaning Decoded Value
0 0x10 16 Opcode Set Time
1 0x14 20 Year (Century) 20xx
2 0x19 25 Year (Year) xx25
3 0x0B 11 Month November
4 0x1C 28 Day 28th
5 0x13 19 Hour 19 (7 PM)
6 0x20 32 Minute 32 min
7 0x26 38 Second 38 sec
8 0x05 5 Day of Week Friday (Mon=1 ... Fri=5)
9 0x00 0 Reserved -
10-11 0x0F D1 - Checksum/End -

📅 Decoded Timestamp: 2025-11-28 19:32:38 (Friday)


2. Handshake / Keep-Alive (0xEA)

Direction: App $\to$ Device
Sequence Nr: 2

This packet verifies the connection is active and typically requests a status update from the device.

Raw Payload: ea 81 8a 8b 59

Byte Index Hex Value Meaning
0 0xEA Opcode: Keep Alive / Ping
1-4 0x81 8A 8B 59 Magic Bytes / Challenge: This specific sequence is a standard "Hello" signature used in Surplife/MagicHome BLE devices.

3. Device Status Report (Response)

Direction: Device $\to$ App (Notification)
UUID: 0000ff02...

The device responds to the handshake by reporting its current state.

Raw Data: ea 81 01 00 c2 03 23 62 01 64 f0 ...

Byte Index Hex Value Deciphered Meaning
0 0xEA Response Opcode (Matches the request 0xEA)
1 0x81 Device Type Category?
2 0x01 Power State: 0x01 = ON
3 0x00 Mode: 0x00 (Likely RGB/Color Mode)
4 0xC2 Device Model ID (Curtain Controller)
5 0x03 Firmware Major Version
6-7 0x23 62 Firmware Minor Version / Build
8 0x01 Active Effect ID?
9 0x64 Brightness / Speed: 100 (100%)
10 0xF0 Data Delimiter

Summary of Initialization

  1. Set Time: The app tells the curtain it is Friday, Nov 28, 2025, at 19:32:38.
  2. Handshake: The app sends the standard "Hello" bytes.
  3. Status: The curtain replies "I am ON, brightness is 100%, and I am a Curtain Device (0xC2)."

Switch On

[BLE UpperTransportLayer.createUpper =>] isAct: false isProtect: false sequenceNr: 3 cmdId: 0a payload: 71 24 len:5
[BLE Write  =>] UUID: 0000ff01-0000-1000-8000-00805f9b34fb data: 0x 0a 71 24 - header : 00 03 80 00 00 02 03  - full: 00 03 80 00 00 02 03 0a 71 24
[BLE Notify <=] UUID: 0000ff02-0000-1000-8000-00805f9b34fb data: 0x  ea 81 01 00 c2 03 23 66 01 32 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00 - header : 04 32 80 00 00 19 1a 15 - full: 04 32 80 00 00 19 1a 15 ea 81 01 00 c2 03 23 66 01 32 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00
[BLE Notify <=] UUID: 0000ff02-0000-1000-8000-00805f9b34fb data: 0x  ea 81 01 00 c2 03 24 66 01 32 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00 - header : 04 33 80 00 00 19 1a 16 - full: 04 33 80 00 00 19 1a 16 ea 81 01 00 c2 03 24 66 01 32 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00

Colourfull mode

Byte Index Field Name Description
0 ? 0xe0
1 Mode 0x0b for colorfull mode
2 Hue color 360 degree mapped to 0-255
3 brightness Represents intensity from 0x00 (Off) to 0xFF (100%).

payload: e2 0b 29 bf

example

[Remote::Gadget ]-> [BLE UpperTransportLayer.createUpper =>] isAct: false isProtect: false sequenceNr: 4 cmdId: 0a payload: e2 0b 29 bf len:11
[BLE Write  =>] UUID: 0000ff01-0000-1000-8000-00805f9b34fb data: 0x 0a e2 0b 29 bf - header : 00 04 80 00 00 04 05  - full: 00 04 80 00 00 04 05 0a e2 0b 29 bf
[BLE UpperTransportLayer.createUpper =>] isAct: false isProtect: false sequenceNr: 5 cmdId: 0a payload: e2 0b 65 9f len:11

Effect mode

Byte Index Field Name Description
0 ? 0xe0
1 Mode 0x02 for effect mode
2 ? 0x00
3 effect id 0x00 to 0x11
4 speed 0x00 to 0x64 (0-100%)
5 brightness 0x00 to 0x64 (0-100%)

payload: e0 02 00 0f 1f 50

[BLE UpperTransportLayer.createUpper =>] isAct: false isProtect: false sequenceNr: 21 cmdId: 0a payload: e0 02 00 02 50 50 len:17
[BLE Write  =>] UUID: 0000ff01-0000-1000-8000-00805f9b34fb data: 0x 0a e0 02 00 02 50 50 - header : 00 15 80 00 00 06 07  - full: 00 15 80 00 00 06 07 0a e0 02 00 02 50 50
[BLE Notify <=] UUID: 0000ff02-0000-1000-8000-00805f9b34fb data: 0x  ea 81 01 00 c2 03 23 67 02 50 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00 - header : 04 3d 80 00 00 19 1a 16 - full: 04 3d 80 00 00 19 1a 16 ea 81 01 00 c2 03 23 67 02 50 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00

Music mode

Byte Index Field Name Description
0 ? 0xe1
1 Mode 0x05 for music
2 active 0x00 off 0x01 on
3 brightness 0x00 to 0x64 (0-100%)
4 effect id 0x00 to 0x11
5 ?
6 ?
7 Sensetivity 0x00 to 0x64 (0-100%)

payload: e1 05 00 64 03 00 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a1 00 00 00 06 a1 00 64 64 a1 96 64 64 a1 78 64 64 a1 5a 64 64 a1 3c 64 64 a1 1e 64 64

[BLE UpperTransportLayer.createUpper =>] isAct: false isProtect: false sequenceNr: 57 cmdId: 0a payload: e1 05 00 64 03 00 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a1 00 00 00 06 a1 00 64 64 a1 96 64 64 a1 78 64 64 a1 5a 64 64 a1 3c 64 64 a1 1e 64 64 len:161
[BLE Write  =>] UUID: 0000ff01-0000-1000-8000-00805f9b34fb data: 0x 0a e1 05 00 64 03 00 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a1 00 00 00 06 a1 00 64 64 a1 96 64 64 a1 78 64 64 a1 5a 64 64 a1 3c 64 64 a1 1e 64 64 - header : 00 39 80 00 00 36 37  - full: 00 39 80 00 00 36 37 0a e1 05 00 64 03 00 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a1 00 00 00 06 a1 00 64 64 a1 96 64 64 a1 78 64 64 a1 5a 64 64 a1 3c 64 64 a1 1e 64 64
[BLE Notify <=] UUID: 0000ff02-0000-1000-8000-00805f9b34fb data: 0x  ea 81 01 00 c2 03 23 62 03 64 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00 - header : 04 5f 80 00 00 19 1a 16 - full: 04 5f 80 00 00 19 1a 16 ea 81 01 00 c2 03 23 62 03 64 f0 00 00 00 00 00 01 01 90 00 00 01 02 03 00

phone music mode

Byte Index Field Name Description
0 ? 0xe2
1 Mode 0x0a for music
2 -18 volume ?
Note, this is preceeded by the ox05 mudic mode setting.
payload with values send several times per second
payload: e2 0a 01 01 01 04 05 06 05 04 03 02 01 01 00 00 00 00 00 00 00 00 len:65

🛠️ Color Calibration Protocol

The calibration process is used to map the app's logical color commands (Red, Green, Blue) to the specific physical output pins on the LED controller. This fixes issues where selecting "Red" might turn the lights "Green" or "Blue" due to different LED strip wiring standards (e.g., RGB vs. GRB vs. RBG).

Parent Opcode: 0xE0 (Direct Control)

1. Sequence Overview

The calibration process follows a strict three-step sequence:

  1. Raw Channel Test (0x15): The app lights up physical pins one by one (bypassing current software mapping) and asks the user what color they see.
  2. Set Mapping (0x13): Based on user input, the app calculates the correct pin order and sends it to the device.
  3. Save & Exit (0x0E): The app tells the device to save this configuration to flash memory.

2. Step 1: Raw Channel Preview

Sub-Command: 0x15

This command drives specific hardware channels directly with a 0-255 intensity value. It ignores any previously saved color calibration.

Format: 0A E0 15 00 00 [Ch1] [Ch2] [Ch3] [Ch4] [Ch5]

Byte Value Description
0 0x0A Protocol Header
1 0xE0 Opcode
2 0x15 Mode: Raw Channel Test
3-4 0x00 Reserved
5 0x00-0xFF Physical Pin 1 Intensity (Default: Red Pin)
6 0x00-0xFF Physical Pin 2 Intensity (Default: Green Pin)
7 0x00-0xFF Physical Pin 3 Intensity (Default: Blue Pin)
8 0x00-0xFF Physical Pin 4 (Warm White)
9 0x00-0xFF Physical Pin 5 (Cool White)

Example from Logs:

  • e0 15 00 00 ff 00 00... -> Turns on Pin 1 to Max.
  • e0 15 00 00 00 ff 00... -> Turns on Pin 2 to Max.

3. Step 2: Set Channel Mapping

Sub-Command: 0x13

This command defines which physical pin corresponds to which logical color.

Format: 0A E0 13 [R_Map] [G_Map] [B_Map] [W_Map] [CW_Map]

Byte Value Description
0 0x0A Protocol Header
1 0xE0 Opcode
2 0x13 Mode: Set Channel Mapping
3 Index Logical Red maps to Physical Pin Index X
4 Index Logical Green maps to Physical Pin Index Y
5 Index Logical Blue maps to Physical Pin Index Z
6 Index Logical Warm White Map
7 Index Logical Cool White Map

Mapping Logic:

  • 00 = Pin 1
  • 01 = Pin 2
  • 02 = Pin 3

Example: If the strip is RGB (Standard): Payload is 00 01 02 (Red=Pin1, Green=Pin2, Blue=Pin3). If the strip is GRB (Common): Payload is 01 00 02 (Red=Pin2, Green=Pin1, Blue=Pin3).

Log Data:

e0 13 00 01 02 03 04 05

  • Red = Pin 0
  • Green = Pin 1
  • Blue = Pin 2
  • (This sets the device to standard RGB order).

4. Step 3: Save Configuration

Sub-Command: 0x0E

Finalizes the procedure. The device writes the mapping from Step 2 into non-volatile memory and returns to normal operation mode.

Format: 0A E0 0E 01

Byte Value Description
0 0x0A Header
1 0xE0 Opcode
2 0x0E Mode: Calibration Config
3 0x01 Action: Save / Confirm

📡 Lower Transport Layer Message Structure

This document explains the structure of the encoded messages and the meaning of each header field used in the LowerTransportLayerEncoder. (this is part of the android remote control app)


🔹 General Message Layout

Messages are composed of a header followed by the payload data.
Depending on the segmentation, headers can be 8 bytes (first segment) or 6 bytes (continuation segments).

Single Segment Message

[ 8-byte header ] + [ payload ]

First Segment of Multi-Segment Message

[ 8-byte header ] + [ first payload chunk ]

Continuation Segment

[ 6-byte header ] + [ subsequent payload chunk ]


🔹 Header Byte Definitions

8-Byte Header (First Segment)

Byte Index Field Name Description
0 Control Byte Bit-packed flags (protection, acknowledgment, multiline, header version).
1 Sequence Number Identifies the transport sequence.
2–3 Line ID 16-bit identifier for the message line.
4–5 Payload Length 16-bit total payload length.
6 Segment Length Length of this segment’s payload chunk.
7 Command ID Identifies the command associated with the payload.

6-Byte Header (Continuation Segment)

Byte Index Field Name Description
0 Control Byte Bit-packed flags (protection, acknowledgment, multiline, header version).
1 Sequence Number Identifies the transport sequence.
2–3 Segment ID 16-bit segment identifier. Last segment is marked with MSB = 1.
4 Chunk Size Size of the payload chunk in this segment.

🔹 Control Byte Bit Layout

The Control Byte (Byte 0) encodes multiple flags:

Bit Position Meaning
7 Always cleared (reserved).
6 Multiline flag1 if message is segmented, 0 if single segment.
5 Protection flag1 if payload is protected, 0 otherwise.
4 Acknowledgment flag1 if acknowledgment required.
3–1 Always cleared (reserved).
0–1 (LSBs) Header Version (2 bits). (0) in all known cases

🔹 Segment Identification

  • Line ID (Bytes 2–3 in first segment): Identifies the logical message line.
  • Segment ID (Bytes 2–3 in continuation segment):
    • Normal segments: sequential index.
    • Last segment: MSB (bit 15) set to 1(32768 | segmentIndex).

🔹 Example Flow

  1. Single short payload → Encoded with 8-byte header + payload. (byte 2-3 will be 0x80 00)
  2. Large payload → Split into:
    • First segment: 8-byte header + first chunk.
    • Continuation segments: 6-byte header + subsequent chunks.
    • Last segment marked with MSB in Segment ID.

📡 Surplife / Magic Home BLE Protocol (Unofficial)

📋 Protocol Basics

  • Target Device: LED Curtain
  • Device Model Identifier: 0xC2
  • Service UUID: 0000f000-0000-1000-8000-00805f9b34fb (Standard Surplife Service)
  • Write Characteristic: 0000ff01-0000-1000-8000-00805f9b34fb
  • Notify Characteristic: 0000ff02-0000-1000-8000-00805f9b34fb
  • Endianness:
    • Transport Layer: Big Endian (Network Byte Order).
    • Frame Sizes (0xEA 02): Little Endian.
    • Payload Data: Mixed/Context dependent.

1. Transport Layer (Segmentation)

The Bluetooth LE MTU is limited (often 20-23 bytes). This protocol wraps all application commands in a Transport Layer header to handle fragmentation and reassembly of large messages (like images or long animations).

Header Structure

The header size changes depending on whether it is the start of a message or a continuation.

Type A: First Packet (8 Bytes + Payload) Used for single-packet commands or the first packet of a multi-packet message.

Byte Field Description
0 Control Flags.
0x00: Single Packet (Complete).
0x40: Start of Fragmented Message (More packets follow).
1 Seq Sequence Number. Increments (0-255) with every new request.
2 Line ID (H) Line Identifier High. Usually 0x80?
3 Line ID (L) Line Identifier Low. Usually 0x00.
4 Total Len (H) Total Application Payload Length (High Byte).
5 Total Len (L) Total Application Payload Length (Low Byte).
6 Seg Len Length of the payload data contained in this specific packet.
7 Cmd ID Application Opcode. Almost always 0x0A.

Type B: Continuation Packet (6 Bytes + Payload) Used for the 2nd, 3rd... Nth packet of a fragmented message.

Byte Field Description
0 Control Same as above (0x40 typically, or 0x00 if it's the very last physical packet, though logic varies).
1 Seq Sequence Number (Matches the First Packet).
2 Seg ID (H) Segment Identifier High.
Bit 7 (MSB): 1 (0x80) = This is the Last Segment.
Bit 7 (MSB): 0 (0x00) = More segments follow.
3 Seg ID (L) Segment Index. Increments sequentially (0, 1, 2...).
4 Seg Len Length of payload in this packet.
5 Reserved 0x00.

Example (Single Packet Construction): To send E2 0B 01 FF (Red Light): 00 15 80 00 00 05 05 0A [E2 0B 01 FF]

  • 00: Single Packet.
  • 15: Sequence 21.
  • 00 05: Total payload is 5 bytes (0A + 4 bytes data).
  • 05: This packet contains 5 bytes.
  • 0A: App Layer Opcode.

2. Application Layer Commands

Note: All examples below represent the Payload portion only (excluding the Transport Header).

⚙️ System Commands

🕒 Time Synchronization (0x10)

Sent immediately after connection to sync the device clock for scheduled timers.

Byte Name Description
0 Opcode 0x10 (Set Time)
1 Century 0x14 (20xx)
2 Year 0x19 (xx25)
3 Month 0x0B (November)
4 Day 0x1C (28th)
5 Hour 0x13 (19:00 / 7PM)
6 Minute 0x20 (32 min)
7 Second 0x26 (38 sec)
8 Weekday 0x05 (Friday. 1=Mon...7=Sun)
9 Reserved 0x00

Example: 10 14 19 0b 1c 13 20 26 05 00 (Fri Nov 28 2025, 19:32:38)

📟 Device Status Report (0xEA)

Received via Notification (0000ff02) in response to commands or heartbeats. Note: The meaning of the data bytes changes based on the active mode.

Structure: EA 81 01 [Mode] [Model] [HW] [FW_Maj] [FW_Min] [Data1] [Data2] F0 ...

Byte Value Meaning
0 0xEA Opcode
1 0x81 Device Type
2 0x01/00 Power (On/Off)
3 0x00 Mode (Generic)
4 0xC2 Model Identifier: LED Curtain
5 0x03 Hardware Version
6-7 23 66 Firmware Version (v3.35.102)
8 Data 1 Current Effect ID
9 Data 2 Context Dependent:
Static Mode: Brightness (0-100).
Effect/Anim/Text Mode: Speed (0-100).
Music Mode: Fixed/Ignored.
10 0xF0 Delimiter

🎨 Basic & Effect Control

💡 Single Static Color (0xE2 0B)

Sets the entire curtain to one color using a Hue/Brightness model.

Byte Name Description
0 Opcode 0xE2 (Extended Mode)
1 Sub-Cmd 0x0B (Single Color)
2 Hue 0x00-0xFF (Mapped from 0-360° color wheel).
3 Brightness 0x00-0xFF (0-100% Intensity).

Example: E2 0B 01 FF (Red at 100% Brightness)

🪄 Built-in Effects (0xE0 02)

Activates factory presets (Rainbow, Strobe, etc.).

Byte Name Description
0 Opcode 0xE0 (Direct Control)
1 Mode 0x02 (Built-in Effect)
2 Reserved 0x00
3 Effect ID 0x00 - 0x11 (The animation pattern ID).
4 Speed 0x00 - 0x64 (0-100%).
5 Brightness 0x00 - 0x64 (0-100%).

Example: E0 02 00 05 32 32 (Effect #5, 50% Speed, 50% Brightness)


🎵 Music Modes

🎤 Phone Microphone Mode (0xE2 0A)

Used when the App is analyzing audio. Streams real-time frequency/amplitude data. These packets are sent rapidly (e.g., 10-20 times per second).

Byte Name Description
0 Opcode 0xE2
1 Sub-Cmd 0x0A (External Audio Stream)
2 Band 1 Amplitude for Column/Band 1 (0x00-0x64).
3 Band 2 Amplitude for Column/Band 2.
... ... ...
N Band N Amplitude for Column/Band N.

Example: E2 0A 01 02 05 08 0F 20 40 64... (Visualizer Data)

📻 Internal Device Mic (0xE1 05)

Used when the Device is analyzing audio via its own microphone.

Byte Name Description
0 Opcode 0xE1
1 Sub-Cmd 0x05 (Set Config)
2 Flag 0x00=Switch Effect, 0x01=Update Params.
3 Brightness 0x00-0x64 (0-100%).
4 Effect ID 0x00-0x0D (Rhythm pattern).
5 Variant 0x00 or 0x02 (Sub-variant of effect).
6 Reserved 0x00 or 0x06.
7 Sensitivity 0x00-0x64 (Mic Sensitivity).
8+ Palette 0xA1... (Color array).

Example: E1 05 00 64 01 00 00 32 A1 00 64 64... (Effect 1, 100% Bri, 50% Sens)


🖼️ Advanced Modes

🖌️ Individual LED Control (Painting Mode)

Allows direct control of individual pixels via a bitmask. Addressing: The matrix is addressed Column-Major. Bit 0 is Top-Left. Bit 1 is the pixel below it.

Sequence:

  1. Clear Canvas (0xE2 0D): Resets the buffer.
    • Payload: E2 0D [90 00 00 90 00 00...] (Flood fill off).
  2. Paint/Erase (0xE2 0C): Updates specific pixels to a specific color.

Update Pixel Payload (0xE2 0C):

Byte Name Description
0 Opcode 0xE2
1 Sub-Cmd 0x0C
2 Marker 0x90
3 Hue 0x01-0xFF: Paint Color. 0x00: Erase.
4 Brightness 0x01-0xFF: Paint Intensity. 0x00: Erase.
5+ Bitmask 159 Bytes. 1 Bit = 1 Pixel.
1: Apply color/erase to this pixel.
0: Leave pixel unchanged.

Example (Paint Red): E2 0C 90 01 FF [Bitmask...]

🎬 Animation Control (0xE2 09)

Controls the playback of a custom GIF or DIY animation (uploaded via 0xEA).

Byte Name Description
0 Opcode 0xE2
1 Sub-Cmd 0x09
2 Enable 0x01 (Play), 0x00 (Stop).
3 Speed 0x00-0x64 (Animation Speed).
4 Brightness 0x00-0x64 (Global Brightness).
5 Mode 0x00 (Looping), 0x02 (Static/Once).

Example: E2 09 01 1F 64 00 (Play Loop, Speed 31%, Brightness 100%)

🔤 Text Mode Protocol

Requires two steps: Uploading the bitmap, then configuring the display.

Step 1: Upload Bitmap (0xE2 04)

  • Payload: E2 04 00 00 [Bitmap Data...]
  • Contains the pixel data for the text.

Step 2: Text Control (0xE2 05)

Byte Name Description
0 Opcode 0xE2
1 Sub-Cmd 0x05
2 BG Mode 00=Static Color, 01=Dynamic Effect.
3-5 BG Params [Effect ID] [Speed/Hue] [Variance].
6-7 Reserved 0x64 0x64
8 FG Mode 00=Single Color, 01=Gradient.
9 FG Param 1 Gradient Direction / Type.
10 FG Param 2 Start Hue.
11 FG Param 3 End Hue.
12 FG Param 4 Saturation/Brightness.
13 Speed 0x00-0x64 (Scroll Speed).
14 Brightness 0x00-0x64 (Global Brightness).
15 Direction 02=Left, 03=Right, 04=Up, 05=Down.

Example: E2 05 00 00 07 00 64 64 01 00 00 01 1E 32 64 04


3. Frame Buffer Protocol (0xEA)

Used to upload Static Images, Animations, and Text Bitmaps.

  • Compression: Data is compressed (Algorithm unknown, likely RLE).
  • Addressing: Data is Column-Major.

Sequence

1. Start Upload (0xEA 01)

Byte Value Description
0-1 EA 01 Opcode
2 01 Index
5 Count Total Frames (e.g., 0x01 for image, 0x4E for GIF).
6 Res Resolution width (0x20).

2. Size Table (0xEA 02) Sends a list of frame sizes so the device knows how to parse the data stream.

Byte Value Description
0-1 EA 02 Opcode
6+ Sizes List of 2-byte sizes (Little Endian) for each frame.

3. Data Stream (0xEA 03) The payload is split into multiple transport packets.

Byte Value Description
0-1 EA 03 Opcode
2 Block H Block Index High.
3 Block L Block Index Low (Increments 1, 2, 3...).
4+ Data Compressed Pixel Data.

4. Commit (0xEA 04) Payload: EA 04 00. Tells the device to render the uploaded buffer.


🛠️ Calibration (Pin Mapping)

Used if Red/Green/Blue colors are swapped.

Step 1: Raw Test (0xE0 15) Directly drives physical pins to identify wiring. E0 15 00 00 [Ch1] [Ch2] [Ch3] [W] [CW] (Values 0-255).

Step 2: Set Mapping (0xE0 13) Sets the logical mapping. E0 13 [R_Idx] [G_Idx] [B_Idx]...

  • 00 01 02 = Standard RGB.
  • 01 00 02 = GRB.

Step 3: Save (0xE0 0E) E0 0E 01 (Write to flash).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment