commit 1eb0591775bfe9bfc47d643c536008c77708fd7c
parent e6387b5128e16f7900689863ac03ea67f2eae784
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Thu, 25 Jul 2024 20:38:39 +0200
create new library for misc hardware emulations
Diffstat:
31 files changed, 813 insertions(+), 772 deletions(-)
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
@@ -42,12 +42,10 @@ if(${CMAKE_PROJECT_NAME}_BUILD_JUCEPLUGIN)
endif()
# ----------------- dependencies
-if(${CMAKE_PROJECT_NAME}_SYNTH_VAVRA OR ${CMAKE_PROJECT_NAME}_SYNTH_XENIA OR ${CMAKE_PROJECT_NAME}_SYNTH_N2X)
- add_subdirectory(mc68k)
- if(${CMAKE_PROJECT_NAME}_SYNTH_VAVRA OR ${CMAKE_PROJECT_NAME}_SYNTH_XENIA)
- add_subdirectory(wLib)
- endif()
-endif()
+
+add_subdirectory(mc68k EXCLUDE_FROM_ALL)
+add_subdirectory(hardwareLib EXCLUDE_FROM_ALL)
+add_subdirectory(wLib EXCLUDE_FROM_ALL)
# ----------------- Synths Osirus/OsTIrus
diff --git a/source/hardwareLib/CMakeLists.txt b/source/hardwareLib/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.10)
+project(hardwareLib)
+
+add_library(hardwareLib STATIC)
+
+set(SOURCES
+ am29f.cpp am29f.h
+ i2c.cpp i2c.h
+ i2cFlash.cpp i2cFlash.h
+ sciMidi.cpp sciMidi.h
+)
+
+target_sources(hardwareLib PRIVATE ${SOURCES})
+source_group("source" FILES ${SOURCES})
+
+target_link_libraries(hardwareLib PUBLIC 68kEmu dsp56kEmu synthLib)
+
+set_property(TARGET hardwareLib PROPERTY FOLDER "Gearmulator")
+
+target_include_directories(hardwareLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
diff --git a/source/hardwareLib/am29f.cpp b/source/hardwareLib/am29f.cpp
@@ -0,0 +1,138 @@
+#include "am29f.h"
+
+#include <cassert>
+
+#include "mc68k/logging.h"
+#include "mc68k/mc68k.h"
+
+namespace hwLib
+{
+ Am29f::Am29f(uint8_t* _buffer, const size_t _size, bool _useWriteEnable, bool _bitreversedCmdAddr): m_buffer(_buffer), m_size(_size), m_useWriteEnable(_useWriteEnable), m_bitreverseCmdAddr(_bitreversedCmdAddr)
+ {
+ auto br = [&](uint16_t x)
+ {
+ return m_bitreverseCmdAddr ? static_cast<uint16_t>(bitreverse(x) >> 4) : x;
+ };
+
+ // Chip Erase
+ m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x80}, {br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x10}}});
+
+ // Sector Erase
+ m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x80}, {br(0x555),0xAA}, {br(0x2AA),0x55}}});
+
+ // Program
+ m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0xA0}}});
+ }
+
+ void Am29f::write(const uint32_t _addr, const uint16_t _data)
+ {
+ const auto reset = [this]()
+ {
+ m_currentBusCycle = 0;
+ m_currentCommand = -1;
+ };
+
+ if(!writeEnabled())
+ {
+ reset();
+ return;
+ }
+
+ bool anyMatch = false;
+
+ const auto d = _data & 0xff;
+
+ for (size_t i=0; i<m_commands.size(); ++i)
+ {
+ auto& cycles = m_commands[i].cycles;
+
+ if(m_currentBusCycle < cycles.size())
+ {
+ const auto& c = cycles[m_currentBusCycle];
+
+ if(c.addr == _addr && c.data == d)
+ {
+ anyMatch = true;
+
+ if(m_currentBusCycle == cycles.size() - 1)
+ m_currentCommand = static_cast<int32_t>(i);
+ }
+ }
+ }
+
+ if(!anyMatch)
+ {
+ if(m_currentCommand >= 0)
+ {
+ const auto c = static_cast<CommandType>(m_currentCommand);
+
+ execCommand(c, _addr, _data);
+ }
+
+ reset();
+ }
+ else
+ {
+ ++m_currentBusCycle;
+ }
+ }
+
+ void Am29f::execCommand(const CommandType _command, uint32_t _addr, const uint16_t _data)
+ {
+ switch (_command)
+ {
+ case CommandType::ChipErase:
+ assert(false);
+ break;
+ case CommandType::SectorErase:
+ {
+ size_t sectorSizekB = 0;
+ switch (_addr)
+ {
+ case 0x00000: sectorSizekB = 16; break;
+ case 0x04000:
+ case 0x06000: sectorSizekB = 8; break;
+ case 0x08000: sectorSizekB = 32; break;
+ case 0x10000:
+ case 0x20000:
+ case 0x30000:
+ case 0x40000:
+ case 0x50000:
+ case 0x60000:
+ case 0x70000: sectorSizekB = 64; break;
+ case 0x78000:
+ case 0x7A000:
+ case 0x7C000:
+ // mq sends erase commands for a flash with top boot block even though a chip with bottom boot block is installed
+ _addr = 0x70000;
+ sectorSizekB = 64;
+ break;
+ default:
+ MCLOG("Unable to erase sector at " << MCHEX(_addr) << ", out of bounds!");
+ return;
+ }
+
+ MCLOG("Erasing Sector at " << MCHEX(_addr) << ", size " << MCHEX(1024 * sectorSizekB));
+ for(size_t i = _addr; i< _addr + sectorSizekB * 1024; ++i)
+ m_buffer[i] = 0xff;
+ }
+ break;
+ case CommandType::Program:
+ {
+ if(_addr >= m_size)
+ return;
+ MCLOG("Programming word at " << MCHEX(_addr) << ", value " << MCHEXN(_data, 4));
+ const auto old = mc68k::Mc68k::readW(m_buffer, _addr);
+ // "A bit cannot be programmed from a 0 back to a 1"
+ const auto v = _data & old;
+ mc68k::Mc68k::writeW(m_buffer, _addr, v);
+ // assert(v == _data);
+ break;
+ }
+ case CommandType::Invalid:
+ default:
+ assert(false);
+ break;
+ }
+ }
+}
+\ No newline at end of file
diff --git a/source/hardwareLib/am29f.h b/source/hardwareLib/am29f.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <cstdint>
+#include <cstddef>
+#include <vector>
+
+namespace hwLib
+{
+ class Am29f
+ {
+ public:
+ struct BusCycle
+ {
+ uint16_t addr;
+ uint8_t data;
+ };
+
+ struct Command
+ {
+ std::vector<BusCycle> cycles;
+ };
+
+ enum class CommandType
+ {
+ Invalid = -1,
+ ChipErase,
+ SectorErase,
+ Program,
+ };
+
+ explicit Am29f(uint8_t* _buffer, size_t _size, bool _useWriteEnable, bool _bitreversedCmdAddr);
+
+ void writeEnable(bool _writeEnable)
+ {
+ m_writeEnable = _writeEnable;
+ }
+
+ void write(uint32_t _addr, uint16_t _data);
+
+ private:
+ bool writeEnabled() const
+ {
+ return !m_useWriteEnable || m_writeEnable;
+ }
+
+ static constexpr uint16_t bitreverse(uint16_t x)
+ {
+ x = ((x & 0xaaaau) >> 1) | static_cast<uint16_t>((x & 0x5555u) << 1);
+ x = ((x & 0xccccu) >> 2) | static_cast<uint16_t>((x & 0x3333u) << 2);
+ x = ((x & 0xf0f0u) >> 4) | static_cast<uint16_t>((x & 0x0f0fu) << 4);
+
+ return ((x & 0xff00) >> 8) | static_cast<uint16_t>((x & 0x00ff) << 8);
+ }
+
+ void execCommand(CommandType _command, uint32_t _addr, uint16_t _data);
+
+ uint8_t* m_buffer;
+ const size_t m_size;
+ const bool m_useWriteEnable;
+ const bool m_bitreverseCmdAddr;
+
+ std::vector<Command> m_commands;
+ bool m_writeEnable = false;
+ uint32_t m_currentBusCycle = 0;
+ int32_t m_currentCommand = -1;
+ };
+}
+\ No newline at end of file
diff --git a/source/hardwareLib/i2c.cpp b/source/hardwareLib/i2c.cpp
@@ -0,0 +1,164 @@
+#include "i2c.h"
+
+#include <cassert>
+
+#include "dsp56kEmu/logging.h"
+
+namespace hwLib
+{
+ void I2c::masterWrite(const bool _sda, const bool _scl)
+ {
+ if(_sda != m_sda && _scl != m_scl)
+ {
+ assert(false && "only one pin should flip");
+ return;
+ }
+
+ if(_sda != m_sda)
+ {
+ m_sda = _sda;
+ sdaFlip(_sda);
+ }
+ else if(_scl != m_scl)
+ {
+ m_scl = _scl;
+ sclFlip(_scl);
+ }
+ }
+
+ std::optional<bool> I2c::masterRead(const bool _scl)
+ {
+ if(_scl == m_scl)
+ return {};
+
+ if(m_state != State::Start)
+ return {};
+
+ m_scl = _scl;
+
+ if(_scl)
+ {
+ if(m_nextBit == BitAck)
+ {
+ m_nextBit = Bit7;
+ return m_ackBit; // this was returned already in onAck()
+ }
+
+ if(m_nextBit >= Bit0 && m_nextBit <= Bit7)
+ {
+ if(m_nextBit == Bit7)
+ m_byte = onReadByte();
+
+ auto res = m_byte & (1<<m_nextBit);
+ --m_nextBit;
+ return res;
+ }
+ }
+
+ return {};
+ }
+
+ std::optional<bool> I2c::setSdaWrite(const bool _write)
+ {
+ if(m_sdaWrite == _write)
+ return {};
+
+ m_sdaWrite = _write;
+
+ if(m_state != State::Start)
+ return {};
+
+ if(!m_sdaWrite)
+ {
+ if(m_nextBit == BitAck)
+ {
+ const auto ackBit = onAck();
+ if(ackBit)
+ {
+ m_ackBit = *ackBit;
+ }
+ return ackBit;
+ }
+ }
+ return {};
+ }
+
+ void I2c::onStateChanged(const State _state)
+ {
+ LOG("state: " << (_state == State::Start ? "start" : "stop"));
+
+ switch (_state)
+ {
+ case State::Stop:
+ m_nextBit = BitInvalid;
+ break;
+ case State::Start:
+ m_nextBit = Bit7;
+ m_byte = 0;
+ break;
+ }
+ }
+
+ void I2c::onStartCondition()
+ {
+ setState(State::Start);
+ }
+
+ void I2c::onStopCondition()
+ {
+ setState(State::Stop);
+ }
+
+ void I2c::onByteWritten()
+ {
+ LOG("Got byte " << HEXN(byte(), 2));
+ }
+
+ void I2c::sdaFlip(const bool _sda)
+ {
+ if(m_scl)
+ {
+ if(!_sda)
+ onStartCondition();
+ else
+ onStopCondition();
+ }
+ }
+
+ void I2c::sclFlip(const bool _scl)
+ {
+ if(_scl && m_state == State::Start)
+ {
+ if(m_nextBit >= Bit0 && m_nextBit <= Bit7)
+ {
+ LOG("next bit " << static_cast<int>(m_nextBit) << " = " << m_sda);
+
+ if(m_nextBit == Bit7)
+ m_byte = 0;
+
+ // data input
+ if(m_sda)
+ m_byte |= (1<<m_nextBit);
+
+ --m_nextBit;
+
+ if(m_nextBit < 0)
+ {
+ onByteWritten();
+ }
+ }
+ else if(m_nextBit == BitAck)
+ {
+ m_nextBit = 7;
+ }
+ }
+ }
+
+ void I2c::setState(const State _state)
+ {
+/* if(m_state == _state)
+ return;
+*/ m_state = _state;
+ onStateChanged(_state);
+ }
+}
diff --git a/source/hardwareLib/i2c.h b/source/hardwareLib/i2c.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <cstdint>
+#include <optional>
+
+namespace hwLib
+{
+ class I2c
+ {
+ public:
+ enum class State
+ {
+ Stop,
+ Start,
+ };
+ enum BitPos : int8_t
+ {
+ Bit7 = 7,
+ Bit6 = 6,
+ Bit5 = 5,
+ Bit4 = 4,
+ Bit3 = 3,
+ Bit2 = 2,
+ Bit1 = 1,
+ Bit0 = 0,
+ BitAck = -1,
+ BitInvalid = -2,
+ };
+
+ I2c() = default;
+
+ virtual ~I2c() = default;
+
+ void masterWrite(bool _sda, bool _scl);
+ virtual std::optional<bool> masterRead(bool _scl);
+ std::optional<bool> setSdaWrite(bool _write);
+
+ bool sda() const { return m_sda; }
+ bool scl() const { return m_scl; }
+ uint8_t byte() const { return m_byte; }
+
+ protected:
+ virtual void onStateChanged(State _state);
+ virtual void onStartCondition();
+ virtual void onStopCondition();
+ virtual void onByteWritten();
+ virtual std::optional<bool> onAck() { return {}; }
+ virtual uint8_t onReadByte() { return 0; }
+
+ private:
+ void sdaFlip(bool _sda);
+ void sclFlip(bool _scl);
+ void setState(State _state);
+
+ bool m_sdaWrite = true; // true = write
+ bool m_sda = false;
+ bool m_scl = false;
+ State m_state = State::Stop;
+ int8_t m_nextBit = BitInvalid;
+ uint8_t m_byte;
+ bool m_ackBit = true;
+ };
+}
diff --git a/source/hardwareLib/i2cFlash.cpp b/source/hardwareLib/i2cFlash.cpp
@@ -0,0 +1,101 @@
+#include "i2cFlash.h"
+
+#include <cassert>
+
+#include "dsp56kEmu/logging.h"
+
+#include "synthLib/os.h"
+
+namespace hwLib
+{
+ void I2cFlash::saveAs(const std::string& _filename) const
+ {
+ synthLib::writeFile(_filename, m_data);
+ }
+
+ void I2cFlash::onStartCondition()
+ {
+ m_state = State::ReadDeviceSelect;
+ I2c::onStartCondition();
+ }
+
+ void I2cFlash::onStopCondition()
+ {
+ I2c::onStopCondition();
+ }
+
+ void I2cFlash::onByteWritten()
+ {
+ I2c::onByteWritten();
+
+ switch (m_state)
+ {
+ case State::ReadDeviceSelect:
+ m_deviceSelect = byte();
+ m_state = State::AckDeviceSelect;
+ break;
+ case State::ReadAddressMSB:
+ m_address = byte() << 8;
+ m_state = State::AckAddressMSB;
+ break;
+ case State::ReadAddressLSB:
+ m_address |= byte();
+ m_state = State::AckAddressLSB;
+ break;
+ case State::ReadWriteData:
+ writeByte(byte());
+ break;
+ default:
+ assert(false && "invalid state");
+ break;
+ }
+ }
+
+ std::optional<bool> I2cFlash::onAck()
+ {
+ switch (m_state)
+ {
+ case State::AckDeviceSelect:
+ m_state = State::ReadAddressMSB;
+ return false;
+ case State::AckAddressMSB:
+ m_state = State::ReadAddressLSB;
+ return false;
+ case State::AckAddressLSB:
+ m_state = State::ReadWriteData;
+ return false;
+ case State::ReadWriteData:
+ return false;
+ default:
+ assert(false && "invalid state");
+ return true;
+ }
+ }
+
+ uint8_t I2cFlash::onReadByte()
+ {
+ assert((m_deviceSelect & DeviceSelectMask::Area) == DeviceSelectValues::AreaMemory);
+ assert((m_deviceSelect & DeviceSelectMask::Rw) == DeviceSelectValues::Read);
+ const auto res = m_data[m_address];
+
+ LOG("I2C op read from " << HEXN(m_address,4) << ", res " << HEXN(res,2));
+ advanceAddress();
+ return res;
+ }
+
+ void I2cFlash::writeByte(uint8_t _byte)
+ {
+ assert((m_deviceSelect & DeviceSelectMask::Area) == DeviceSelectValues::AreaMemory);
+ assert((m_deviceSelect & DeviceSelectMask::Rw) == DeviceSelectValues::Write);
+
+ m_data[m_address] = _byte;
+
+ LOG("I2C op write to " << HEXN(m_address,4) << ", val " << HEXN(_byte,2));
+ advanceAddress();
+ }
+
+ void I2cFlash::advanceAddress()
+ {
+ m_address = (m_address & 0xFF80) | ((m_address + 1) & 0x7F);
+ }
+}
diff --git a/source/hardwareLib/i2cFlash.h b/source/hardwareLib/i2cFlash.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include <array>
+#include <optional>
+#include <string>
+
+#include "i2c.h"
+
+namespace hwLib
+{
+ // M24512 64kx 8 i2c flash chip emulation
+ class I2cFlash : public I2c
+ {
+ public:
+ using Data = std::array<uint8_t, 0x10000>;
+
+ I2cFlash()
+ {
+ m_data.fill(0xff);
+ }
+
+ explicit I2cFlash(const Data& _data) : m_data(_data)
+ {
+ }
+
+ void saveAs(const std::string& _filename) const;
+
+ private:
+ enum class State
+ {
+ ReadDeviceSelect, AckDeviceSelect,
+ ReadAddressMSB, AckAddressMSB,
+ ReadAddressLSB, AckAddressLSB,
+ ReadWriteData,
+ };
+
+ enum DeviceSelectMask
+ {
+ Area = 0b1111'000'0,
+ ChipEnable = 0b0000'111'0,
+ Rw = 0b0000'000'1,
+ };
+
+ enum DeviceSelectValues
+ {
+ AreaMemory = 0b1010'000'0,
+ AreaId = 0b1011'000'0,
+ Read = 0b0000'000'1,
+ Write = 0b0000'000'0,
+ };
+
+ void onStartCondition() override;
+ void onStopCondition() override;
+ void onByteWritten() override;
+ std::optional<bool> onAck() override;
+ uint8_t onReadByte() override;
+ void writeByte(uint8_t _byte);
+ void advanceAddress();
+
+ State m_state = State::ReadDeviceSelect;
+ uint8_t m_deviceSelect = 0;
+ uint64_t m_address = 0;
+
+ Data m_data;
+ };
+}
diff --git a/source/hardwareLib/sciMidi.cpp b/source/hardwareLib/sciMidi.cpp
@@ -0,0 +1,101 @@
+#include "sciMidi.h"
+
+#include <deque>
+
+#include "mc68k/qsm.h"
+
+namespace hwLib
+{
+ // pause 0.1 seconds for a sysex size of 500, delay is calculated for other sysex sizes accordingly
+ static constexpr float g_sysexSendDelaySeconds = 0.1f;
+ static constexpr uint32_t g_sysexSendDelaySize = 500;
+
+ SciMidi::SciMidi(mc68k::Qsm& _qsm) : m_qsm(_qsm)
+ {
+ }
+
+ void SciMidi::process(const uint32_t _numSamples)
+ {
+ std::unique_lock lock(m_mutex);
+
+ if(m_readingSysex)
+ return;
+
+ auto remainingSamples = _numSamples;
+
+ while(!m_pendingSysexBuffers.empty())
+ {
+ if(m_remainingSysexDelay > 0)
+ {
+ const auto sub = std::min(m_remainingSysexDelay, remainingSamples);
+ remainingSamples -= sub;
+
+ m_remainingSysexDelay -= sub;
+ }
+
+ if(m_remainingSysexDelay)
+ break;
+
+ const auto& msg = m_pendingSysexBuffers.front();
+
+ for (const auto b : msg)
+ m_qsm.writeSciRX(b);
+
+ m_remainingSysexDelay = static_cast<uint32_t>(static_cast<float>(msg.size()) * 44100.0f * g_sysexSendDelaySeconds / static_cast<float>(g_sysexSendDelaySize));
+
+ m_pendingSysexBuffers.pop_front();
+ }
+ }
+
+ void SciMidi::writeMidi(const uint8_t _byte)
+ {
+ std::unique_lock lock(m_mutex);
+
+ if(_byte == 0xf0)
+ {
+ m_writingSysex = true;
+ }
+
+ if(m_writingSysex)
+ {
+ m_pendingSysexMessage.push_back(_byte);
+ }
+ else
+ {
+ m_qsm.writeSciRX(_byte);
+ }
+
+ if (_byte == 0xf7)
+ {
+ m_writingSysex = false;
+
+ if (!m_pendingSysexMessage.empty())
+ m_pendingSysexBuffers.push_back(std::move(m_pendingSysexMessage));
+
+ m_pendingSysexMessage.clear();
+ }
+ }
+
+ void SciMidi::readTransmitBuffer(std::vector<uint8_t>& _result)
+ {
+ std::deque<uint16_t> midiData;
+ m_qsm.readSciTX(midiData);
+ if (midiData.empty())
+ return;
+
+ _result.clear();
+ _result.reserve(midiData.size());
+
+ for (const auto data : midiData)
+ {
+ const uint8_t d = data & 0xff;
+
+ if(d == 0xf0)
+ m_readingSysex = true;
+ else if(d == 0xf7)
+ m_readingSysex = false;
+
+ _result.push_back(d);
+ }
+ }
+}
diff --git a/source/hardwareLib/sciMidi.h b/source/hardwareLib/sciMidi.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <deque>
+#include <vector>
+#include <cstdint>
+#include <mutex>
+
+namespace mc68k
+{
+ class Qsm;
+}
+
+namespace hwLib
+{
+ class SciMidi
+ {
+ public:
+ explicit SciMidi(mc68k::Qsm& _qsm);
+
+ void process(uint32_t _numSamples);
+
+ void writeMidi(uint8_t _byte);
+ void writeMidi(const std::initializer_list<uint8_t>& _bytes)
+ {
+ for (const uint8_t byte : _bytes)
+ writeMidi(byte);
+ }
+ void writeMidi(const std::vector<uint8_t>& _bytes)
+ {
+ for (const uint8_t byte : _bytes)
+ writeMidi(byte);
+ }
+ void readTransmitBuffer(std::vector<uint8_t>& _result);
+
+ private:
+ mc68k::Qsm& m_qsm;
+
+ bool m_readingSysex = false;
+ bool m_writingSysex = false;
+ uint32_t m_remainingSysexDelay = 0;
+
+ std::deque< std::vector<uint8_t> > m_pendingSysexBuffers;
+ std::vector<uint8_t> m_pendingSysexMessage;
+ std::mutex m_mutex;
+ };
+}
diff --git a/source/mqLib/mqhardware.h b/source/mqLib/mqhardware.h
@@ -10,9 +10,8 @@
#include "dsp56kEmu/dspthread.h"
-#include "synthLib/midiTypes.h"
+#include "hardwareLib/sciMidi.h"
-#include "wLib/wMidi.h"
#include "wLib/wHardware.h"
namespace mqLib
@@ -54,7 +53,7 @@ namespace mqLib
void initVoiceExpansion();
- wLib::Midi& getMidi() override
+ hwLib::SciMidi& getMidi() override
{
return m_midi;
}
@@ -79,6 +78,6 @@ namespace mqLib
TAudioOutputs m_audioOutputs;
std::array<MqDsp,g_dspCount> m_dsps;
- wLib::Midi m_midi;
+ hwLib::SciMidi m_midi;
};
}
diff --git a/source/mqLib/mqmc.cpp b/source/mqLib/mqmc.cpp
@@ -33,7 +33,7 @@ namespace mqLib
m_romRuntimeData.resize(ROM::size());
memcpy(m_romRuntimeData.data(), m_rom.getData(), ROM::size());
- m_flash.reset(new wLib::Am29f(m_romRuntimeData.data(), m_romRuntimeData.size(), false, true));
+ m_flash.reset(new hwLib::Am29f(m_romRuntimeData.data(), m_romRuntimeData.size(), false, true));
m_memory.resize(g_memorySize, 0);
diff --git a/source/mqLib/mqmc.h b/source/mqLib/mqmc.h
@@ -6,7 +6,8 @@
#include "buttons.h"
#include "lcd.h"
#include "leds.h"
-#include "wLib/am29f.h"
+
+#include "hardwareLib/am29f.h"
#include "mc68k/mc68k.h"
#include "mc68k/hdi08periph.h"
@@ -66,7 +67,7 @@ namespace mqLib
const ROM& m_rom;
std::vector<uint8_t> m_romRuntimeData;
- std::unique_ptr<wLib::Am29f> m_flash;
+ std::unique_ptr<hwLib::Am29f> m_flash;
LCD m_lcd;
Buttons m_buttons;
Leds m_leds;
diff --git a/source/nord/n2x/n2xLib/CMakeLists.txt b/source/nord/n2x/n2xLib/CMakeLists.txt
@@ -5,13 +5,12 @@ project(n2xLib)
add_library(n2xLib STATIC)
set(SOURCES
- i2c.cpp i2c.h
n2xdevice.cpp n2xdevice.h
n2xdsp.cpp n2xdsp.h
+ n2xflash.cpp n2xflash.h
n2xfrontpanel.cpp n2xfrontpanel.h
n2xhardware.cpp n2xhardware.h
n2xhdi08.cpp n2xhdi08.h
- n2xi2cflash.cpp n2xi2cflash.h
n2xkeyboard.cpp n2xkeyboard.h
n2xmc.cpp n2xmc.h
n2xmiditypes.h
@@ -23,7 +22,7 @@ set(SOURCES
target_sources(n2xLib PRIVATE ${SOURCES})
source_group("source" FILES ${SOURCES})
-target_link_libraries(n2xLib PUBLIC synthLib 68kEmu wLib)
+target_link_libraries(n2xLib PUBLIC synthLib 68kEmu hardwareLib)
if(DSP56300_DEBUGGER)
target_link_libraries(n2xLib PUBLIC dsp56kDebugger)
diff --git a/source/nord/n2x/n2xLib/i2c.cpp b/source/nord/n2x/n2xLib/i2c.cpp
@@ -1,164 +0,0 @@
-#include "i2c.h"
-
-#include <cassert>
-
-#include "dsp56kEmu/logging.h"
-
-namespace n2x
-{
- void I2c::masterWrite(const bool _sda, const bool _scl)
- {
- if(_sda != m_sda && _scl != m_scl)
- {
- assert(false && "only one pin should flip");
- return;
- }
-
- if(_sda != m_sda)
- {
- m_sda = _sda;
- sdaFlip(_sda);
- }
- else if(_scl != m_scl)
- {
- m_scl = _scl;
- sclFlip(_scl);
- }
- }
-
- std::optional<bool> I2c::masterRead(const bool _scl)
- {
- if(_scl == m_scl)
- return {};
-
- if(m_state != State::Start)
- return {};
-
- m_scl = _scl;
-
- if(_scl)
- {
- if(m_nextBit == BitAck)
- {
- m_nextBit = Bit7;
- return m_ackBit; // this was returned already in onAck()
- }
-
- if(m_nextBit >= Bit0 && m_nextBit <= Bit7)
- {
- if(m_nextBit == Bit7)
- m_byte = onReadByte();
-
- auto res = m_byte & (1<<m_nextBit);
- --m_nextBit;
- return res;
- }
- }
-
- return {};
- }
-
- std::optional<bool> I2c::setSdaWrite(const bool _write)
- {
- if(m_sdaWrite == _write)
- return {};
-
- m_sdaWrite = _write;
-
- if(m_state != State::Start)
- return {};
-
- if(!m_sdaWrite)
- {
- if(m_nextBit == BitAck)
- {
- const auto ackBit = onAck();
- if(ackBit)
- {
- m_ackBit = *ackBit;
- }
- return ackBit;
- }
- }
- return {};
- }
-
- void I2c::onStateChanged(const State _state)
- {
- LOG("state: " << (_state == State::Start ? "start" : "stop"));
-
- switch (_state)
- {
- case State::Stop:
- m_nextBit = BitInvalid;
- break;
- case State::Start:
- m_nextBit = Bit7;
- m_byte = 0;
- break;
- }
- }
-
- void I2c::onStartCondition()
- {
- setState(State::Start);
- }
-
- void I2c::onStopCondition()
- {
- setState(State::Stop);
- }
-
- void I2c::onByteWritten()
- {
- LOG("Got byte " << HEXN(byte(), 2));
- }
-
- void I2c::sdaFlip(const bool _sda)
- {
- if(m_scl)
- {
- if(!_sda)
- onStartCondition();
- else
- onStopCondition();
- }
- }
-
- void I2c::sclFlip(const bool _scl)
- {
- if(_scl && m_state == State::Start)
- {
- if(m_nextBit >= Bit0 && m_nextBit <= Bit7)
- {
- LOG("next bit " << static_cast<int>(m_nextBit) << " = " << m_sda);
-
- if(m_nextBit == Bit7)
- m_byte = 0;
-
- // data input
- if(m_sda)
- m_byte |= (1<<m_nextBit);
-
- --m_nextBit;
-
- if(m_nextBit < 0)
- {
- onByteWritten();
- }
- }
- else if(m_nextBit == BitAck)
- {
- m_nextBit = 7;
- }
- }
- }
-
- void I2c::setState(const State _state)
- {
-/* if(m_state == _state)
- return;
-*/ m_state = _state;
- onStateChanged(_state);
- }
-}
diff --git a/source/nord/n2x/n2xLib/i2c.h b/source/nord/n2x/n2xLib/i2c.h
@@ -1,63 +0,0 @@
-#pragma once
-
-#include <cstdint>
-#include <optional>
-
-namespace n2x
-{
- class I2c
- {
- public:
- enum class State
- {
- Stop,
- Start,
- };
- enum BitPos : int8_t
- {
- Bit7 = 7,
- Bit6 = 6,
- Bit5 = 5,
- Bit4 = 4,
- Bit3 = 3,
- Bit2 = 2,
- Bit1 = 1,
- Bit0 = 0,
- BitAck = -1,
- BitInvalid = -2,
- };
-
- I2c() = default;
-
- virtual ~I2c() = default;
-
- void masterWrite(bool _sda, bool _scl);
- virtual std::optional<bool> masterRead(bool _scl);
- std::optional<bool> setSdaWrite(bool _write);
-
- bool sda() const { return m_sda; }
- bool scl() const { return m_scl; }
- uint8_t byte() const { return m_byte; }
-
- protected:
- virtual void onStateChanged(State _state);
- virtual void onStartCondition();
- virtual void onStopCondition();
- virtual void onByteWritten();
- virtual std::optional<bool> onAck() { return {}; }
- virtual uint8_t onReadByte() { return 0; }
-
- private:
- void sdaFlip(bool _sda);
- void sclFlip(bool _scl);
- void setState(State _state);
-
- bool m_sdaWrite = true; // true = write
- bool m_sda = false;
- bool m_scl = false;
- State m_state = State::Stop;
- int8_t m_nextBit = BitInvalid;
- uint8_t m_byte;
- bool m_ackBit = true;
- };
-}
diff --git a/source/nord/n2x/n2xLib/n2xflash.cpp b/source/nord/n2x/n2xLib/n2xflash.cpp
diff --git a/source/nord/n2x/n2xLib/n2xflash.h b/source/nord/n2x/n2xLib/n2xflash.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "hardwareLib/i2cFlash.h"
+
+namespace n2x
+{
+ class Flash : public hwLib::I2cFlash
+ {
+ };
+}
diff --git a/source/nord/n2x/n2xLib/n2xi2cflash.cpp b/source/nord/n2x/n2xLib/n2xi2cflash.cpp
@@ -1,102 +0,0 @@
-#include "n2xi2cflash.h"
-
-#include <cassert>
-
-#include "dsp56kEmu/logging.h"
-
-namespace n2x
-{
- template<> RomData<g_flashSize>::RomData();
-
- I2cFlash::I2cFlash()
- {
- if(!isValid())
- data().fill(0xff);
- }
-
- void I2cFlash::onStartCondition()
- {
- m_state = State::ReadDeviceSelect;
- I2c::onStartCondition();
- }
-
- void I2cFlash::onStopCondition()
- {
- I2c::onStopCondition();
- }
-
- void I2cFlash::onByteWritten()
- {
- I2c::onByteWritten();
-
- switch (m_state)
- {
- case State::ReadDeviceSelect:
- m_deviceSelect = byte();
- m_state = State::AckDeviceSelect;
- break;
- case State::ReadAddressMSB:
- m_address = byte() << 8;
- m_state = State::AckAddressMSB;
- break;
- case State::ReadAddressLSB:
- m_address |= byte();
- m_state = State::AckAddressLSB;
- break;
- case State::ReadWriteData:
- writeByte(byte());
- break;
- default:
- assert(false && "invalid state");
- break;
- }
- }
-
- std::optional<bool> I2cFlash::onAck()
- {
- switch (m_state)
- {
- case State::AckDeviceSelect:
- m_state = State::ReadAddressMSB;
- return false;
- case State::AckAddressMSB:
- m_state = State::ReadAddressLSB;
- return false;
- case State::AckAddressLSB:
- m_state = State::ReadWriteData;
- return false;
- case State::ReadWriteData:
- return false;
- default:
- assert(false && "invalid state");
- return true;
- }
- }
-
- uint8_t I2cFlash::onReadByte()
- {
- assert((m_deviceSelect & DeviceSelectMask::Area) == DeviceSelectValues::AreaMemory);
- assert((m_deviceSelect & DeviceSelectMask::Rw) == DeviceSelectValues::Read);
- const auto res = data()[m_address];
-
- LOG("I2C op read from " << HEXN(m_address,4) << ", res " << HEXN(res,2));
- advanceAddress();
- return res;
- }
-
- void I2cFlash::writeByte(uint8_t _byte)
- {
- assert((m_deviceSelect & DeviceSelectMask::Area) == DeviceSelectValues::AreaMemory);
- assert((m_deviceSelect & DeviceSelectMask::Rw) == DeviceSelectValues::Write);
-
- data()[m_address] = _byte;
-
- LOG("I2C op write to " << HEXN(m_address,4) << ", val " << HEXN(_byte,2));
- advanceAddress();
- }
-
- void I2cFlash::advanceAddress()
- {
- m_address = (m_address & 0xFF80) | ((m_address + 1) & 0x7F);
- }
-}
diff --git a/source/nord/n2x/n2xLib/n2xi2cflash.h b/source/nord/n2x/n2xLib/n2xi2cflash.h
@@ -1,52 +0,0 @@
-#pragma once
-
-#include <optional>
-
-#include "i2c.h"
-#include "n2xromdata.h"
-#include "n2xtypes.h"
-
-namespace n2x
-{
- class I2cFlash : public I2c, public RomData<g_flashSize>
- {
- public:
- I2cFlash();
-
- private:
- enum class State
- {
- ReadDeviceSelect, AckDeviceSelect,
- ReadAddressMSB, AckAddressMSB,
- ReadAddressLSB, AckAddressLSB,
- ReadWriteData,
- };
-
- enum DeviceSelectMask
- {
- Area = 0b1111'000'0,
- ChipEnable = 0b0000'111'0,
- Rw = 0b0000'000'1,
- };
-
- enum DeviceSelectValues
- {
- AreaMemory = 0b1010'000'0,
- AreaId = 0b1011'000'0,
- Read = 0b0000'000'1,
- Write = 0b0000'000'0,
- };
-
- void onStartCondition() override;
- void onStopCondition() override;
- void onByteWritten() override;
- std::optional<bool> onAck() override;
- uint8_t onReadByte() override;
- void writeByte(uint8_t _byte);
- void advanceAddress();
-
- State m_state = State::ReadDeviceSelect;
- uint8_t m_deviceSelect = 0;
- uint64_t m_address = 0;
- };
-}
diff --git a/source/nord/n2x/n2xLib/n2xmc.cpp b/source/nord/n2x/n2xLib/n2xmc.cpp
@@ -4,7 +4,7 @@
#include "n2xdsp.h"
#include "n2xrom.h"
-#include "synthLib/midiTypes.h"
+
#include "synthLib/os.h"
namespace n2x
diff --git a/source/nord/n2x/n2xLib/n2xmc.h b/source/nord/n2x/n2xLib/n2xmc.h
@@ -2,11 +2,12 @@
#include "n2xfrontpanel.h"
#include "n2xhdi08.h"
-#include "n2xi2cflash.h"
+#include "n2xflash.h"
#include "n2xtypes.h"
-#include "mc68k/hdi08.h"
+
#include "mc68k/mc68k.h"
-#include "wLib/wMidi.h"
+
+#include "hardwareLib/sciMidi.h"
namespace n2x
{
@@ -36,7 +37,7 @@ namespace n2x
std::array<uint8_t, g_romSize> m_rom;
std::array<uint8_t, g_ramSize> m_ram;
- I2cFlash m_flash;
+ Flash m_flash;
Hdi08DspA m_hdi08A;
Hdi08DspB m_hdi08B;
@@ -45,7 +46,7 @@ namespace n2x
FrontPanel m_panel;
uint32_t m_prevPC;
- wLib::Midi m_midi;
+ hwLib::SciMidi m_midi;
uint64_t m_totalCycles = 0;
bool m_hasSentMidi = false;
};
diff --git a/source/wLib/CMakeLists.txt b/source/wLib/CMakeLists.txt
@@ -5,14 +5,12 @@ project(wLib)
add_library(wLib STATIC)
set(SOURCES
- am29f.cpp am29f.h
dspBootCode.h
lcd.cpp lcd.h
lcdfonts.cpp lcdfonts.h
wDevice.cpp wDevice.h
wDsp.cpp wDsp.h
wHardware.cpp wHardware.h
- wMidi.cpp wMidi.h
wMidiTypes.h
wPlugin.cpp wPlugin.h
wRom.cpp wRom.h
@@ -22,6 +20,6 @@ set(SOURCES
target_sources(wLib PRIVATE ${SOURCES})
source_group("source" FILES ${SOURCES})
-target_link_libraries(wLib PUBLIC synthLib 68kEmu)
+target_link_libraries(wLib PUBLIC synthLib 68kEmu hardwareLib)
target_include_directories(wLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
diff --git a/source/wLib/am29f.cpp b/source/wLib/am29f.cpp
@@ -1,139 +0,0 @@
-#include "am29f.h"
-
-#include <cassert>
-
-#include "mc68k/logging.h"
-#include "mc68k/mc68k.h"
-
-namespace wLib
-{
- Am29f::Am29f(uint8_t* _buffer, const size_t _size, bool _useWriteEnable, bool _bitreversedCmdAddr): m_buffer(_buffer), m_size(_size), m_useWriteEnable(_useWriteEnable), m_bitreverseCmdAddr(_bitreversedCmdAddr)
- {
- auto br = [&](uint16_t x)
- {
- return m_bitreverseCmdAddr ? static_cast<uint16_t>(bitreverse(x) >> 4) : x;
- };
-
- // Chip Erase
- m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x80}, {br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x10}}});
-
- // Sector Erase
- m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x80}, {br(0x555),0xAA}, {br(0x2AA),0x55}}});
-
- // Program
- m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0xA0}}});
- }
-
- void Am29f::write(const uint32_t _addr, const uint16_t _data)
- {
- const auto reset = [this]()
- {
- m_currentBusCycle = 0;
- m_currentCommand = -1;
- };
-
- if(!writeEnabled())
- {
- reset();
- return;
- }
-
- bool anyMatch = false;
-
- const auto d = _data & 0xff;
-
- for (size_t i=0; i<m_commands.size(); ++i)
- {
- auto& cycles = m_commands[i].cycles;
-
- if(m_currentBusCycle < cycles.size())
- {
- const auto& c = cycles[m_currentBusCycle];
-
- if(c.addr == _addr && c.data == d)
- {
- anyMatch = true;
-
- if(m_currentBusCycle == cycles.size() - 1)
- m_currentCommand = static_cast<int32_t>(i);
- }
- }
- }
-
- if(!anyMatch)
- {
- if(m_currentCommand >= 0)
- {
- const auto c = static_cast<CommandType>(m_currentCommand);
-
- execCommand(c, _addr, _data);
- }
-
- reset();
- }
- else
- {
- ++m_currentBusCycle;
- }
- }
-
- void Am29f::execCommand(const CommandType _command, uint32_t _addr, const uint16_t _data)
- {
- switch (_command)
- {
- case CommandType::ChipErase:
- assert(false);
- break;
- case CommandType::SectorErase:
- {
- size_t sectorSizekB = 0;
- switch (_addr)
- {
- case 0x00000: sectorSizekB = 16; break;
- case 0x04000:
- case 0x06000: sectorSizekB = 8; break;
- case 0x08000: sectorSizekB = 32; break;
- case 0x10000:
- case 0x20000:
- case 0x30000:
- case 0x40000:
- case 0x50000:
- case 0x60000:
- case 0x70000: sectorSizekB = 64; break;
- case 0x78000:
- case 0x7A000:
- case 0x7C000:
- // mq sends erase commands for a flash with top boot block even though a chip with bottom boot block is installed
- _addr = 0x70000;
- sectorSizekB = 64;
- break;
- default:
- MCLOG("Unable to erase sector at " << MCHEX(_addr) << ", out of bounds!");
- return;
- }
-
- MCLOG("Erasing Sector at " << MCHEX(_addr) << ", size " << MCHEX(1024 * sectorSizekB));
- for(size_t i = _addr; i< _addr + sectorSizekB * 1024; ++i)
- m_buffer[i] = 0xff;
- }
- break;
- case CommandType::Program:
- {
- if(_addr >= m_size)
- return;
- MCLOG("Programming word at " << MCHEX(_addr) << ", value " << MCHEXN(_data, 4));
- const auto old = mc68k::Mc68k::readW(m_buffer, _addr);
- // "A bit cannot be programmed from a 0 back to a 1"
- const auto v = _data & old;
- mc68k::Mc68k::writeW(m_buffer, _addr, v);
- // assert(v == _data);
- break;
- }
- case CommandType::Invalid:
- default:
- assert(false);
- break;
- }
- }
-
-}
-\ No newline at end of file
diff --git a/source/wLib/am29f.h b/source/wLib/am29f.h
@@ -1,67 +0,0 @@
-#pragma once
-
-#include <cstdint>
-#include <cstddef>
-#include <vector>
-
-namespace wLib
-{
- class Am29f
- {
- public:
- struct BusCycle
- {
- uint16_t addr;
- uint8_t data;
- };
-
- struct Command
- {
- std::vector<BusCycle> cycles;
- };
-
- enum class CommandType
- {
- Invalid = -1,
- ChipErase,
- SectorErase,
- Program,
- };
-
- explicit Am29f(uint8_t* _buffer, size_t _size, bool _useWriteEnable, bool _bitreversedCmdAddr);
-
- void writeEnable(bool _writeEnable)
- {
- m_writeEnable = _writeEnable;
- }
-
- void write(uint32_t _addr, uint16_t _data);
-
- private:
- bool writeEnabled() const
- {
- return !m_useWriteEnable || m_writeEnable;
- }
-
- static constexpr uint16_t bitreverse(uint16_t x)
- {
- x = ((x & 0xaaaau) >> 1) | static_cast<uint16_t>((x & 0x5555u) << 1);
- x = ((x & 0xccccu) >> 2) | static_cast<uint16_t>((x & 0x3333u) << 2);
- x = ((x & 0xf0f0u) >> 4) | static_cast<uint16_t>((x & 0x0f0fu) << 4);
-
- return ((x & 0xff00) >> 8) | static_cast<uint16_t>((x & 0x00ff) << 8);
- }
-
- void execCommand(CommandType _command, uint32_t _addr, uint16_t _data);
-
- uint8_t* m_buffer;
- const size_t m_size;
- const bool m_useWriteEnable;
- const bool m_bitreverseCmdAddr;
-
- std::vector<Command> m_commands;
- bool m_writeEnable = false;
- uint32_t m_currentBusCycle = 0;
- int32_t m_currentCommand = -1;
- };
-}
-\ No newline at end of file
diff --git a/source/wLib/wHardware.cpp b/source/wLib/wHardware.cpp
@@ -1,10 +1,11 @@
#include "wHardware.h"
-#include "wMidi.h"
#include "dsp56kEmu/audio.h"
#include "synthLib/midiBufferParser.h"
+#include "hardwareLib/sciMidi.h"
+
#include "mc68k/mc68k.h"
namespace wLib
diff --git a/source/wLib/wHardware.h b/source/wLib/wHardware.h
@@ -8,6 +8,11 @@
#include "synthLib/midiTypes.h"
+namespace hwLib
+{
+ class SciMidi;
+}
+
namespace mc68k
{
class Mc68k;
@@ -20,15 +25,13 @@ namespace dsp56k
namespace wLib
{
- class Midi;
-
class Hardware
{
public:
Hardware(const double& _samplerate);
virtual ~Hardware() = default;
- virtual Midi& getMidi() = 0;
+ virtual hwLib::SciMidi& getMidi() = 0;
virtual mc68k::Mc68k& getUc() = 0;
void haltDSP();
diff --git a/source/wLib/wMidi.cpp b/source/wLib/wMidi.cpp
@@ -1,101 +0,0 @@
-#include "wMidi.h"
-
-#include <deque>
-
-#include "mc68k/qsm.h"
-
-namespace wLib
-{
- // pause 0.1 seconds for a sysex size of 500, delay is calculated for other sysex sizes accordingly
- static constexpr float g_sysexSendDelaySeconds = 0.1f;
- static constexpr uint32_t g_sysexSendDelaySize = 500;
-
- Midi::Midi(mc68k::Qsm& _qsm) : m_qsm(_qsm)
- {
- }
-
- void Midi::process(const uint32_t _numSamples)
- {
- std::unique_lock lock(m_mutex);
-
- if(m_readingSysex)
- return;
-
- auto remainingSamples = _numSamples;
-
- while(!m_pendingSysexBuffers.empty())
- {
- if(m_remainingSysexDelay > 0)
- {
- const auto sub = std::min(m_remainingSysexDelay, remainingSamples);
- remainingSamples -= sub;
-
- m_remainingSysexDelay -= sub;
- }
-
- if(m_remainingSysexDelay)
- break;
-
- const auto& msg = m_pendingSysexBuffers.front();
-
- for (const auto b : msg)
- m_qsm.writeSciRX(b);
-
- m_remainingSysexDelay = static_cast<uint32_t>(static_cast<float>(msg.size()) * 44100.0f * g_sysexSendDelaySeconds / static_cast<float>(g_sysexSendDelaySize));
-
- m_pendingSysexBuffers.pop_front();
- }
- }
-
- void Midi::writeMidi(const uint8_t _byte)
- {
- std::unique_lock lock(m_mutex);
-
- if(_byte == 0xf0)
- {
- m_writingSysex = true;
- }
-
- if(m_writingSysex)
- {
- m_pendingSysexMessage.push_back(_byte);
- }
- else
- {
- m_qsm.writeSciRX(_byte);
- }
-
- if (_byte == 0xf7)
- {
- m_writingSysex = false;
-
- if (!m_pendingSysexMessage.empty())
- m_pendingSysexBuffers.push_back(std::move(m_pendingSysexMessage));
-
- m_pendingSysexMessage.clear();
- }
- }
-
- void Midi::readTransmitBuffer(std::vector<uint8_t>& _result)
- {
- std::deque<uint16_t> midiData;
- m_qsm.readSciTX(midiData);
- if (midiData.empty())
- return;
-
- _result.clear();
- _result.reserve(midiData.size());
-
- for (const auto data : midiData)
- {
- const uint8_t d = data & 0xff;
-
- if(d == 0xf0)
- m_readingSysex = true;
- else if(d == 0xf7)
- m_readingSysex = false;
-
- _result.push_back(d);
- }
- }
-}
diff --git a/source/wLib/wMidi.h b/source/wLib/wMidi.h
@@ -1,46 +0,0 @@
-#pragma once
-
-#include <deque>
-#include <vector>
-#include <cstdint>
-#include <mutex>
-
-namespace mc68k
-{
- class Qsm;
-}
-
-namespace wLib
-{
- class Midi
- {
- public:
- explicit Midi(mc68k::Qsm& _qsm);
-
- void process(uint32_t _numSamples);
-
- void writeMidi(uint8_t _byte);
- void writeMidi(const std::initializer_list<uint8_t>& _bytes)
- {
- for (const uint8_t byte : _bytes)
- writeMidi(byte);
- }
- void writeMidi(const std::vector<uint8_t>& _bytes)
- {
- for (const uint8_t byte : _bytes)
- writeMidi(byte);
- }
- void readTransmitBuffer(std::vector<uint8_t>& _result);
-
- private:
- mc68k::Qsm& m_qsm;
-
- bool m_readingSysex = false;
- bool m_writingSysex = false;
- uint32_t m_remainingSysexDelay = 0;
-
- std::deque< std::vector<uint8_t> > m_pendingSysexBuffers;
- std::vector<uint8_t> m_pendingSysexMessage;
- std::mutex m_mutex;
- };
-}
diff --git a/source/xtLib/xtHardware.h b/source/xtLib/xtHardware.h
@@ -1,14 +1,13 @@
#pragma once
-#include <string>
-
#include "xtDSP.h"
#include "xtRom.h"
#include "xtUc.h"
#include "dsp56kEmu/dspthread.h"
-#include "wLib/wMidi.h"
+#include "hardwareLib/sciMidi.h"
+
#include "wLib/wHardware.h"
namespace xt
@@ -50,7 +49,7 @@ namespace xt
void initVoiceExpansion();
- wLib::Midi& getMidi() override
+ hwLib::SciMidi& getMidi() override
{
return m_midi;
}
@@ -70,6 +69,6 @@ namespace xt
TAudioInputs m_audioInputs;
TAudioOutputs m_audioOutputs;
std::array<DSP,g_dspCount> m_dsps;
- wLib::Midi m_midi;
+ hwLib::SciMidi m_midi;
};
}
diff --git a/source/xtLib/xtUc.h b/source/xtLib/xtUc.h
@@ -9,7 +9,7 @@
#include "mc68k/mc68k.h"
#include "mc68k/hdi08periph.h"
-#include "wLib/am29f.h"
+#include "hardwareLib/am29f.h"
namespace xt
{
@@ -51,7 +51,7 @@ namespace xt
std::array<uint8_t, g_romSize> m_romRuntimeData;
xtHdi08A m_hdiA;
- wLib::Am29f m_flash;
+ hwLib::Am29f m_flash;
Pic m_pic;
Lcd m_lcd;