From 73a1add2f13ddb2fa4be777f7025b6c4e5dc7c9c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 25 Mar 2022 21:19:33 +0100 Subject: [PATCH] panel --- console.h | 4 +-- console_ncurses.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++--- console_ncurses.h | 14 +++++++-- utils.cpp | 23 ++++++++++++++- utils.h | 2 ++ 5 files changed, 106 insertions(+), 9 deletions(-) diff --git a/console.h b/console.h index d6baf90..38210ff 100644 --- a/console.h +++ b/console.h @@ -13,8 +13,6 @@ constexpr const int t_height { 25 }; class console { private: - std::atomic_bool *const terminate { nullptr }; - std::vector input_buffer; char screen_buffer[t_height][t_width]; @@ -22,6 +20,8 @@ private: uint8_t ty { 0 }; protected: + std::atomic_bool *const terminate { nullptr }; + bus *const b { nullptr }; std::thread *th { nullptr }; std::atomic_bool disk_read_activity_flag { false }; diff --git a/console_ncurses.cpp b/console_ncurses.cpp index 924eb92..970a011 100644 --- a/console_ncurses.cpp +++ b/console_ncurses.cpp @@ -4,7 +4,9 @@ #include #include "console_ncurses.h" +#include "cpu.h" #include "error.h" +#include "utils.h" console_ncurses::console_ncurses(std::atomic_bool *const terminate, bus *const b) : @@ -14,32 +16,51 @@ console_ncurses::console_ncurses(std::atomic_bool *const terminate, bus *const b resize_terminal(); - th = new std::thread(std::ref(*this)); + th = new std::thread(std::ref(*this)); + + th_panel = new std::thread(&console_ncurses::panel_update_thread, this); } console_ncurses::~console_ncurses() { + if (th_panel) { + th_panel->join(); + + delete th_panel; + } + if (th) { th->join(); delete th; } + std::unique_lock lck(ncurses_mutex); + wprintw(w_main->win, "\n\n *** PRESS ENTER TO TERMINATE ***\n"); mydoupdate(); while(getch() != 13) { } + delete_window(w_panel_b); + delete_window(w_panel); + + delete_window(w_main_b); + delete_window(w_main); + endwin(); } int console_ncurses::wait_for_char(const int timeout) { - struct pollfd fds[] = { { STDIN_FILENO, POLLIN, timeout } }; + struct pollfd fds[] = { { STDIN_FILENO, POLLIN, 0 } }; + + if (poll(fds, 1, timeout) == 1 && fds[0].revents) { + std::unique_lock lck(ncurses_mutex); - if (poll(fds, 1, 0) == 1 && fds[0].revents) return getch(); + } return -1; } @@ -47,14 +68,20 @@ int console_ncurses::wait_for_char(const int timeout) void console_ncurses::put_char_ll(const char c) { if (c >= 32 || (c != 12 && c != 27 && c != 13)) { + std::unique_lock lck(ncurses_mutex); + wprintw(w_main->win, "%c", c); + getyx(w_main->win, ty, tx); + mydoupdate(); } } void console_ncurses::resize_terminal() { + std::unique_lock lck(ncurses_mutex); + determine_terminal_size(); if (ERR == resizeterm(max_y, max_x)) @@ -70,7 +97,9 @@ void console_ncurses::resize_terminal() delete_window(w_main_b); delete_window(w_main); - create_win_border(0, 0, max_x - 2, max_y - 2, "window", &w_main_b, &w_main, false); + create_win_border(0, 0, max_x - 2, max_y - 6, "window", &w_main_b, &w_main, false); + + create_win_border(0, max_y - 4, max_x - 2, 2, "panel", &w_panel_b, &w_panel, false); scrollok(w_main -> win, TRUE); @@ -79,4 +108,39 @@ void console_ncurses::resize_terminal() void console_ncurses::panel_update_thread() { + cpu *const c = b->getCpu(); + + while(!*terminate) { + myusleep(1000000 / 50); // 50 updates/sec + + // note that these are approximately as there's no mutex on the emulation + uint16_t current_PC = c->getPC(); + uint32_t full_addr = b->calculate_full_address(current_PC); + + uint16_t current_instr = b->readWord(current_PC); + + uint16_t current_PSW = c->getPSW(); + + //uint32_t led_color = run_mode_led_color[current_PSW >> 14]; + + std::unique_lock lck(ncurses_mutex); + + for(uint8_t b=0; b<22; b++) + mvwprintw(w_panel->win, 0, 1 + 22 - b, "%c", full_addr & (1 << b) ? '1' : '0'); + + for(uint8_t b=0; b<16; b++) + mvwprintw(w_panel->win, 1, 1 + 16 - b, "%c", current_PSW & (1 << b) ? '1' : '0'); + + for(uint8_t b=0; b<16; b++) + mvwprintw(w_panel->win, 1, 1 + 16 - b + 17, "%c", current_instr & (1 << b) ? '1' : '0'); + + mvwprintw(w_panel->win, 1, 1 + 35, "%c%c%c", + running_flag ? '+' : '-', + disk_read_activity_flag ? '*' : 'o', + disk_write_activity_flag ? '*' : 'o'); + + wmove(w_main->win, ty, tx); + + mydoupdate(); + } } diff --git a/console_ncurses.h b/console_ncurses.h index ffd6ff3..1d41059 100644 --- a/console_ncurses.h +++ b/console_ncurses.h @@ -1,3 +1,4 @@ +#include #include #include "console.h" @@ -7,8 +8,17 @@ class console_ncurses : public console { private: - NEWWIN *w_main_b { nullptr }; - NEWWIN *w_main { nullptr }; + NEWWIN *w_main_b { nullptr }; + NEWWIN *w_main { nullptr }; + NEWWIN *w_panel_b { nullptr }; + NEWWIN *w_panel { nullptr }; + + std::mutex ncurses_mutex; + + std::thread *th_panel { nullptr }; + + int tx { 0 }; + int ty { 0 }; protected: int wait_for_char(const int timeout) override; diff --git a/utils.cpp b/utils.cpp index 8aa0edc..3c28616 100644 --- a/utils.cpp +++ b/utils.cpp @@ -1,11 +1,13 @@ -// (C) 2018 by Folkert van Heusden +// (C) 2018-2022 by Folkert van Heusden // Released under Apache License v2.0 #if defined(ESP32) #include #endif +#include #include #include #include +#include #include void setBit(uint16_t & v, const int bit, const bool vb) @@ -50,3 +52,22 @@ int parity(int v) { return __builtin_parity(v); // FIXME } + +void myusleep(uint64_t us) +{ + struct timespec req; + + req.tv_sec = us / 1000000l; + req.tv_nsec = (us % 1000000l) * 1000l; + + for(;;) { + struct timespec rem { 0, 0 }; + + int rc = nanosleep(&req, &rem); + if (rc == 0 || (rc == -1 && errno != EINTR)) + break; + + memcpy(&req, &rem, sizeof(struct timespec)); + } +} + diff --git a/utils.h b/utils.h index 8d3652b..e87cae0 100644 --- a/utils.h +++ b/utils.h @@ -9,4 +9,6 @@ int parity(int v); #define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) ) std::string format(const char *const fmt, ...); + unsigned long get_ms(); +void myusleep(uint64_t us);