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 }