From e09dbd07be0eb2306ae471aa235ad8c0f8fc4bd1 Mon Sep 17 00:00:00 2001 From: ChaosNuggets <46007806+ChaosNuggets@users.noreply.github.com> Date: Sat, 10 Feb 2024 17:16:41 -0500 Subject: [PATCH 1/9] fixed excessive RAM usage bug --- src/performance.cpp | 80 ++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/src/performance.cpp b/src/performance.cpp index 49bf79b..cf1fba7 100644 --- a/src/performance.cpp +++ b/src/performance.cpp @@ -33,44 +33,47 @@ const static Color YELLOW_3 = Color(255, 128, 0 ); const static Color ORANGE_3 = Color(255, 32, 0 ); struct Scene { - const Color start; - const Color end; + const Color& start; + const Color& end; uint32_t duration; // TODO: add types of transitions. R/G/B balanced transition or R+G+B combined transition - Scene(const Color start, const Color end, double duration) + Scene(const Color& start, const Color& end, uint32_t duration) : start(start), end(end), duration(duration) {} }; -static Scene scenes[] = { -Scene(WHITE_1, WHITE_1, 6683), -Scene(WHITE_1, YELLOW_3, 1166), -Scene(YELLOW_3, YELLOW_3, 36633), -Scene(RED_3, RED_3, 333), // // umbrella -Scene(YELLOW_3, YELLOW_3, 316), // // umbrella -Scene(RED_3, RED_3, 333), // // umbrella -Scene(YELLOW_3, YELLOW_3, 316), // // umbrella -Scene(RED_3, RED_3, 333), // // umbrella -Scene(YELLOW_3, YELLOW_3, 316), // // umbrella -Scene(RED_3, RED_3, 333), // // umbrella -Scene(YELLOW_3, YELLOW_3, 316), // // umbrella -Scene(RED_3, RED_3, 333), // // umbrella -Scene(YELLOW_3, YELLOW_3, 316), // // umbrella -Scene(RED_3, RED_3, 333), // // umbrella -Scene(YELLOW_3, YELLOW_3, 316), // // umbrella -Scene(RED_3, RED_3, 333), // // umbrella -Scene(YELLOW_3, YELLOW_3, 316), // // umbrella -Scene(RED_3, ORANGE_3, 650), // // umbrella -Scene(ORANGE_3, ORANGE_3, 21200), // // after umbrella -Scene(ORANGE_3, BLUE_3, 2733), // // transition -Scene(BLUE_3, BLUE_3, 17950), // // around the world -Scene(BLUE_3, YELLOW_3, 2733), // // transition -Scene(YELLOW_3, RED_3, 1483), // // transition -Scene(RED_3, RED_3, 17850), // // dragon -Scene(RED_3, WHITE_3, 2916), // // transition -// Scene(WHITE_3, WHITE_3, 251016), // -}; +Scene get_current_scene(uint8_t scene_num) { + switch (scene_num) { + case 1: return Scene(WHITE_1, WHITE_1, 6683); + case 2: return Scene(WHITE_1, YELLOW_3, 1166); + case 3: return Scene(YELLOW_3, YELLOW_3, 36633); + case 4: return Scene(RED_3, RED_3, 333); // // umbrella + case 5: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella + case 6: return Scene(RED_3, RED_3, 333); // // umbrella + case 7: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella + case 8: return Scene(RED_3, RED_3, 333); // // umbrella + case 9: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella + case 10: return Scene(RED_3, RED_3, 333); // // umbrella + case 11: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella + case 12: return Scene(RED_3, RED_3, 333); // // umbrella + case 13: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella + case 14: return Scene(RED_3, RED_3, 333); // // umbrella + case 15: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella + case 16: return Scene(RED_3, RED_3, 333); // // umbrella + case 17: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella + case 18: return Scene(RED_3, ORANGE_3, 650); // // umbrella + case 19: return Scene(ORANGE_3, ORANGE_3, 21200); // // after umbrella + case 20: return Scene(ORANGE_3, BLUE_3, 2733); // // transition + case 21: return Scene(BLUE_3, BLUE_3, 17950); // // around the world + case 22: return Scene(BLUE_3, YELLOW_3, 2733); // // transition + case 23: return Scene(YELLOW_3, RED_3, 1483); // // transition + case 24: return Scene(RED_3, RED_3, 17850); // // dragon + case 25: return Scene(RED_3, WHITE_3, 2916); // // transition + case 26: return Scene(WHITE_3, WHITE_3, 251016); // + } +} +const static uint8_t TOTAL_SCENES = 26; uint8_t scene_num = 0; unsigned long past_scene_durations = 0; @@ -95,7 +98,7 @@ void loop() { if (Diabolo_Light::get_current_mode() != 1) return; - Scene scene = scenes[scene_num]; + Scene scene = get_current_scene(scene_num); // Progress within current scene, from 0-1 double progress = @@ -108,17 +111,12 @@ void loop() { scene_num++; // Turn off after last scene - // if (scene_num >= sizeof(scenes) / sizeof(scenes[0])) { - // Diabolo_Light::set_current_mode(0); - // } + if (scene_num >= TOTAL_SCENES) { + Diabolo_Light::set_current_mode(0); + } } - if (scene_num >= sizeof(scenes) / sizeof(scenes[0])) { - // HACK - set_all_pixels(pixels.Color(255, 255, 255)); - return; - } - else if (scene.start == scene.end) { + if (scene.start == scene.end) { set_all_pixels(pixels.Color( scene.start.r, scene.start.g, From 3c1ee65d59a92020c078e0565567ef13db2f8099 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Fri, 16 Feb 2024 21:11:38 -0800 Subject: [PATCH 2/9] Start scene numbering at 1 --- src/performance.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/performance.cpp b/src/performance.cpp index cf1fba7..c4696b4 100644 --- a/src/performance.cpp +++ b/src/performance.cpp @@ -74,7 +74,7 @@ Scene get_current_scene(uint8_t scene_num) { } const static uint8_t TOTAL_SCENES = 26; -uint8_t scene_num = 0; +uint8_t scene_num = 1; unsigned long past_scene_durations = 0; void set_all_pixels(uint32_t color) { @@ -88,7 +88,7 @@ void setup() { pixels.begin(); Diabolo_Light::begin(1, 0, [](){ - scene_num = 0; + scene_num = 1; past_scene_durations = 0; }); } From d9e46f6a0f8a9876710e5267eca20642a266d463 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Fri, 16 Feb 2024 20:37:30 -0800 Subject: [PATCH 3/9] Limit file handle scope --- src/read_fcp_xml.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/read_fcp_xml.py b/src/read_fcp_xml.py index d8e13ee..8e3dac6 100755 --- a/src/read_fcp_xml.py +++ b/src/read_fcp_xml.py @@ -20,18 +20,18 @@ def generate_scenes(fcp_xml): with open(fcp_xml) as f: root = ET.fromstring(f.read()) - marker_pattern = re.compile(r'LED_MARKER ([A-Z]+_\d), ([A-Z]+_\d)( \/\/ .*)?') - - for video in root.iter('video'): - if video.attrib['name'].startswith('LED_MARKER'): - match = marker_pattern.search(video.attrib['name']) - if match: - color1 = match.group(1) - color2 = match.group(2) - comment = match.group(3) or '' - print(f"Scene({color1}, {color2}, {duration_to_ms(video.attrib['duration'])}), // {comment}") - else: - print(f"Scene(, , {duration_to_ms(video.attrib['duration'])}),") + marker_pattern = re.compile(r'LED_MARKER ([A-Z]+_\d), ([A-Z]+_\d)( \/\/ .*)?') + + for video in root.iter('video'): + if video.attrib['name'].startswith('LED_MARKER'): + match = marker_pattern.search(video.attrib['name']) + if match: + color1 = match.group(1) + color2 = match.group(2) + comment = match.group(3) or '' + print(f"Scene({color1}, {color2}, {duration_to_ms(video.attrib['duration'])}), // {comment}") + else: + print(f"Scene(, , {duration_to_ms(video.attrib['duration'])}),") def duration_to_ms(duration_str): From 844e2e9eea375f38eb1623a48303c5445cde5805 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Fri, 16 Feb 2024 21:16:08 -0800 Subject: [PATCH 4/9] Update code generation script to use switch/case --- src/performance.cpp | 52 ++++++++++++++++++++++----------------------- src/read_fcp_xml.py | 37 ++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/performance.cpp b/src/performance.cpp index c4696b4..9c43439 100644 --- a/src/performance.cpp +++ b/src/performance.cpp @@ -44,32 +44,32 @@ struct Scene { Scene get_current_scene(uint8_t scene_num) { switch (scene_num) { - case 1: return Scene(WHITE_1, WHITE_1, 6683); - case 2: return Scene(WHITE_1, YELLOW_3, 1166); - case 3: return Scene(YELLOW_3, YELLOW_3, 36633); - case 4: return Scene(RED_3, RED_3, 333); // // umbrella - case 5: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella - case 6: return Scene(RED_3, RED_3, 333); // // umbrella - case 7: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella - case 8: return Scene(RED_3, RED_3, 333); // // umbrella - case 9: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella - case 10: return Scene(RED_3, RED_3, 333); // // umbrella - case 11: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella - case 12: return Scene(RED_3, RED_3, 333); // // umbrella - case 13: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella - case 14: return Scene(RED_3, RED_3, 333); // // umbrella - case 15: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella - case 16: return Scene(RED_3, RED_3, 333); // // umbrella - case 17: return Scene(YELLOW_3, YELLOW_3, 316); // // umbrella - case 18: return Scene(RED_3, ORANGE_3, 650); // // umbrella - case 19: return Scene(ORANGE_3, ORANGE_3, 21200); // // after umbrella - case 20: return Scene(ORANGE_3, BLUE_3, 2733); // // transition - case 21: return Scene(BLUE_3, BLUE_3, 17950); // // around the world - case 22: return Scene(BLUE_3, YELLOW_3, 2733); // // transition - case 23: return Scene(YELLOW_3, RED_3, 1483); // // transition - case 24: return Scene(RED_3, RED_3, 17850); // // dragon - case 25: return Scene(RED_3, WHITE_3, 2916); // // transition - case 26: return Scene(WHITE_3, WHITE_3, 251016); // + case 1: return Scene(WHITE_1, WHITE_1, 6683); + case 2: return Scene(WHITE_1, YELLOW_3, 1166); + case 3: return Scene(YELLOW_3, YELLOW_3, 36633); // before umbrella + case 4: return Scene(RED_3, RED_3, 333); // umbrella + case 5: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 6: return Scene(RED_3, RED_3, 333); // umbrella + case 7: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 8: return Scene(RED_3, RED_3, 333); // umbrella + case 9: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 10: return Scene(RED_3, RED_3, 333); // umbrella + case 11: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 12: return Scene(RED_3, RED_3, 333); // umbrella + case 13: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 14: return Scene(RED_3, RED_3, 333); // umbrella + case 15: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 16: return Scene(RED_3, RED_3, 333); // umbrella + case 17: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 18: return Scene(RED_3, ORANGE_3, 650); // umbrella + case 19: return Scene(ORANGE_3, ORANGE_3, 21200); // after umbrella + case 20: return Scene(ORANGE_3, BLUE_3, 2733); // transition + case 21: return Scene(BLUE_3, BLUE_3, 17950); // around the world + case 22: return Scene(BLUE_3, YELLOW_3, 2733); // transition + case 23: return Scene(YELLOW_3, RED_3, 1483); // transition + case 24: return Scene(RED_3, RED_3, 17850); // dragon + case 25: return Scene(RED_3, WHITE_3, 2916); // transition + case 26: return Scene(WHITE_3, WHITE_3, 251016); } } diff --git a/src/read_fcp_xml.py b/src/read_fcp_xml.py index 8e3dac6..cdb84e3 100755 --- a/src/read_fcp_xml.py +++ b/src/read_fcp_xml.py @@ -6,6 +6,7 @@ import re import sys +from textwrap import dedent import xml.etree.ElementTree as ET @@ -22,6 +23,10 @@ def generate_scenes(fcp_xml): marker_pattern = re.compile(r'LED_MARKER ([A-Z]+_\d), ([A-Z]+_\d)( \/\/ .*)?') + scene_number = 1 + scene_template = 'case {number}: return Scene({color1}, {color2}, {duration}); {comment}' + scene_lines = [] + for video in root.iter('video'): if video.attrib['name'].startswith('LED_MARKER'): match = marker_pattern.search(video.attrib['name']) @@ -29,9 +34,37 @@ def generate_scenes(fcp_xml): color1 = match.group(1) color2 = match.group(2) comment = match.group(3) or '' - print(f"Scene({color1}, {color2}, {duration_to_ms(video.attrib['duration'])}), // {comment}") + scene_lines.append( + scene_template.format( + number=scene_number, + color1=color1, + color2=color2, + duration=duration_to_ms(video.attrib['duration']), + comment=comment, + ) + ) else: - print(f"Scene(, , {duration_to_ms(video.attrib['duration'])}),") + scene_lines.append( + scene_template.format( + number=scene_number, + color1='', + color2='', + duration=duration_to_ms(video.attrib['duration']), + comment='', + ) + ) + scene_number += 1 + + print(dedent("""\ + Scene get_current_scene(uint8_t scene_num) {{ + switch (scene_num) {{ + {case_statements} + }} + }} + + const static uint8_t TOTAL_SCENES = {size}; + """).format(case_statements='\n '.join(scene_lines), + size=len(scene_lines))) def duration_to_ms(duration_str): From 126aacddd480eb7d83275e15703e93ecd42853c0 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Sat, 17 Feb 2024 10:55:02 -0800 Subject: [PATCH 5/9] Fix last scene This should have been included in "Start scene numbering at 1" (3c1ee65d59). --- src/performance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/performance.cpp b/src/performance.cpp index 9c43439..87eef97 100644 --- a/src/performance.cpp +++ b/src/performance.cpp @@ -111,7 +111,7 @@ void loop() { scene_num++; // Turn off after last scene - if (scene_num >= TOTAL_SCENES) { + if (scene_num > TOTAL_SCENES) { Diabolo_Light::set_current_mode(0); } } From 20b46e2b01602bd4c5197405ab9cbe27a6f38147 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Fri, 16 Feb 2024 22:17:16 -0800 Subject: [PATCH 6/9] Support disabled clips from FCP --- src/read_fcp_xml.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/read_fcp_xml.py b/src/read_fcp_xml.py index cdb84e3..510146e 100755 --- a/src/read_fcp_xml.py +++ b/src/read_fcp_xml.py @@ -28,7 +28,9 @@ def generate_scenes(fcp_xml): scene_lines = [] for video in root.iter('video'): - if video.attrib['name'].startswith('LED_MARKER'): + disabled = ('enabled' in video.attrib) and (video.attrib['enabled'] == '0') + + if video.attrib['name'].startswith('LED_MARKER') and not disabled: match = marker_pattern.search(video.attrib['name']) if match: color1 = match.group(1) From 11c69ffdce8c123a5a6ee5386f6d235518039999 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Fri, 16 Feb 2024 22:16:28 -0800 Subject: [PATCH 7/9] Update for 2/17 show --- src/color_lab.cpp | 1 + src/performance.cpp | 67 +++++++++++++++++++++++++++------------------ src/read_fcp_xml.py | 2 +- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/color_lab.cpp b/src/color_lab.cpp index 3499261..37d8ab0 100644 --- a/src/color_lab.cpp +++ b/src/color_lab.cpp @@ -12,6 +12,7 @@ typedef uint32_t Color; static Color colors[] = { pixels.Color(255, 0 , 0 ), // red + pixels.Color(255, 32 , 0 ), // orange pixels.Color(255, 64 , 0 ), // orange pixels.Color(255, 128, 0 ), // warm yellow pixels.Color(255, 192, 0 ), // yellow-green diff --git a/src/performance.cpp b/src/performance.cpp index 87eef97..93189a8 100644 --- a/src/performance.cpp +++ b/src/performance.cpp @@ -24,13 +24,14 @@ struct Color { } }; -const static Color WHITE_1 = Color(20, 20, 20 ); +const static Color WHITE_1 = Color(20 , 20 , 20 ); const static Color WHITE_3 = Color(255, 255, 255); -const static Color RED_3 = Color(255, 0, 0 ); +const static Color RED_3 = Color(255, 0 , 0 ); const static Color GREEN_3 = Color(128, 255, 0 ); -const static Color BLUE_3 = Color(0, 0, 255); +const static Color BLUE_3 = Color(0 , 64 , 255); const static Color YELLOW_3 = Color(255, 128, 0 ); -const static Color ORANGE_3 = Color(255, 32, 0 ); +const static Color ORANGE_3 = Color(255, 32 , 0 ); +const static Color BLUE_2 = Color(0 , 128, 255); struct Scene { const Color& start; @@ -46,34 +47,46 @@ Scene get_current_scene(uint8_t scene_num) { switch (scene_num) { case 1: return Scene(WHITE_1, WHITE_1, 6683); case 2: return Scene(WHITE_1, YELLOW_3, 1166); - case 3: return Scene(YELLOW_3, YELLOW_3, 36633); // before umbrella - case 4: return Scene(RED_3, RED_3, 333); // umbrella - case 5: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella - case 6: return Scene(RED_3, RED_3, 333); // umbrella - case 7: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella - case 8: return Scene(RED_3, RED_3, 333); // umbrella - case 9: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella - case 10: return Scene(RED_3, RED_3, 333); // umbrella - case 11: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella - case 12: return Scene(RED_3, RED_3, 333); // umbrella - case 13: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella - case 14: return Scene(RED_3, RED_3, 333); // umbrella - case 15: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 3: return Scene(YELLOW_3, YELLOW_3, 20966); + case 4: return Scene(YELLOW_3, BLUE_2, 816); // toss up + case 5: return Scene(BLUE_2, YELLOW_3, 816); // toss down + case 6: return Scene(YELLOW_3, YELLOW_3, 1016); // before umbrella + case 7: return Scene(YELLOW_3, BLUE_2, 816); // toss up + case 8: return Scene(BLUE_2, YELLOW_3, 816); // toss down + case 9: return Scene(YELLOW_3, YELLOW_3, 933); + case 10: return Scene(YELLOW_3, WHITE_3, 1283); // before umbrella + case 11: return Scene(WHITE_3, WHITE_3, 1250); // before umbrella + case 12: return Scene(WHITE_3, BLUE_2, 816); // toss up + case 13: return Scene(BLUE_2, WHITE_3, 816); // toss down + case 14: return Scene(WHITE_3, WHITE_3, 950); // before umbrella + case 15: return Scene(WHITE_3, WHITE_3, 5333); // flower case 16: return Scene(RED_3, RED_3, 333); // umbrella case 17: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella - case 18: return Scene(RED_3, ORANGE_3, 650); // umbrella - case 19: return Scene(ORANGE_3, ORANGE_3, 21200); // after umbrella - case 20: return Scene(ORANGE_3, BLUE_3, 2733); // transition - case 21: return Scene(BLUE_3, BLUE_3, 17950); // around the world - case 22: return Scene(BLUE_3, YELLOW_3, 2733); // transition - case 23: return Scene(YELLOW_3, RED_3, 1483); // transition - case 24: return Scene(RED_3, RED_3, 17850); // dragon - case 25: return Scene(RED_3, WHITE_3, 2916); // transition - case 26: return Scene(WHITE_3, WHITE_3, 251016); + case 18: return Scene(RED_3, RED_3, 333); // umbrella + case 19: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 20: return Scene(RED_3, RED_3, 333); // umbrella + case 21: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 22: return Scene(RED_3, RED_3, 333); // umbrella + case 23: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 24: return Scene(RED_3, RED_3, 333); // umbrella + case 25: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 26: return Scene(RED_3, RED_3, 333); // umbrella + case 27: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 28: return Scene(RED_3, RED_3, 333); // umbrella + case 29: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 30: return Scene(RED_3, ORANGE_3, 650); // umbrella + case 31: return Scene(ORANGE_3, ORANGE_3, 21200); // after umbrella + case 32: return Scene(ORANGE_3, BLUE_3, 2733); // transition + case 33: return Scene(BLUE_3, BLUE_3, 17950); // around the world + case 34: return Scene(BLUE_3, YELLOW_3, 2733); // transition + case 35: return Scene(YELLOW_3, RED_3, 1483); // transition + case 36: return Scene(RED_3, RED_3, 17850); // dragon + case 37: return Scene(RED_3, WHITE_3, 2916); // transition + case 38: return Scene(WHITE_3, WHITE_3, 251016); } } -const static uint8_t TOTAL_SCENES = 26; +const static uint8_t TOTAL_SCENES = 38; uint8_t scene_num = 1; unsigned long past_scene_durations = 0; diff --git a/src/read_fcp_xml.py b/src/read_fcp_xml.py index 510146e..66ec422 100755 --- a/src/read_fcp_xml.py +++ b/src/read_fcp_xml.py @@ -21,7 +21,7 @@ def generate_scenes(fcp_xml): with open(fcp_xml) as f: root = ET.fromstring(f.read()) - marker_pattern = re.compile(r'LED_MARKER ([A-Z]+_\d), ([A-Z]+_\d)( \/\/ .*)?') + marker_pattern = re.compile(r'LED_MARKER ([A-Z_\d]+), ([A-Z_\d]+)( \/\/ .*)?') scene_number = 1 scene_template = 'case {number}: return Scene({color1}, {color2}, {duration}); {comment}' From b67ee9f828ab77cde6ac0de88448cd9094317dd8 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Fri, 16 Feb 2024 23:02:56 -0800 Subject: [PATCH 8/9] Rename performance program and make a copy Prepping for separate effects on different diabolos. --- README.md | 6 +- ...performance.cpp => genshin-fountain-1.cpp} | 0 src/genshin-fountain-2.cpp | 146 ++++++++++++++++++ 3 files changed, 149 insertions(+), 3 deletions(-) rename src/{performance.cpp => genshin-fountain-1.cpp} (100%) create mode 100644 src/genshin-fountain-2.cpp diff --git a/README.md b/README.md index b18f83e..b69391a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of programs using [ChaosNuggets/Diabolo_Light](https://github.com/C PlatformIO is configured to upload a `src/main.cpp` file. Choose which program to use by symlinking: - ln -Fs performance.cpp src/main.cpp + ln -Fs single_color.cpp src/main.cpp ## `src/color_lab.cpp` @@ -16,9 +16,9 @@ This program is used to pick colors that look good on the LED kit. This program shows a color on initial button press, and will turn off on the 2nd press. -## `src/performance.cpp` +## `src/genshin-fountain-*.cpp` -This program defines a performance consisting of scenes which are defined by colors and transitions between colors. Contains generic structs which I hope to pull out into a separate file eventually. +These programs are used to create a performance consisting of scenes which are defined by colors and transitions between colors. Contains generic structs which I hope to pull out into a separate file eventually. I use Final Cut Pro's Export XML functionality and a custom script `src/read_fcp_xml.py` to facilitate definition of scenes for this program. Not enough time to document now, but here's a screenshot: diff --git a/src/performance.cpp b/src/genshin-fountain-1.cpp similarity index 100% rename from src/performance.cpp rename to src/genshin-fountain-1.cpp diff --git a/src/genshin-fountain-2.cpp b/src/genshin-fountain-2.cpp new file mode 100644 index 0000000..93189a8 --- /dev/null +++ b/src/genshin-fountain-2.cpp @@ -0,0 +1,146 @@ +#include +#include +#include + +Adafruit_NeoPixel pixels( + Diabolo_Light::NUM_LEDS, + Diabolo_Light::LED_PIN, + Diabolo_Light::LED_TYPE +); + +typedef uint8_t DiodeBrightness; +typedef int8_t DiodeBrightnessOffset; + +struct Color { + const DiodeBrightness r; + const DiodeBrightness g; + const DiodeBrightness b; + + Color(DiodeBrightness r, DiodeBrightness g, DiodeBrightness b) + : r(r), g(g), b(b) {} + + bool operator==(const Color& other) const { + return r == other.r && g == other.g && b == other.b; + } +}; + +const static Color WHITE_1 = Color(20 , 20 , 20 ); +const static Color WHITE_3 = Color(255, 255, 255); +const static Color RED_3 = Color(255, 0 , 0 ); +const static Color GREEN_3 = Color(128, 255, 0 ); +const static Color BLUE_3 = Color(0 , 64 , 255); +const static Color YELLOW_3 = Color(255, 128, 0 ); +const static Color ORANGE_3 = Color(255, 32 , 0 ); +const static Color BLUE_2 = Color(0 , 128, 255); + +struct Scene { + const Color& start; + const Color& end; + uint32_t duration; + // TODO: add types of transitions. R/G/B balanced transition or R+G+B combined transition + + Scene(const Color& start, const Color& end, uint32_t duration) + : start(start), end(end), duration(duration) {} +}; + +Scene get_current_scene(uint8_t scene_num) { + switch (scene_num) { + case 1: return Scene(WHITE_1, WHITE_1, 6683); + case 2: return Scene(WHITE_1, YELLOW_3, 1166); + case 3: return Scene(YELLOW_3, YELLOW_3, 20966); + case 4: return Scene(YELLOW_3, BLUE_2, 816); // toss up + case 5: return Scene(BLUE_2, YELLOW_3, 816); // toss down + case 6: return Scene(YELLOW_3, YELLOW_3, 1016); // before umbrella + case 7: return Scene(YELLOW_3, BLUE_2, 816); // toss up + case 8: return Scene(BLUE_2, YELLOW_3, 816); // toss down + case 9: return Scene(YELLOW_3, YELLOW_3, 933); + case 10: return Scene(YELLOW_3, WHITE_3, 1283); // before umbrella + case 11: return Scene(WHITE_3, WHITE_3, 1250); // before umbrella + case 12: return Scene(WHITE_3, BLUE_2, 816); // toss up + case 13: return Scene(BLUE_2, WHITE_3, 816); // toss down + case 14: return Scene(WHITE_3, WHITE_3, 950); // before umbrella + case 15: return Scene(WHITE_3, WHITE_3, 5333); // flower + case 16: return Scene(RED_3, RED_3, 333); // umbrella + case 17: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 18: return Scene(RED_3, RED_3, 333); // umbrella + case 19: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 20: return Scene(RED_3, RED_3, 333); // umbrella + case 21: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 22: return Scene(RED_3, RED_3, 333); // umbrella + case 23: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 24: return Scene(RED_3, RED_3, 333); // umbrella + case 25: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 26: return Scene(RED_3, RED_3, 333); // umbrella + case 27: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 28: return Scene(RED_3, RED_3, 333); // umbrella + case 29: return Scene(YELLOW_3, YELLOW_3, 316); // umbrella + case 30: return Scene(RED_3, ORANGE_3, 650); // umbrella + case 31: return Scene(ORANGE_3, ORANGE_3, 21200); // after umbrella + case 32: return Scene(ORANGE_3, BLUE_3, 2733); // transition + case 33: return Scene(BLUE_3, BLUE_3, 17950); // around the world + case 34: return Scene(BLUE_3, YELLOW_3, 2733); // transition + case 35: return Scene(YELLOW_3, RED_3, 1483); // transition + case 36: return Scene(RED_3, RED_3, 17850); // dragon + case 37: return Scene(RED_3, WHITE_3, 2916); // transition + case 38: return Scene(WHITE_3, WHITE_3, 251016); + } +} + +const static uint8_t TOTAL_SCENES = 38; +uint8_t scene_num = 1; +unsigned long past_scene_durations = 0; + +void set_all_pixels(uint32_t color) { + for (unsigned int i = 0; i < Diabolo_Light::NUM_LEDS; i++) { + pixels.setPixelColor(i, color); + } + pixels.show(); +} + +void setup() { + pixels.begin(); + + Diabolo_Light::begin(1, 0, [](){ + scene_num = 1; + past_scene_durations = 0; + }); +} + +void loop() { + Diabolo_Light::handle_button(); + + if (Diabolo_Light::get_current_mode() != 1) return; + + Scene scene = get_current_scene(scene_num); + + // Progress within current scene, from 0-1 + double progress = + static_cast(Diabolo_Light::awake_time() - past_scene_durations) + / scene.duration; + + // Go to next scene + if (progress >= 1) { + past_scene_durations = past_scene_durations + scene.duration; + scene_num++; + + // Turn off after last scene + if (scene_num > TOTAL_SCENES) { + Diabolo_Light::set_current_mode(0); + } + } + + if (scene.start == scene.end) { + set_all_pixels(pixels.Color( + scene.start.r, + scene.start.g, + scene.start.b + )); + } + else { + set_all_pixels(pixels.Color( + scene.start.r + static_cast((scene.end.r - scene.start.r) * progress), + scene.start.g + static_cast((scene.end.g - scene.start.g) * progress), + scene.start.b + static_cast((scene.end.b - scene.start.b) * progress) + )); + } +} From 556f4c7ca0e51087c2aa05aee628487f347e0a28 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Sat, 17 Feb 2024 10:43:38 -0800 Subject: [PATCH 9/9] genshin-fountain: Alternate tosses on 2nd program --- src/genshin-fountain-2.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/genshin-fountain-2.cpp b/src/genshin-fountain-2.cpp index 93189a8..2c8a9a1 100644 --- a/src/genshin-fountain-2.cpp +++ b/src/genshin-fountain-2.cpp @@ -48,13 +48,13 @@ Scene get_current_scene(uint8_t scene_num) { case 1: return Scene(WHITE_1, WHITE_1, 6683); case 2: return Scene(WHITE_1, YELLOW_3, 1166); case 3: return Scene(YELLOW_3, YELLOW_3, 20966); - case 4: return Scene(YELLOW_3, BLUE_2, 816); // toss up - case 5: return Scene(BLUE_2, YELLOW_3, 816); // toss down - case 6: return Scene(YELLOW_3, YELLOW_3, 1016); // before umbrella - case 7: return Scene(YELLOW_3, BLUE_2, 816); // toss up - case 8: return Scene(BLUE_2, YELLOW_3, 816); // toss down - case 9: return Scene(YELLOW_3, YELLOW_3, 933); - case 10: return Scene(YELLOW_3, WHITE_3, 1283); // before umbrella + case 4: return Scene(YELLOW_3, YELLOW_3, 1233); // before umbrella + case 5: return Scene(YELLOW_3, BLUE_2, 816); // toss up + case 6: return Scene(BLUE_2, YELLOW_3, 816); // toss down + case 7: return Scene(YELLOW_3, YELLOW_3, 1066); // before umbrella + case 8: return Scene(YELLOW_3, BLUE_2, 816); // toss up + case 9: return Scene(BLUE_2, YELLOW_3, 816); // toss down + case 10: return Scene(YELLOW_3, WHITE_3, 933); // before umbrella case 11: return Scene(WHITE_3, WHITE_3, 1250); // before umbrella case 12: return Scene(WHITE_3, BLUE_2, 816); // toss up case 13: return Scene(BLUE_2, WHITE_3, 816); // toss down