1+ #pragma once
2+ #include " MatrixOS.h"
3+ #include " ui/UI.h"
4+ #include " Arpeggiator.h"
5+
6+ struct ArpDirVisual {
7+ uint8_t step[8 ]; // 8 steps to visualize the pattern, 0=no show, 1-4=first cycle, 5-8=second cycle
8+ };
9+
10+ const ArpDirVisual arpDirVisuals[16 ] = {
11+ // 0 as no show, 1~4 means first repeat, 5~8 means second repeat
12+ /* ARP_UP*/ {{1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }},
13+ /* ARP_DOWN*/ {{4 , 3 , 2 , 1 , 8 , 7 , 6 , 5 }},
14+ /* ARP_UP_DOWN*/ {{1 , 2 , 3 , 4 , 3 , 2 , 5 , 0 }},
15+ /* ARP_DOWN_UP*/ {{4 , 3 , 2 , 1 , 2 , 3 , 8 , 7 }},
16+ /* ARP_UP_N_DOWN*/ {{1 , 2 , 3 , 4 , 4 , 3 , 2 , 5 }},
17+ /* ARP_DOWN_N_UP*/ {{4 , 3 , 2 , 1 , 1 , 2 , 3 , 8 }},
18+ /* ARP_RANDOM*/ {{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }},
19+ /* ARP_PLAY_ORDER*/ {{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }},
20+ /* ARP_CONVERGE*/ {{1 , 4 , 2 , 3 , 5 , 8 , 6 , 7 }},
21+ /* ARP_DIVERGE*/ {{2 , 3 , 1 , 4 , 6 , 7 , 5 , 8 }},
22+ /* ARP_CON_DIVERGE*/ {{1 , 4 , 2 , 3 , 2 , 3 , 1 , 4 }},
23+ /* ARP_DIV_CONVERGE*/ {{2 , 3 , 1 , 4 , 1 , 4 , 2 , 3 }},
24+ /* ARP_PINKY_UP*/ {{1 , 4 , 2 , 4 , 3 , 4 , 5 , 8 }},
25+ /* ARP_PINKY_UP_DOWN*/ {{1 , 4 , 2 , 4 , 3 , 4 , 2 , 4 }},
26+ /* ARP_THUMB_UP*/ {{1 , 2 , 1 , 3 , 1 , 4 , 5 , 6 }},
27+ /* ARP_THUMB_UP_DOWN*/ {{1 , 2 , 1 , 3 , 1 , 4 , 1 , 3 }},
28+ };
29+
30+ class ArpDirVisualizer : public UIComponent {
31+ public:
32+ Color color;
33+ ArpDirection* direction;
34+ ArpDirection lastDirection;
35+ uint64_t lastUpdateTime = 0 ;
36+ uint8_t currentStep = 0 ;
37+
38+ ArpDirVisualizer (ArpDirection* direction, Color color) {
39+ this ->direction = direction;
40+ this ->lastDirection = *direction;
41+ this ->color = color;
42+ }
43+
44+ virtual Color GetColor () { return color; }
45+ virtual Dimension GetSize () { return Dimension (8 , 4 ); }
46+
47+ bool IsEnabled () {
48+ if (enableFunc) {
49+ enabled = (*enableFunc)();
50+ }
51+ if (!enabled)
52+ {
53+ currentStep = 0 ;
54+ lastUpdateTime = 0 ;
55+ }
56+ return enabled;
57+ }
58+
59+ virtual bool Render (Point origin) {
60+ // For other modes, use the animated pattern from arpDirVisuals
61+ uint64_t currentTime = MatrixOS::SYS::Millis ();
62+
63+ // Reset animation if direction changed or not inited
64+ if (*direction != lastDirection || lastUpdateTime == 0 ) {
65+ currentStep = 0 ;
66+ lastUpdateTime = currentTime;
67+ lastDirection = *direction;
68+ }
69+
70+ if (*direction == ARP_RANDOM)
71+ {
72+ // R
73+ MatrixOS::LED::SetColor (origin + Point (0 , 0 ), color);
74+ MatrixOS::LED::SetColor (origin + Point (0 , 1 ), color);
75+ MatrixOS::LED::SetColor (origin + Point (0 , 2 ), color);
76+ MatrixOS::LED::SetColor (origin + Point (0 , 3 ), color);
77+ MatrixOS::LED::SetColor (origin + Point (1 , 0 ), color);
78+ MatrixOS::LED::SetColor (origin + Point (1 , 2 ), color);
79+ MatrixOS::LED::SetColor (origin + Point (2 , 0 ), color);
80+ MatrixOS::LED::SetColor (origin + Point (2 , 1 ), color);
81+ MatrixOS::LED::SetColor (origin + Point (2 , 3 ), color);
82+
83+ // n
84+ MatrixOS::LED::SetColor (origin + Point (3 , 1 ), Color (0xFFFFFF ));
85+ MatrixOS::LED::SetColor (origin + Point (3 , 2 ), Color (0xFFFFFF ));
86+ MatrixOS::LED::SetColor (origin + Point (3 , 3 ), Color (0xFFFFFF ));
87+ MatrixOS::LED::SetColor (origin + Point (4 , 1 ), Color (0xFFFFFF ));
88+ MatrixOS::LED::SetColor (origin + Point (5 , 2 ), Color (0xFFFFFF ));
89+ MatrixOS::LED::SetColor (origin + Point (5 , 3 ), Color (0xFFFFFF ));
90+
91+ // d
92+ MatrixOS::LED::SetColor (origin + Point (6 , 2 ), color);
93+ MatrixOS::LED::SetColor (origin + Point (6 , 3 ), color);
94+ MatrixOS::LED::SetColor (origin + Point (7 , 0 ), color);
95+ MatrixOS::LED::SetColor (origin + Point (7 , 1 ), color);
96+ MatrixOS::LED::SetColor (origin + Point (7 , 2 ), color);
97+ MatrixOS::LED::SetColor (origin + Point (7 , 3 ), color);
98+ }
99+ else if (*direction == ARP_PLAY_ORDER)
100+ {
101+ // O
102+ MatrixOS::LED::SetColor (origin + Point (0 , 0 ), color);
103+ MatrixOS::LED::SetColor (origin + Point (0 , 1 ), color);
104+ MatrixOS::LED::SetColor (origin + Point (0 , 2 ), color);
105+ MatrixOS::LED::SetColor (origin + Point (0 , 3 ), color);
106+ MatrixOS::LED::SetColor (origin + Point (1 , 0 ), color);
107+ MatrixOS::LED::SetColor (origin + Point (1 , 3 ), color);
108+ MatrixOS::LED::SetColor (origin + Point (2 , 0 ), color);
109+ MatrixOS::LED::SetColor (origin + Point (2 , 1 ), color);
110+ MatrixOS::LED::SetColor (origin + Point (2 , 2 ), color);
111+ MatrixOS::LED::SetColor (origin + Point (2 , 3 ), color);
112+
113+ // R
114+ MatrixOS::LED::SetColor (origin + Point (3 , 0 ), Color (0xFFFFFF ));
115+ MatrixOS::LED::SetColor (origin + Point (3 , 1 ), Color (0xFFFFFF ));
116+ MatrixOS::LED::SetColor (origin + Point (3 , 2 ), Color (0xFFFFFF ));
117+ MatrixOS::LED::SetColor (origin + Point (3 , 3 ), Color (0xFFFFFF ));
118+ MatrixOS::LED::SetColor (origin + Point (4 , 0 ), Color (0xFFFFFF ));
119+ MatrixOS::LED::SetColor (origin + Point (4 , 2 ), Color (0xFFFFFF ));
120+ MatrixOS::LED::SetColor (origin + Point (5 , 0 ), Color (0xFFFFFF ));
121+ MatrixOS::LED::SetColor (origin + Point (5 , 1 ), Color (0xFFFFFF ));
122+ MatrixOS::LED::SetColor (origin + Point (5 , 3 ), Color (0xFFFFFF ));
123+
124+ // d
125+ MatrixOS::LED::SetColor (origin + Point (6 , 2 ), color);
126+ MatrixOS::LED::SetColor (origin + Point (6 , 3 ), color);
127+ MatrixOS::LED::SetColor (origin + Point (7 , 0 ), color);
128+ MatrixOS::LED::SetColor (origin + Point (7 , 1 ), color);
129+ MatrixOS::LED::SetColor (origin + Point (7 , 2 ), color);
130+ MatrixOS::LED::SetColor (origin + Point (7 , 3 ), color);
131+ }
132+ else
133+ {
134+ // Update animation step every 300ms
135+ if (currentTime - lastUpdateTime > 300 ) {
136+ currentStep = (currentStep + 1 ) % 9 ;
137+ lastUpdateTime = currentTime;
138+ }
139+
140+ const ArpDirVisual& visual = arpDirVisuals[*direction];
141+
142+ for (uint8_t i = 0 ; i < 8 ; i++) {
143+ uint8_t stepValue = visual.step [i];
144+
145+ if (stepValue == 0 ) {
146+ // No show - skip
147+ continue ;
148+ }
149+
150+ uint8_t y = stepValue; // 1-based y coordinate
151+ Point xy;
152+ Color ledColor;
153+
154+ if (y <= 4 ) {
155+ // Normal range: render at Point(i, 4-y)
156+ xy = origin + Point (i, 4 - y);
157+ if (i < currentStep) {
158+ ledColor = color; // Current step - bright
159+ } else {
160+ ledColor = color.Dim (); // Dim
161+ }
162+ } else {
163+ // y > 4: render at Point(i, 8-y) with white color
164+ xy = origin + Point (i, 8 - y);
165+ if (i < currentStep) {
166+ ledColor = Color (0xFFFFFF ); // Current step - bright white
167+ } else {
168+ ledColor = Color (0xFFFFFF ).Dim (); // Dim white
169+ }
170+ }
171+
172+ MatrixOS::LED::SetColor (xy, ledColor);
173+ }
174+ }
175+ return true ;
176+ }
177+
178+ virtual bool KeyEvent (Point xy, KeyInfo* keyInfo) {
179+ // No key interaction for visualizer
180+ if (keyInfo->State () == HOLD)
181+ {
182+ MatrixOS::UIUtility::TextScroll (arpDirectionNames[*direction], color);
183+ }
184+ return false ;
185+ }
186+ };
0 commit comments