The card applies this image at boot. The vendor's
CSendAndSaveRcvParam::GetRcvParamBufForSPIFlash (libCLTDevice @ 0x1eb270)
builds it as a fixed-offset scatter of pack bodies. There is no per-region
framing, length, terminator or checksum; the host-side region directory that
drives the scatter is not itself written to flash.
The map below comes from the disassembly and is pinned against the day-one
flash dump (block 7 at 0x70000; the dump is kept outside the repository and
the tests skip without it): Block7Builder in
crates/rcvbp/src/image/ rebuilds that block byte-exactly from erased
flash (crates/rcvbp/tests/day_one.rs).
Pages no directory entry covers are never written and read back as erased
flash (0xFF): 0x900 (when there is no chip block), 0xD00-0xFFF,
0x2800-0x2FFF, 0x6400-0x67FF (single scan table), and everything after the
embedded .rcvbp.
Page 0xF0 (flash 0x7F000) is the mirror of the card's on-board EEPROM and is not part of the image. It is not only a screen-size record: bytes 0x02..0x2b are the control area (startX, startY, endX, endY) that decides which pixels this card keeps. See receiver-identity.md and eeprom-map.md. A block-0x07 erase clears it, and nothing in this image restores it.
| image | len | content | derivation | for one 128x64 module |
|---|---|---|---|---|
| 0x0000 | 0x100 | basic-parameter pack body (GetBasicParam @ 0x1dfb50, pack+4) |
spec / record fields, see record-0x01-fields.md; generated by spec/basic_pack.rs |
geometry fields change |
| 0x0100 | 0x400 | void table (GetVoidTablePack @ 0x1e5710) |
mode byte OBJ[0xc3a0] = 0 makes the builder error out: zeros | zeros |
| 0x0500 | 0x100 | data-swap pack body (GetDataSwapEx2ParamPack @ 0x1ec700) |
64-byte lane map = record 0x01 +0x19A..0x1D9 (identity 0x40..0x7F); zeros; three deseam pairs at +0xEA/+0xF0/+0xF6 = 01 00 (8.8 fixed-point 1.0, deseam off) |
unchanged |
| 0x0600 | 0x300 | module-position pack body (type 0x17, pack+5) | GetDefaultModulePos @ 0x1558b0: screen (MaxW x MaxH) tiled by the grid unit (record +0x057/+0x058 lo, +0x24E/+0x24F hi = 16x16); count at +0x005; 10-byte entries from +0x016: [outer, inner, x BE, y BE, w BE, h BE]. Direction variants: line_dir 0 (R2L) [row, nc-1-col] compacted, 1 (L2R) [row, col] compacted, 2 (T2B) [col, row] positional, 3 (B2T) [nc-1-col, nr-1-row] positional; R2L/L2R drop tiles with inner index >= 8 and rows >= 32. All-zero when tiles > 64 (the reference file's 256x384 wall = 384 tiles) |
non-zero: count 0x20, 32 entries |
| 0x0900 | 0x100 | chip-register block (record 0x84 verbatim, pack+4) | written only if IsMultiRegisterChip(): true for chip 0x14C in LEDVISION 9.6 / iSet 7; false in the older tool that produced the day-one image (the page is 0xFF there). ExchangeChipRegisterWhenColorChanged @ 0x1ea370 (via the DP5525 handler for this chip) permutes per-colour registers only when the colour source triple (+0x02C..0x02E) is exchanged; for (2,1,0) all three branches fall through (identity) |
optional (boot.arm_at_boot) |
| 0x0A00 | 0x200 | current segment (CChipCurrentCalculator::GetCurrentSegmentBuf @ 0x0d4860) |
chip-id range check 0x14C-8 > 0xFB fails: zeros |
zeros |
| 0x0C00 | 0x100 | current exchange (GetCurrentExchangeParam @ 0x1adb20) |
a hub-data-group to module-index map, one byte per group; with a single module every group maps to module 0, so the vendor's output is the all-zero buffer it starts from | zeros |
| 0x1000 | 0x800 | void-line packs 0-1 (type 0x1F, pack+8): 1024 per-line byte offsets at 0x1000, 1024 per-column offsets at 0x1400, physical = a + table[a] |
the vendor writes zeros (no void lines). Block7Builder::void_line_columns sets the column entries width..2*width to 0xFF when mapping.gate_phantom_positions is on (default), displacing the positions the card drives with a fixed pattern off the chain (rendering.md) |
line half zeros; column half 0xFF at 128..256 |
| 0x1800 | 0x1000 | anti-void-line packs 0-3 (type 0x32, pack+8) | GetAntiVoidLineParam @ 0x1604d0: two identical blocks of 2048 u16-BE counters 0x2000+n (bit 5 = marker, bit 7 cleared for every line since none are void), sliced 4 x 0x400 |
unchanged |
| 0x3000 | 0x3000 | pixel-sequence packs x16 (type 0x03, pack+4) | record 0x03 (the mapping): 4096 entries (flag, u16), u16 flipped LE to BE, sliced into 16 x 256 entries; ExchangePixelSequence is identity here |
unchanged (per module) |
| 0x6000 | 0x400 | scan table (GetScanTable @ 0x1eabc0 calling CalScanTalbeDefault @ 0x14d710) |
generated (image/scan_table.rs): InitFieldTable16Segment picks the 16-slot level and a hand-coded per-gray block (14-bit transcribed); FromSegmentToFrameTime @ 0x1d0a70 assigns bit times 2^L * minOE / seg snapped to 8-unit quanta (all zero at the vendor's minOE = 1e-4); FieldTableToScanTable @ 0x1d1c00 buckets slots by slot % nSeg and emits (level, 24-bit BE value/8) with (start, end) pairs at +0x3C0; the tail writes the scan mode and an identity line order. Byte-exact against the day-one for both 512- and 256-clock loads (the width only enters a frame-time estimate; the_scan_table_is_invariant_to_the_load_width_for_this_chip) |
unchanged, computed |
| 0x6800 | 0x800 | void-line packs 2-3 | zeros | zeros |
| 0x7000 | 0x1000 | anti-void packs 4-7 | only 4 packs without large-load (> 1024 px) support: zeros | zeros |
| 0x8000 | u32-LE length + the .rcvbp source (clamped at 0x6FFC) |
verbatim | regenerated |
Pack header sizes, for converting pack offsets to image offsets: type 0x05 (basic / data-swap / chip) 4; 0x10 / 0x18 / 0x03 4; 0x1F / 0x32 8; 0x17 5.
rxp config gen --spec config/panels/<panel>.toml builds the image from
erased flash in this order (Block7Builder::from_generated; a later placement
wins an overlapping page): zero regions, basic pack, data-swap, module
positions, anti-void counters, void-line columns, mapping, scan table, then
the chip page (if boot.arm_at_boot) and the embedded .rcvbp. Every byte
comes from the spec, the chip library or a decoded formula; the sources file
names which.
- 0x1800-0x27FF is anti-void-line counter data, not two gamma LUTs.
- The data-swap tail bytes are deseam fixed-point 1.0, not padding.
- The scan-table bytes are the renderer's output (48 3-entry rows, scalars, line order, start/end pairs), not a copied template.
- The void-line and anti-void ranges are one pack array each, split across two image ranges (packs 0-1 / 2-3 and 0-3 / 4-7), not independent tables.
GetScanTableis at 0x1eabc0 andGetDataSwapEx2ParamPackat 0x1ec700.
- The scan-table solver is transcribed for the default style, 16 segments and 14-bit gray; other gray depths need their own hand-coded vendor blocks.
- Module-position generation covers the plain grid (split segment 1).
- The chip page is written only for
arm_at_boot = true; measured: booting from flash with it written arms the drivers on every power-cycle.