Adding loop function
This commit is contained in:
+32
-13
@@ -28,7 +28,7 @@ SHOWS_DIR = SCRIPT_DIR / "shows"
|
||||
SKETCH_DIR = ROOT_DIR / "arduino" / "cosplay_lights"
|
||||
|
||||
# The special first show — always placed at index 0.
|
||||
HOME_SHOW = "blue_pulse"
|
||||
HOME_SHOW = "blue_breath"
|
||||
|
||||
# Regex to match a valid step line: #RRGGBB, duration_ms
|
||||
STEP_PATTERN = re.compile(r'^\s*#([0-9A-Fa-f]{6})\s*,\s*(\d+)')
|
||||
@@ -36,6 +36,16 @@ STEP_PATTERN = re.compile(r'^\s*#([0-9A-Fa-f]{6})\s*,\s*(\d+)')
|
||||
|
||||
# ---- Helpers -----------------------------------------------------------
|
||||
|
||||
def parse_mode(filepath: Path) -> str:
|
||||
"""Return the C mode constant for this show. Defaults to SHOW_LOOP."""
|
||||
with open(filepath) as f:
|
||||
for line in f:
|
||||
m = re.match(r'^\s*//\s*mode:\s*(\w+)', line, re.IGNORECASE)
|
||||
if m:
|
||||
return "SHOW_SINGLE" if m.group(1).lower() == "single" else "SHOW_LOOP"
|
||||
return "SHOW_LOOP"
|
||||
|
||||
|
||||
def filename_to_symbol(stem: str) -> str:
|
||||
"""Convert a filename stem to an uppercase C array symbol. e.g. 'example_fade' → 'SHOW_EXAMPLE_FADE'"""
|
||||
clean = re.sub(r'[^a-zA-Z0-9]', '_', stem)
|
||||
@@ -94,15 +104,15 @@ def render_show_header(steps: list, source_name: str, symbol: str) -> str:
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def render_shows_index(ordered_stems: list[str]) -> str:
|
||||
"""Render the master shows.h index file."""
|
||||
includes = "\n".join(f'#include "show_{stem}.h"' for stem in ordered_stems)
|
||||
def render_shows_index(ordered: list[tuple[str, str]]) -> str:
|
||||
"""Render the master shows.h index file. ordered = [(stem, mode_constant), ...]"""
|
||||
includes = "\n".join(f'#include "show_{stem}.h"' for stem, _ in ordered)
|
||||
entries = "\n".join(
|
||||
f" {{{filename_to_symbol(s)}, {filename_to_symbol(s)}_LENGTH}},"
|
||||
f" {{{filename_to_symbol(s)}, {filename_to_symbol(s)}_LENGTH, {mode}}},"
|
||||
+ (" // 0 — home show" if i == 0 else f" // {i}")
|
||||
for i, s in enumerate(ordered_stems)
|
||||
for i, (s, mode) in enumerate(ordered)
|
||||
)
|
||||
count = len(ordered_stems)
|
||||
count = len(ordered)
|
||||
return f"""\
|
||||
// =====================================================================
|
||||
// shows.h — Master show index.
|
||||
@@ -110,7 +120,7 @@ def render_shows_index(ordered_stems: list[str]) -> str:
|
||||
// Do not edit manually — add .txt files to converter/shows/ instead.
|
||||
// =====================================================================
|
||||
//
|
||||
// Show 0 is always the home/reset show (slow blue pulse).
|
||||
// Show 0 is always the home/reset show (blue breath).
|
||||
// Holding the button resets back to show 0.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
@@ -133,7 +143,7 @@ const uint8_t SHOW_COUNT = {count};
|
||||
# ---- Main --------------------------------------------------------------
|
||||
|
||||
def main() -> None:
|
||||
txt_files = sorted(SHOWS_DIR.glob("*.txt"))
|
||||
txt_files = sorted(SHOWS_DIR.glob("*.txt"), key=lambda p: p.stem.lower())
|
||||
if not txt_files:
|
||||
print(f"No .txt files found in {SHOWS_DIR}")
|
||||
sys.exit(1)
|
||||
@@ -150,19 +160,20 @@ def main() -> None:
|
||||
|
||||
SKETCH_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
converted = []
|
||||
converted = [] # list of (stem, mode_constant)
|
||||
errors = []
|
||||
|
||||
for txt_path in ordered_files:
|
||||
stem = txt_path.stem
|
||||
symbol = filename_to_symbol(stem)
|
||||
mode = parse_mode(txt_path)
|
||||
try:
|
||||
steps = parse_show(txt_path)
|
||||
header = render_show_header(steps, txt_path.name, symbol)
|
||||
out = SKETCH_DIR / f"show_{stem}.h"
|
||||
out.write_text(header, encoding="utf-8")
|
||||
print(f" OK {txt_path.name} → show_{stem}.h ({len(steps)} steps)")
|
||||
converted.append(stem)
|
||||
print(f" OK {txt_path.name} → show_{stem}.h ({len(steps)} steps, {mode})")
|
||||
converted.append((stem, mode))
|
||||
except ValueError as e:
|
||||
print(f" ERR {e}")
|
||||
errors.append(stem)
|
||||
@@ -174,10 +185,18 @@ def main() -> None:
|
||||
print("No shows converted — shows.h not updated.")
|
||||
sys.exit(1)
|
||||
|
||||
# Remove stale show_*.h files no longer in the converted list.
|
||||
expected = {SKETCH_DIR / f"show_{stem}.h" for stem, _ in converted}
|
||||
for stale in SKETCH_DIR.glob("show_*.h"):
|
||||
if stale not in expected:
|
||||
stale.unlink()
|
||||
print(f" RM {stale.name} (removed — no matching .txt file)")
|
||||
|
||||
# Regenerate shows.h
|
||||
index_path = SKETCH_DIR / "shows.h"
|
||||
index_path.write_text(render_shows_index(converted), encoding="utf-8")
|
||||
print(f"\n OK shows.h updated ({len(converted)} shows, show 0 = {converted[0]})")
|
||||
stems = [s for s, _ in converted]
|
||||
print(f"\n OK shows.h updated ({len(converted)} shows, show 0 = {stems[0]})")
|
||||
print( " Run 'make upload' to compile and send to the Arduino.")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Blue breath — home / reset show (always index 0)
|
||||
// A slow, natural breathing effect in deep blue.
|
||||
// Loops continuously as the default show.
|
||||
//
|
||||
// mode: loop
|
||||
// Format: #RRGGBB, duration_ms
|
||||
|
||||
#050018, 0 // snap to near-black blue — sets the starting point
|
||||
#2020FF, 2500 // breathe in — slow rise to bright blue
|
||||
#2020FF, 400 // hold at peak
|
||||
#050018, 2500 // breathe out — slow fall to near-black
|
||||
#050018, 800 // pause before next breath
|
||||
@@ -1,9 +0,0 @@
|
||||
// Blue pulse — home / reset show (always index 0)
|
||||
// A slow, gentle breathing effect in deep blue.
|
||||
// Loops continuously as the default show.
|
||||
//
|
||||
// Format: #RRGGBB, duration_ms
|
||||
|
||||
#050025, 0 // snap to dim blue — sets the starting point
|
||||
#2828FF, 3000 // slow breathe up to bright blue
|
||||
#050025, 3000 // slow breathe back down to dim
|
||||
Reference in New Issue
Block a user