diff --git a/debugger/tms7000/pins_tms7000.cpp b/debugger/tms7000/pins_tms7000.cpp index 35e81510..227616f3 100644 --- a/debugger/tms7000/pins_tms7000.cpp +++ b/debugger/tms7000/pins_tms7000.cpp @@ -33,8 +33,10 @@ struct PinsTms7000 Pins; namespace { -constexpr auto clkin_hi_ns = 500; -constexpr auto clkin_lo_ns = 500; +constexpr auto clkin2_hi_ns = 500; +constexpr auto clkin2_lo_ns = 500; +constexpr auto clkin4_hi_ns = 250; +constexpr auto clkin4_lo_ns = 250; inline void clkin_hi() { digitalWriteFast(PIN_CLKIN, HIGH); @@ -60,7 +62,11 @@ inline auto signal_rw() { return digitalReadFast(PIN_RW); } -void negate_reset() { +inline void assert_reset() { + digitalWriteFast(PIN_RESET, LOW); +} + +inline void negate_reset() { digitalWriteFast(PIN_RESET, HIGH); } @@ -109,32 +115,91 @@ const uint8_t PINS_INPUT[] = { PIN_PB3, }; -inline void clkin_cycle_lo() { +inline void clkin2_cycle() { clkin_hi(); - delayNanoseconds(clkin_hi_ns); + delayNanoseconds(clkin2_hi_ns); clkin_lo(); + delayNanoseconds(clkin2_lo_ns); } -inline void clkin_cycle() { - clkin_cycle_lo(); - delayNanoseconds(clkin_lo_ns); +inline void clkin4_cycle_hi() { + clkin_lo(); + delayNanoseconds(clkin4_lo_ns); + clkin_hi(); } } // namespace +void (*PinsTms7000::_clk_hi)(); +void (*PinsTms7000::_clk_lo)(); +void (*PinsTms7000::_clk_cycle)(); + +void PinsTms7000::clk2_hi() { + clkin_hi(); +} + +void PinsTms7000::clk2_lo() { + clkin_lo(); +} + +void PinsTms7000::clk4_cycle_hi() { + clkin4_cycle_hi(); +} + +void PinsTms7000::clk_cycle2() { + clkin2_cycle(); +} + +void PinsTms7000::clk_cycle4() { + clkin4_cycle_hi(); + delayNanoseconds(clkin4_hi_ns); + clkin4_cycle_hi(); + delayNanoseconds(clkin4_hi_ns); +} + +void PinsTms7000::synchronize_clk() { + // CLKOUT works only when #RESET=H + negate_reset(); + while (signal_clkout() != LOW) + clkin2_cycle(); + assert_debug(); + while (signal_clkout() == LOW) + clkin2_cycle(); + // CLKOUT=H + clkin2_cycle(); // /2:CLKOUT=L, /4:CLKOUT=H + clkin2_cycle(); // /2:CLKOUT=H, /4:CLKOUT=L + negate_debug(); + if (signal_clkout() != LOW) { + // /2 clock option + _clk_hi = clk2_hi; + _clk_lo = clk2_lo; + _clk_cycle = clk_cycle2; + } else { + // /4 clock option + _clk_hi = clk4_cycle_hi; + _clk_lo = clk4_cycle_hi; + _clk_cycle = clk_cycle4; + clkin_hi(); + delayNanoseconds(clkin4_hi_ns); + } + // CLKOUT=H; Assert #RESET again + assert_reset(); +} + void PinsTms7000::reset() { // Assert reset condition pinsMode(PINS_LOW, sizeof(PINS_LOW), OUTPUT, LOW); pinsMode(PINS_HIGH, sizeof(PINS_HIGH), OUTPUT, HIGH); pinsMode(PINS_INPUT, sizeof(PINS_INPUT), INPUT); + synchronize_clk(); // The RESET function is initiated when the #RESET line of the // TMS7000 device is held at a logic zero level for at least five // clock cycles. - for (auto i = 0; i < 100; i++) - clkin_cycle(); + for (auto i = 0; i < 10; i++) + clk_cycle(); negate_reset(); - clkin_cycle(); + clk_cycle(); Signals::resetCycles(); // Clear IOCNT0 (>0100) to disable interrupts cycle(); @@ -167,80 +232,80 @@ void PinsTms7000::checkHardwareType() { Signals *PinsTms7000::prepareCycle() const { auto s = Signals::put(); while (signal_alatch() == LOW) - clkin_cycle(); + clk_cycle(); // CLKOUT=H, ALATCH=H - clkin_hi(); - delayNanoseconds(clkin_hi_ns); + clk_hi(); + delayNanoseconds(clkin2_hi_ns); // CLKOUT=L - clkin_lo(); - // assert_debug(); + clk_lo(); + assert_debug(); s->getAddress(); - // negate_debug(); - delayNanoseconds(clkin_lo_ns); + negate_debug(); + delayNanoseconds(clkin2_lo_ns); // CLKOUT=H - clkin_hi(); - delayNanoseconds(clkin_hi_ns); - // assert_debug(); + clk_hi(); + delayNanoseconds(clkin2_hi_ns); + assert_debug(); s->getDirection(); - // negate_debug(); + negate_debug(); return s; } Signals *PinsTms7000::completeCycle(Signals *s) const { if (s->read()) { // External read - clkin_lo(); + clk_lo(); if (s->readMemory()) { s->data = Memory.read(s->addr); } else { ; // inject } - delayNanoseconds(clkin_lo_ns); + delayNanoseconds(clkin2_lo_ns); // CLKOUT=L - clkin_hi(); - // assert_debug(); + clk_hi(); + assert_debug(); s->outData(); - // negate_debug(); - delayNanoseconds(clkin_hi_ns); - clkin_lo(); - delayNanoseconds(clkin_lo_ns); + negate_debug(); + delayNanoseconds(clkin2_hi_ns); + clk_lo(); + delayNanoseconds(clkin2_lo_ns); // CLKOUT=H - clkin_hi(); + clk_hi(); while (signal_enable() == LOW) ; - // assert_debug(); + assert_debug(); s->inputMode(); - // negate_debug(); - delayNanoseconds(clkin_hi_ns); - clkin_lo(); - delayNanoseconds(clkin_lo_ns); + negate_debug(); + delayNanoseconds(clkin2_hi_ns); + clk_lo(); + delayNanoseconds(clkin2_lo_ns); } else if (s->write()) { // External write - clkin_lo(); - delayNanoseconds(clkin_lo_ns); + clk_lo(); + delayNanoseconds(clkin2_lo_ns); // CLKOUT=L - clkin_hi(); - // assert_debug(); + clk_hi(); + assert_debug(); s->getData(); - // negate_debug(); - delayNanoseconds(clkin_hi_ns); - clkin_lo(); + negate_debug(); + delayNanoseconds(clkin2_hi_ns); + clk_lo(); if (s->writeMemory()) { Memory.write(s->addr, s->data); } else { ; // capture } - delayNanoseconds(clkin_lo_ns); + delayNanoseconds(clkin2_lo_ns); } else { // Internal cycle - clkin_lo(); - delayNanoseconds(clkin_lo_ns); - // assert_debug(); + clk_lo(); + delayNanoseconds(clkin2_lo_ns); + assert_debug(); s->getData(); - // negate_debug(); + negate_debug(); } - // assert_debug(); + assert_debug(); Signals::nextCycle(); - // negate_debug(); + negate_debug(); while (signal_alatch() == LOW) - clkin_cycle(); + clk_cycle(); return s; } @@ -322,10 +387,8 @@ bool PinsTms7000::rawStep() { const auto opc = Memory.raw_read(s->addr); const auto cycles = InstTms7000::busCycles(opc); if (opc == InstTms7000::IDLE || cycles == 0) { - assert_debug(); completeCycle(s->inject(InstTms7000::JMP)); inject(InstTms7000::JMP_HERE); - negate_debug(); Signals::discard(s); return false; } diff --git a/debugger/tms7000/pins_tms7000.h b/debugger/tms7000/pins_tms7000.h index a16585c6..e6719b06 100644 --- a/debugger/tms7000/pins_tms7000.h +++ b/debugger/tms7000/pins_tms7000.h @@ -65,6 +65,11 @@ enum HardwareType : uint8_t { HW_TMS7002 = 2, // TMS7002 }; +enum ClockType : uint8_t { + CLK_DIV2 = 0, // NL2 + CLK_DIV4 = 3, // NL4 +}; + enum IntrName : uint8_t { INTR_NONE = 0, INTR_INT1 = 1, @@ -84,18 +89,34 @@ struct PinsTms7000 final : Pins { void captureWrites(const uint8_t *inst, uint8_t len, uint8_t *buf, uint8_t max, uint16_t *addr = nullptr); HardwareType hardwareType() const { return _hardType; } + ClockType clockType() const { + return _clk_cycle == clk_cycle4 ? CLK_DIV4 : CLK_DIV2; + } private: HardwareType _hardType; + static void (*_clk_hi)(); + static void (*_clk_lo)(); + static void (*_clk_cycle)(); + static void clk2_hi(); + static void clk2_lo(); + static void clk4_cycle_hi(); + static void clk_cycle2(); + static void clk_cycle4(); + static void clk_hi() { _clk_hi(); } + static void clk_lo() { _clk_lo(); } + static void clk_cycle() { _clk_cycle(); } + void setBreakInst(uint32_t addr) const override; + void synchronize_clk(); void checkHardwareType(); - void loop(); Signals *prepareCycle() const; - Signals *completeCycle(Signals *signals) const; + Signals *completeCycle(Signals *s) const; Signals *cycle() const; Signals *inject(uint8_t data) const; + void loop(); bool rawStep(); void execute(const uint8_t *inst, uint8_t len, uint8_t *buf = nullptr, uint8_t max = 0, uint16_t *addr = nullptr); diff --git a/debugger/tms7000/regs_tms7000.cpp b/debugger/tms7000/regs_tms7000.cpp index eca818ca..dbd39df8 100644 --- a/debugger/tms7000/regs_tms7000.cpp +++ b/debugger/tms7000/regs_tms7000.cpp @@ -13,9 +13,11 @@ struct RegsTms7000 Regs; namespace { constexpr const char *const CPU_NAMES[/*HardwareType*/] = { - "TMS7000", - "TMS7001", - "TMS7002", + "TMS7000NL2", // 0 + "TMS7001NL2", // 1 + "TMS7002", // 2 + "TMS7000NL4", // 0+3 + "TMS7001NL4", // 1+3 }; } @@ -24,7 +26,7 @@ const char *RegsTms7000::cpu() const { } const char *RegsTms7000::cpuName() const { - const auto type = Pins.hardwareType(); + const auto type = Pins.hardwareType() + Pins.clockType(); return CPU_NAMES[type]; }