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 }