diff --git a/CMakeLists.txt b/CMakeLists.txt index 219ca54..3e51244 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ add_executable( console_ncurses.cpp console_posix.cpp cpu.cpp + dc11.cpp debugger.cpp disk_backend.cpp disk_backend_file.cpp diff --git a/bus.cpp b/bus.cpp index 89301c5..1ec2ce9 100644 --- a/bus.cpp +++ b/bus.cpp @@ -8,6 +8,7 @@ #include "bus.h" #include "gen.h" #include "cpu.h" +#include "dc11.h" #include "kw11-l.h" #include "log.h" #include "memory.h" @@ -41,6 +42,7 @@ bus::~bus() delete tty_; delete mmu_; delete m; + delete dc11_; } #if IS_POSIX @@ -69,7 +71,7 @@ json_t *bus::serialize() const if (rk05_) json_object_set(j_out, "rk05", rk05_->serialize()); - // TODO: tm11 + // TODO: tm11, dc11 return j_out; } @@ -122,7 +124,7 @@ bus *bus::deserialize(const json_t *const j, console *const cnsl, std::atomic_ui b->add_rk05(rk05_); } - // TODO: tm11 + // TODO: tm11, dc11 return b; } @@ -156,6 +158,8 @@ void bus::reset() tty_->reset(); if (kw11_l_) kw11_l_->reset(); + if (dc11_) + dc11_->reset(); } void bus::add_KW11_L(kw11_l *const kw11_l_) @@ -203,7 +207,13 @@ void bus::add_rl02(rl02 *const rl02_) void bus::add_tty(tty *const tty_) { delete this->tty_; - this->tty_ = tty_; + this->tty_ = tty_; +} + +void bus::add_DC11(dc11 *const dc11_) +{ + delete this->dc11_; + this->dc11_ = dc11_; } void bus::init() @@ -457,29 +467,20 @@ uint16_t bus::read(const uint16_t addr_in, const word_mode_t word_mode, const rm } } - if (tm11 && a >= TM_11_BASE && a < TM_11_END && !peek_only) { - DOLOG(debug, false, "READ-I/O TM11 register %d", (a - TM_11_BASE) / 2); - + if (tm11 && a >= TM_11_BASE && a < TM_11_END && !peek_only) return word_mode == wm_byte ? tm11->readByte(a) : tm11->readWord(a); - } - - if (rk05_ && a >= RK05_BASE && a < RK05_END && !peek_only) { - DOLOG(debug, false, "READ-I/O RK05 register %d", (a - RK05_BASE) / 2); + if (rk05_ && a >= RK05_BASE && a < RK05_END && !peek_only) return word_mode == wm_byte ? rk05_->readByte(a) : rk05_->readWord(a); - } - - if (rl02_ && a >= RL02_BASE && a < RL02_END && !peek_only) { - DOLOG(debug, false, "READ-I/O RL02 register %d", (a - RL02_BASE) / 2); + if (rl02_ && a >= RL02_BASE && a < RL02_END && !peek_only) return word_mode == wm_byte ? rl02_->readByte(a) : rl02_->readWord(a); - } - - if (tty_ && a >= PDP11TTY_BASE && a < PDP11TTY_END && !peek_only) { - DOLOG(debug, false, "READ-I/O TTY register %d", (a - PDP11TTY_BASE) / 2); + if (tty_ && a >= PDP11TTY_BASE && a < PDP11TTY_END && !peek_only) return word_mode == wm_byte ? tty_->readByte(a) : tty_->readWord(a); - } + + if (dc11_ && a >= DC11_BASE && a < DC11_END && !peek_only) + return word_mode == wm_byte ? dc11_->read_byte(a) : dc11_->read_word(a); // LO size register field must be all 1s, so subtract 1 uint32_t system_size = m->get_memory_size() / 64 - 1; diff --git a/bus.h b/bus.h index 800e926..79c7e5e 100644 --- a/bus.h +++ b/bus.h @@ -9,6 +9,7 @@ #include #include "gen.h" +#include "dc11.h" #include "mmu.h" #include "rk05.h" #include "rl02.h" @@ -77,6 +78,7 @@ private: kw11_l *kw11_l_ { nullptr }; mmu *mmu_ { nullptr }; memory *m { nullptr }; + dc11 *dc11_ { nullptr }; uint16_t microprogram_break_register { 0 }; @@ -113,6 +115,7 @@ public: void add_rl02 (rl02 *const rl02_ ); void add_tty (tty *const tty_ ); void add_KW11_L(kw11_l *const kw11_l_); + void add_DC11 (dc11 *const dc11_ ); memory *getRAM() { return m; } cpu *getCpu() { return c; } @@ -121,6 +124,7 @@ public: mmu *getMMU() { return mmu_; } rk05 *getRK05() { return rk05_; } rl02 *getRL02() { return rl02_; } + dc11 *getDC11() { return dc11_; } uint16_t read (const uint16_t a, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool peek_only=false, const d_i_space_t s = i_space); uint16_t readByte(const uint16_t a) { return read(a, wm_byte, rm_cur); } diff --git a/dc11.cpp b/dc11.cpp new file mode 100644 index 0000000..9923ef4 --- /dev/null +++ b/dc11.cpp @@ -0,0 +1,65 @@ +// (C) 2024 by Folkert van Heusden +// Released under MIT license + +#include "bus.h" +#include "dc11.h" + + +dc11::dc11(bus *const b): b(b) +{ +} + +dc11::~dc11() +{ + stop_flag = true; +} + +void dc11::reset() +{ +} + +uint8_t dc11::read_byte(const uint16_t addr) +{ + uint16_t v = read_word(addr & ~1); + + if (addr & 1) + return v >> 8; + + return v; +} + +uint16_t dc11::read_word(const uint16_t addr) +{ + const int reg = (addr - DC11_BASE) / 2; + + uint16_t vtemp = registers[reg]; + + DOLOG(debug, false, "DC11: read register %06o (%d): %06o", addr, reg, vtemp); + + return vtemp; +} + +void dc11::write_byte(const uint16_t addr, const uint8_t v) +{ + uint16_t vtemp = registers[(addr - DC11_BASE) / 2]; + + if (addr & 1) { + vtemp &= ~0xff00; + vtemp |= v << 8; + } + else { + vtemp &= ~0x00ff; + vtemp |= v; + } + + write_word(addr, vtemp); +} + +void dc11::write_word(const uint16_t addr, uint16_t v) +{ + const int reg = (addr - DC11_BASE) / 2; + + DOLOG(debug, false, "DC11: set register %06o (%d) to %o", addr, reg, v); + + registers[reg] = v; +} diff --git a/dc11.h b/dc11.h new file mode 100644 index 0000000..3112931 --- /dev/null +++ b/dc11.h @@ -0,0 +1,42 @@ +// (C) 2024 by Folkert van Heusden +// Released under MIT license + +#pragma once +#include +#include + +#include "gen.h" +#include "bus.h" +#include "log.h" + +#define DC11_RCSR 0174000 // receiver status register +#define DC11_BASE DC11_RCSR +#define DC11_END (DC11_RCSR + 2) + +class bus; + +class dc11 +{ +private: + bus *const b { nullptr }; + + uint16_t registers[4] { }; + std::atomic_bool stop_flag { false }; + +public: + dc11(bus *const b); + virtual ~dc11(); + +#if IS_POSIX +// json_t *serialize(); +// static tty *deserialize(const json_t *const j, bus *const b, console *const cnsl); +#endif + + void reset(); + + uint8_t read_byte(const uint16_t addr); + uint16_t read_word(const uint16_t addr); + + void write_byte(const uint16_t addr, const uint8_t v); + void write_word(const uint16_t addr, uint16_t v); +};