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

microcontroller.h (4607B)


      1 #pragma once
      2 
      3 #include "romfile.h"
      4 
      5 #include "synthLib/deviceTypes.h"
      6 #include "synthLib/midiTypes.h"
      7 #include "synthLib/buildconfig.h"
      8 
      9 #include <list>
     10 #include <mutex>
     11 #include <limits>
     12 
     13 #include "hdi08List.h"
     14 #include "hdi08MidiQueue.h"
     15 #include "hdi08TxParser.h"
     16 #include "microcontrollerTypes.h"
     17 
     18 namespace virusLib
     19 {
     20 	struct FrontpanelState;
     21 	class DspSingle;
     22 	class DemoPlayback;
     23 
     24 class Microcontroller
     25 {
     26 	friend class DemoPlayback;
     27 public:
     28 	using TPreset = ROMFile::TPreset;
     29 
     30 	explicit Microcontroller(DspSingle& _dsp, const ROMFile& romFile, bool _useEsaiBasedMidiTiming);
     31 
     32 	bool sendMIDI(const synthLib::SMidiEvent& _ev, FrontpanelState* _fpState = nullptr);
     33 	bool sendSysex(const std::vector<uint8_t>& _data, std::vector<synthLib::SMidiEvent>& _responses, synthLib::MidiEventSource _source);
     34 
     35 	bool writeSingle(BankNumber _bank, uint8_t _program, const TPreset& _data);
     36 	bool writeMulti(BankNumber _bank, uint8_t _program, const TPreset& _data);
     37 	bool requestMulti(BankNumber _bank, uint8_t _program, TPreset& _data);
     38 	bool requestSingle(BankNumber _bank, uint8_t _program, TPreset& _data);
     39 
     40 	void sendInitControlCommands(uint8_t _masterVolume = 0xff);
     41 
     42 	void createDefaultState();
     43 	void process();
     44 
     45 #if !SYNTHLIB_DEMO_MODE
     46 	bool getState(std::vector<unsigned char>& _state, synthLib::StateType _type);
     47 	bool setState(const std::vector<unsigned char>& _state, synthLib::StateType _type);
     48 	bool setState(const std::vector<synthLib::SMidiEvent>& _events);
     49 #endif
     50 
     51 	void addDSP(DspSingle& _dsp, bool _useEsaiBasedMidiTiming);
     52 
     53 	void readMidiOut(std::vector<synthLib::SMidiEvent>& _midiOut);
     54 	void sendPendingMidiEvents(uint32_t _maxOffset);
     55 	Hdi08MidiQueue& getMidiQueue(size_t _index) { return m_midiQueues[_index]; }
     56 
     57 	static PresetVersion getPresetVersion(const TPreset& _preset);
     58 	static PresetVersion getPresetVersion(uint8_t _versionCode);
     59 
     60 	static uint8_t calcChecksum(const std::vector<uint8_t>& _data, size_t _offset = 5, size_t _count = std::numeric_limits<size_t>::max());
     61 
     62 	bool dspHasBooted() const;
     63 
     64 	const ROMFile& getROM() const { return m_rom; }
     65 
     66 	uint32_t getPartCount() const;
     67 
     68 
     69 	void setSamplerate(float _samplerate);
     70 
     71 	uint8_t getPartMidiChannel(uint8_t _part) const;
     72 	bool isPolyPressureForPageBEnabled() const;
     73 
     74 private:
     75 	bool send(Page page, uint8_t part, uint8_t param, uint8_t value);
     76 	void sendControlCommand(ControlCommand command, uint8_t value);
     77 	bool sendPreset(uint8_t program, const TPreset& _data, bool isMulti = false);
     78 	void writeHostBitsWithWait(uint8_t flag0, uint8_t flag1);
     79 	std::vector<dsp56k::TWord> presetToDSPWords(const TPreset& _preset, bool _isMulti) const;
     80 	bool getSingle(BankNumber _bank, uint32_t _preset, TPreset& _result) const;
     81 
     82 	bool partBankSelect(uint8_t _part, uint8_t _value, bool _immediatelySelectSingle);
     83 	bool partProgramChange(uint8_t _part, uint8_t _value);
     84 	bool multiProgramChange(uint8_t _value);
     85 	bool loadMulti(uint8_t _program, const TPreset& _multi);
     86 	bool loadMultiSingle(uint8_t _part);
     87 	bool loadMultiSingle(uint8_t _part, const TPreset& _multi);
     88 
     89 	void applyToSingleEditBuffer(Page _page, uint8_t _part, uint8_t _param, uint8_t _value);
     90 	static void applyToSingleEditBuffer(TPreset& _single, Page _page, uint8_t _param, uint8_t _value);
     91 	void applyToMultiEditBuffer(Page _page, uint8_t _part, uint8_t _param, uint8_t _value);
     92 	Page globalSettingsPage() const;
     93 	bool isPageSupported(Page _page) const;
     94 	void processHdi08Tx(std::vector<synthLib::SMidiEvent>& _midiEvents);
     95 	bool waitingForPresetReceiveConfirmation() const;
     96 	void receiveUpgradedPreset();
     97 
     98 	static bool isValid(const TPreset& _preset);
     99 
    100 	Hdi08List m_hdi08;
    101 	std::vector<Hdi08TxParser> m_hdi08TxParsers;
    102 	std::vector<Hdi08MidiQueue> m_midiQueues;
    103 
    104 	const ROMFile& m_rom;
    105 
    106 	std::array<TPreset,128> m_multis{};
    107 	TPreset m_multiEditBuffer;
    108 
    109 	std::array<uint32_t, 256> m_globalSettings;
    110 	std::vector<std::vector<TPreset>> m_singles;
    111 
    112 	// Multi mode
    113 	std::array<TPreset,16> m_singleEditBuffers{};
    114 
    115 	// Single mode
    116 	TPreset m_singleEditBuffer{};
    117 	uint8_t m_currentBank = 0;
    118 	uint8_t m_currentSingle = 0;
    119 
    120 	uint8_t m_sentPresetProgram = 0;
    121 	bool m_sentPresetIsMulti = false;
    122 
    123 	// Device does not like if we send everything at once, therefore we delay the send of Singles after sending a Multi
    124 	struct SPendingPresetWrite
    125 	{
    126 		uint8_t program = 0;
    127 		bool isMulti = false;
    128 		TPreset data;
    129 	};
    130 
    131 	std::list<SPendingPresetWrite> m_pendingPresetWrites;
    132 
    133 	std::vector<std::pair<synthLib::MidiEventSource, std::vector<uint8_t>>> m_pendingSysexInput;
    134 	std::vector<synthLib::SMidiEvent> m_midiOutput;
    135 
    136 	mutable std::recursive_mutex m_mutex;
    137 	bool m_loadingState = false;
    138 };
    139 
    140 }