gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

xtSysexRemoteControl.cpp (4066B)


      1 #include "xtSysexRemoteControl.h"
      2 
      3 #include "xtMidiTypes.h"
      4 #include "xt.h"
      5 #include "xtButtons.h"
      6 #include "xtHardware.h"
      7 #include "xtLeds.h"
      8 
      9 #include "synthLib/midiTypes.h"
     10 
     11 namespace xt
     12 {
     13 	enum class ButtonType;
     14 
     15 	void SysexRemoteControl::createSysexHeader(std::vector<uint8_t>& _dst, xt::SysexCommand _cmd)
     16 	{
     17 		constexpr uint8_t devId = 0;
     18 		_dst.assign({0xf0, wLib::IdWaldorf, IdMw2, devId, static_cast<uint8_t>(_cmd)});
     19 	}
     20 
     21 	void SysexRemoteControl::sendSysexLCD(std::vector<synthLib::SMidiEvent>& _dst) const
     22 	{
     23 		std::array<char, 80> lcdData{};
     24 		m_mq.readLCD(lcdData);
     25 
     26 		synthLib::SMidiEvent ev(synthLib::MidiEventSource::Internal);
     27 		createSysexHeader(ev.sysex, SysexCommand::EmuLCD);
     28 		ev.sysex.insert(ev.sysex.end(), lcdData.begin(), lcdData.end());
     29 
     30 		ev.sysex.push_back(0xf7);
     31 		_dst.emplace_back(ev);
     32 	}
     33 	
     34 	void SysexRemoteControl::sendSysexButtons(std::vector<synthLib::SMidiEvent>& _dst) const
     35 	{
     36 		static_assert(static_cast<uint32_t>(ButtonType::Count) < 24, "too many buttons");
     37 		uint32_t buttons = 0;
     38 		for(uint32_t i=0; i<static_cast<uint32_t>(ButtonType::Count); ++i)
     39 		{
     40 			if(m_mq.getButton(static_cast<ButtonType>(i)))
     41 				buttons |= (1<<i);
     42 		}
     43 
     44 		auto& ev = _dst.emplace_back(synthLib::MidiEventSource::Internal);
     45 
     46 		createSysexHeader(ev.sysex, SysexCommand::EmuButtons);
     47 
     48 		ev.sysex.push_back((buttons>>16) & 0xff);
     49 		ev.sysex.push_back((buttons>>8) & 0xff);
     50 		ev.sysex.push_back(buttons & 0xff);
     51 		ev.sysex.push_back(0xf7);
     52 	}
     53 
     54 	void SysexRemoteControl::sendSysexLEDs(std::vector<synthLib::SMidiEvent>& _dst) const
     55 	{
     56 		static_assert(static_cast<uint32_t>(LedType::Count) < 32, "too many LEDs");
     57 		uint32_t leds = 0;
     58 		for(uint32_t i=0; i<static_cast<uint32_t>(LedType::Count); ++i)
     59 		{
     60 			if(m_mq.getLedState(static_cast<LedType>(i)))
     61 				leds |= (1<<i);
     62 		}
     63 		auto& ev = _dst.emplace_back(synthLib::MidiEventSource::Internal);
     64 		auto& response = ev.sysex;
     65 		createSysexHeader(response, SysexCommand::EmuLEDs);
     66 		response.push_back((leds>>24) & 0xff);
     67 		response.push_back((leds>>16) & 0xff);
     68 		response.push_back((leds>>8) & 0xff);
     69 		response.push_back(leds & 0xff);
     70 		response.push_back(0xf7);
     71 	}
     72 
     73 	void SysexRemoteControl::sendSysexRotaries(std::vector<synthLib::SMidiEvent>& _dst) const
     74 	{
     75 /*		auto& ev= _dst.emplace_back(synthLib::MidiEventSource::Internal);
     76 		auto& response = ev.sysex;
     77 
     78 		createSysexHeader(response, SysexCommand::EmuRotaries);
     79 
     80 		for(uint32_t i=0; i<static_cast<uint32_t>(Buttons::Encoders::Count); ++i)
     81 		{
     82 			const auto value = m_mq.getEncoder(static_cast<Buttons::Encoders>(i));
     83 			response.push_back(value);
     84 		}
     85 */	}
     86 
     87 	bool SysexRemoteControl::receive(std::vector<synthLib::SMidiEvent>& _output, const std::vector<unsigned char>& _input) const
     88 	{
     89 		if(_input.size() < 5)
     90 			return false;
     91 
     92 		if(_input[1] != wLib::IdWaldorf || _input[2] != IdMw2)
     93 			return false;
     94 
     95 		const auto cmd = _input[4];
     96 
     97 		switch (static_cast<SysexCommand>(cmd))
     98 		{
     99 		case SysexCommand::EmuLCD:
    100 			sendSysexLCD(_output);
    101 			return true;
    102 		case SysexCommand::EmuButtons:
    103 			{
    104 				if(_input.size() > 6)
    105 				{
    106 					const auto button = static_cast<ButtonType>(_input[5]);
    107 					const auto state = _input[6];
    108 					m_mq.getHardware()->getUC().setButton(button, state != 0);
    109 				}
    110 				else
    111 				{
    112 					sendSysexButtons(_output);
    113 				}
    114 			}
    115 			return true;
    116 		case SysexCommand::EmuLEDs:
    117 			{
    118 				sendSysexLEDs(_output);
    119 			}
    120 			return true;
    121 		case SysexCommand::EmuRotaries:
    122 			{
    123 				return false;
    124 /*				if(_input.size() > 6)
    125 				{
    126 					const auto encoder = static_cast<Encoders>(_input[5]);
    127 					const auto amount = static_cast<int>(_input[6]) - 64;
    128 					if(amount)
    129 						m_mq.rotateEncoder(encoder, amount);
    130 				}
    131 				else
    132 				{
    133 					sendSysexRotaries(_output);
    134 				}
    135 */			}
    136 			return true;
    137 		default:
    138 			return false;
    139 		}
    140 	}
    141 
    142 	void SysexRemoteControl::handleDirtyFlags(std::vector<synthLib::SMidiEvent>& _output, const uint32_t _dirtyFlags) const
    143 	{
    144 		if(_dirtyFlags & static_cast<uint32_t>(Xt::DirtyFlags::Lcd))
    145 			sendSysexLCD(_output);
    146 		if(_dirtyFlags & static_cast<uint32_t>(Xt::DirtyFlags::Leds))
    147 			sendSysexLEDs(_output);
    148 	}
    149 }