Skip to content

Commit 337ca5c

Browse files
authored
Merge pull request #25 from 203Electronics/2.4
Matrix OS 2.4
2 parents c9a3340 + faf20f5 commit 337ca5c

10 files changed

Lines changed: 325 additions & 77 deletions

File tree

applications/Performance/8x8/Performance8x8.cpp

Lines changed: 112 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ void Performance::Setup() {
77
}
88

99
void Performance::Loop() {
10-
if (stfuTimer.Tick(10))
10+
if (stfu && stfuTimer.Tick(10))
1111
{ stfuScan(); }
1212

1313
struct KeyEvent keyEvent;
@@ -16,20 +16,24 @@ void Performance::Loop() {
1616

1717
struct MidiPacket midiPacket;
1818
while (MatrixOS::MIDI::Get(&midiPacket))
19-
{ MidiEventHandler(midiPacket, true); }
19+
{ MidiEventHandler(midiPacket); }
2020
}
2121

22-
void Performance::MidiEventHandler(MidiPacket midiPacket, bool renderOnActive) {
22+
void Performance::MidiEventHandler(MidiPacket midiPacket) {
2323
// MatrixOS::Logging::LogDebug("Performance", "Midi Recived %d %d %d %d", midiPacket.status, midiPacket.data[0],
2424
// midiPacket.data[1], midiPacket.data[2]);
2525
switch (midiPacket.status)
2626
{
2727
case NoteOn:
2828
case ControlChange:
29-
NoteHandler(midiPacket.channel(), midiPacket.note(), midiPacket.velocity(), renderOnActive);
29+
NoteHandler(midiPacket.channel(), midiPacket.note(), midiPacket.velocity());
3030
break;
3131
case NoteOff:
32-
NoteHandler(midiPacket.channel(), midiPacket.note(), 0, renderOnActive);
32+
NoteHandler(midiPacket.channel(), midiPacket.note(), 0);
33+
break;
34+
case SysExData:
35+
case SysExEnd:
36+
SysExHandler(midiPacket);
3337
break;
3438
default:
3539
break;
@@ -95,7 +99,7 @@ int8_t Performance::XYToNote(Point xy) {
9599
return -1;
96100
}
97101

98-
void Performance::NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity, bool renderOnActive) {
102+
void Performance::NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity) {
99103
// MatrixOS::Logging::LogDebug("Performance", "Midi Recivied %#02X %#02X %#02X", channel, note, velocity);
100104
Point xy = NoteToXY(note);
101105

@@ -104,20 +108,13 @@ void Performance::NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity, b
104108
channel = 1; // So it will use legacy palette
105109
}
106110

111+
107112
if (xy && !(velocity == 0 && stfu))
108113
{
109114
// MatrixOS::Logging::LogDebug("Performance", "Set LED");
110-
MatrixOS::LED::SetColor(xy, palette[channel % 2][velocity], renderOnActive? 0 : canvasLedLayer);
115+
MatrixOS::LED::SetColor(xy, palette[channel % 2][velocity], uiOpened ? canvasLedLayer : 0);
111116
}
112-
// else if(!xy)
113-
// {
114-
// MatrixOS::Logging::LogDebug("Performance", "XY incorrect");
115-
// }
116-
// else if((velocity == 0 && stfu))
117-
// {
118-
// MatrixOS::Logging::LogDebug("Performance", "STFU");
119-
// }
120-
if (stfu)
117+
else if (stfu)
121118
{
122119
if (velocity == 0)
123120
{ stfuMap[note] = stfu; }
@@ -126,6 +123,102 @@ void Performance::NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity, b
126123
}
127124
}
128125

126+
vector<uint8_t> sysExBuffer;
127+
void Performance::SysExHandler(MidiPacket midiPacket)
128+
{
129+
// New SysEx, clear buffer
130+
if(sysExBuffer.empty())
131+
{
132+
sysExBuffer.reserve(400);
133+
}
134+
135+
// Insert data to buffer
136+
sysExBuffer.insert(sysExBuffer.end(), midiPacket.data, midiPacket.data + midiPacket.Length());
137+
138+
// If not end of sysex, return, do not parse
139+
if(midiPacket.status != SysExEnd)
140+
{ return; }
141+
142+
//Get rid of the 0xF7 ending byte
143+
sysExBuffer.pop_back();
144+
145+
// Parsing because sysex is completed
146+
switch (sysExBuffer[0])
147+
{
148+
case 0x5f: //Apollo batch fill - https://github.com/mat1jaczyyy/lpp-performance-cfw/blob/0c2ec2a71030306ab7e5491bd49d72440d8c0199/src/sysex/sysex.c#L54-L120
149+
{
150+
// MatrixOS::Logging::LogDebug("Performance", "Apollo batch Fill");
151+
if(sysExBuffer.size() < 5) { return; }
152+
153+
uint8_t targetLayer = uiOpened ? canvasLedLayer : 0;
154+
155+
uint16_t ptr = 1; // Index 0 is the command 0x5f, we start ptr at 1
156+
while (ptr < sysExBuffer.size())
157+
{
158+
// Extract the color data
159+
uint8_t colorR = (sysExBuffer[ptr] & 0x3F);
160+
uint8_t colorG = (sysExBuffer[ptr + 1] & 0x3F);
161+
uint8_t colorB = (sysExBuffer[ptr + 2] & 0x3F);
162+
163+
// Remapped color from 6 bit to 8 bit
164+
colorR = (colorR << 2) + (colorR >> 4);
165+
colorG = (colorG << 2) + (colorG >> 4);
166+
colorB = (colorB << 2) + (colorB >> 4);
167+
168+
// Create the color
169+
Color color = Color(colorR, colorG, colorB);
170+
171+
// Get how many NN (Note Numbers) follows
172+
uint8_t n_count = ((sysExBuffer[ptr] & 0x40) >> 4) | ((sysExBuffer[ptr + 1] & 0x40) >> 5) | ((sysExBuffer[ptr + 2] & 0x40) >> 6);
173+
174+
ptr += 3; //We finish reading the first 3 bit, inc the ptr by 3
175+
176+
//If nums of NN is 0, then the next byte is the number of NN
177+
if(n_count == 0) { n_count = sysExBuffer[ptr++]; } //If all 3 bits are 0, then it's 64 (0b111111
178+
179+
// MatrixOS::Logging::LogDebug("Performance", "Color: #%.2X%.2X%.2X, NN count: %d", color.R, color.G, color.B, n_count);
180+
181+
// Goes through all N
182+
for (uint16_t n = 0; n < n_count; n++)
183+
{
184+
if (sysExBuffer[ptr] == 0) // Global full
185+
{ MatrixOS::LED::Fill(color, targetLayer); }
186+
else if (sysExBuffer[ptr] < 99) // Grid
187+
{
188+
Point xy = Point(sysExBuffer[ptr] % 10 - 1, 8 - (sysExBuffer[ptr] / 10));
189+
// MatrixOS::Logging::LogDebug("Performance", "Grid %d %d", xy.x, xy.y);
190+
MatrixOS::LED::SetColor(xy, color, targetLayer);
191+
}
192+
else if (sysExBuffer[ptr] == 99) // Mode Light
193+
{
194+
// Not implemented - Maybe a TODO
195+
}
196+
else if (sysExBuffer[ptr] < 110) // Row Fill
197+
{
198+
int8_t row = 108 - sysExBuffer[ptr];
199+
for (int8_t x = 0; x < 10; x++)
200+
{ MatrixOS::LED::SetColor(Point(x, row), color, targetLayer); }
201+
}
202+
else if (sysExBuffer[ptr] < 120) // Column Fill
203+
{
204+
int8_t column = sysExBuffer[ptr] - 111;
205+
for (int8_t y = 0; y < 10; y++)
206+
{ MatrixOS::LED::SetColor(Point(column, y), color, targetLayer); }
207+
}
208+
ptr++; //Since ptr is the pointer of in vector, we need to read the next NN, inc the ptr by 1
209+
}
210+
}
211+
}
212+
break;
213+
214+
default:
215+
break;
216+
}
217+
218+
// Clear buffer since we are done parsing SysEx
219+
sysExBuffer.clear();
220+
}
221+
129222
void Performance::KeyEventHandler(uint16_t KeyID, KeyInfo* keyInfo) {
130223
Point xy = MatrixOS::KEYPAD::ID2XY(KeyID);
131224
if (xy) // IF XY is vaild, means it's on the main grid
@@ -237,7 +330,7 @@ void Performance::ActionMenu() {
237330
actionMenu.SetLoopFunc([&]() -> void { //Keep buffer updated even when action menu is currently open
238331
struct MidiPacket midiPacket;
239332
while (MatrixOS::MIDI::Get(&midiPacket))
240-
{ MidiEventHandler(midiPacket, false); }
333+
{ MidiEventHandler(midiPacket); }
241334
});
242335

243336
actionMenu.SetKeyEventHandler([&](KeyEvent* keyEvent) -> bool {
@@ -252,7 +345,9 @@ void Performance::ActionMenu() {
252345
return false;
253346
});
254347

348+
uiOpened = true;
255349
actionMenu.Start();
350+
uiOpened = false;
256351

257352
MatrixOS::Logging::LogDebug(name, "Exit Action Menu");
258353
}

applications/Performance/8x8/Performance8x8.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class Performance : public Application {
2626
uint8_t currentKeymap = 0;
2727

2828
uint8_t canvasLedLayer;
29+
bool uiOpened = false;
2930

3031
// Saved Variables
3132
CreateSavedVar(APPLICATION_NAME, compatibilityMode, bool, false);
@@ -38,10 +39,9 @@ class Performance : public Application {
3839
Point NoteToXY(uint8_t note);
3940
int8_t XYToNote(Point xy);
4041

41-
void MidiEventHandler(MidiPacket midiPacket, bool renderOnActive);
42-
void NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity, bool renderOnActive);
43-
// void note_on_handler(uint8_t channel, uint8_t note, uint8_t velocity);
44-
// void note_off_handler(uint8_t channel, uint8_t note, uint8_t velocity);
42+
void MidiEventHandler(MidiPacket midiPacket);
43+
void NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity);
44+
void SysExHandler(MidiPacket midiPacket);
4545

4646
void KeyEventHandler(uint16_t keyID, KeyInfo* keyInfo);
4747

os/MatrixOS.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ namespace MatrixOS
110110
{
111111
noexpose void Init(void);
112112

113-
bool Get(MidiPacket* midipacket_dest, uint16_t timeout_ms = 0);
114-
bool Send(MidiPacket midiPacket);
113+
bool Get(MidiPacket* midiPacketDest, uint16_t timeout_ms = 0);
114+
bool Send(MidiPacket midiPacket, uint16_t timeout_ms = 0);
115+
bool SendSysEx(uint16_t port, uint16_t length, uint8_t* data, bool includeMeta = true); // If include meta, it will send the correct header and ending;
115116

116117
// Those APIs are only for MidiPort to use
117118
noexpose bool RegisterMidiPort(uint16_t port_id, MidiPort* midiPort);

0 commit comments

Comments
 (0)