Skip to content

Commit 60d07d9

Browse files
committed
chore: update version tag to v1.5.5
1 parent b13043d commit 60d07d9

5 files changed

Lines changed: 416 additions & 5 deletions

File tree

Source/fpbinject_version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
#define FPBINJECT_VERSION_MAJOR 1
1515
#define FPBINJECT_VERSION_MINOR 5
16-
#define FPBINJECT_VERSION_PATCH 4
16+
#define FPBINJECT_VERSION_PATCH 5
1717

18-
#define FPBINJECT_VERSION_STRING "v1.5.4"
18+
#define FPBINJECT_VERSION_STRING "v1.5.5"
1919

2020
#endif /* FPBINJECT_VERSION_H */

Tools/WebServer/fb_fill.py

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
#!/usr/bin/env python3
2+
"""Framebuffer fill script - writes color patterns via fpb_cli mem-write"""
3+
4+
import subprocess
5+
import sys
6+
import os
7+
import time
8+
import argparse
9+
10+
# 默认参数
11+
DEFAULT_PORT = "/dev/ttyACM1"
12+
DEFAULT_BAUDRATE = 921600
13+
DEFAULT_FB_ADDR = 0x2005E000
14+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
15+
CLI_PATH = os.path.join(SCRIPT_DIR, "cli", "fpb_cli.py")
16+
17+
# 常用颜色 (RGB565 big-endian)
18+
COLORS = {
19+
"red": "F800",
20+
"green": "07E0",
21+
"blue": "001F",
22+
"white": "FFFF",
23+
"black": "0000",
24+
"yellow": "FFE0",
25+
"cyan": "07FF",
26+
"magenta": "F81F",
27+
"orange": "FD20",
28+
}
29+
30+
31+
def mem_write(port, baudrate, addr, data_hex):
32+
"""调用 CLI 写内存"""
33+
cmd = [
34+
sys.executable, CLI_PATH,
35+
"--port", port,
36+
"--baudrate", str(baudrate),
37+
"mem-write", hex(addr), data_hex,
38+
]
39+
env = os.environ.copy()
40+
env["PYTHONPATH"] = SCRIPT_DIR + os.pathsep + env.get("PYTHONPATH", "")
41+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10,
42+
cwd=SCRIPT_DIR, env=env)
43+
if result.returncode != 0:
44+
print(f" FAIL @ {hex(addr)}: {result.stderr.strip()}")
45+
return False
46+
return True
47+
48+
49+
def fill_solid(port, baudrate, fb_addr, width, height, color_hex):
50+
"""纯色填充"""
51+
# 每次写 128 像素 = 256 字节 = 512 hex chars
52+
chunk_pixels = 128
53+
chunk_hex = color_hex * chunk_pixels
54+
total_pixels = width * height
55+
addr = fb_addr
56+
57+
print(f"Filling {width}x{height} with #{color_hex} ({total_pixels} pixels)...")
58+
written = 0
59+
while written < total_pixels:
60+
n = min(chunk_pixels, total_pixels - written)
61+
data = color_hex * n
62+
if not mem_write(port, baudrate, addr, data):
63+
return
64+
addr += n * 2 # 2 bytes per pixel
65+
written += n
66+
pct = written * 100 // total_pixels
67+
print(f"\r Progress: {pct}% ({written}/{total_pixels})", end="", flush=True)
68+
print("\n Done!")
69+
70+
71+
def fill_stripes_h(port, baudrate, fb_addr, width, height, colors, stripe_h=16):
72+
"""水平条纹"""
73+
chunk_pixels = 128
74+
total_pixels = width * height
75+
addr = fb_addr
76+
77+
print(f"Filling {width}x{height} horizontal stripes (h={stripe_h})...")
78+
written = 0
79+
for y in range(height):
80+
color_idx = (y // stripe_h) % len(colors)
81+
color = colors[color_idx]
82+
row_written = 0
83+
while row_written < width:
84+
n = min(chunk_pixels, width - row_written)
85+
data = color * n
86+
if not mem_write(port, baudrate, addr, data):
87+
return
88+
addr += n * 2
89+
row_written += n
90+
written += width
91+
if y % 8 == 0:
92+
pct = written * 100 // total_pixels
93+
print(f"\r Progress: {pct}% (row {y}/{height})", end="", flush=True)
94+
print("\n Done!")
95+
96+
97+
def fill_stripes_v(port, baudrate, fb_addr, width, height, colors, stripe_w=32):
98+
"""垂直条纹"""
99+
chunk_pixels = 128
100+
total_pixels = width * height
101+
addr = fb_addr
102+
103+
print(f"Filling {width}x{height} vertical stripes (w={stripe_w})...")
104+
written = 0
105+
for y in range(height):
106+
# 构建一行像素
107+
row = ""
108+
for x in range(width):
109+
color_idx = (x // stripe_w) % len(colors)
110+
row += colors[color_idx]
111+
# 分块写入
112+
offset = 0
113+
while offset < len(row):
114+
chunk = row[offset:offset + chunk_pixels * 4] # 4 hex chars per pixel
115+
byte_len = len(chunk) // 2
116+
if not mem_write(port, baudrate, addr, chunk):
117+
return
118+
addr += byte_len
119+
offset += len(chunk)
120+
written += width
121+
if y % 8 == 0:
122+
pct = written * 100 // total_pixels
123+
print(f"\r Progress: {pct}% (row {y}/{height})", end="", flush=True)
124+
print("\n Done!")
125+
126+
127+
def fill_gradient(port, baudrate, fb_addr, width, height):
128+
"""红绿渐变"""
129+
chunk_pixels = 128
130+
total_pixels = width * height
131+
addr = fb_addr
132+
133+
print(f"Filling {width}x{height} gradient...")
134+
written = 0
135+
for y in range(height):
136+
row = ""
137+
for x in range(width):
138+
r = (x * 31) // width # 0-31
139+
g = (y * 63) // height # 0-63
140+
b = 0
141+
rgb565 = (r << 11) | (g << 5) | b
142+
row += f"{rgb565:04X}"
143+
offset = 0
144+
while offset < len(row):
145+
chunk = row[offset:offset + chunk_pixels * 4]
146+
byte_len = len(chunk) // 2
147+
if not mem_write(port, baudrate, addr, chunk):
148+
return
149+
addr += byte_len
150+
offset += len(chunk)
151+
written += width
152+
if y % 8 == 0:
153+
pct = written * 100 // total_pixels
154+
print(f"\r Progress: {pct}% (row {y}/{height})", end="", flush=True)
155+
print("\n Done!")
156+
157+
158+
def fill_checkerboard(port, baudrate, fb_addr, width, height, c1="F800", c2="001F", block=16):
159+
"""棋盘格"""
160+
chunk_pixels = 128
161+
total_pixels = width * height
162+
addr = fb_addr
163+
164+
print(f"Filling {width}x{height} checkerboard (block={block})...")
165+
written = 0
166+
for y in range(height):
167+
row = ""
168+
for x in range(width):
169+
if ((x // block) + (y // block)) % 2 == 0:
170+
row += c1
171+
else:
172+
row += c2
173+
offset = 0
174+
while offset < len(row):
175+
chunk = row[offset:offset + chunk_pixels * 4]
176+
byte_len = len(chunk) // 2
177+
if not mem_write(port, baudrate, addr, chunk):
178+
return
179+
addr += byte_len
180+
offset += len(chunk)
181+
written += width
182+
if y % 8 == 0:
183+
pct = written * 100 // total_pixels
184+
print(f"\r Progress: {pct}% (row {y}/{height})", end="", flush=True)
185+
print("\n Done!")
186+
187+
188+
PATTERNS = {
189+
"solid": "纯色填充",
190+
"hstripe": "水平条纹",
191+
"vstripe": "垂直条纹",
192+
"gradient": "红绿渐变",
193+
"checker": "棋盘格",
194+
"all": "依次执行所有图案",
195+
}
196+
197+
198+
def main():
199+
parser = argparse.ArgumentParser(description="Framebuffer fill via FPB CLI")
200+
parser.add_argument("--port", default=DEFAULT_PORT)
201+
parser.add_argument("--baudrate", type=int, default=DEFAULT_BAUDRATE)
202+
parser.add_argument("--addr", default=hex(DEFAULT_FB_ADDR),
203+
help=f"帧缓冲区地址 (default: {hex(DEFAULT_FB_ADDR)})")
204+
parser.add_argument("--width", type=int, default=466, help="屏幕宽度 (pixels)")
205+
parser.add_argument("--height", type=int, default=466, help="屏幕高度 (pixels)")
206+
parser.add_argument("--color", default="red", choices=list(COLORS.keys()),
207+
help="纯色填充的颜色")
208+
parser.add_argument("pattern", choices=list(PATTERNS.keys()),
209+
help="填充图案: " + ", ".join(f"{k}={v}" for k, v in PATTERNS.items()))
210+
211+
args = parser.parse_args()
212+
fb_addr = int(args.addr, 16)
213+
214+
print(f"Port: {args.port} @ {args.baudrate}")
215+
print(f"FB addr: {hex(fb_addr)}, size: {args.width}x{args.height}")
216+
print()
217+
218+
patterns_to_run = []
219+
if args.pattern == "all":
220+
patterns_to_run = ["solid", "hstripe", "vstripe", "gradient", "checker"]
221+
else:
222+
patterns_to_run = [args.pattern]
223+
224+
for pat in patterns_to_run:
225+
t0 = time.time()
226+
if pat == "solid":
227+
fill_solid(args.port, args.baudrate, fb_addr,
228+
args.width, args.height, COLORS[args.color])
229+
elif pat == "hstripe":
230+
fill_stripes_h(args.port, args.baudrate, fb_addr,
231+
args.width, args.height,
232+
["F800", "07E0", "001F", "FFFF"], stripe_h=16)
233+
elif pat == "vstripe":
234+
fill_stripes_v(args.port, args.baudrate, fb_addr,
235+
args.width, args.height,
236+
["F800", "07E0", "001F", "FFE0"], stripe_w=32)
237+
elif pat == "gradient":
238+
fill_gradient(args.port, args.baudrate, fb_addr,
239+
args.width, args.height)
240+
elif pat == "checker":
241+
fill_checkerboard(args.port, args.baudrate, fb_addr,
242+
args.width, args.height)
243+
elapsed = time.time() - t0
244+
print(f" Time: {elapsed:.1f}s\n")
245+
246+
if len(patterns_to_run) > 1:
247+
time.sleep(2)
248+
249+
250+
if __name__ == "__main__":
251+
main()

0 commit comments

Comments
 (0)