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

hdi08TxParser.cpp (4470B)


      1 #include "hdi08TxParser.h"
      2 
      3 #include <chrono>
      4 #include <sstream>
      5 #include <thread>
      6 
      7 #include "microcontroller.h"
      8 #include "romfile.h"
      9 
     10 #include "dsp56kEmu/logging.h"
     11 
     12 #define LOGTX(S)
     13 
     14 namespace virusLib
     15 {
     16 	const std::vector<dsp56k::TWord> g_knownPatterns[] =
     17 	{
     18 		{0xf40000, 0x7f0000}		// sent after DSP has booted
     19 	};
     20 
     21 	bool Hdi08TxParser::append(const dsp56k::TWord _data)
     22 	{
     23 //		LOGTX("HDI08 TX: " << HEX(_data));
     24 
     25 		const auto byte = static_cast<uint8_t>(_data >> 16);
     26 
     27 		switch (m_state)
     28 		{
     29 		case State::Default:
     30 			if(_data == 0xf4f4f4)
     31 			{
     32 				m_remainingPresetBytes = 0;
     33 				m_state = State::Default;
     34 				LOGTX("Finished receiving preset, no upgrade needed");
     35 			}
     36 			else if(_data == 0xf50000)
     37 			{
     38 				m_state = State::StatusReport;
     39 				m_remainingStatusBytes = isABCFamily(m_mc.getROM().getModel()) ? 1 : 2;
     40 			}
     41 			else if(_data == 0xf400f4)
     42 			{
     43 				m_state = State::Preset;
     44 				LOGTX("Begin receiving upgraded preset");
     45 
     46 				m_presetData.clear();
     47 
     48 				if(m_remainingPresetBytes == 0)
     49 				{
     50 					m_remainingPresetBytes = std::numeric_limits<uint32_t>::max();
     51 					LOGTX("No one requested a preset upgrade, assuming preset size based on first word (version number)");
     52 				}
     53 			}
     54 			else if((_data & 0xff0000) == 0xf00000)
     55 			{
     56 				LOGTX("Begin reading sysex");
     57 				m_state = State::Sysex;
     58 				m_sysexData.push_back(byte);
     59 				m_sysexReceiveIndex = 1;
     60 			}
     61 			else
     62 			{
     63 				size_t i=0;
     64 				bool matched = false;
     65 
     66 				m_nonPatternWords.emplace_back(_data);
     67 
     68 				for (const auto& pattern : g_knownPatterns)
     69 				{
     70 					auto& pos = m_patternPositions[i];
     71 
     72 					if(pattern[pos] == _data)
     73 					{
     74 						matched = true;
     75 
     76 						++pos;
     77 						if(pos == std::size(pattern))
     78 						{
     79 //							LOGTX("Matched pattern " << i);
     80 							const auto p = static_cast<PatternType>(i);
     81 
     82 							switch (p)
     83 							{
     84 							case PatternType::DspBoot:
     85 								m_dspHasBooted = true;
     86 								LOGTX("DSP boot completed");
     87 								break;
     88 							default:
     89 								m_matchedPatterns.push_back(p);
     90 								break;
     91 							}
     92 
     93 							pos = 0;
     94 							m_nonPatternWords.clear();
     95 						}
     96 					}
     97 					else
     98 					{
     99 						pos = 0;
    100 					}
    101 
    102 					++i;
    103 				}
    104 
    105 				if(!matched)
    106 				{
    107 /*					std::stringstream s;
    108 					for (const auto& w : m_nonPatternWords)
    109 						s << HEX(w) << ' ';
    110 					LOGTX("Unknown DSP words: " << s.str());
    111 */
    112 					m_nonPatternWords.clear();
    113 				}
    114 			}
    115 			break;
    116 		case State::Sysex:
    117 			{
    118 				if(_data & 0xffff)
    119 				{
    120 					LOGTX("Abort reading sysex, received invalid midi byte " << HEX(_data));
    121 					m_state = State::Default;
    122 					m_midiData.clear();
    123 					return append(_data);
    124 				}
    125 
    126 				// TI seems to send 3 valid bytes and then a fourth invalid one, no idea what this is good for, drop it
    127 				++m_sysexReceiveIndex;
    128 				if(m_mc.getROM().isTIFamily() && (m_sysexReceiveIndex & 3) == 0)
    129 					return true;
    130 
    131 				m_sysexData.push_back(byte);
    132 
    133 				if(byte == 0xf7)
    134 				{
    135 					LOGTX("End reading sysex");
    136 
    137 					m_state = State::Default;
    138 
    139 					std::stringstream s;
    140 					for (const auto b : m_sysexData)
    141 						s << HEXN(b, 2);
    142 
    143 					LOGTX("Received sysex: " << s.str());
    144 
    145 					synthLib::SMidiEvent ev(synthLib::MidiEventSource::Plugin);
    146 					std::swap(ev.sysex, m_sysexData);
    147 					m_midiData.emplace_back(ev);
    148 
    149 					return true;
    150 				}
    151 			}
    152 			break;
    153 		case State::Preset:
    154 			{
    155 				if(m_remainingPresetBytes == std::numeric_limits<uint32_t>::max())
    156 				{
    157 					const auto version = byte;
    158 
    159 					switch (version)
    160 					{
    161 					case 1:
    162 					case 2:
    163 						m_remainingPresetBytes = m_mc.getROM().getMultiPresetSize();
    164 						break;
    165 					default:
    166 						m_remainingPresetBytes = m_mc.getROM().getSinglePresetSize();
    167 						break;
    168 					}
    169 					LOGTX("Preset size for version code " << static_cast<int>(version) << " is " << m_remainingPresetBytes);
    170 				}
    171 
    172 				uint32_t shift = 16;
    173 				uint32_t i=0;
    174 				while(m_remainingPresetBytes > 0 && i < 3)
    175 				{
    176 					m_presetData.push_back((_data >> shift) & 0xff);
    177 					shift -= 8;
    178 					--m_remainingPresetBytes;
    179 					++i;
    180 				}
    181 
    182 				if(m_remainingPresetBytes == 0)
    183 				{
    184 					LOGTX("Succesfully received preset");
    185 					m_state = State::Default;
    186 				}
    187 			}
    188 			break;
    189 		case State::StatusReport:
    190 			m_dspStatus.push_back(_data);
    191 			if(--m_remainingStatusBytes == 0)
    192 				m_state = State::Default;
    193 			break;
    194 		}
    195 
    196 		return false;
    197 	}
    198 
    199 	void Hdi08TxParser::waitForPreset(uint32_t _byteCount)
    200 	{
    201 		m_remainingPresetBytes = _byteCount;
    202 	}
    203 
    204 	void Hdi08TxParser::getPresetData(std::vector<uint8_t>& _data)
    205 	{
    206 		std::swap(m_presetData, _data);
    207 		m_presetData.clear();
    208 	}
    209 }