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

n2xmc.cpp (6920B)


      1 #include "n2xmc.h"
      2 
      3 #include <cassert>
      4 
      5 #include "n2xdsp.h"
      6 #include "n2xrom.h"
      7 
      8 #include "baseLib/filesystem.h"
      9 
     10 #define MC68K_CLASS n2x::Microcontroller
     11 #include "mc68k/musashiEntry.h"
     12 
     13 namespace n2x
     14 {
     15 	// OC2 = PGP4 = SDA
     16 	// OC3 = PGP5 = SCL
     17 	// OC5 = PGP7 = sustain pedal
     18 
     19 	static constexpr uint32_t g_bitResetDSP = 3;
     20 	static constexpr uint32_t g_bitSDA = 4;
     21 	static constexpr uint32_t g_bitSCL = 5;
     22 	static constexpr uint32_t g_bitResetDAC = 6;
     23 
     24 	static constexpr uint32_t g_maskResetDSP = 1 << g_bitResetDSP;
     25 	static constexpr uint32_t g_maskResetDAC = 1 << g_bitResetDAC;
     26 
     27 	Microcontroller::Microcontroller(Hardware& _hardware, const Rom& _rom)
     28 	: m_flash(_hardware)
     29 	, m_hdi08(m_hdi08A, m_hdi08B)
     30 	, m_panel(_hardware)
     31 	, m_midi(getQSM(), g_samplerate)
     32 	{
     33 		if(!_rom.isValid())
     34 			return;
     35 
     36 		m_romRam.fill(0);
     37 		std::copy(std::begin(_rom.data()), std::end(_rom.data()), std::begin(m_romRam));
     38 
     39 		m_midi.setSysexDelay(0.0f, 1);
     40 
     41 //		dumpAssembly("n2x_68k.asm", g_romAddress, g_romSize);
     42 
     43 		reset();
     44 
     45 		setPC(g_pcInitial);
     46 
     47 		// keyboard irqs, we do not really care but as the UC spinlooped once while waiting for it to become high we set it to high all the time
     48 		getPortF().writeRX(0xff);
     49 
     50 		getPortGP().setWriteTXCallback([this](const mc68k::Port& _port)
     51 		{
     52 			const auto v = _port.read();
     53 			const auto d = _port.getDirection();
     54 
     55 			const auto sdaV = (v >> g_bitSDA) & 1;
     56 			const auto sclV = (v >> g_bitSCL) & 1;
     57 
     58 			const auto sdaD = (d >> g_bitSDA) & 1;
     59 			const auto sclD = (d >> g_bitSCL) & 1;
     60 
     61 //			LOG("PortGP write SDA=" << sdaV << " SCL=" << sclV);
     62 
     63 			if(d & g_maskResetDAC)
     64 			{
     65 				if(v & g_maskResetDAC)
     66 				{
     67 				}
     68 				else
     69 				{
     70 					LOG("Reset DAC");
     71 				}
     72 			}
     73 			if((d & g_maskResetDSP))
     74 			{
     75 				if(v & g_maskResetDSP)
     76 				{
     77 				}
     78 				else
     79 				{
     80 					LOG("Reset DSP");
     81 				}
     82 			}
     83 
     84 			if(sdaD && sclD)
     85 				m_flash.masterWrite(sdaV, sclV);
     86 			else if(!sdaD && sclD)
     87 			{
     88 				if(const auto res = m_flash.masterRead(sclV))
     89 				{
     90 					auto r = v;
     91 					r &= ~(1 << g_bitSDA);
     92 					r |= *res ? (1<<g_bitSDA) : 0;
     93 
     94 					getPortGP().writeRX(r);
     95 					LOG("PortGP return SDA=" << *res);
     96 				}
     97 				else
     98 				{
     99 //					LOG("PortGP return SDA={}, wrong SCL");
    100 				}
    101 			}
    102 		});
    103 		getPortGP().setDirectionChangeCallback([this](const mc68k::Port& _port)
    104 		{
    105 			// OC2 = PGP4 = SDA
    106 			// OC3 = PGP5 = SCL
    107 			const auto p = _port.getDirection();
    108 			const auto sda = (p >> g_bitSDA) & 1;
    109 			const auto scl = (p >> g_bitSCL) & 1;
    110 			LOG("PortGP dir SDA=" << (sda?"w":"r") << " SCL=" << (scl?"w":"r"));
    111 			if(scl)
    112 			{
    113 				const auto ack = m_flash.setSdaWrite(sda);
    114 				if(ack)
    115 				{
    116 					LOG("Write ACK " << (*ack));
    117 					getPortGP().writeRX(*ack ? (1<<g_bitSDA) : 0);
    118 				}
    119 			}
    120 		});
    121 	}
    122 
    123 	uint16_t Microcontroller::read16(const uint32_t _addr)
    124 	{
    125 		if(_addr < m_romRam.size())
    126 		{
    127 			const auto r = mc68k::memoryOps::readU16(m_romRam.data(), _addr);
    128 			return r;
    129 		}
    130 
    131 		const auto pa = static_cast<mc68k::PeriphAddress>(_addr);
    132 
    133 		if(m_hdi08A.isInRange(pa))	return m_hdi08A.read16(pa);
    134 		if(m_hdi08B.isInRange(pa))	return m_hdi08B.read16(pa);
    135 		if(m_hdi08.isInRange(pa))	return m_hdi08.read16(pa);
    136 
    137 		if(m_panel.cs4().isInRange(pa))
    138 		{
    139 //			LOG("Read Frontpanel CS4 " << HEX(_addr));
    140 			return m_panel.cs4().read16(pa);
    141 		}
    142 
    143 		if(m_panel.cs6().isInRange(pa))
    144 		{
    145 //			LOG("Read Frontpanel CS6 " << HEX(_addr));
    146 			return m_panel.cs6().read16(pa);
    147 		}
    148 
    149 #ifdef _DEBUG
    150 		if(_addr >= g_keyboardAddress && _addr < g_keyboardAddress + g_keyboardSize)
    151 		{
    152 			assert(false && "keyboard access is unexpected");
    153 			LOG("Read Keyboard " << HEX(_addr));
    154 			return 0;
    155 		}
    156 #endif
    157 		return Mc68k::read16(_addr);
    158 	}
    159 
    160 	uint8_t Microcontroller::read8(const uint32_t _addr)
    161 	{
    162 		if(_addr < m_romRam.size())
    163 		{
    164 			const auto r = m_romRam[_addr];
    165 //			LOG("read " << HEX(_addr) << "=" << HEXN(r,2));
    166 			return r;
    167 		}
    168 
    169 		const auto pa = static_cast<mc68k::PeriphAddress>(_addr);
    170 
    171 		if(m_hdi08A.isInRange(pa))	return m_hdi08A.read8(pa);
    172 		if(m_hdi08B.isInRange(pa))	return m_hdi08B.read8(pa);
    173 		if(m_hdi08.isInRange(pa))	return m_hdi08.read8(pa);
    174 		
    175 		if(m_panel.cs4().isInRange(pa))
    176 		{
    177 //			LOG("Read Frontpanel CS4 " << HEX(_addr));
    178 			return m_panel.cs4().read8(pa);
    179 		}
    180 
    181 		if(m_panel.cs6().isInRange(pa))
    182 		{
    183 //			LOG("Read Frontpanel CS6 " << HEX(_addr));
    184 			return m_panel.cs6().read8(pa);
    185 		}
    186 
    187 #ifdef _DEBUG
    188 		if(_addr >= g_keyboardAddress && _addr < g_keyboardAddress + g_keyboardSize)
    189 		{
    190 			assert(false && "keyboard access is unexpected");
    191 			LOG("Read Keyboard " << HEX(_addr));
    192 			return 0;
    193 		}
    194 #endif
    195 		return Mc68k::read8(_addr);
    196 	}
    197 
    198 	void Microcontroller::write16(const uint32_t _addr, const uint16_t _val)
    199 	{
    200 		if(_addr < m_romRam.size())
    201 		{
    202 			assert(_addr >= g_ramAddress);
    203 			mc68k::memoryOps::writeU16(m_romRam.data(), _addr, _val);
    204 			return;
    205 		}
    206 
    207 		const auto pa = static_cast<mc68k::PeriphAddress>(_addr);
    208 
    209 		if(m_hdi08A.isInRange(pa))
    210 		{
    211 			m_hdi08A.write16(pa, _val);
    212 			return;
    213 		}
    214 
    215 		if(m_hdi08B.isInRange(pa))
    216 		{
    217 			m_hdi08B.write16(pa, _val);
    218 			return;
    219 		}
    220 
    221 		if(m_hdi08.isInRange(pa))
    222 		{
    223 			m_hdi08.write16(pa, _val);
    224 			return;
    225 		}
    226 
    227 		if(m_panel.cs4().isInRange(pa))
    228 		{
    229 //			LOG("Write Frontpanel CS4 " << HEX(_addr) << "=" << HEXN(_val, 4));
    230 			m_panel.cs4().write16(pa, _val);
    231 			return;
    232 		}
    233 
    234 		if(m_panel.cs6().isInRange(pa))
    235 		{
    236 //			LOG("Write Frontpanel CS6 " << HEX(_addr) << "=" << HEXN(_val, 4));
    237 			m_panel.cs6().write16(pa, _val);
    238 			return;
    239 		}
    240 
    241 		Mc68k::write16(_addr, _val);
    242 	}
    243 
    244 	void Microcontroller::write8(const uint32_t _addr, const uint8_t _val)
    245 	{
    246 		if(_addr < m_romRam.size())
    247 		{
    248 			assert(_addr >= g_ramAddress);
    249 			m_romRam[_addr] = _val;
    250 			return;
    251 		}
    252 
    253 		const auto pa = static_cast<mc68k::PeriphAddress>(_addr);
    254 
    255 		if(m_hdi08A.isInRange(pa))
    256 		{
    257 			m_hdi08A.write8(pa, _val);
    258 			return;
    259 		}
    260 
    261 		if(m_hdi08B.isInRange(pa))
    262 		{
    263 			m_hdi08B.write8(pa, _val);
    264 			return;
    265 		}
    266 		
    267 		if(m_hdi08.isInRange(pa))
    268 		{
    269 			m_hdi08.write8(pa, _val);
    270 			return;
    271 		}
    272 		
    273 		if(m_panel.cs4().isInRange(pa))
    274 		{
    275 			LOG("Write Frontpanel CS4 " << HEX(_addr) << "=" << HEXN(_val, 2));
    276 			m_panel.cs4().write8(pa, _val);
    277 			return;
    278 		}
    279 
    280 		if(m_panel.cs6().isInRange(pa))
    281 		{
    282 //			LOG("Write Frontpanel CS6 " << HEX(_addr) << "=" << HEXN(_val, 2));
    283 			m_panel.cs6().write8(pa, _val);
    284 			return;
    285 		}
    286 
    287 		Mc68k::write8(_addr, _val);
    288 	}
    289 
    290 	uint32_t Microcontroller::exec()
    291 	{
    292 #ifdef _DEBUG
    293 		const auto pc = getPC();
    294 		m_prevPC = pc;
    295 
    296 //		LOG("uc PC=" << HEX(pc));
    297 		if(pc >= g_ramAddress)
    298 		{
    299 //			if(pc == 0x1000c8)
    300 //				dumpAssembly("nl2x_68k_ram.asm", g_ramAddress, g_ramSize);
    301 		}
    302 
    303 		static volatile bool writeFlash = false;
    304 		static volatile bool writeRam = false;
    305 
    306 		if(writeFlash)
    307 		{
    308 			writeFlash = false;
    309 			m_flash.saveAs("flash_runtime.bin");
    310 		}
    311 
    312 		if(writeRam)
    313 		{
    314 			writeRam = false;
    315 			baseLib::filesystem::writeFile("romRam_runtime.bin", m_romRam);
    316 		}
    317 #endif
    318 		const auto cycles = Mc68k::exec();
    319 
    320 //		m_hdi08A.exec(cycles);
    321 //		m_hdi08B.exec(cycles);
    322 
    323 		return cycles;
    324 	}
    325 }