uzbek-plus/b9/b9b/gen-patterns.py
q 4a7224c41f B9: built-in display (ST7735S SPI) in Linux and persistent B9C cache
- B9A: read-only audit of stock LK/DT: the panel is an ST7735S 128x128 on SPI (BLSP1 QUP4,
  16 MHz, mode 3, D/C GPIO116, RESET GPIO118), backlight = PM8916 MPP4 current sink 40 mA.
- B9B: upstream panel-mipi-dbi with the stock init sequence as firmware; MPP4 sink via pinctrl
  + gpio-backlight; first light with correct colours/orientation/offsets.
- B9C: fbcon (6x8, 21x16) on tty1 + getty, UART console kept, aurora-display service;
  cache B9C b9ce13c9 written and verified, cold boots with LTE + Wi-Fi + display.
- B9L (RAM only): lk2nd second stage with an msm8916 SPI panel port shows a picture before Linux.
- Sanitizer: whitelist for b8/ and b9/.
2026-10-03 01:45:02 +03:00

56 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""B9B: 128x128 test frames for /dev/fb0, in RGB565 (little-endian u16, fb native) and XRGB8888, plus PNG previews.
Frames: red, green, blue, white, black, and 'geo' = geometry/orientation/colour chart:
- 1-px white border on the outermost rows/columns (all 4 edges must be visible -> no crop/offset error),
- 2nd row/column inside the border black (a 1-px shift shows up as a doubled or missing line),
- corner blocks 24x24: top-left RED, top-right GREEN, bottom-left BLUE, bottom-right WHITE,
- centre: 3 vertical bars R | G | B (rows 40..87), and a yellow arrow pointing UP above them.
usage: gen-patterns.py outdir"""
import os, struct, sys, zlib
W = H = 128
O = sys.argv[1]; os.makedirs(O, exist_ok=True)
R, G, B, Wh, K, Y = (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 255), (0, 0, 0), (255, 255, 0)
def solid(c): return [[c] * W for _ in range(H)]
def geo():
p = solid(K)
for y in range(H):
for x in range(W):
if x in (0, W - 1) or y in (0, H - 1):
p[y][x] = Wh
elif 2 <= x < 26 and 2 <= y < 26:
p[y][x] = R
elif W - 26 <= x < W - 2 and 2 <= y < 26:
p[y][x] = G
elif 2 <= x < 26 and H - 26 <= y < H - 2:
p[y][x] = B
elif W - 26 <= x < W - 2 and H - 26 <= y < H - 2:
p[y][x] = Wh
elif 40 <= y < 88 and 28 <= x < 100:
p[y][x] = (R, G, B)[(x - 28) // 24]
elif 6 <= y < 34 and abs(x - 63.5) <= (y - 6) * 0.5 and y < 22: # arrow head
p[y][x] = Y
elif 22 <= y < 34 and 58 <= x < 70: # arrow shaft
p[y][x] = Y
return p
def rgb565(p): return b''.join(struct.pack('<H', (r >> 3) << 11 | (g >> 2) << 5 | b >> 3) for row in p for (r, g, b) in row)
def xrgb8888(p): return b''.join(struct.pack('<I', r << 16 | g << 8 | b) for row in p for (r, g, b) in row)
def png(path, p, s=2):
def ch(t, b): return struct.pack('>I', len(b)) + t + b + struct.pack('>I', zlib.crc32(t + b) & 0xffffffff)
rows = []
for row in p:
line = b'\0' + b''.join(bytes(c) * s for c in row)
rows += [line] * s
open(path, 'wb').write(b'\x89PNG\r\n\x1a\n' + ch(b'IHDR', struct.pack('>IIBBBBB', W * s, H * s, 8, 2, 0, 0, 0))
+ ch(b'IDAT', zlib.compress(b''.join(rows))) + ch(b'IEND', b''))
frames = {'red': solid(R), 'green': solid(G), 'blue': solid(B), 'white': solid(Wh), 'black': solid(K), 'geo': geo()}
for n, p in frames.items():
open(f'{O}/{n}.565', 'wb').write(rgb565(p))
open(f'{O}/{n}.8888', 'wb').write(xrgb8888(p))
png(f'{O}/geo-expected.png', frames['geo'], 3)
print('ok', sorted(os.listdir(O)))