main
Rithesh03 Update 4: improved README (V1 overview, images, LED order), Version 2 proposal files b874429 13d ago
"""LED-order diagram of the finished Version 1 board, for the Wiki README.

Reads firmware/led-order.csv (LED1..LED107 positions) and writes docs/images/led-order-v1.svg / .png:
the 300 x 70 mm outline, every LED with its chain number, the data path, and the LED1 start point.

Usage: python3 docs/tools/make_led_order_diagram.py
"""
import csv
import os
import subprocess

ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
OUT = os.path.join(ROOT, "docs", "images")
W, H = 300.0, 70.0
LED = 5.0


def text(x, y, s, size, color, anchor="middle", weight="normal"):
    return (f'<text x="{x:.2f}" y="{y:.2f}" font-size="{size}" fill="{color}" text-anchor="{anchor}" '
            f'font-weight="{weight}">{s}</text>\n')


def main():
    rows = list(csv.DictReader(open(os.path.join(ROOT, "firmware", "led-order.csv"))))
    pts = [(int(r["LED"][3:]), r["letter"], float(r["x mm"]), float(r["y mm"])) for r in rows]
    pts.sort()
    assert [p[0] for p in pts] == list(range(1, 108))
    m = 8
    s = (f'<svg xmlns="http://www.w3.org/2000/svg" width="{(W + 2 * m) * 8:.0f}" height="{(H + 2 * m + 6) * 8:.0f}" '
         f'viewBox="{-m} {-m} {W + 2 * m} {H + 2 * m + 6}" font-family="DejaVu Sans, Arial, sans-serif">\n'
         f'<rect x="{-m}" y="{-m}" width="{W + 2 * m}" height="{H + 2 * m + 6}" fill="#ffffff"/>\n'
         f'<rect x="0" y="0" width="{W}" height="{H}" rx="2" fill="#1f5f3a" stroke="#333" stroke-width="0.3"/>\n')
    s += (f'<polyline points="{" ".join(f"{x:.2f},{y:.2f}" for _, _, x, y in pts)}" fill="none" '
          f'stroke="#ffb000" stroke-width="0.6" stroke-linejoin="round"/>\n')
    for n, letter, x, y in pts:
        s += (f'<rect x="{x - LED / 2}" y="{y - LED / 2}" width="{LED}" height="{LED}" rx="0.5" fill="#f4f4f4" '
              f'stroke="#111" stroke-width="0.15"/>' + text(x, y + 0.75, n, 2.1, "#111", weight="bold"))
    first, last = pts[0], pts[-1]
    s += text(first[2], first[3] - 4.3, "LED1 (data in)", 2.6, "#ffd84d", weight="bold")
    s += text(last[2], last[3] + 6.2, "LED107", 2.6, "#ffd84d", weight="bold")
    # ESP32 (x 40 mm, antenna at the bottom edge) and USB-C (x 90 mm), as placed on the V1 board
    for (x, y, w, h, label) in [(33.4, 53.4, 13.2, 16.6, "ESP32"), (85.5, 62.7, 9.0, 7.3, "USB-C")]:
        s += (f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="0.8" fill="none" stroke="#9fe39f" '
              f'stroke-width="0.4" stroke-dasharray="1.5 1"/>' + text(x + w / 2, y + h / 2 + 1, label, 2.4, "#9fe39f"))
    s += text(W / 2, H + 5.5, "RITHESH Version 1: the 107 LEDs are one chain, LED1 to LED107. Numbers = order on the data "
              "line (WLED index = number - 1). The chain zig-zags inside each letter.", 2.5, "#222")
    os.makedirs(OUT, exist_ok=True)
    p = os.path.join(OUT, "led-order-v1.svg")
    open(p, "w").write(s + "</svg>\n")
    subprocess.run(["rsvg-convert", "-o", p[:-4] + ".png", p], check=True)
    print("wrote", p, "and", p[:-4] + ".png")


if __name__ == "__main__":
    main()