panel
This commit is contained in:
parent
73027de4d2
commit
73a1add2f1
5 changed files with 106 additions and 9 deletions
|
@ -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 };
|
||||||
|
|
|
@ -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) :
|
||||||
|
@ -14,32 +16,51 @@ 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <mutex>
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
@ -7,8 +8,17 @@
|
||||||
class console_ncurses : public console
|
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;
|
||||||
|
|
23
utils.cpp
23
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
|
// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
2
utils.h
2
utils.h
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue