commit 9442722906683f6e800dfbaa8016c216c7717f57
parent 0c51c32af1525a0a1ca975240c9999d946fd9cb0
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Thu, 18 Jul 2024 18:59:10 +0200
continuing attempts to boot n2x
Diffstat:
6 files changed, 146 insertions(+), 18 deletions(-)
diff --git a/source/nord/n2x/n2xLib/n2xdsp.cpp b/source/nord/n2x/n2xLib/n2xdsp.cpp
@@ -1,7 +1,9 @@
#include "n2xdsp.h"
#include "n2xhardware.h"
+#include "dsp56kDebugger/debugger.h"
#include "dsp56kEmu/dspthread.h"
+#include "mc68k/hdi08.h"
namespace n2x
{
@@ -74,12 +76,13 @@ namespace n2x
config.aguSupportBitreverse = true;
config.linkJitBlocks = true;
- config.dynamicPeripheralAddressing = false;
+ config.dynamicPeripheralAddressing = true;
#ifdef _DEBUG
config.debugDynamicPeripheralAddressing = true;
#endif
config.maxInstructionsPerBlock = 0;
config.support16BitSCMode = true;
+ config.dynamicFastInterrupts = true;
m_dsp.getJit().setConfig(config);
@@ -106,6 +109,9 @@ namespace n2x
// set OMR pins so that bootcode wants program data via HDI08 RX
m_dsp.setPC(g_bootCodeBase);
m_dsp.regs().omr.var |= OMR_MA | OMR_MB | OMR_MC | OMR_MD;
+
+ hdi08().setRXRateLimit(0);
+ hdi08().setTransmitDataAlwaysEmpty(false);
m_hdiUC.setRxEmptyCallback([&](const bool _needMoreData)
{
@@ -123,51 +129,112 @@ namespace n2x
{
return hdiUcReadIsr(_isr);
});
+ m_hdiUC.setInitHdi08Callback([&]
+ {
+ // clear init flag again immediately, code is waiting for it to happen
+ m_hdiUC.icr(m_hdiUC.icr() & 0x7f);
+ m_hdiUC.isr(m_hdiUC.isr() | mc68k::Hdi08::IsrBits::Txde | mc68k::Hdi08::IsrBits::Trdy);
+ });
#if DSP56300_DEBUGGER
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp.dsp())));
-#else
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
+ if(!m_index)
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp)));
+ else
#endif
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
m_thread->setLogToStdout(false);
}
void DSP::onUCRxEmpty(bool _needMoreData)
{
+ hdiTransferDSPtoUC();
}
void DSP::hdiTransferUCtoDSP(const uint32_t _word)
{
- LOG('[' << m_name << "] toDSP writeRX=" << HEX(_word));
+ LOG('[' << m_name << "] toDSP writeRX=" << HEX(_word) << ", ucPC=" << HEX(m_hardware.getUC().getPC()));
hdi08().writeRX(&_word, 1);
+ m_hdiUC.isr(m_hdiUC.isr() & ~(mc68k::Hdi08::IsrBits::Txde | mc68k::Hdi08::IsrBits::Trdy));
}
- void DSP::hdiSendIrqToDSP(uint8_t _irq)
+ void DSP::hdiSendIrqToDSP(const uint8_t _irq)
{
- dsp().injectExternalInterrupt(_irq);
+ LOG('[' << m_name << "] sendIRQtoDSP " << HEXN(_irq, 2));
+
+ waitDspRxEmpty();
+ const auto& rxData = hdi08().rxData();
+ auto& rxHack = const_cast<std::decay_t<decltype(rxData)>&>(rxData);
- while(dsp().hasPendingInterrupts())
+ if(hdi08().rxData().size() > 1)
{
- std::this_thread::yield();
+ dsp56k::TWord v;
+ while(!hdi08().rxData().empty())
+ {
+ v = rxHack.pop_front();
+ LOG("Discarding UC2DSP HDI word " << HEX(v));
+ }
+ LOG("Re-sending word " << HEX(v));
+ hdi08().writeRX(&v,1);
}
+
+ dsp().injectExternalInterrupt(_irq);
+
+ m_hardware.ucYieldLoop([&]
+ {
+ return dsp().hasPendingInterrupts();
+ });
+
+ hdiTransferDSPtoUC();
}
uint8_t DSP::hdiUcReadIsr(uint8_t _isr)
{
+ // transfer DSP host flags HF2&3 to uc
+ const auto hf23 = hdi08().readControlRegister() & 0x18;
+ _isr &= ~0x18;
+ _isr |= hf23;
+ if(hdi08().hasRXData())
+ _isr &= ~mc68k::Hdi08::IsrBits::Txde;
+ else if(_isr & mc68k::Hdi08::IsrBits::Txde)
+ _isr |= mc68k::Hdi08::IsrBits::Trdy;
return _isr;
}
+ void DSP::transferHostFlagsUc2Dsdp()
+ {
+ const uint32_t hf01 = m_hdiUC.icr() & 0x18;
+
+ if (hf01 != m_hdiHF01)
+ {
+// LOG('[' << m_name << "] HDI HF01=" << HEXN((hf01>>3),1));
+
+ waitDspRxEmpty();
+
+ m_hdiHF01 = hf01;
+ hdi08().setPendingHostFlags01(hf01);
+ }
+ }
+
bool DSP::hdiTransferDSPtoUC()
{
if (m_hdiUC.canReceiveData() && hdi08().hasTX())
{
const auto v = hdi08().readTX();
- LOG('[' << m_name << "] HDI dsp2uc=" << HEX(v));
+ LOG('[' << m_name << "] HDI dsp2UC=" << HEX(v));
m_hdiUC.writeRx(v);
return true;
}
return false;
}
+ void DSP::waitDspRxEmpty()
+ {
+ m_hardware.ucYieldLoop([&]()
+ {
+ return (hdi08().hasRXData() && hdi08().rxInterruptEnabled()) || dsp().hasPendingInterrupts();
+ });
+// assert(!hdi08().hasRXData());
+// LOG("writeRX wait over");
+ }
}
diff --git a/source/nord/n2x/n2xLib/n2xdsp.h b/source/nord/n2x/n2xLib/n2xdsp.h
@@ -40,7 +40,11 @@ namespace n2x
void hdiTransferUCtoDSP(uint32_t _word);
void hdiSendIrqToDSP(uint8_t _irq);
uint8_t hdiUcReadIsr(uint8_t _isr);
+ public:
+ void transferHostFlagsUc2Dsdp();
+ private:
bool hdiTransferDSPtoUC();
+ void waitDspRxEmpty();
Hardware& m_hardware;
mc68k::Hdi08& m_hdiUC;
@@ -56,5 +60,6 @@ namespace n2x
std::unique_ptr<dsp56k::DSPThread> m_thread;
bool m_receivedMagicEsaiPacket = false;
+ uint32_t m_hdiHF01 = 0;
};
}
diff --git a/source/nord/n2x/n2xLib/n2xhardware.cpp b/source/nord/n2x/n2xLib/n2xhardware.cpp
@@ -19,5 +19,13 @@ namespace n2x
void Hardware::process()
{
m_uc.exec();
+ m_dspA.transferHostFlagsUc2Dsdp();
+ m_dspB.transferHostFlagsUc2Dsdp();
+ }
+
+ void Hardware::ucYieldLoop(const std::function<bool()>& _continue)
+ {
+ while(_continue())
+ std::this_thread::yield();
}
}
diff --git a/source/nord/n2x/n2xLib/n2xhardware.h b/source/nord/n2x/n2xLib/n2xhardware.h
@@ -14,6 +14,9 @@ namespace n2x
void process();
+ Microcontroller& getUC() {return m_uc; }
+ void ucYieldLoop(const std::function<bool()>& _continue);
+
private:
Rom m_rom;
Microcontroller m_uc;
diff --git a/source/nord/n2x/n2xLib/n2xmc.cpp b/source/nord/n2x/n2xLib/n2xmc.cpp
@@ -2,6 +2,7 @@
#include <cassert>
+#include "n2xdsp.h"
#include "n2xrom.h"
namespace n2x
@@ -14,7 +15,7 @@ namespace n2x
m_rom = _rom.data();
m_ram.fill(0);
- dumpAssembly("n2x_68k.asm", g_romAddress, g_romSize);
+// dumpAssembly("n2x_68k.asm", g_romAddress, g_romSize);
reset();
@@ -49,6 +50,24 @@ namespace n2x
if(m_hdi08A.isInRange(pa)) return m_hdi08A.read16(pa);
if(m_hdi08B.isInRange(pa)) return m_hdi08B.read16(pa);
+ if(_addr >= g_frontPanelAddressA && _addr < g_frontPanelAddressA + g_frontPanelSize)
+ {
+ LOG("Read Frontpanel A " << HEX(_addr));
+ return 0;
+ }
+
+ if(_addr >= g_frontPanelAddressB && _addr < g_frontPanelAddressB + g_frontPanelSize)
+ {
+ LOG("Read Frontpanel B " << HEX(_addr));
+ return 0;
+ }
+
+ if(_addr >= g_keyboardAddress && _addr < g_keyboardAddress + g_keyboardSize)
+ {
+ LOG("Read Keyboard A " << HEX(_addr));
+ return 0;
+ }
+
return Mc68k::read16(_addr);
}
@@ -61,6 +80,24 @@ namespace n2x
if(m_hdi08A.isInRange(pa)) return m_hdi08A.read8(pa);
if(m_hdi08B.isInRange(pa)) return m_hdi08B.read8(pa);
+
+ if(_addr >= g_frontPanelAddressA && _addr < g_frontPanelAddressA + g_frontPanelSize)
+ {
+ LOG("Read Frontpanel A " << HEX(_addr));
+ return 0xff;
+ }
+
+ if(_addr >= g_frontPanelAddressB && _addr < g_frontPanelAddressB + g_frontPanelSize)
+ {
+ LOG("Read Frontpanel B " << HEX(_addr));
+ return 0xff;
+ }
+
+ if(_addr >= g_keyboardAddress && _addr < g_keyboardAddress + g_keyboardSize)
+ {
+ LOG("Read Keyboard A " << HEX(_addr));
+ return 0xff;
+ }
return Mc68k::read8(_addr);
}
@@ -130,10 +167,11 @@ namespace n2x
uint32_t Microcontroller::exec()
{
const auto pc = getPC();
+// LOG("uc PC=" << HEX(pc));
if(pc >= g_ramAddress)
{
- if(pc == 0x1000c8)
- dumpAssembly("nl2x_68k_ram.asm", g_ramAddress, g_ramSize);
+// if(pc == 0x1000c8)
+// dumpAssembly("nl2x_68k_ram.asm", g_ramAddress, g_ramSize);
}
const auto cycles = Mc68k::exec();
diff --git a/source/nord/n2x/n2xLib/n2xtypes.h b/source/nord/n2x/n2xLib/n2xtypes.h
@@ -22,11 +22,18 @@ namespace n2x
static constexpr uint32_t g_romSize = 1024 * 512;
static constexpr uint32_t g_ramSize = 1024 * 256;
- static constexpr uint32_t g_pcInitial = 0xc2;
+ static constexpr uint32_t g_pcInitial = 0xc2;
- static constexpr uint32_t g_romAddress = 0;
- static constexpr uint32_t g_ramAddress = 0x100000;
+ static constexpr uint32_t g_romAddress = 0;
+ static constexpr uint32_t g_ramAddress = 0x100000;
- static constexpr uint32_t g_dspAAddress = 0x200008;
- static constexpr uint32_t g_dspBAddress = 0x200010;
+ static constexpr uint32_t g_dspAAddress = 0x200008;
+ static constexpr uint32_t g_dspBAddress = 0x200010;
+
+ static constexpr uint32_t g_frontPanelAddressA = 0x202800;
+ static constexpr uint32_t g_frontPanelAddressB = 0x202000;
+ static constexpr uint32_t g_keyboardAddress = 0x203000;
+
+ static constexpr uint32_t g_frontPanelSize = 0x800;
+ static constexpr uint32_t g_keyboardSize = 0x800;
}