diff --git a/bus.cpp b/bus.cpp index 8198ae3..b19807c 100644 --- a/bus.cpp +++ b/bus.cpp @@ -8,6 +8,7 @@ #include "bus.h" #include "gen.h" #include "cpu.h" +#include "kw11-l.h" #include "log.h" #include "memory.h" #include "mmu.h" @@ -26,15 +27,14 @@ bus::bus() mmu_ = new mmu(); - reset(); + kw11_l_ = new kw11_l(this); -#if defined(BUILD_FOR_RP2040) - xSemaphoreGive(lf_csr_lock); // initialize -#endif + reset(); } bus::~bus() { + delete kw11_l_; delete c; delete tm11; delete rk05_; @@ -220,22 +220,8 @@ uint16_t bus::read(const uint16_t addr_in, const word_mode_t word_mode, const rm return temp; } - if (a == ADDR_LFC) { // line frequency clock and status register -#if defined(BUILD_FOR_RP2040) - xSemaphoreTake(lf_csr_lock, portMAX_DELAY); -#else - std::unique_lock lck(lf_csr_lock); -#endif - - uint16_t temp = lf_csr; - if (!peek_only) DOLOG(debug, false, "READ-I/O line frequency clock: %o", temp); - -#if defined(BUILD_FOR_RP2040) - xSemaphoreGive(lf_csr_lock); -#endif - - return temp; - } + if (a == ADDR_LFC) // line frequency clock and status register + return kw11_l_->readWord(a); if (a == ADDR_LP11CSR) { // printer, CSR register, LP11 uint16_t temp = 0x80; @@ -848,17 +834,8 @@ write_rc_t bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint1 } if (a == ADDR_LFC) { // line frequency clock and status register -#if defined(BUILD_FOR_RP2040) - xSemaphoreTake(lf_csr_lock, portMAX_DELAY); -#else - std::unique_lock lck(lf_csr_lock); -#endif + kw11_l_->writeWord(a, value); - DOLOG(debug, false, "WRITE-I/O set line frequency clock/status register: %06o", value); - lf_csr = value; -#if defined(BUILD_FOR_RP2040) - xSemaphoreGive(lf_csr_lock); -#endif return { false }; } @@ -1023,35 +1000,3 @@ void bus::writeUnibusByte(const uint32_t a, const uint8_t v) DOLOG(debug, false, "writeUnibusByte[%08o]=%03o", a, v); m->writeByte(a, v); } - -void bus::set_lf_crs_b7() -{ -#if defined(BUILD_FOR_RP2040) - xSemaphoreTake(lf_csr_lock, portMAX_DELAY); -#else - std::unique_lock lck(lf_csr_lock); -#endif - - lf_csr |= 128; - -#if defined(BUILD_FOR_RP2040) - xSemaphoreGive(lf_csr_lock); -#endif -} - -uint8_t bus::get_lf_crs() -{ -#if defined(BUILD_FOR_RP2040) - xSemaphoreTake(lf_csr_lock, portMAX_DELAY); -#else - std::unique_lock lck(lf_csr_lock); -#endif - - uint8_t rc = lf_csr; - -#if defined(BUILD_FOR_RP2040) - xSemaphoreGive(lf_csr_lock); -#endif - - return rc; -} diff --git a/bus.h b/bus.h index e61243a..1065d03 100644 --- a/bus.h +++ b/bus.h @@ -54,6 +54,7 @@ #define ADDR_SYSTEM_ID 0177764 class cpu; +class kw11_l; class memory; class tty; @@ -75,23 +76,17 @@ typedef struct { class bus { private: - cpu *c { nullptr }; - tm_11 *tm11 { nullptr }; - rk05 *rk05_ { nullptr }; - rl02 *rl02_ { nullptr }; - tty *tty_ { nullptr }; + cpu *c { nullptr }; + tm_11 *tm11 { nullptr }; + rk05 *rk05_ { nullptr }; + rl02 *rl02_ { nullptr }; + tty *tty_ { nullptr }; + kw11_l *kw11_l_ { nullptr }; - mmu *mmu_ { nullptr }; + mmu *mmu_ { nullptr }; int n_pages { DEFAULT_N_PAGES }; - memory *m { nullptr }; - -#if defined(BUILD_FOR_RP2040) - SemaphoreHandle_t lf_csr_lock { xSemaphoreCreateBinary() }; -#else - std::mutex lf_csr_lock; -#endif - uint16_t lf_csr { 0 }; + memory *m { nullptr }; uint16_t microprogram_break_register { 0 }; @@ -103,35 +98,29 @@ public: ~bus(); void reset(); + void init(); // invoked by 'RESET' command void set_console_switches(const uint16_t new_state) { console_switches = new_state; } void set_console_switch(const int bit, const bool state) { console_switches &= ~(1 << bit); console_switches |= state << bit; } uint16_t get_console_switches() { return console_switches; } void set_debug_mode() { console_switches |= 128; } + uint16_t get_console_leds() { return console_leds; } int get_memory_size() const { return n_pages; } void set_memory_size(const int n_pages); void mmudebug(const uint16_t a); - uint16_t get_console_leds() { return console_leds; } + void add_cpu (cpu *const c ); + void add_tm11(tm_11 *const tm11 ); + void add_rk05(rk05 *const rk05_); + void add_rl02(rl02 *const rl02_); + void add_tty (tty *const tty_ ); - void add_cpu (cpu *const c); - void add_tm11(tm_11 *const tm11); - void add_rk05(rk05 *const rk05_); - void add_rl02(rl02 *const rl02_); - void add_tty (tty *const tty_); - - cpu *getCpu() { return c; } - - tty *getTty() { return tty_; } - - mmu *getMMU() { return mmu_; } - - void init(); // invoked by 'RESET' command - - void set_lf_crs_b7(); - uint8_t get_lf_crs(); + cpu *getCpu() { return c; } + kw11_l *getKW11_L() { return kw11_l_; } + tty *getTty() { return tty_; } + mmu *getMMU() { return mmu_; } 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/kw11-l.cpp b/kw11-l.cpp index 9081eb3..449bfb2 100644 --- a/kw11-l.cpp +++ b/kw11-l.cpp @@ -25,13 +25,8 @@ void thread_wrapper_kw11(void *p) } #endif -kw11_l::kw11_l(bus *const b, console *const cnsl) : b(b), cnsl(cnsl) +kw11_l::kw11_l(bus *const b): b(b) { -#if defined(ESP32) || defined(BUILD_FOR_RP2040) - xTaskCreate(&thread_wrapper_kw11, "kw11-l", 2048, this, 1, nullptr); -#else - th = new std::thread(std::ref(*this)); -#endif } kw11_l::~kw11_l() @@ -39,9 +34,26 @@ kw11_l::~kw11_l() stop_flag = true; #if !defined(ESP32) && !defined(BUILD_FOR_RP2040) - th->join(); + if (th) { + th->join(); - delete th; + delete th; + } +#endif +} + +void kw11_l::begin(console *const cnsl) +{ + this->cnsl = cnsl; + +#if defined(ESP32) || defined(BUILD_FOR_RP2040) + xTaskCreate(&thread_wrapper_kw11, "kw11-l", 2048, this, 1, nullptr); + +#if defined(BUILD_FOR_RP2040) + xSemaphoreGive(lf_csr_lock); // initialize +#endif +#else + th = new std::thread(std::ref(*this)); #endif } @@ -53,9 +65,9 @@ void kw11_l::operator()() while(!stop_flag) { if (*cnsl->get_running_flag()) { - b->set_lf_crs_b7(); + set_lf_crs_b7(); - if (b->get_lf_crs() & 64) + if (get_lf_crs() & 64) b->getCpu()->queue_interrupt(6, 0100); // TODO: dependant on cpu cycles processed @@ -68,3 +80,77 @@ void kw11_l::operator()() DOLOG(debug, true, "KW11-L thread terminating"); } + +uint16_t kw11_l::readWord(const uint16_t a) +{ + if (a != ADDR_LFC) { + DOLOG(debug, true, "KW11-L readWord not for us (%06o)", a); + return 0; + } + +#if defined(BUILD_FOR_RP2040) + xSemaphoreTake(lf_csr_lock, portMAX_DELAY); +#else + std::unique_lock lck(lf_csr_lock); +#endif + + uint16_t temp = lf_csr; + +#if defined(BUILD_FOR_RP2040) + xSemaphoreGive(lf_csr_lock); +#endif + + return temp; +} + +void kw11_l::writeWord(const uint16_t a, const uint16_t value) +{ + if (a != ADDR_LFC) { + DOLOG(debug, true, "KW11-L writeWord not for us (%06o to %06o)", value, a); + return; + } + +#if defined(BUILD_FOR_RP2040) + xSemaphoreTake(lf_csr_lock, portMAX_DELAY); +#else + std::unique_lock lck(lf_csr_lock); +#endif + + DOLOG(debug, false, "WRITE-I/O set line frequency clock/status register: %06o", value); + lf_csr = value; +#if defined(BUILD_FOR_RP2040) + xSemaphoreGive(lf_csr_lock); +#endif +} + +void kw11_l::set_lf_crs_b7() +{ +#if defined(BUILD_FOR_RP2040) + xSemaphoreTake(lf_csr_lock, portMAX_DELAY); +#else + std::unique_lock lck(lf_csr_lock); +#endif + + lf_csr |= 128; + +#if defined(BUILD_FOR_RP2040) + xSemaphoreGive(lf_csr_lock); +#endif +} + +uint8_t kw11_l::get_lf_crs() +{ +#if defined(BUILD_FOR_RP2040) + xSemaphoreTake(lf_csr_lock, portMAX_DELAY); +#else + std::unique_lock lck(lf_csr_lock); +#endif + + uint8_t rc = lf_csr; + +#if defined(BUILD_FOR_RP2040) + xSemaphoreGive(lf_csr_lock); +#endif + + return rc; +} diff --git a/kw11-l.h b/kw11-l.h index 416f1f7..666ac40 100644 --- a/kw11-l.h +++ b/kw11-l.h @@ -1,26 +1,39 @@ -// (C) 2018-2023 by Folkert van Heusden +// (C) 2018-2024 by Folkert van Heusden // Released under MIT license #include #include #include "bus.h" +#include "console.h" class kw11_l { private: - bus *const b { nullptr }; - console *const cnsl { nullptr }; + bus *const b { nullptr }; + console *cnsl { nullptr }; -#if !defined(BUILD_FOR_RP2040) - std::thread * th { nullptr }; +#if defined(BUILD_FOR_RP2040) + SemaphoreHandle_t lf_csr_lock { xSemaphoreCreateBinary() }; +#else + std::thread *th { nullptr }; + std::mutex lf_csr_lock; #endif - std::atomic_bool stop_flag { false }; + uint16_t lf_csr { 0 }; + + std::atomic_bool stop_flag { false }; + + uint8_t get_lf_crs(); + void set_lf_crs_b7(); public: - kw11_l(bus *const b, console *const cnsl); + kw11_l(bus *const b); virtual ~kw11_l(); - void operator()(); + void begin(console *const cnsl); + void operator()(); + + uint16_t readWord (const uint16_t a); + void writeWord(const uint16_t a, const uint16_t v); }; diff --git a/main.cpp b/main.cpp index 71fa638..e36e4e9 100644 --- a/main.cpp +++ b/main.cpp @@ -584,14 +584,14 @@ int main(int argc, char *argv[]) if (test.empty() == false) load_p11_x11(b, test); - kw11_l *lf = new kw11_l(b, cnsl); - std::thread *metrics_thread = nullptr; if (metrics) metrics_thread = new std::thread(get_metrics, c); cnsl->start_thread(); + b->getKW11_L()->begin(cnsl); + if (is_bic) run_bic(cnsl, b, &event, tracing, bic_start.value()); else if (run_debugger || (bootloader == BL_NONE && test.empty() && tape.empty())) @@ -624,11 +624,11 @@ int main(int argc, char *argv[]) delete metrics_thread; } - delete lf; - - delete cnsl; + cnsl->stop_thread(); delete b; + delete cnsl; + return 0; }