Skip to content

Commit

Permalink
add key update buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
vsicurella committed Aug 21, 2023
1 parent a6651b7 commit d3ef79a
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 36 deletions.
54 changes: 24 additions & 30 deletions Source/LumatoneController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ LumatoneController::LumatoneController()
: midiDriver(getNumBoards())
, errorVisualizer(TerpstraSysExApplication::getApp().getLookAndFeel())
, readQueueSize(0)
, keyUpdater(midiDriver)
{
reset(bufferReadSize);
midiDriver.addMessageCollector(this);
Expand Down Expand Up @@ -174,34 +175,19 @@ Combined (hi-level) commands
*/


void LumatoneController::sendAllParamsOfBoard(int boardIndex, LumatoneBoard boardData)
void LumatoneController::sendAllParamsOfBoard(int boardIndex, LumatoneBoard boardData, bool bufferMessages)
{
if (determinedVersion >= LumatoneFirmwareVersion::VERSION_1_0_11)
for (int keyIndex = 0; keyIndex < octaveSize; keyIndex++)
{
for (int keyIndex = 0; keyIndex < octaveSize; keyIndex++)
{
auto key = &boardData.theKeys[keyIndex];
midiDriver.sendKeyFunctionParameters(boardIndex, keyIndex, key->noteNumber, key->channelNumber, key->keyType & 0x3);
midiDriver.sendKeyLightParameters(boardIndex, keyIndex, key->colour.getRed(), key->colour.getGreen(), key->colour.getBlue());
*getKey(boardIndex - 1, keyIndex) = *key;
}
}
else
{
for (int keyIndex = 0; keyIndex < octaveSize; keyIndex++)
{
auto key = &boardData.theKeys[keyIndex];
midiDriver.sendKeyFunctionParameters(boardIndex, keyIndex, key->noteNumber, key->channelNumber, key->keyType & 0x3);
midiDriver.sendKeyLightParameters_Version_1_0_0(boardIndex, keyIndex, key->colour.getRed() / 2, key->colour.getGreen() / 2, key->colour.getBlue() / 2);
*getKey(boardIndex - 1, keyIndex) = *key;
}
auto key = &boardData.theKeys[keyIndex];
sendKeyParam(boardIndex, keyIndex, *key, bufferMessages);
}
}

void LumatoneController::sendCompleteMapping(LumatoneLayout mappingData)
void LumatoneController::sendCompleteMapping(LumatoneLayout mappingData, bool bufferMessages)
{
for (int boardIndex = 1; boardIndex <= getNumBoards(); boardIndex++)
sendAllParamsOfBoard(boardIndex, *mappingData.getBoard(boardIndex - 1));
sendAllParamsOfBoard(boardIndex, *mappingData.getBoard(boardIndex - 1), bufferMessages);
}

void LumatoneController::sendGetMappingOfBoardRequest(int boardIndex)
Expand Down Expand Up @@ -292,12 +278,12 @@ void LumatoneController::testCurrentDeviceConnection()
}
}

void LumatoneController::sendKeyParam(int boardIndex, int keyIndex, LumatoneKey keyData)
void LumatoneController::sendKeyParam(int boardIndex, int keyIndex, LumatoneKey keyData, bool bufferMessages)
// Send parametrization of one key to the device
{
// Default CC polarity = 1, Inverted CC polarity = 0
sendKeyConfig(boardIndex, keyIndex, keyData.noteNumber, keyData.channelNumber, keyData.keyType, keyData.ccFaderDefault);
sendKeyColourConfig(boardIndex, keyIndex, keyData.colour);
sendKeyConfig(boardIndex, keyIndex, keyData.noteNumber, keyData.channelNumber, keyData.keyType, keyData.ccFaderDefault, bufferMessages);
sendKeyColourConfig(boardIndex, keyIndex, keyData.colour, bufferMessages);
}

// Send configuration of a certain look up table
Expand Down Expand Up @@ -326,20 +312,28 @@ void LumatoneController::sendTableConfig(LumatoneConfigTable::TableType velocity
// Mid-level firmware functions

// Send note, channel, cc, and fader polarity data
void LumatoneController::sendKeyConfig(int boardIndex, int keyIndex, int noteOrCCNum, int channel, int keyType, bool faderUpIsNull)
void LumatoneController::sendKeyConfig(int boardIndex, int keyIndex, int noteOrCCNum, int channel, int keyType, bool faderUpIsNull, bool bufferMessages)
{
midiDriver.sendKeyFunctionParameters(boardIndex, keyIndex, noteOrCCNum, channel, keyType & 0x3, faderUpIsNull);
if (bufferMessages)
keyUpdater.sendKeyConfig(boardIndex, keyIndex, noteOrCCNum, channel, keyType & 0x3, faderUpIsNull);
else
midiDriver.sendKeyFunctionParameters(boardIndex, keyIndex, noteOrCCNum, channel, keyType & 0x3, faderUpIsNull);

auto key = getKey(boardIndex - 1, keyIndex);
*key = LumatoneKey((LumatoneKeyType)keyType, channel - 1, noteOrCCNum, key->colour, faderUpIsNull);
}

void LumatoneController::sendKeyColourConfig(int boardIndex, int keyIndex, Colour colour)
void LumatoneController::sendKeyColourConfig(int boardIndex, int keyIndex, Colour colour, bool bufferMessages)
{
if (determinedVersion >= LumatoneFirmwareVersion::VERSION_1_0_11)
midiDriver.sendKeyLightParameters(boardIndex, keyIndex, colour.getRed(), colour.getGreen(), colour.getBlue());
if (bufferMessages)
keyUpdater.sendKeyColourConfig(boardIndex, keyIndex, colour);
else
midiDriver.sendKeyLightParameters_Version_1_0_0(boardIndex, keyIndex, colour.getRed() / 2, colour.getGreen() / 2, colour.getBlue() / 2);
{
if (determinedVersion >= LumatoneFirmwareVersion::VERSION_1_0_11)
midiDriver.sendKeyLightParameters(boardIndex, keyIndex, colour.getRed(), colour.getGreen(), colour.getBlue());
else
midiDriver.sendKeyLightParameters_Version_1_0_0(boardIndex, keyIndex, colour.getRed() / 2, colour.getGreen() / 2, colour.getBlue() / 2);
}

getKey(boardIndex - 1, keyIndex)->colour = colour;
}
Expand Down
15 changes: 9 additions & 6 deletions Source/LumatoneController.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "TerpstraMidiDriver.h"
#include "DeviceActivityMonitor.h"
#include "FirmwareTransfer.h"
#include "key_update_buffer.h"

//==============================================================================
// Helper class for parsing and comparing (todo) firmware versions
Expand All @@ -41,7 +42,7 @@ class LumatoneController : private TerpstraMidiDriver::Collector,

FirmwareVersion getFirmwareVersion() const { return firmwareVersion; }

LumatoneFirmwareVersion getConfirmedVersion() const { return determinedVersion; }
LumatoneFirmwareVersion getLumatoneVersion() const { return determinedVersion; }

const FirmwareSupport& getFirmwareSupport() const { return firmwareSupport; }

Expand Down Expand Up @@ -92,10 +93,10 @@ class LumatoneController : private TerpstraMidiDriver::Collector,
// Combined (hi-level) commands

// Send all parametrizations of one sub board
void sendAllParamsOfBoard(int boardIndex, LumatoneBoard boardData);
void sendAllParamsOfBoard(int boardIndex, LumatoneBoard boardData, bool bufferMessages=false);

// Send and save a complete key mapping
void sendCompleteMapping(LumatoneLayout mappingData);
void sendCompleteMapping(LumatoneLayout mappingData, bool bufferMessages=false);

// Send request to receive the current mapping of one sub board on the controller
void sendGetMappingOfBoardRequest(int boardIndex);
Expand All @@ -104,7 +105,7 @@ class LumatoneController : private TerpstraMidiDriver::Collector,
void sendGetCompleteMappingRequest();

// Send parametrization of one key to the device
void sendKeyParam(int boardIndex, int keyIndex, LumatoneKey keyData);
void sendKeyParam(int boardIndex, int keyIndex, LumatoneKey keyData, bool bufferMessages = false);

// Send configuration of a certain look up table
void sendTableConfig(LumatoneConfigTable::TableType velocityCurveType, const uint8* table);
Expand All @@ -122,9 +123,9 @@ class LumatoneController : private TerpstraMidiDriver::Collector,
// Single (mid-level) commands

// Send note, channel, cc, and fader polarity data
void sendKeyConfig(int boardIndex, int keyIndex, int noteOrCCNum, int channel, int keyType, bool faderUpIsNull = true);
void sendKeyConfig(int boardIndex, int keyIndex, int noteOrCCNum, int channel, int keyType, bool faderUpIsNull = true, bool bufferMessages = false);

void sendKeyColourConfig(int boardIndex, int keyIndex, Colour colour);
void sendKeyColourConfig(int boardIndex, int keyIndex, Colour colour, bool bufferMessages = false);

// Send expression pedal sensivity
void sendExpressionPedalSensivity(unsigned char value);
Expand Down Expand Up @@ -373,6 +374,8 @@ class LumatoneController : private TerpstraMidiDriver::Collector,
HajuErrorVisualizer errorVisualizer;
TerpstraMidiDriver midiDriver;

LumatoneKeyUpdateBuffer keyUpdater;

std::unique_ptr<DeviceActivityMonitor> deviceMonitor;

std::unique_ptr<FirmwareTransfer> firmwareTransfer;
Expand Down
1 change: 1 addition & 0 deletions Source/Main.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class TerpstraSysExApplication : public JUCEApplication
int getOctaveBoardSize() const { return lumatoneController->getOctaveBoardSize(); }
int getNumBoards() const { return lumatoneController->getNumBoards(); }

LumatoneFirmwareVersion getLumatoneVersion() const { return lumatoneController->getLumatoneVersion(); }
FirmwareVersion getFirmwareVersion() const { return lumatoneController->getFirmwareVersion(); }
String getFirmwareVersionStr() const { return lumatoneController->getFirmwareVersion().toDisplayString(); }

Expand Down
134 changes: 134 additions & 0 deletions Source/key_update_buffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include "key_update_buffer.h"
#include "Main.h"

LumatoneKeyUpdateBuffer::LumatoneKeyUpdateBuffer(TerpstraMidiDriver& driverIn)
: midiDriver(driverIn)
{
keysToUpdate.remapTable(280);
}

LumatoneKeyUpdateBuffer::~LumatoneKeyUpdateBuffer()
{

}

int LumatoneKeyUpdateBuffer::getKeyNum(int boardIndex, int keyIndex) const
{
return boardIndex * TerpstraSysExApplication::getApp().getOctaveBoardSize() + keyIndex;
}

LumatoneKeyCoord LumatoneKeyUpdateBuffer::getKeyCoord(int keyNum) const
{
return LumatoneKeyCoord(keyNum / TerpstraSysExApplication::getApp().getOctaveBoardSize(),
keyNum % TerpstraSysExApplication::getApp().getOctaveBoardSize());
}

void LumatoneKeyUpdateBuffer::sendKeyConfig(int boardId, int keyIndex, const LumatoneKey& noteDataConfig, bool signalEditorListeners)
{
updateKeyConfig(boardId - 1, keyIndex, noteDataConfig);
}

void LumatoneKeyUpdateBuffer::sendKeyConfig(int boardIndex, int keyIndex, int noteOrCCNum, int channel, int keyType, bool faderUpIsNull)
{
auto config = LumatoneKey(LumatoneKeyType(keyType), channel, noteOrCCNum, juce::Colour(), faderUpIsNull);
updateKeyConfig(boardIndex, keyIndex, config);
}

void LumatoneKeyUpdateBuffer::sendKeyColourConfig(int boardId, int keyIndex, juce::Colour colour, bool signalEditorListeners)
{
updateKeyColour(boardId - 1, keyIndex, colour);
}

void LumatoneKeyUpdateBuffer::updateKeyConfig(int boardIndex, int keyIndex, const LumatoneKey& config)
{
lock.enter();
// while (!lock.tryEnter()) {}

auto keyNum = getKeyNum(boardIndex, keyIndex);
MappedLumatoneKey currentUpdateData = keysToUpdate[keyNum];

auto currentKey = TerpstraSysExApplication::getApp().getMappingData()->readKey(boardIndex, keyIndex);
preUpdateLayout.getBoard(boardIndex)->theKeys[keyIndex] = *currentKey;

if (*currentKey == config)
{
keysToUpdate.set(keyNum, MappedLumatoneKey());
}
else if (currentUpdateData.boardIndex < 0 || currentUpdateData.keyIndex < 0)
{
keysToUpdate.set(keyNum, MappedLumatoneKey(config.withColour(currentKey->colour), boardIndex, keyIndex));
}
else if (!currentUpdateData.configIsEqual(config))
{
keysToUpdate.set(keyNum, MappedLumatoneKey(config.withColour(currentUpdateData.colour), boardIndex, keyIndex));
}

lock.exit();
startTimer(updateMs);
}

void LumatoneKeyUpdateBuffer::updateKeyColour(int boardIndex, int keyIndex, juce::Colour colour)
{
lock.enter();
// while (!lock.tryEnter()) {}

auto keyNum = getKeyNum(boardIndex, keyIndex);
MappedLumatoneKey currentUpdateData = keysToUpdate[keyNum];
auto currentKey = TerpstraSysExApplication::getApp().getMappingData()->readKey(boardIndex, keyIndex);
preUpdateLayout.getBoard(boardIndex)->theKeys[keyIndex] = *currentKey;

if (currentKey->colour == colour && currentKey->configIsEqual(currentUpdateData))
{
keysToUpdate.set(keyNum, MappedLumatoneKey());
}
else if (currentUpdateData.boardIndex < 0 || currentUpdateData.keyIndex < 0)
{
keysToUpdate.set(keyNum, MappedLumatoneKey(currentKey->withColour(colour), boardIndex, keyIndex));
}
else if (currentUpdateData.colour != colour)
{
keysToUpdate.set(keyNum, MappedLumatoneKey(currentUpdateData.withColour(colour), boardIndex, keyIndex));
}

lock.exit();
startTimer(updateMs);
}

void LumatoneKeyUpdateBuffer::timerCallback()
{
stopTimer();

if (! lock.tryEnter())
return;

int keyNum = 0;
for (int board = 0; board < TerpstraSysExApplication::getApp().getNumBoards(); board++)
{
int boardId = board + 1;
for (int keyIndex = 0; keyIndex < TerpstraSysExApplication::getApp().getOctaveBoardSize(); keyIndex++)
{
auto keyUpdate = keysToUpdate[keyNum];
if (keyUpdate.boardIndex >= 0 && keyUpdate.keyIndex >= 0)
{
// auto currentKey = getKey(board, keyIndex);
auto currentKey = preUpdateLayout.getBoard(board)->theKeys[keyIndex];
if (!currentKey.configIsEqual(keyUpdate))
midiDriver.sendKeyFunctionParameters(boardId, keyIndex, keyUpdate.noteNumber, keyUpdate.channelNumber, keyUpdate.keyType, keyUpdate.ccFaderDefault);

if (!currentKey.colourIsEqual(keyUpdate))
{
auto colour = keyUpdate.colour;
if (TerpstraSysExApplication::getApp().getLumatoneVersion() >= LumatoneFirmwareVersion::VERSION_1_0_11)
midiDriver.sendKeyLightParameters(boardId, keyIndex, colour.getRed(), colour.getGreen(), colour.getBlue());
else
midiDriver.sendKeyLightParameters_Version_1_0_0(boardId, keyIndex, colour.getRed() * 0.5f, colour.getGreen() * 0.5f, colour.getBlue() * 0.5f);
}
}

keysToUpdate.set(keyNum, MappedLumatoneKey());
keyNum++;
}
}

lock.exit();
}
40 changes: 40 additions & 0 deletions Source/key_update_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include "./data/lumatone_layout.h"

#include "TerpstraMidiDriver.h"

class LumatoneKeyUpdateBuffer : private juce::Timer
{
public:

LumatoneKeyUpdateBuffer(TerpstraMidiDriver& midiDriver);
~LumatoneKeyUpdateBuffer() override;

void sendKeyConfig(int boardId, int keyIndex, const LumatoneKey& noteDataConfig, bool signalEditorListeners = true);
void sendKeyConfig(int boardIndex, int keyIndex, int noteOrCCNum, int channel, int keyType, bool faderUpIsNull = true);

void sendKeyColourConfig(int boardId, int keyIndex, juce::Colour colour, bool signalEditorListeners = true);

void timerCallback() override;

private:

int getKeyNum(int boardIndex, int keyIndex) const;
LumatoneKeyCoord getKeyCoord(int keyNum) const;

void updateKeyConfig(int boardIndex, int keyIndex, const LumatoneKey& config);
void updateKeyColour(int boardIndex, int keyIndex, juce::Colour colour);

private:

juce::CriticalSection lock;

TerpstraMidiDriver& midiDriver;

juce::HashMap<int, MappedLumatoneKey> keysToUpdate;

LumatoneLayout preUpdateLayout;

int updateMs = 300;
};
4 changes: 4 additions & 0 deletions TerpstraSysEx.jucer
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@
<FILE id="pKv4Ei" name="TuningTable.cpp" compile="1" resource="0" file="Source/tuning/TuningTable.cpp"/>
<FILE id="thzIk5" name="TuningTable.h" compile="0" resource="0" file="Source/tuning/TuningTable.h"/>
</GROUP>
<FILE id="i3lnlL" name="key_update_buffer.cpp" compile="1" resource="0"
file="Source/key_update_buffer.cpp"/>
<FILE id="sPQ3wT" name="key_update_buffer.h" compile="0" resource="0"
file="Source/key_update_buffer.h"/>
<FILE id="JdAwbS" name="lumatone_render.h" compile="0" resource="0"
file="Source/lumatone_render.h"/>
<FILE id="vms2bU" name="lumatone_render.cpp" compile="1" resource="0"
Expand Down

0 comments on commit d3ef79a

Please sign in to comment.