Skip to content

Commit

Permalink
Merge pull request #25 from 203Electronics/2.4
Browse files Browse the repository at this point in the history
Matrix OS 2.4
  • Loading branch information
203Null authored Jan 21, 2023
2 parents c9a3340 + faf20f5 commit 337ca5c
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 77 deletions.
129 changes: 112 additions & 17 deletions applications/Performance/8x8/Performance8x8.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ void Performance::Setup() {
}

void Performance::Loop() {
if (stfuTimer.Tick(10))
if (stfu && stfuTimer.Tick(10))
{ stfuScan(); }

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

struct MidiPacket midiPacket;
while (MatrixOS::MIDI::Get(&midiPacket))
{ MidiEventHandler(midiPacket, true); }
{ MidiEventHandler(midiPacket); }
}

void Performance::MidiEventHandler(MidiPacket midiPacket, bool renderOnActive) {
void Performance::MidiEventHandler(MidiPacket midiPacket) {
// MatrixOS::Logging::LogDebug("Performance", "Midi Recived %d %d %d %d", midiPacket.status, midiPacket.data[0],
// midiPacket.data[1], midiPacket.data[2]);
switch (midiPacket.status)
{
case NoteOn:
case ControlChange:
NoteHandler(midiPacket.channel(), midiPacket.note(), midiPacket.velocity(), renderOnActive);
NoteHandler(midiPacket.channel(), midiPacket.note(), midiPacket.velocity());
break;
case NoteOff:
NoteHandler(midiPacket.channel(), midiPacket.note(), 0, renderOnActive);
NoteHandler(midiPacket.channel(), midiPacket.note(), 0);
break;
case SysExData:
case SysExEnd:
SysExHandler(midiPacket);
break;
default:
break;
Expand Down Expand Up @@ -95,7 +99,7 @@ int8_t Performance::XYToNote(Point xy) {
return -1;
}

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

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


if (xy && !(velocity == 0 && stfu))
{
// MatrixOS::Logging::LogDebug("Performance", "Set LED");
MatrixOS::LED::SetColor(xy, palette[channel % 2][velocity], renderOnActive? 0 : canvasLedLayer);
MatrixOS::LED::SetColor(xy, palette[channel % 2][velocity], uiOpened ? canvasLedLayer : 0);
}
// else if(!xy)
// {
// MatrixOS::Logging::LogDebug("Performance", "XY incorrect");
// }
// else if((velocity == 0 && stfu))
// {
// MatrixOS::Logging::LogDebug("Performance", "STFU");
// }
if (stfu)
else if (stfu)
{
if (velocity == 0)
{ stfuMap[note] = stfu; }
Expand All @@ -126,6 +123,102 @@ void Performance::NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity, b
}
}

vector<uint8_t> sysExBuffer;
void Performance::SysExHandler(MidiPacket midiPacket)
{
// New SysEx, clear buffer
if(sysExBuffer.empty())
{
sysExBuffer.reserve(400);
}

// Insert data to buffer
sysExBuffer.insert(sysExBuffer.end(), midiPacket.data, midiPacket.data + midiPacket.Length());

// If not end of sysex, return, do not parse
if(midiPacket.status != SysExEnd)
{ return; }

//Get rid of the 0xF7 ending byte
sysExBuffer.pop_back();

// Parsing because sysex is completed
switch (sysExBuffer[0])
{
case 0x5f: //Apollo batch fill - https://github.com/mat1jaczyyy/lpp-performance-cfw/blob/0c2ec2a71030306ab7e5491bd49d72440d8c0199/src/sysex/sysex.c#L54-L120
{
// MatrixOS::Logging::LogDebug("Performance", "Apollo batch Fill");
if(sysExBuffer.size() < 5) { return; }

uint8_t targetLayer = uiOpened ? canvasLedLayer : 0;

uint16_t ptr = 1; // Index 0 is the command 0x5f, we start ptr at 1
while (ptr < sysExBuffer.size())
{
// Extract the color data
uint8_t colorR = (sysExBuffer[ptr] & 0x3F);
uint8_t colorG = (sysExBuffer[ptr + 1] & 0x3F);
uint8_t colorB = (sysExBuffer[ptr + 2] & 0x3F);

// Remapped color from 6 bit to 8 bit
colorR = (colorR << 2) + (colorR >> 4);
colorG = (colorG << 2) + (colorG >> 4);
colorB = (colorB << 2) + (colorB >> 4);

// Create the color
Color color = Color(colorR, colorG, colorB);

// Get how many NN (Note Numbers) follows
uint8_t n_count = ((sysExBuffer[ptr] & 0x40) >> 4) | ((sysExBuffer[ptr + 1] & 0x40) >> 5) | ((sysExBuffer[ptr + 2] & 0x40) >> 6);

ptr += 3; //We finish reading the first 3 bit, inc the ptr by 3

//If nums of NN is 0, then the next byte is the number of NN
if(n_count == 0) { n_count = sysExBuffer[ptr++]; } //If all 3 bits are 0, then it's 64 (0b111111

// MatrixOS::Logging::LogDebug("Performance", "Color: #%.2X%.2X%.2X, NN count: %d", color.R, color.G, color.B, n_count);

// Goes through all N
for (uint16_t n = 0; n < n_count; n++)
{
if (sysExBuffer[ptr] == 0) // Global full
{ MatrixOS::LED::Fill(color, targetLayer); }
else if (sysExBuffer[ptr] < 99) // Grid
{
Point xy = Point(sysExBuffer[ptr] % 10 - 1, 8 - (sysExBuffer[ptr] / 10));
// MatrixOS::Logging::LogDebug("Performance", "Grid %d %d", xy.x, xy.y);
MatrixOS::LED::SetColor(xy, color, targetLayer);
}
else if (sysExBuffer[ptr] == 99) // Mode Light
{
// Not implemented - Maybe a TODO
}
else if (sysExBuffer[ptr] < 110) // Row Fill
{
int8_t row = 108 - sysExBuffer[ptr];
for (int8_t x = 0; x < 10; x++)
{ MatrixOS::LED::SetColor(Point(x, row), color, targetLayer); }
}
else if (sysExBuffer[ptr] < 120) // Column Fill
{
int8_t column = sysExBuffer[ptr] - 111;
for (int8_t y = 0; y < 10; y++)
{ MatrixOS::LED::SetColor(Point(column, y), color, targetLayer); }
}
ptr++; //Since ptr is the pointer of in vector, we need to read the next NN, inc the ptr by 1
}
}
}
break;

default:
break;
}

// Clear buffer since we are done parsing SysEx
sysExBuffer.clear();
}

void Performance::KeyEventHandler(uint16_t KeyID, KeyInfo* keyInfo) {
Point xy = MatrixOS::KEYPAD::ID2XY(KeyID);
if (xy) // IF XY is vaild, means it's on the main grid
Expand Down Expand Up @@ -237,7 +330,7 @@ void Performance::ActionMenu() {
actionMenu.SetLoopFunc([&]() -> void { //Keep buffer updated even when action menu is currently open
struct MidiPacket midiPacket;
while (MatrixOS::MIDI::Get(&midiPacket))
{ MidiEventHandler(midiPacket, false); }
{ MidiEventHandler(midiPacket); }
});

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

uiOpened = true;
actionMenu.Start();
uiOpened = false;

MatrixOS::Logging::LogDebug(name, "Exit Action Menu");
}
Expand Down
8 changes: 4 additions & 4 deletions applications/Performance/8x8/Performance8x8.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Performance : public Application {
uint8_t currentKeymap = 0;

uint8_t canvasLedLayer;
bool uiOpened = false;

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

void MidiEventHandler(MidiPacket midiPacket, bool renderOnActive);
void NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity, bool renderOnActive);
// void note_on_handler(uint8_t channel, uint8_t note, uint8_t velocity);
// void note_off_handler(uint8_t channel, uint8_t note, uint8_t velocity);
void MidiEventHandler(MidiPacket midiPacket);
void NoteHandler(uint8_t channel, uint8_t note, uint8_t velocity);
void SysExHandler(MidiPacket midiPacket);

void KeyEventHandler(uint16_t keyID, KeyInfo* keyInfo);

Expand Down
2 changes: 1 addition & 1 deletion lib/printf
5 changes: 3 additions & 2 deletions os/MatrixOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ namespace MatrixOS
{
noexpose void Init(void);

bool Get(MidiPacket* midipacket_dest, uint16_t timeout_ms = 0);
bool Send(MidiPacket midiPacket);
bool Get(MidiPacket* midiPacketDest, uint16_t timeout_ms = 0);
bool Send(MidiPacket midiPacket, uint16_t timeout_ms = 0);
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;

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

0 comments on commit 337ca5c

Please sign in to comment.