This commit is contained in:
folkert van heusden 2022-03-25 21:19:33 +01:00
parent 73027de4d2
commit 73a1add2f1
5 changed files with 106 additions and 9 deletions

View file

@ -13,8 +13,6 @@ constexpr const int t_height { 25 };
class console class console
{ {
private: private:
std::atomic_bool *const terminate { nullptr };
std::vector<char> input_buffer; std::vector<char> input_buffer;
char screen_buffer[t_height][t_width]; char screen_buffer[t_height][t_width];
@ -22,6 +20,8 @@ private:
uint8_t ty { 0 }; uint8_t ty { 0 };
protected: protected:
std::atomic_bool *const terminate { nullptr };
bus *const b { nullptr }; bus *const b { nullptr };
std::thread *th { nullptr }; std::thread *th { nullptr };
std::atomic_bool disk_read_activity_flag { false }; std::atomic_bool disk_read_activity_flag { false };

View file

@ -4,7 +4,9 @@
#include <unistd.h> #include <unistd.h>
#include "console_ncurses.h" #include "console_ncurses.h"
#include "cpu.h"
#include "error.h" #include "error.h"
#include "utils.h"
console_ncurses::console_ncurses(std::atomic_bool *const terminate, bus *const b) : console_ncurses::console_ncurses(std::atomic_bool *const terminate, bus *const b) :
@ -15,31 +17,50 @@ console_ncurses::console_ncurses(std::atomic_bool *const terminate, bus *const b
resize_terminal(); 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() console_ncurses::~console_ncurses()
{ {
if (th_panel) {
th_panel->join();
delete th_panel;
}
if (th) { if (th) {
th->join(); th->join();
delete th; delete th;
} }
std::unique_lock<std::mutex> lck(ncurses_mutex);
wprintw(w_main->win, "\n\n *** PRESS ENTER TO TERMINATE ***\n"); wprintw(w_main->win, "\n\n *** PRESS ENTER TO TERMINATE ***\n");
mydoupdate(); mydoupdate();
while(getch() != 13) { while(getch() != 13) {
} }
delete_window(w_panel_b);
delete_window(w_panel);
delete_window(w_main_b);
delete_window(w_main);
endwin(); endwin();
} }
int console_ncurses::wait_for_char(const int timeout) 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<std::mutex> lck(ncurses_mutex);
if (poll(fds, 1, 0) == 1 && fds[0].revents)
return getch(); return getch();
}
return -1; return -1;
} }
@ -47,14 +68,20 @@ int console_ncurses::wait_for_char(const int timeout)
void console_ncurses::put_char_ll(const char c) void console_ncurses::put_char_ll(const char c)
{ {
if (c >= 32 || (c != 12 && c != 27 && c != 13)) { if (c >= 32 || (c != 12 && c != 27 && c != 13)) {
std::unique_lock<std::mutex> lck(ncurses_mutex);
wprintw(w_main->win, "%c", c); wprintw(w_main->win, "%c", c);
getyx(w_main->win, ty, tx);
mydoupdate(); mydoupdate();
} }
} }
void console_ncurses::resize_terminal() void console_ncurses::resize_terminal()
{ {
std::unique_lock<std::mutex> lck(ncurses_mutex);
determine_terminal_size(); determine_terminal_size();
if (ERR == resizeterm(max_y, max_x)) 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_b);
delete_window(w_main); 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); scrollok(w_main -> win, TRUE);
@ -79,4 +108,39 @@ void console_ncurses::resize_terminal()
void console_ncurses::panel_update_thread() 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<std::mutex> 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();
}
} }

View file

@ -1,3 +1,4 @@
#include <mutex>
#include <ncurses.h> #include <ncurses.h>
#include "console.h" #include "console.h"
@ -9,6 +10,15 @@ class console_ncurses : public console
private: private:
NEWWIN *w_main_b { nullptr }; NEWWIN *w_main_b { nullptr };
NEWWIN *w_main { 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: protected:
int wait_for_char(const int timeout) override; int wait_for_char(const int timeout) override;

View file

@ -1,11 +1,13 @@
// (C) 2018 by Folkert van Heusden // (C) 2018-2022 by Folkert van Heusden
// Released under Apache License v2.0 // Released under Apache License v2.0
#if defined(ESP32) #if defined(ESP32)
#include <Arduino.h> #include <Arduino.h>
#endif #endif
#include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <string.h>
#include <sys/time.h> #include <sys/time.h>
void setBit(uint16_t & v, const int bit, const bool vb) void setBit(uint16_t & v, const int bit, const bool vb)
@ -50,3 +52,22 @@ int parity(int v)
{ {
return __builtin_parity(v); // FIXME 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));
}
}

View file

@ -9,4 +9,6 @@ int parity(int v);
#define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) ) #define sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) )
std::string format(const char *const fmt, ...); std::string format(const char *const fmt, ...);
unsigned long get_ms(); unsigned long get_ms();
void myusleep(uint64_t us);