Merge branch 'master' into memory-management
This commit is contained in:
commit
ab0c9f1a62
17 changed files with 354 additions and 302 deletions
|
@ -8,6 +8,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|||
add_executable(
|
||||
kek
|
||||
bus.cpp
|
||||
console.cpp
|
||||
console_ncurses.cpp
|
||||
console_posix.cpp
|
||||
cpu.cpp
|
||||
error.cpp
|
||||
main.cpp
|
||||
|
|
1
ESP32/console.cpp
Symbolic link
1
ESP32/console.cpp
Symbolic link
|
@ -0,0 +1 @@
|
|||
../console.cpp
|
1
ESP32/console.h
Symbolic link
1
ESP32/console.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../console.h
|
36
ESP32/console_esp32.cpp
Normal file
36
ESP32/console_esp32.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "console_esp32.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
console_esp32::console_esp32(std::atomic_bool *const terminate) : console(terminate)
|
||||
{
|
||||
}
|
||||
|
||||
console_esp32::~console_esp32()
|
||||
{
|
||||
}
|
||||
|
||||
int console_esp32::wait_for_char(const int timeout)
|
||||
{
|
||||
for(int i=0; i<timeout / 10; i++) {
|
||||
if (Serial.available())
|
||||
return Serial.read();
|
||||
|
||||
delay(10);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void console_esp32::put_char(const char c)
|
||||
{
|
||||
Serial.print(c);
|
||||
}
|
||||
|
||||
void console_esp32::resize_terminal()
|
||||
{
|
||||
}
|
18
ESP32/console_esp32.h
Normal file
18
ESP32/console_esp32.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
#include "console.h"
|
||||
|
||||
|
||||
class console_esp32 : public console
|
||||
{
|
||||
protected:
|
||||
int wait_for_char(const int timeout) override;
|
||||
|
||||
public:
|
||||
console_esp32(std::atomic_bool *const terminate);
|
||||
virtual ~console_esp32();
|
||||
|
||||
void put_char(const char c) override;
|
||||
|
||||
void resize_terminal() override;
|
||||
};
|
177
ESP32/main.ino
177
ESP32/main.ino
|
@ -10,6 +10,7 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "console_esp32.h"
|
||||
#include "cpu.h"
|
||||
#include "error.h"
|
||||
#include "esp32.h"
|
||||
|
@ -20,9 +21,10 @@
|
|||
|
||||
#define NEOPIXELS_PIN 25
|
||||
|
||||
bus *b = nullptr;
|
||||
cpu *c = nullptr;
|
||||
tty *tty_ = nullptr;
|
||||
bus *b = nullptr;
|
||||
cpu *c = nullptr;
|
||||
tty *tty_ = nullptr;
|
||||
console *cnsl = nullptr;
|
||||
|
||||
uint32_t event = 0;
|
||||
|
||||
|
@ -30,11 +32,12 @@ uint16_t exec_addr = 0;
|
|||
|
||||
uint32_t start_ts = 0;
|
||||
|
||||
std::atomic_bool running { false };
|
||||
std::atomic_bool on_wifi { false };
|
||||
std::atomic_bool console_telnet_clients { false };
|
||||
std::atomic_bool disk_read_activity { false };
|
||||
std::atomic_bool disk_write_activity { false };
|
||||
std::atomic_bool terminate { false };
|
||||
|
||||
std::atomic_bool running { false };
|
||||
std::atomic_bool on_wifi { false };
|
||||
std::atomic_bool disk_read_activity { false };
|
||||
std::atomic_bool disk_write_activity { false };
|
||||
|
||||
void setBootLoader(bus *const b) {
|
||||
cpu *const c = b->getCpu();
|
||||
|
@ -134,145 +137,9 @@ void panel(void *p) {
|
|||
}
|
||||
}
|
||||
|
||||
SemaphoreHandle_t terminal_mutex = xSemaphoreCreateMutex();
|
||||
|
||||
constexpr int terminal_columns = 80;
|
||||
constexpr int terminal_rows = 25;
|
||||
char terminal[terminal_columns * terminal_rows];
|
||||
uint8_t tx = 0, ty = terminal_rows - 1;
|
||||
QueueHandle_t to_telnet_queue = xQueueCreate(10, sizeof(char));
|
||||
|
||||
void delete_first_line() {
|
||||
memmove(&terminal[0], &terminal[terminal_columns], terminal_columns * (terminal_rows - 1));
|
||||
memset(&terminal[terminal_columns * (terminal_rows - 1)], ' ', terminal_columns);
|
||||
}
|
||||
|
||||
void telnet_terminal(void *p) {
|
||||
bus *const b = reinterpret_cast<bus *>(p);
|
||||
tty *const tty_ = b->getTty();
|
||||
|
||||
Serial.println(F("telnet_terminal task started"));
|
||||
|
||||
if (!tty_)
|
||||
Serial.println(F(" *** NO TTY ***"));
|
||||
|
||||
for(;;) {
|
||||
char cc { 0 };
|
||||
|
||||
xQueueReceive(tty_->getTerminalQueue(), &cc, portMAX_DELAY);
|
||||
|
||||
Serial.print(cc);
|
||||
|
||||
// update terminal buffer
|
||||
xSemaphoreTake(terminal_mutex, portMAX_DELAY);
|
||||
|
||||
if (cc == 13)
|
||||
tx = 0;
|
||||
else if (cc == 10)
|
||||
ty++;
|
||||
else {
|
||||
terminal[ty * terminal_columns + tx] = cc;
|
||||
|
||||
tx++;
|
||||
|
||||
if (tx == terminal_columns)
|
||||
tx = 0, ty++;
|
||||
}
|
||||
|
||||
if (ty == terminal_rows) {
|
||||
delete_first_line();
|
||||
ty--;
|
||||
}
|
||||
|
||||
xSemaphoreGive(terminal_mutex);
|
||||
|
||||
// pass through to telnet clients
|
||||
if (xQueueSend(to_telnet_queue, &cc, portMAX_DELAY) != pdTRUE)
|
||||
Serial.println(F("queue TTY character failed"));
|
||||
}
|
||||
}
|
||||
|
||||
void wifi(void *p) {
|
||||
Serial.println(F("wifi task started"));
|
||||
|
||||
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
struct sockaddr_in server { 0 };
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = htons(23);
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&server, sizeof(server)) == -1)
|
||||
Serial.println(F("bind failed"));
|
||||
|
||||
if (listen(fd, 3) == -1)
|
||||
Serial.println(F("listen failed"));
|
||||
|
||||
struct pollfd fds[] = { { fd, POLLIN, 0 } };
|
||||
|
||||
std::vector<int> clients;
|
||||
|
||||
for(;;) {
|
||||
on_wifi = WiFi.status() == WL_CONNECTED;
|
||||
|
||||
int rc = poll(fds, 1, 10);
|
||||
|
||||
if (rc == 1) {
|
||||
int client = accept(fd, nullptr, nullptr);
|
||||
if (client != -1) {
|
||||
clients.push_back(client);
|
||||
|
||||
constexpr const uint8_t dont_auth[] = { 0xff, 0xf4, 0x25, // don't auth
|
||||
0xff, 0xfb, 0x03, // suppress goahead
|
||||
0xff, 0xfe, 0x22, // don't line-mode
|
||||
0xff, 0xfe, 0x27, // don't new envt0
|
||||
0xff, 0xfb, 0x01, // will echo
|
||||
0xff, 0xfe, 0x01, // don't echo
|
||||
0xff, 0xfd, 0x2d }; // no echo
|
||||
|
||||
write(client, dont_auth, sizeof(dont_auth));
|
||||
|
||||
// send initial terminal stat
|
||||
write(client, "\033[2J", 4);
|
||||
|
||||
xSemaphoreTake(terminal_mutex, portMAX_DELAY);
|
||||
|
||||
for(int y=0; y<terminal_rows; y++) {
|
||||
std::string out = format("\033[%dH", y + 1);
|
||||
if (write(client, out.c_str(), out.size()) != out.size())
|
||||
break;
|
||||
|
||||
if (write(client, &terminal[y * terminal_columns], terminal_columns) != terminal_columns)
|
||||
break;
|
||||
}
|
||||
|
||||
xSemaphoreGive(terminal_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
console_telnet_clients = clients.empty() == false;
|
||||
|
||||
std::string out;
|
||||
char c { 0 };
|
||||
while (xQueueReceive(to_telnet_queue, &c, 10 / portMAX_DELAY) == pdTRUE)
|
||||
out += c;
|
||||
|
||||
if (!out.empty()) {
|
||||
for(size_t i=0; i<clients.size();) {
|
||||
if (write(clients.at(i), out.c_str(), out.size()) == -1) {
|
||||
close(clients.at(i));
|
||||
clients.erase(clients.begin() + i);
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup_wifi_stations()
|
||||
{
|
||||
#if 0
|
||||
WiFi.mode(WIFI_STA);
|
||||
|
||||
WiFi.softAP("PDP-11 KEK", nullptr, 5, 0, 4);
|
||||
|
@ -317,6 +184,7 @@ void setup_wifi_stations()
|
|||
on_wifi = true;
|
||||
|
||||
Serial.println(WiFi.localIP());
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup() {
|
||||
|
@ -346,8 +214,11 @@ void setup() {
|
|||
|
||||
c->setEmulateMFPT(true);
|
||||
|
||||
Serial.println(F("Init console"));
|
||||
cnsl = new console_esp32(&terminate);
|
||||
|
||||
Serial.println(F("Init TTY"));
|
||||
tty_ = new tty(poll_char, get_char, put_char);
|
||||
tty_ = new tty(cnsl);
|
||||
Serial.println(F("Connect TTY to bus"));
|
||||
b->add_tty(tty_);
|
||||
|
||||
|
@ -356,12 +227,7 @@ void setup() {
|
|||
Serial.println(F(")"));
|
||||
xTaskCreatePinnedToCore(&panel, "panel", 2048, b, 1, nullptr, 0);
|
||||
|
||||
memset(terminal, ' ', sizeof(terminal));
|
||||
xTaskCreatePinnedToCore(&telnet_terminal, "telnet", 2048, b, 7, nullptr, 0);
|
||||
|
||||
xTaskCreatePinnedToCore(&wifi, "wifi", 2048, b, 7, nullptr, 0);
|
||||
|
||||
setup_wifi_stations();
|
||||
// setup_wifi_stations();
|
||||
|
||||
Serial.println(F("Load RK05"));
|
||||
b->add_rk05(new rk05("", b, &disk_read_activity, &disk_write_activity));
|
||||
|
@ -448,7 +314,7 @@ void loop() {
|
|||
|
||||
c->step();
|
||||
|
||||
if (event) {
|
||||
if (event || terminate) {
|
||||
running = false;
|
||||
|
||||
Serial.println(F(""));
|
||||
|
@ -463,6 +329,9 @@ void loop() {
|
|||
start_ts = millis();
|
||||
icount = 0;
|
||||
|
||||
running = true;
|
||||
terminate = false;
|
||||
event = 0;
|
||||
|
||||
running = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,5 +16,5 @@ 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
|
||||
build_flags = -std=c++17 -Ofast -DESP32=1
|
||||
build_unflags = -std=gnu++11 -Os
|
||||
|
|
47
console.cpp
Normal file
47
console.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "console.h"
|
||||
|
||||
|
||||
console::console(std::atomic_bool *const terminate) :
|
||||
terminate(terminate)
|
||||
{
|
||||
th = new std::thread(std::ref(*this));
|
||||
}
|
||||
|
||||
console::~console()
|
||||
{
|
||||
th->join();
|
||||
|
||||
delete th;
|
||||
}
|
||||
|
||||
bool console::poll_char()
|
||||
{
|
||||
return buffer.empty() == false;
|
||||
}
|
||||
|
||||
uint8_t console::get_char()
|
||||
{
|
||||
if (buffer.empty())
|
||||
return 0x00;
|
||||
|
||||
char c = buffer.at(0);
|
||||
|
||||
buffer.erase(buffer.begin() + 0);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void console::operator()()
|
||||
{
|
||||
while(!*terminate) {
|
||||
int c = wait_for_char(500);
|
||||
|
||||
if (c == -1)
|
||||
continue;
|
||||
|
||||
if (c == 3)
|
||||
*terminate = true;
|
||||
else
|
||||
buffer.push_back(c);
|
||||
}
|
||||
}
|
33
console.h
Normal file
33
console.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class console
|
||||
{
|
||||
private:
|
||||
std::atomic_bool *const terminate { nullptr };
|
||||
|
||||
std::thread *th { nullptr };
|
||||
|
||||
std::vector<char> buffer;
|
||||
|
||||
protected:
|
||||
virtual int wait_for_char(const int timeout) = 0;
|
||||
|
||||
public:
|
||||
console(std::atomic_bool *const terminate);
|
||||
virtual ~console();
|
||||
|
||||
bool poll_char();
|
||||
|
||||
uint8_t get_char();
|
||||
|
||||
virtual void put_char(const char c) = 0;
|
||||
|
||||
virtual void resize_terminal() = 0;
|
||||
|
||||
void operator()();
|
||||
};
|
69
console_ncurses.cpp
Normal file
69
console_ncurses.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <ncurses.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "console_ncurses.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
console_ncurses::console_ncurses(std::atomic_bool *const terminate) : console(terminate)
|
||||
{
|
||||
init_ncurses(true);
|
||||
|
||||
resize_terminal();
|
||||
}
|
||||
|
||||
console_ncurses::~console_ncurses()
|
||||
{
|
||||
wprintw(w_main->win, "\n\n *** PRESS ENTER TO TERMINATE ***\n");
|
||||
mydoupdate();
|
||||
|
||||
while(getch() != 13) {
|
||||
}
|
||||
|
||||
endwin();
|
||||
}
|
||||
|
||||
int console_ncurses::wait_for_char(const int timeout)
|
||||
{
|
||||
struct pollfd fds[] = { { STDIN_FILENO, POLLIN, timeout } };
|
||||
|
||||
if (poll(fds, 1, 0) == 1 && fds[0].revents)
|
||||
return getch();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void console_ncurses::put_char(const char c)
|
||||
{
|
||||
if (c >= 32 || (c != 12 && c != 27 && c != 13)) {
|
||||
wprintw(w_main->win, "%c", c);
|
||||
|
||||
mydoupdate();
|
||||
}
|
||||
}
|
||||
|
||||
void console_ncurses::resize_terminal()
|
||||
{
|
||||
determine_terminal_size();
|
||||
|
||||
if (ERR == resizeterm(max_y, max_x))
|
||||
error_exit(true, "problem resizing terminal");
|
||||
|
||||
wresize(stdscr, max_y, max_x);
|
||||
|
||||
endwin();
|
||||
refresh();
|
||||
|
||||
wclear(stdscr);
|
||||
|
||||
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);
|
||||
|
||||
scrollok(w_main -> win, TRUE);
|
||||
|
||||
mydoupdate();
|
||||
}
|
23
console_ncurses.h
Normal file
23
console_ncurses.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <ncurses.h>
|
||||
|
||||
#include "console.h"
|
||||
#include "terminal.h"
|
||||
|
||||
|
||||
class console_ncurses : public console
|
||||
{
|
||||
private:
|
||||
NEWWIN *w_main_b { nullptr };
|
||||
NEWWIN *w_main { nullptr };
|
||||
|
||||
protected:
|
||||
int wait_for_char(const int timeout) override;
|
||||
|
||||
public:
|
||||
console_ncurses(std::atomic_bool *const terminate);
|
||||
virtual ~console_ncurses();
|
||||
|
||||
void put_char(const char c) override;
|
||||
|
||||
void resize_terminal() override;
|
||||
};
|
47
console_posix.cpp
Normal file
47
console_posix.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "console_posix.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
console_posix::console_posix(std::atomic_bool *const terminate) : console(terminate)
|
||||
{
|
||||
if (tcgetattr(STDIN_FILENO, &org_tty_opts) == -1)
|
||||
error_exit(true, "console_posix: tcgetattr failed");
|
||||
|
||||
struct termios tty_opts_raw { 0 };
|
||||
cfmakeraw(&tty_opts_raw);
|
||||
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw) == -1)
|
||||
error_exit(true, "console_posix: tcsetattr failed");
|
||||
}
|
||||
|
||||
console_posix::~console_posix()
|
||||
{
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &org_tty_opts) == -1)
|
||||
error_exit(true, "~console_posix: tcsetattr failed");
|
||||
}
|
||||
|
||||
int console_posix::wait_for_char(const int timeout)
|
||||
{
|
||||
struct pollfd fds[] = { { STDIN_FILENO, POLLIN, timeout } };
|
||||
|
||||
if (poll(fds, 1, 0) == 1 && fds[0].revents)
|
||||
return getchar();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void console_posix::put_char(const char c)
|
||||
{
|
||||
printf("%c", c);
|
||||
|
||||
fflush(nullptr);
|
||||
}
|
||||
|
||||
void console_posix::resize_terminal()
|
||||
{
|
||||
}
|
21
console_posix.h
Normal file
21
console_posix.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include <termios.h>
|
||||
|
||||
#include "console.h"
|
||||
|
||||
|
||||
class console_posix : public console
|
||||
{
|
||||
private:
|
||||
struct termios org_tty_opts { 0 };
|
||||
|
||||
protected:
|
||||
int wait_for_char(const int timeout) override;
|
||||
|
||||
public:
|
||||
console_posix(std::atomic_bool *const terminate);
|
||||
virtual ~console_posix();
|
||||
|
||||
void put_char(const char c) override;
|
||||
|
||||
void resize_terminal() override;
|
||||
};
|
2
cpu.cpp
2
cpu.cpp
|
@ -878,7 +878,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
|
|||
setPSW_z(v == 0);
|
||||
setPSW_v(false);
|
||||
|
||||
fprintf(stderr, "MTP%c: address %06o, value %06o\n", word_mode ? 'D' : 'I', a, v);
|
||||
D(fprintf(stderr, "MTP%c: address %06o, value %06o\n", word_mode ? 'D' : 'I', a, v);)
|
||||
|
||||
if (dst_mode == 0)
|
||||
putGAM(dst_mode, dst_reg, false, v, false); // ???
|
||||
|
|
121
main.cpp
121
main.cpp
|
@ -1,14 +1,14 @@
|
|||
// (C) 2018-2022 by Folkert van Heusden
|
||||
// Released under Apache License v2.0
|
||||
#include <atomic>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "console_ncurses.h"
|
||||
#include "console_posix.h"
|
||||
#include "cpu.h"
|
||||
#include "tty.h"
|
||||
#include "utils.h"
|
||||
|
@ -16,20 +16,11 @@
|
|||
#include "terminal.h"
|
||||
#include "error.h"
|
||||
|
||||
struct termios org_tty_opts { 0 };
|
||||
bool withUI { false };
|
||||
uint32_t event { 0 };
|
||||
std::atomic_bool terminate { false };
|
||||
|
||||
|
||||
void reset_terminal()
|
||||
{
|
||||
if (withUI)
|
||||
endwin();
|
||||
else
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &org_tty_opts);
|
||||
}
|
||||
|
||||
void loadbin(bus *const b, uint16_t base, const char *const file)
|
||||
{
|
||||
FILE *fh = fopen(file, "rb");
|
||||
|
@ -133,30 +124,6 @@ uint16_t loadTape(bus *const b, const char *const file)
|
|||
return start;
|
||||
}
|
||||
|
||||
NEWWIN *w_main_b = nullptr, *w_main = nullptr;
|
||||
|
||||
void resize_terminal()
|
||||
{
|
||||
determine_terminal_size();
|
||||
|
||||
if (ERR == resizeterm(max_y, max_x))
|
||||
error_exit(true, "problem resizing terminal");
|
||||
|
||||
wresize(stdscr, max_y, max_x);
|
||||
|
||||
endwin();
|
||||
refresh();
|
||||
|
||||
wclear(stdscr);
|
||||
|
||||
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);
|
||||
scrollok(w_main -> win, TRUE);
|
||||
|
||||
mydoupdate();
|
||||
}
|
||||
|
||||
volatile bool sw = false;
|
||||
void sw_handler(int s)
|
||||
{
|
||||
|
@ -169,47 +136,6 @@ void sw_handler(int s)
|
|||
}
|
||||
}
|
||||
|
||||
bool poll_char()
|
||||
{
|
||||
struct pollfd fds[] = { { STDIN_FILENO, POLLIN, 0 } };
|
||||
|
||||
return poll(fds, 1, 0) == 1 && fds[0].revents;
|
||||
}
|
||||
|
||||
char get_char()
|
||||
{
|
||||
char c = getchar();
|
||||
|
||||
if (c == 3)
|
||||
event = 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
char get_char_ui()
|
||||
{
|
||||
char c = getch();
|
||||
|
||||
if (c == 3)
|
||||
event = 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void put_char(char c)
|
||||
{
|
||||
printf("%c", c);
|
||||
fflush(nullptr);
|
||||
}
|
||||
|
||||
void put_char_ui(char c)
|
||||
{
|
||||
if (c >= 32 || (c != 12 && c != 27 && c != 13)) {
|
||||
wprintw(w_main -> win, "%c", c);
|
||||
mydoupdate();
|
||||
}
|
||||
}
|
||||
|
||||
void help()
|
||||
{
|
||||
printf("-h this help\n");
|
||||
|
@ -285,13 +211,15 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
tty *tty_ = nullptr;
|
||||
|
||||
console *cnsl = nullptr;
|
||||
|
||||
if (withUI)
|
||||
tty_ = new tty(poll_char, get_char_ui, put_char_ui);
|
||||
cnsl = new console_ncurses(&terminate);
|
||||
else
|
||||
tty_ = new tty(poll_char, get_char, put_char);
|
||||
cnsl = new console_posix(&terminate);
|
||||
|
||||
tty *tty_ = new tty(cnsl);
|
||||
|
||||
b->add_tty(tty_);
|
||||
|
||||
|
@ -306,25 +234,11 @@ int main(int argc, char *argv[])
|
|||
sa.sa_flags = SA_RESTART;
|
||||
|
||||
if (withUI) {
|
||||
init_ncurses(true);
|
||||
|
||||
sigaction(SIGWINCH, &sa, nullptr);
|
||||
|
||||
resize_terminal();
|
||||
}
|
||||
|
||||
sigaction(SIGTERM , &sa, nullptr);
|
||||
sigaction(SIGINT , &sa, nullptr);
|
||||
|
||||
atexit(reset_terminal);
|
||||
|
||||
tcgetattr(STDIN_FILENO, &org_tty_opts);
|
||||
|
||||
struct termios tty_opts_raw { 0 };
|
||||
cfmakeraw(&tty_opts_raw);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw);
|
||||
|
||||
struct pollfd fds[] = { { STDIN_FILENO, POLLIN, 0 } };
|
||||
sigaction(SIGTERM, &sa, nullptr);
|
||||
sigaction(SIGINT , &sa, nullptr);
|
||||
|
||||
uint32_t icount = 0;
|
||||
uint64_t total_icount = 0;
|
||||
|
@ -376,11 +290,11 @@ int main(int argc, char *argv[])
|
|||
|
||||
fprintf(stderr, "instructions_executed: %u, took_ms: %lu, new refresh_interval: %u\n", icount, took_ms, refresh_interval);
|
||||
|
||||
if (withUI) {
|
||||
mvwprintw(w_main_b -> win, 0, 24, "%.1f/s ", icount * 1000.0 / took_ms);
|
||||
mvwprintw(w_main_b -> win, 0, 42, "%06o", b->get_switch_register());
|
||||
mydoupdate();
|
||||
}
|
||||
// if (withUI) {
|
||||
// mvwprintw(w_main_b -> win, 0, 24, "%.1f/s ", icount * 1000.0 / took_ms);
|
||||
// mvwprintw(w_main_b -> win, 0, 42, "%06o", b->get_switch_register());
|
||||
// mydoupdate();
|
||||
// }
|
||||
|
||||
if (terminate)
|
||||
event = 1;
|
||||
|
@ -390,8 +304,9 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if (withUI)
|
||||
endwin();
|
||||
terminate = true;
|
||||
|
||||
delete cnsl;
|
||||
|
||||
fprintf(stderr, "Instructions per second: %.3f\n\n", icount * 1000.0 / (get_ms() - start));
|
||||
|
||||
|
|
37
tty.cpp
37
tty.cpp
|
@ -1,11 +1,6 @@
|
|||
// (C) 2018 by Folkert van Heusden
|
||||
// // Released under Apache License v2.0
|
||||
#include <errno.h>
|
||||
#if defined(ESP32)
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -14,10 +9,6 @@
|
|||
#include "memory.h"
|
||||
#include "utils.h"
|
||||
|
||||
#if !defined(ESP32)
|
||||
#include "terminal.h"
|
||||
extern NEWWIN *w_main;
|
||||
#endif
|
||||
|
||||
const char * const regnames[] = {
|
||||
"reader status ",
|
||||
|
@ -26,17 +17,8 @@ const char * const regnames[] = {
|
|||
"puncher buffer"
|
||||
};
|
||||
|
||||
tty::tty(std::function<bool()> poll_char, std::function<uint8_t()> get_char, std::function<void(char c)> put_char) :
|
||||
poll_char(poll_char),
|
||||
get_char(get_char),
|
||||
put_char(put_char)
|
||||
tty::tty(console *const c) : c(c)
|
||||
{
|
||||
#if defined(ESP32)
|
||||
queue = xQueueCreate(10, sizeof(char));
|
||||
|
||||
if (queue == nullptr)
|
||||
Serial.println(F("Problem creating TTY queue"));
|
||||
#endif
|
||||
}
|
||||
|
||||
tty::~tty()
|
||||
|
@ -63,7 +45,7 @@ uint16_t tty::readWord(const uint16_t addr)
|
|||
have_char_2 = true;
|
||||
}
|
||||
else if (have_char_2 == false) {
|
||||
have_char_1 = poll_char();
|
||||
have_char_1 = c->poll_char();
|
||||
}
|
||||
|
||||
if (addr == PDP11TTY_TKS) {
|
||||
|
@ -71,9 +53,9 @@ uint16_t tty::readWord(const uint16_t addr)
|
|||
}
|
||||
else if (addr == PDP11TTY_TKB) {
|
||||
if (have_char_2) {
|
||||
uint8_t c = get_char();
|
||||
uint8_t ch = c->get_char();
|
||||
|
||||
vtemp = c | (parity(c) << 7);
|
||||
vtemp = ch | (parity(ch) << 7);
|
||||
|
||||
have_char_2 = false;
|
||||
}
|
||||
|
@ -115,16 +97,11 @@ void tty::writeWord(const uint16_t addr, uint16_t v)
|
|||
D(fprintf(stderr, "PDP11TTY write %o (%s): %o\n", addr, regnames[reg], v);)
|
||||
|
||||
if (addr == PDP11TTY_TPB) {
|
||||
char c = v & 127;
|
||||
char ch = v & 127;
|
||||
|
||||
D(fprintf(stderr, "PDP11TTY print '%c'\n", c);)
|
||||
D(fprintf(stderr, "PDP11TTY print '%c'\n", ch);)
|
||||
|
||||
#if defined(ESP32)
|
||||
if (xQueueSend(queue, &c, portMAX_DELAY) != pdTRUE)
|
||||
Serial.println(F("queue TTY character failed"));
|
||||
#else
|
||||
put_char(c);
|
||||
#endif
|
||||
c->put_char(ch);
|
||||
}
|
||||
|
||||
D(fprintf(stderr, "set register %o to %o\n", addr, v);)
|
||||
|
|
18
tty.h
18
tty.h
|
@ -2,11 +2,13 @@
|
|||
// Released under Apache License v2.0
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "console.h"
|
||||
|
||||
|
||||
#define PDP11TTY_TKS 0177560 // reader status
|
||||
#define PDP11TTY_TKB 0177562 // reader buffer
|
||||
#define PDP11TTY_TPS 0177564 // puncher status
|
||||
|
@ -19,26 +21,16 @@ class memory;
|
|||
class tty
|
||||
{
|
||||
private:
|
||||
std::function<bool()> poll_char;
|
||||
std::function<uint8_t()> get_char;
|
||||
std::function<void(char c)> put_char;
|
||||
console *const c { nullptr };
|
||||
bool have_char_1 { false }; // RCVR BUSY bit high (11)
|
||||
bool have_char_2 { false }; // RCVR DONE bit high (7)
|
||||
uint16_t registers[4] { 0 };
|
||||
bool withUI { false };
|
||||
|
||||
#if defined(ESP32)
|
||||
QueueHandle_t queue { nullptr };
|
||||
#endif
|
||||
|
||||
public:
|
||||
tty(std::function<bool()> poll_char, std::function<uint8_t()> get_char, std::function<void(char c)> put_char);
|
||||
tty(console *const c);
|
||||
virtual ~tty();
|
||||
|
||||
#if defined(ESP32)
|
||||
QueueHandle_t & getTerminalQueue() { return queue; }
|
||||
#endif
|
||||
|
||||
uint8_t readByte(const uint16_t addr);
|
||||
uint16_t readWord(const uint16_t addr);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue