diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..416c72b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ESP32/SHAdisplay"] + path = ESP32/SHAdisplay + url = https://github.com/krzychb/esp-epaper-29-dke diff --git a/CMakeLists.txt b/CMakeLists.txt index 424619a..396612b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ add_compile_options(-Wall -pedantic -Wextra) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) +if (NOT WIN32) + add_executable( kek bus.cpp @@ -34,6 +36,10 @@ add_executable( utils.cpp ) +endif (NOT WIN32) + +if (WIN32) + add_executable( kek-win32 bus.cpp @@ -58,6 +64,8 @@ add_executable( win32.cpp ) +endif (WIN32) + include(CheckIPOSupported) check_ipo_supported(RESULT supported) @@ -68,10 +76,13 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads) +if (NOT WIN32) target_link_libraries(kek Threads::Threads) +else () target_link_libraries(kek-win32 Threads::Threads) target_link_libraries(kek-win32 ws2_32) +endif () include(FindPkgConfig) diff --git a/ESP32/SHAdisplay b/ESP32/SHAdisplay new file mode 160000 index 0000000..18b4249 --- /dev/null +++ b/ESP32/SHAdisplay @@ -0,0 +1 @@ +Subproject commit 18b42491ceecbfdb70e0dac69a379f5787a84a5d diff --git a/ESP32/console_esp32.cpp b/ESP32/console_esp32.cpp index 675d7b9..d4026dd 100644 --- a/ESP32/console_esp32.cpp +++ b/ESP32/console_esp32.cpp @@ -9,12 +9,13 @@ #include "console_esp32.h" #include "cpu.h" #include "error.h" +#include "utils.h" #define NEOPIXELS_PIN 25 -console_esp32::console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector & io_ports) : - console(stop_event, b), +console_esp32::console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector & io_ports, const int t_width, const int t_height) : + console(stop_event, b, t_width, t_height), io_ports(io_ports) { } @@ -104,31 +105,39 @@ void console_esp32::panel_update_thread() for(;;) { vTaskDelay(20 / portTICK_RATE_MS); - // note that these are approximately as there's no mutex on the emulation - uint16_t current_PSW = c->getPSW(); - int run_mode = current_PSW >> 14; + try { + // note that these are approximately as there's no mutex on the emulation + uint16_t current_PSW = c->getPSW(); + int run_mode = current_PSW >> 14; - uint16_t current_PC = c->getPC(); - uint32_t full_addr = b->calculate_physical_address(run_mode, current_PC, false, false, true, i_space); + uint16_t current_PC = c->getPC(); + uint32_t full_addr = b->calculate_physical_address(run_mode, current_PC, false, false, true, i_space); - uint16_t current_instr = b->readWord(current_PC); + uint16_t current_instr = b->readWord(current_PC); - uint32_t led_color = run_mode_led_color[run_mode]; + uint32_t led_color = run_mode_led_color[run_mode]; - for(uint8_t b=0; b<22; b++) - pixels.setPixelColor(b, full_addr & (1 << b) ? led_color : 0); + for(uint8_t b=0; b<22; b++) + pixels.setPixelColor(b, full_addr & (1 << b) ? led_color : 0); - for(uint8_t b=0; b<16; b++) - pixels.setPixelColor(b + 22, current_PSW & (1l << b) ? magenta : 0); + for(uint8_t b=0; b<16; b++) + pixels.setPixelColor(b + 22, current_PSW & (1l << b) ? magenta : 0); - for(uint8_t b=0; b<16; b++) - pixels.setPixelColor(b + 38, current_instr & (1l << b) ? red : 0); + for(uint8_t b=0; b<16; b++) + pixels.setPixelColor(b + 38, current_instr & (1l << b) ? red : 0); - pixels.setPixelColor(54, running_flag ? white : 0); + pixels.setPixelColor(54, running_flag ? white : 0); - pixels.setPixelColor(55, disk_read_activity_flag ? blue : 0); - pixels.setPixelColor(56, disk_write_activity_flag ? blue : 0); + pixels.setPixelColor(55, disk_read_activity_flag ? blue : 0); + pixels.setPixelColor(56, disk_write_activity_flag ? blue : 0); - pixels.show(); + pixels.show(); + } + catch(std::exception & e) { + put_string_lf(format("Exception in panel thread: %s", e.what())); + } + catch(...) { + put_string_lf("Unknown exception in panel thread"); + } } } diff --git a/ESP32/console_esp32.h b/ESP32/console_esp32.h index 69254be..fd3aa30 100644 --- a/ESP32/console_esp32.h +++ b/ESP32/console_esp32.h @@ -18,7 +18,7 @@ protected: void put_char_ll(const char c) override; public: - console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector & io_ports); + console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector & io_ports, const int t_width, const int t_height); virtual ~console_esp32(); void put_string_lf(const std::string & what) override; diff --git a/ESP32/console_shabadge.cpp b/ESP32/console_shabadge.cpp new file mode 100644 index 0000000..8720724 --- /dev/null +++ b/ESP32/console_shabadge.cpp @@ -0,0 +1,77 @@ +// (C) 2023 by Folkert van Heusden +// Released under MIT license + +#include +#include +#include +#include + +#include "console_shabadge.h" +#include "cpu.h" +#include "error.h" +#include "utils.h" + + +#define COLORED 0 +#define UNCOLORED 1 + +console_shabadge::console_shabadge(std::atomic_uint32_t *const stop_event, bus *const b, std::vector & io_ports) : + console_esp32(stop_event, b, io_ports, 296 / 8, 128 / 8) +{ + if (epd.Init() != 0) + Serial.println("Init of DEPG0290B01 failed"); + else { + Serial.println("DEPG0290B01 initialized"); + + paint = new Paint(image, 0, 0); + + paint->SetRotate(ROTATE_270); + paint->SetWidth(128); + paint->SetHeight(296); + paint->Clear(UNCOLORED); + + epd.ClearFrameMemory(UNCOLORED); + } +} + +console_shabadge::~console_shabadge() +{ + stop_thread(); + + delete paint; +} + +void console_shabadge::put_char_ll(const char c) +{ + console_esp32::put_char_ll(c); + + screen_updated_ts = millis(); + screen_updated = true; +} + +void console_shabadge::panel_update_thread() +{ + for(;;) { + vTaskDelay(100 / portTICK_RATE_MS); + + if (screen_updated && millis() - screen_updated_ts >= 1000) { + screen_updated = false; + + paint->Clear(UNCOLORED); + + for(int y=0; yDrawCharAt(x * 8, y * 8, c, &Font8, COLORED); + } + } + + epd.SetFrameMemory(paint->GetImage(), 0, 0, paint->GetWidth(), paint->GetHeight()); + epd.DisplayFrame(); + } + } +} diff --git a/ESP32/console_shabadge.h b/ESP32/console_shabadge.h new file mode 100644 index 0000000..8a77cb2 --- /dev/null +++ b/ESP32/console_shabadge.h @@ -0,0 +1,29 @@ +// (C) 2023 by Folkert van Heusden +// Released under MIT license + +#include +#include +#include +#include + +#include "console_esp32.h" + + +class console_shabadge : public console_esp32 +{ +private: + unsigned char image[4736]; + Paint *paint { nullptr }; + Epd epd; + + std::atomic_int screen_updated_ts { 0 }; + std::atomic_bool screen_updated { false }; + + void put_char_ll(const char c) override; + +public: + console_shabadge(std::atomic_uint32_t *const stop_event, bus *const b, std::vector & io_ports); + virtual ~console_shabadge(); + + void panel_update_thread() override; +}; diff --git a/ESP32/disk_backend_esp32.cpp b/ESP32/disk_backend_esp32.cpp index 0b34005..b207d24 100644 --- a/ESP32/disk_backend_esp32.cpp +++ b/ESP32/disk_backend_esp32.cpp @@ -37,7 +37,7 @@ bool disk_backend_esp32::read(const off_t offset, const size_t n, uint8_t *const { DOLOG(debug, false, "disk_backend_esp32::read: read %zu bytes from offset %zu", n, offset); -#if defined(ESP32) +#if defined(ESP32) && !defined(SHA2017) digitalWrite(LED_BUILTIN, LOW); #endif @@ -49,7 +49,7 @@ bool disk_backend_esp32::read(const off_t offset, const size_t n, uint8_t *const if (fh->read(target, n) != size_t(n)) { DOLOG(debug, true, "fread error: %s", strerror(errno)); -#if defined(ESP32) +#if defined(ESP32) && !defined(SHA2017) digitalWrite(LED_BUILTIN, HIGH); #endif return false; @@ -57,7 +57,7 @@ bool disk_backend_esp32::read(const off_t offset, const size_t n, uint8_t *const yield(); -#if defined(ESP32) +#if defined(ESP32) && !defined(SHA2017) digitalWrite(LED_BUILTIN, HIGH); #endif @@ -68,7 +68,7 @@ bool disk_backend_esp32::write(const off_t offset, const size_t n, const uint8_t { DOLOG(debug, false, "disk_backend_esp32::write: write %zu bytes to offset %zu", n, offset); -#if defined(ESP32) +#if defined(ESP32) && !defined(SHA2017) digitalWrite(LED_BUILTIN, LOW); #endif @@ -80,7 +80,7 @@ bool disk_backend_esp32::write(const off_t offset, const size_t n, const uint8_t if (fh->write(from, n) != n) { DOLOG(ll_error, true, "RK05 fwrite error %s", strerror(errno)); -#if defined(ESP32) +#if defined(ESP32) && !defined(SHA2017) digitalWrite(LED_BUILTIN, HIGH); #endif return false; @@ -88,8 +88,8 @@ bool disk_backend_esp32::write(const off_t offset, const size_t n, const uint8_t yield(); -#if defined(ESP32) - digitalWrite(LED_BUILTIN, HIGH); +#if defined(ESP32) && !defined(SHA2017) + digitalWrite(LED_BUILTIN, HIGH); #endif return true; diff --git a/ESP32/main.ino b/ESP32/main.ino index 1104989..9c0d26a 100644 --- a/ESP32/main.ino +++ b/ESP32/main.ino @@ -14,7 +14,11 @@ #include #include +#if defined(SHA2017) +#include "console_shabadge.h" +#else #include "console_esp32.h" +#endif #include "cpu.h" #include "debugger.h" #include "disk_backend.h" @@ -188,8 +192,12 @@ std::optional select_disk_backend(console *const c) c->put_string("1. network (NBD), 2. local SD card, 9. abort"); int ch = -1; - while(ch == -1 && ch != '1' && ch != '2' && ch != '9') - ch = c->wait_char(500); + while(ch == -1 && ch != '1' && ch != '2' && ch != '9') { + auto temp = c->wait_char(500); + + if (temp.has_value()) + ch = temp.value(); + } c->put_string_lf(format("%c", ch)); @@ -208,8 +216,12 @@ std::optional select_disk_type(console *const c) c->put_string("1. RK05, 2. RL02, 9. abort"); int ch = -1; - while(ch == -1 && ch != '1' && ch != '2' && ch != '9') - ch = c->wait_char(500); + while(ch == -1 && ch != '1' && ch != '2' && ch != '9') { + auto temp = c->wait_char(500); + + if (temp.has_value()) + ch = temp.value(); + } c->put_string_lf(format("%c", ch)); @@ -274,8 +286,13 @@ std::optional, std::vector c->put_string_lf("Files on SD-card:"); +#if defined(SHA2017) + if (!sd.begin(21, SD_SCK_MHZ(10))) + sd.initErrorHalt(); +#else if (!sd.begin(SS, SD_SCK_MHZ(15))) sd.initErrorHalt(); +#endif for(;;) { sd.ls("/", LS_DATE | LS_SIZE | LS_R); @@ -340,7 +357,7 @@ void set_disk_configuration(std::pair, std::vectorput_string_lf("Load disk"); auto backend = select_disk_backend(cnsl); @@ -505,7 +522,11 @@ void setup() Serial_RS232.println(F("\014Console enabled on TTY")); std::vector serial_ports { &Serial_RS232, &Serial }; - cnsl = new console_esp32(&stop_event, b, serial_ports); +#if defined(SHA2017) + cnsl = new console_shabadge(&stop_event, b, serial_ports); +#else + cnsl = new console_esp32(&stop_event, b, serial_ports, 80, 25); +#endif Serial.println(F("Start line-frequency interrupt")); kw11_l *lf = new kw11_l(b, cnsl); @@ -525,11 +546,15 @@ void setup() Serial.print(F("Free RAM after init: ")); Serial.println(ESP.getFreeHeap()); +#if !defined(SHA2017) pinMode(LED_BUILTIN, OUTPUT); +#endif Serial.flush(); cnsl->start_thread(); + + cnsl->put_string_lf("PDP-11/70 emulator, (C) Folkert van Heusden"); } void loop() diff --git a/ESP32/platformio.ini b/ESP32/platformio.ini index c0cbd90..b36016a 100644 --- a/ESP32/platformio.ini +++ b/ESP32/platformio.ini @@ -2,12 +2,12 @@ # Released under MIT license [platformio] -default_envs = ESP32 +default_envs = ESP32-wemos src_dir = . +lib_ignore = SHAdisplay -[env:ESP32] -lib_ldf_mode = deep+ -build_src_filter = +<*> -<.git/> -<.svn/> - - - - - - +[env:ESP32-wemos] +build_src_filter = +<*> -<.git/> -<.svn/> - - - - - - - - platform = espressif32 board = wemos_d1_mini32 framework = arduino @@ -20,15 +20,17 @@ lib_deps = greiman/SdFat@^2.1.2 build_flags = -std=gnu++17 -Ofast -DESP32=1 -ggdb3 -D_GLIBCXX_USE_C99 build_unflags = -std=gnu++11 -Os -#[env:PICO] -#lib_ldf_mode = deep+ -#src_filter = +<*> -<.git/> -<.svn/> - - - - - - -#platform = raspberrypi -#board = pico -#framework = arduino -#monitor_speed = 115200 -#upload_speed = 1000000 -#lib_deps = greiman/SdFat@^2.1.2 -# adafruit/Adafruit NeoPixel@^1.10.4 -#build_flags = -std=gnu++17 -Ofast -DESP32=1 -ggdb3 -D_GLIBCXX_USE_C99 -#build_unflags = -std=gnu++11 -Os +[env:SHA2017-badge] +build_src_filter = +<*> -<.git/> -<.svn/> - - - - - - - - - +platform = espressif32 +board = esp32doit-devkit-v1 +framework = arduino +monitor_speed = 115200 +upload_speed = 460800 +board_build.filesystem = littlefs +lib_deps = greiman/SdFat@^2.1.2 + adafruit/Adafruit NeoPixel + bblanchon/ArduinoJson@^6.19.4 +build_flags = -std=gnu++17 -Ofast -DESP32=1 -DSHA2017 -ggdb3 -D_GLIBCXX_USE_C99 -ISHAdisplay/Arduino/libraries/epd2in9-badge -ISHAdisplay/Arduino/libraries/epdpaint -ISHAdisplay/components/epaper-29-dke +build_unflags = -std=gnu++11 -Os +upload_protocol = esptool diff --git a/README.md b/README.md index 014a19f..571a573 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ To build for e.g. linux: mkdir build cd build cmake .. - make kek + make Required: * libncursesw5-dev @@ -16,7 +16,7 @@ To build for e.g. windows: mkdir build-win32 cd build-win32 cmake -DCMAKE_TOOLCHAIN_FILE=../mingw64.cmake .. - make kek-win32 + make To run a disk image: @@ -50,6 +50,19 @@ Wiring of the MAX232 connection: * RX : 16 +See SHA2017-badge.md if you want to flash your SHA20127 badge with this software. + + +Some pictures: + +![(running on a regular ESP32 connected to a VT510 terminal)](images/KEK-ESP32-VT510.jpg) + +![(running on a SHA2017-badge)](images/KEK-sha2017badge.jpg) + +Click on the following picture to see it running (opens a youtube link): + +[![running on a Linux laptop](images/KEK-linux-frame.jpg)](https://youtu.be/MPaGmVli8NA) + Released under MIT license. Folkert van Heusden diff --git a/SHA2017-badge.md b/SHA2017-badge.md new file mode 100644 index 0000000..ab8aa4e --- /dev/null +++ b/SHA2017-badge.md @@ -0,0 +1,12 @@ +This procedure will remove the default micropython environment. +Maybe you can undo that, but I have not tried that. + +* esptool.py erase\_flash + +* pio run -e SHA2017-badge + +* esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default\_reset --after hard\_reset write\_flash -z --flash\_mode dio --flash\_freq 80m --flash\_size detect 0x1000 ./.pio/build/ESP32-wemos/bootloader.bin + +* pio run -e SHA2017-badge -t upload + +After this, you can connect a serial terminal to /dev/ttyUSB0 at 115k2 bps. diff --git a/bus.cpp b/bus.cpp index 0026ad3..5d4cf1c 100644 --- a/bus.cpp +++ b/bus.cpp @@ -14,6 +14,8 @@ #include "tty.h" #if defined(ESP32) +#include + // ESP32 goes in a crash-loop when allocating 128kB // see also https://github.com/espressif/esp-idf/issues/1934 constexpr int n_pages = 12; @@ -641,7 +643,19 @@ void bus::addToMMR1(const int8_t delta, const uint8_t reg) assert(reg >= 0 && reg <= 7); assert(delta >= -2 && delta <= 2); + if (getMMR0() & 0160000) // MMR1 etc are locked + return; + +#if defined(ESP32) + if (MMR1 > 255) + esp_backtrace_print(32); +#else + if (MMR1 > 255) { + extern FILE *lfh; + fflush(lfh); + } assert(MMR1 < 256); +#endif MMR1 <<= 8; diff --git a/config.h b/config.h index 8e8d4c6..30eafeb 100644 --- a/config.h +++ b/config.h @@ -1,4 +1,4 @@ // (C) 2018-2023 by Folkert van Heusden // Released under MIT license -#define TURBO +// #define TURBO diff --git a/console.cpp b/console.cpp index 6e825e6..68f98c1 100644 --- a/console.cpp +++ b/console.cpp @@ -2,6 +2,7 @@ // Released under MIT license #include +#include #include #include #include @@ -14,11 +15,14 @@ #include "utils.h" -console::console(std::atomic_uint32_t *const stop_event, bus *const b) : +console::console(std::atomic_uint32_t *const stop_event, bus *const b, const int t_width, const int t_height) : stop_event(stop_event), - b(b) + b(b), + t_width(t_width), + t_height(t_height) { - memset(screen_buffer, ' ', sizeof screen_buffer); + + screen_buffer = new char[t_width * t_height](); } console::~console() @@ -26,6 +30,8 @@ console::~console() // done as well in subclasses but also here to // stop lgtm.com complaining about it stop_thread(); + + delete [] screen_buffer; } void console::start_thread() @@ -70,7 +76,7 @@ int console::get_char() return c; } -int console::wait_char(const int timeout_ms) +std::optional console::wait_char(const int timeout_ms) { std::unique_lock lck(input_lock); @@ -86,7 +92,7 @@ int console::wait_char(const int timeout_ms) } } - return -1; + return { }; } void console::flush_input() @@ -111,34 +117,34 @@ std::string console::read_line(const std::string & prompt) std::string str; for(;;) { - char c = wait_char(500); + auto c = wait_char(250); if (*stop_event == EVENT_TERMINATE) return ""; - if (c == -1 || c == 255 /* ESP32 has unsigned char? */) + if (c.has_value() == false) continue; - if (c == 13 || c == 10) + if (c.value() == 13 || c.value() == 10) break; - if (c == 8 || c == 127) { // backspace + if (c.value() == 8 || c.value() == 127) { // backspace if (!str.empty()) { str = str.substr(0, str.size() - 1); emit_backspace(); } } - else if (c == 21) { // ^u + else if (c.value() == 21) { // ^u for(size_t i=0; i= 32) { - str += c; + else if (c.value() >= 32) { + str += c.value(); - put_char(c); + put_char(c.value()); } } @@ -186,7 +192,7 @@ void console::put_char(const char c) tx--; } else { - screen_buffer[ty][tx++] = c; + screen_buffer[ty * t_width + tx++] = c; if (tx == t_width) { tx = 0; @@ -199,11 +205,11 @@ void console::put_char(const char c) } if (ty == t_height) { - memmove(&screen_buffer[0], &screen_buffer[1], sizeof(char) * t_width * (t_height - 1)); + memmove(&screen_buffer[0 * t_width], &screen_buffer[1 * t_width], sizeof(char) * t_width * (t_height - 1)); ty--; - memset(screen_buffer[t_height - 1], ' ', t_width); + memset(&screen_buffer[(t_height - 1) * t_width], ' ', t_width); } } diff --git a/console.h b/console.h index f24a595..9beed04 100644 --- a/console.h +++ b/console.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -15,9 +16,6 @@ #endif -constexpr const int t_width { 80 }; -constexpr const int t_height { 25 }; - class console { private: @@ -36,7 +34,9 @@ protected: bool stop_thread_flag { false }; - char screen_buffer[t_height][t_width]; + const int t_width { 0 }; + const int t_height { 0 }; + char *screen_buffer { nullptr }; uint8_t tx { 0 }; uint8_t ty { 0 }; @@ -47,7 +47,7 @@ protected: virtual void put_char_ll(const char c) = 0; public: - console(std::atomic_uint32_t *const stop_event, bus *const b); + console(std::atomic_uint32_t *const stop_event, bus *const b, const int t_width = 80, const int t_height = 25); virtual ~console(); void start_thread(); @@ -55,7 +55,7 @@ public: bool poll_char(); int get_char(); - int wait_char(const int timeout_ms); + std::optional wait_char(const int timeout_ms); std::string read_line(const std::string & prompt); void flush_input(); diff --git a/cpu.cpp b/cpu.cpp index 8d79475..b1b0d9d 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -71,7 +71,7 @@ std::tuple cpu::get_mips_rel_speed() { uint64_t instr_count = get_instructions_executed_count(); - uint32_t t_diff = get_ms() - running_since; + uint32_t t_diff = get_ms() - running_since; // TODO fix this because we now implement WAIT where it sits idle double mips = instr_count / (1000.0 * t_diff); @@ -259,7 +259,7 @@ bool cpu::check_queued_interrupts() uint8_t current_level = getPSW_spl(); // uint8_t start_level = current_level <= 3 ? 0 : current_level + 1; - uint8_t start_level = current_level + 1; + uint8_t start_level = current_level + 1; for(uint8_t i=start_level; i < 8; i++) { auto interrupts = queued_interrupts.find(i); @@ -301,9 +301,6 @@ void cpu::queue_interrupt(const uint8_t level, const uint8_t vector) void cpu::addToMMR1(const uint8_t mode, const uint8_t reg, const word_mode_t word_mode) { - if (b->getMMR0() & 0160000 /* bits frozen? */) - return; - bool neg = mode == 4 || mode == 5; if (word_mode == wm_word || reg >= 6 || mode == 6 || mode == 7) @@ -406,13 +403,13 @@ gam_rc_t cpu::getGAMAddress(const uint8_t mode, const int reg, const word_mode_t bool cpu::double_operand_instructions(const uint16_t instr) { - const word_mode_t word_mode = instr & 0x8000 ? wm_byte : wm_word; - const uint8_t operation = (instr >> 12) & 7; if (operation == 0b000) return single_operand_instructions(instr); + const word_mode_t word_mode = instr & 0x8000 ? wm_byte : wm_word; + if (operation == 0b111) { if (word_mode == wm_byte) return false; @@ -424,11 +421,6 @@ bool cpu::double_operand_instructions(const uint16_t instr) const uint8_t src_mode = (src >> 3) & 7; const uint8_t src_reg = src & 7; - gam_rc_t g_src { wm_word, rm_cur, i_space, { }, { }, { } }; - - if (operation != 0b110) - g_src = getGAM(src_mode, src_reg, word_mode, rm_cur); - const uint8_t dst = instr & 63; const uint8_t dst_mode = (dst >> 3) & 7; const uint8_t dst_reg = dst & 7; @@ -437,6 +429,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) switch(operation) { case 0b001: { // MOV/MOVB Move Word/Byte + gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur); + if (word_mode == wm_byte && dst_mode == 0) setRegister(dst_reg, int8_t(g_src.value.value())); // int8_t: sign extension else { @@ -452,6 +446,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b010: { // CMP/CMPB Compare Word/Byte + gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur); uint16_t temp = (g_src.value.value() - g_dst.value.value()) & (word_mode == wm_byte ? 0xff : 0xffff); @@ -465,7 +461,10 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b011: { // BIT/BITB Bit Test Word/Byte + gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur); + uint16_t result = (g_dst.value.value() & g_src.value.value()) & (word_mode == wm_byte ? 0xff : 0xffff); setPSW_flags_nzv(result, word_mode); @@ -474,6 +473,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b100: { // BIC/BICB Bit Clear Word/Byte + gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur); uint16_t result = g_dst.value.value() & ~g_src.value.value(); @@ -485,6 +486,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b101: { // BIS/BISB Bit Set Word/Byte + gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur); uint16_t result = g_dst.value.value() | g_src.value.value(); @@ -1549,8 +1552,7 @@ bool cpu::misc_operations(const uint16_t instr) int dst_reg = instr & 7; - word_mode_t word_mode = wm_word; - setPC(getGAMAddress(dst_mode, dst_reg, word_mode).addr.value()); + setPC(getGAMAddress(dst_mode, dst_reg, wm_word).addr.value()); return true; } @@ -1569,14 +1571,14 @@ bool cpu::misc_operations(const uint16_t instr) // PUSH link pushStack(getRegister(link_reg)); + b->addToMMR1(-2, 6); + // MOVE PC,link setRegister(link_reg, getPC()); // JMP dst setPC(dst_value); - b->addToMMR1(-2, 6); - return true; } @@ -1625,15 +1627,15 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt) } } else { - bool mmr1_locked = b->getMMR0() & 0160000; - before_psw = getPSW(); - if (!mmr1_locked) - b->addToMMR1(-2, 6); + + b->addToMMR1(-2, 6); before_pc = getPC(); - if (!mmr1_locked) - b->addToMMR1(-2, 6); + + b->addToMMR1(-2, 6); + + // TODO set MMR2? } // make sure the trap vector is retrieved from kernel space @@ -2163,8 +2165,10 @@ void cpu::step_a() if ((b->getMMR0() & 0160000) == 0) b->clearMMR1(); - if (any_queued_interrupts && check_queued_interrupts()) - return; // documentation + if (any_queued_interrupts && check_queued_interrupts()) { + if ((b->getMMR0() & 0160000) == 0) + b->clearMMR1(); + } } void cpu::step_b() diff --git a/images/KEK-ESP32-VT510.jpg b/images/KEK-ESP32-VT510.jpg new file mode 100644 index 0000000..6fe6846 Binary files /dev/null and b/images/KEK-ESP32-VT510.jpg differ diff --git a/images/KEK-linux-frame.jpg b/images/KEK-linux-frame.jpg new file mode 100644 index 0000000..e9cacd8 Binary files /dev/null and b/images/KEK-linux-frame.jpg differ diff --git a/images/KEK-linux.mp4 b/images/KEK-linux.mp4 new file mode 100644 index 0000000..75cb18e Binary files /dev/null and b/images/KEK-linux.mp4 differ diff --git a/images/KEK-sha2017badge.jpg b/images/KEK-sha2017badge.jpg new file mode 100644 index 0000000..417a5f5 Binary files /dev/null and b/images/KEK-sha2017badge.jpg differ diff --git a/tty.cpp b/tty.cpp index b31b2db..b38a920 100644 --- a/tty.cpp +++ b/tty.cpp @@ -45,6 +45,14 @@ uint8_t tty::readByte(const uint16_t addr) return v; } +void tty::notify_rx() +{ + registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] |= 128; + + if (registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] & 64) + b->getCpu()->queue_interrupt(4, 060); +} + uint16_t tty::readWord(const uint16_t addr) { const int reg = (addr - PDP11TTY_BASE) / 2; @@ -69,12 +77,8 @@ uint16_t tty::readWord(const uint16_t addr) vtemp = ch | (parity(ch) << 7); - if (chars.empty() == false) { - registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] |= 128; - - if (registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] & 64) - b->getCpu()->queue_interrupt(4, 060); - } + if (chars.empty() == false) + notify_rx(); } } else if (addr == PDP11TTY_TPS) { @@ -96,10 +100,7 @@ void tty::operator()() chars.push_back(c->get_char()); - registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] |= 128; - - if (registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] & 64) - b->getCpu()->queue_interrupt(4, 060); + notify_rx(); } else { myusleep(100000); diff --git a/tty.h b/tty.h index 2491bc5..b5792a3 100644 --- a/tty.h +++ b/tty.h @@ -35,6 +35,8 @@ private: std::thread *th { nullptr }; std::atomic_bool stop_flag { false }; + void notify_rx(); + public: tty(console *const c, bus *const b); virtual ~tty();