Merge branch 'master' into RP2040
This commit is contained in:
commit
e6b7b3dbab
23 changed files with 317 additions and 108 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "ESP32/SHAdisplay"]
|
||||||
|
path = ESP32/SHAdisplay
|
||||||
|
url = https://github.com/krzychb/esp-epaper-29-dke
|
|
@ -9,6 +9,8 @@ add_compile_options(-Wall -pedantic -Wextra)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
kek
|
kek
|
||||||
bus.cpp
|
bus.cpp
|
||||||
|
@ -34,6 +36,10 @@ add_executable(
|
||||||
utils.cpp
|
utils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
endif (NOT WIN32)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
kek-win32
|
kek-win32
|
||||||
bus.cpp
|
bus.cpp
|
||||||
|
@ -58,6 +64,8 @@ add_executable(
|
||||||
win32.cpp
|
win32.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
endif (WIN32)
|
||||||
|
|
||||||
include(CheckIPOSupported)
|
include(CheckIPOSupported)
|
||||||
check_ipo_supported(RESULT supported)
|
check_ipo_supported(RESULT supported)
|
||||||
|
|
||||||
|
@ -68,10 +76,13 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
|
||||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
|
if (NOT WIN32)
|
||||||
target_link_libraries(kek Threads::Threads)
|
target_link_libraries(kek Threads::Threads)
|
||||||
|
else ()
|
||||||
target_link_libraries(kek-win32 Threads::Threads)
|
target_link_libraries(kek-win32 Threads::Threads)
|
||||||
|
|
||||||
target_link_libraries(kek-win32 ws2_32)
|
target_link_libraries(kek-win32 ws2_32)
|
||||||
|
endif ()
|
||||||
|
|
||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
|
|
||||||
|
|
1
ESP32/SHAdisplay
Submodule
1
ESP32/SHAdisplay
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 18b42491ceecbfdb70e0dac69a379f5787a84a5d
|
|
@ -9,12 +9,13 @@
|
||||||
#include "console_esp32.h"
|
#include "console_esp32.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
#define NEOPIXELS_PIN 25
|
#define NEOPIXELS_PIN 25
|
||||||
|
|
||||||
console_esp32::console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector<Stream *> & io_ports) :
|
console_esp32::console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector<Stream *> & io_ports, const int t_width, const int t_height) :
|
||||||
console(stop_event, b),
|
console(stop_event, b, t_width, t_height),
|
||||||
io_ports(io_ports)
|
io_ports(io_ports)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -104,31 +105,39 @@ void console_esp32::panel_update_thread()
|
||||||
for(;;) {
|
for(;;) {
|
||||||
vTaskDelay(20 / portTICK_RATE_MS);
|
vTaskDelay(20 / portTICK_RATE_MS);
|
||||||
|
|
||||||
// note that these are approximately as there's no mutex on the emulation
|
try {
|
||||||
uint16_t current_PSW = c->getPSW();
|
// note that these are approximately as there's no mutex on the emulation
|
||||||
int run_mode = current_PSW >> 14;
|
uint16_t current_PSW = c->getPSW();
|
||||||
|
int run_mode = current_PSW >> 14;
|
||||||
|
|
||||||
uint16_t current_PC = c->getPC();
|
uint16_t current_PC = c->getPC();
|
||||||
uint32_t full_addr = b->calculate_physical_address(run_mode, current_PC, false, false, true, i_space);
|
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++)
|
for(uint8_t b=0; b<22; b++)
|
||||||
pixels.setPixelColor(b, full_addr & (1 << b) ? led_color : 0);
|
pixels.setPixelColor(b, full_addr & (1 << b) ? led_color : 0);
|
||||||
|
|
||||||
for(uint8_t b=0; b<16; b++)
|
for(uint8_t b=0; b<16; b++)
|
||||||
pixels.setPixelColor(b + 22, current_PSW & (1l << b) ? magenta : 0);
|
pixels.setPixelColor(b + 22, current_PSW & (1l << b) ? magenta : 0);
|
||||||
|
|
||||||
for(uint8_t b=0; b<16; b++)
|
for(uint8_t b=0; b<16; b++)
|
||||||
pixels.setPixelColor(b + 38, current_instr & (1l << b) ? red : 0);
|
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(55, disk_read_activity_flag ? blue : 0);
|
||||||
pixels.setPixelColor(56, disk_write_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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ protected:
|
||||||
void put_char_ll(const char c) override;
|
void put_char_ll(const char c) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector<Stream *> & io_ports);
|
console_esp32(std::atomic_uint32_t *const stop_event, bus *const b, std::vector<Stream *> & io_ports, const int t_width, const int t_height);
|
||||||
virtual ~console_esp32();
|
virtual ~console_esp32();
|
||||||
|
|
||||||
void put_string_lf(const std::string & what) override;
|
void put_string_lf(const std::string & what) override;
|
||||||
|
|
77
ESP32/console_shabadge.cpp
Normal file
77
ESP32/console_shabadge.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// (C) 2023 by Folkert van Heusden
|
||||||
|
// Released under MIT license
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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<Stream *> & 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; y<t_height; y++) {
|
||||||
|
for(int x=0; x<t_width; x++) {
|
||||||
|
char c = screen_buffer[y * t_width + x];
|
||||||
|
|
||||||
|
if (c <= 0)
|
||||||
|
c = ' ';
|
||||||
|
|
||||||
|
paint->DrawCharAt(x * 8, y * 8, c, &Font8, COLORED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
epd.SetFrameMemory(paint->GetImage(), 0, 0, paint->GetWidth(), paint->GetHeight());
|
||||||
|
epd.DisplayFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
ESP32/console_shabadge.h
Normal file
29
ESP32/console_shabadge.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// (C) 2023 by Folkert van Heusden
|
||||||
|
// Released under MIT license
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <epd2in9-badge.h>
|
||||||
|
#include <epdpaint.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#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<Stream *> & io_ports);
|
||||||
|
virtual ~console_shabadge();
|
||||||
|
|
||||||
|
void panel_update_thread() override;
|
||||||
|
};
|
|
@ -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);
|
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);
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
#endif
|
#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)) {
|
if (fh->read(target, n) != size_t(n)) {
|
||||||
DOLOG(debug, true, "fread error: %s", strerror(errno));
|
DOLOG(debug, true, "fread error: %s", strerror(errno));
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32) && !defined(SHA2017)
|
||||||
digitalWrite(LED_BUILTIN, HIGH);
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
@ -57,7 +57,7 @@ bool disk_backend_esp32::read(const off_t offset, const size_t n, uint8_t *const
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32) && !defined(SHA2017)
|
||||||
digitalWrite(LED_BUILTIN, HIGH);
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
#endif
|
#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);
|
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);
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
#endif
|
#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) {
|
if (fh->write(from, n) != n) {
|
||||||
DOLOG(ll_error, true, "RK05 fwrite error %s", strerror(errno));
|
DOLOG(ll_error, true, "RK05 fwrite error %s", strerror(errno));
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32) && !defined(SHA2017)
|
||||||
digitalWrite(LED_BUILTIN, HIGH);
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
@ -88,8 +88,8 @@ bool disk_backend_esp32::write(const off_t offset, const size_t n, const uint8_t
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32) && !defined(SHA2017)
|
||||||
digitalWrite(LED_BUILTIN, HIGH);
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -14,7 +14,11 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if defined(SHA2017)
|
||||||
|
#include "console_shabadge.h"
|
||||||
|
#else
|
||||||
#include "console_esp32.h"
|
#include "console_esp32.h"
|
||||||
|
#endif
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
#include "disk_backend.h"
|
#include "disk_backend.h"
|
||||||
|
@ -188,8 +192,12 @@ std::optional<disk_backend_t> select_disk_backend(console *const c)
|
||||||
c->put_string("1. network (NBD), 2. local SD card, 9. abort");
|
c->put_string("1. network (NBD), 2. local SD card, 9. abort");
|
||||||
|
|
||||||
int ch = -1;
|
int ch = -1;
|
||||||
while(ch == -1 && ch != '1' && ch != '2' && ch != '9')
|
while(ch == -1 && ch != '1' && ch != '2' && ch != '9') {
|
||||||
ch = c->wait_char(500);
|
auto temp = c->wait_char(500);
|
||||||
|
|
||||||
|
if (temp.has_value())
|
||||||
|
ch = temp.value();
|
||||||
|
}
|
||||||
|
|
||||||
c->put_string_lf(format("%c", ch));
|
c->put_string_lf(format("%c", ch));
|
||||||
|
|
||||||
|
@ -208,8 +216,12 @@ std::optional<disk_type_t> select_disk_type(console *const c)
|
||||||
c->put_string("1. RK05, 2. RL02, 9. abort");
|
c->put_string("1. RK05, 2. RL02, 9. abort");
|
||||||
|
|
||||||
int ch = -1;
|
int ch = -1;
|
||||||
while(ch == -1 && ch != '1' && ch != '2' && ch != '9')
|
while(ch == -1 && ch != '1' && ch != '2' && ch != '9') {
|
||||||
ch = c->wait_char(500);
|
auto temp = c->wait_char(500);
|
||||||
|
|
||||||
|
if (temp.has_value())
|
||||||
|
ch = temp.value();
|
||||||
|
}
|
||||||
|
|
||||||
c->put_string_lf(format("%c", ch));
|
c->put_string_lf(format("%c", ch));
|
||||||
|
|
||||||
|
@ -274,8 +286,13 @@ std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *>
|
||||||
|
|
||||||
c->put_string_lf("Files on SD-card:");
|
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)))
|
if (!sd.begin(SS, SD_SCK_MHZ(15)))
|
||||||
sd.initErrorHalt();
|
sd.initErrorHalt();
|
||||||
|
#endif
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
sd.ls("/", LS_DATE | LS_SIZE | LS_R);
|
sd.ls("/", LS_DATE | LS_SIZE | LS_R);
|
||||||
|
@ -340,7 +357,7 @@ void set_disk_configuration(std::pair<std::vector<disk_backend *>, std::vector<d
|
||||||
void configure_disk(console *const c)
|
void configure_disk(console *const c)
|
||||||
{
|
{
|
||||||
for(;;) {
|
for(;;) {
|
||||||
Serial.println(F("Load disk"));
|
c->put_string_lf("Load disk");
|
||||||
|
|
||||||
auto backend = select_disk_backend(cnsl);
|
auto backend = select_disk_backend(cnsl);
|
||||||
|
|
||||||
|
@ -505,7 +522,11 @@ void setup()
|
||||||
Serial_RS232.println(F("\014Console enabled on TTY"));
|
Serial_RS232.println(F("\014Console enabled on TTY"));
|
||||||
|
|
||||||
std::vector<Stream *> serial_ports { &Serial_RS232, &Serial };
|
std::vector<Stream *> 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"));
|
Serial.println(F("Start line-frequency interrupt"));
|
||||||
kw11_l *lf = new kw11_l(b, cnsl);
|
kw11_l *lf = new kw11_l(b, cnsl);
|
||||||
|
@ -525,11 +546,15 @@ void setup()
|
||||||
Serial.print(F("Free RAM after init: "));
|
Serial.print(F("Free RAM after init: "));
|
||||||
Serial.println(ESP.getFreeHeap());
|
Serial.println(ESP.getFreeHeap());
|
||||||
|
|
||||||
|
#if !defined(SHA2017)
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
#endif
|
||||||
|
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
|
|
||||||
cnsl->start_thread();
|
cnsl->start_thread();
|
||||||
|
|
||||||
|
cnsl->put_string_lf("PDP-11/70 emulator, (C) Folkert van Heusden");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
# Released under MIT license
|
# Released under MIT license
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
default_envs = ESP32
|
default_envs = ESP32-wemos
|
||||||
src_dir = .
|
src_dir = .
|
||||||
|
lib_ignore = SHAdisplay
|
||||||
|
|
||||||
[env:ESP32]
|
[env:ESP32-wemos]
|
||||||
lib_ldf_mode = deep+
|
build_src_filter = +<*> -<.git/> -<.svn/> -<example/> -<examples/> -<test/> -<tests/> -<build> -<player.cpp> -<SHAdisplay/> -<console_shabadge.cpp>
|
||||||
build_src_filter = +<*> -<.git/> -<.svn/> -<example/> -<examples/> -<test/> -<tests/> -<build> -<player.cpp>
|
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = wemos_d1_mini32
|
board = wemos_d1_mini32
|
||||||
framework = arduino
|
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_flags = -std=gnu++17 -Ofast -DESP32=1 -ggdb3 -D_GLIBCXX_USE_C99
|
||||||
build_unflags = -std=gnu++11 -Os
|
build_unflags = -std=gnu++11 -Os
|
||||||
|
|
||||||
#[env:PICO]
|
[env:SHA2017-badge]
|
||||||
#lib_ldf_mode = deep+
|
build_src_filter = +<*> -<.git/> -<.svn/> -<example/> -<examples/> -<test/> -<tests/> -<build> -<player.cpp> -<SHAdisplay/main/> -<SHAdisplay/components> -<SHAdisplay/Arduino/epd2in9-badge>
|
||||||
#src_filter = +<*> -<.git/> -<.svn/> -<example/> -<examples/> -<test/> -<tests/> -<build> -<player.cpp>
|
platform = espressif32
|
||||||
#platform = raspberrypi
|
board = esp32doit-devkit-v1
|
||||||
#board = pico
|
framework = arduino
|
||||||
#framework = arduino
|
monitor_speed = 115200
|
||||||
#monitor_speed = 115200
|
upload_speed = 460800
|
||||||
#upload_speed = 1000000
|
board_build.filesystem = littlefs
|
||||||
#lib_deps = greiman/SdFat@^2.1.2
|
lib_deps = greiman/SdFat@^2.1.2
|
||||||
# adafruit/Adafruit NeoPixel@^1.10.4
|
adafruit/Adafruit NeoPixel
|
||||||
#build_flags = -std=gnu++17 -Ofast -DESP32=1 -ggdb3 -D_GLIBCXX_USE_C99
|
bblanchon/ArduinoJson@^6.19.4
|
||||||
#build_unflags = -std=gnu++11 -Os
|
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
|
||||||
|
|
17
README.md
17
README.md
|
@ -6,7 +6,7 @@ To build for e.g. linux:
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
make kek
|
make
|
||||||
|
|
||||||
Required:
|
Required:
|
||||||
* libncursesw5-dev
|
* libncursesw5-dev
|
||||||
|
@ -16,7 +16,7 @@ To build for e.g. windows:
|
||||||
mkdir build-win32
|
mkdir build-win32
|
||||||
cd build-win32
|
cd build-win32
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=../mingw64.cmake ..
|
cmake -DCMAKE_TOOLCHAIN_FILE=../mingw64.cmake ..
|
||||||
make kek-win32
|
make
|
||||||
|
|
||||||
|
|
||||||
To run a disk image:
|
To run a disk image:
|
||||||
|
@ -50,6 +50,19 @@ Wiring of the MAX232 connection:
|
||||||
* RX : 16
|
* RX : 16
|
||||||
|
|
||||||
|
|
||||||
|
See SHA2017-badge.md if you want to flash your SHA20127 badge with this software.
|
||||||
|
|
||||||
|
|
||||||
|
Some pictures:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Click on the following picture to see it running (opens a youtube link):
|
||||||
|
|
||||||
|
[](https://youtu.be/MPaGmVli8NA)
|
||||||
|
|
||||||
Released under MIT license.
|
Released under MIT license.
|
||||||
|
|
||||||
Folkert van Heusden
|
Folkert van Heusden
|
||||||
|
|
12
SHA2017-badge.md
Normal file
12
SHA2017-badge.md
Normal file
|
@ -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.
|
14
bus.cpp
14
bus.cpp
|
@ -14,6 +14,8 @@
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
|
#include <esp_debug_helpers.h>
|
||||||
|
|
||||||
// ESP32 goes in a crash-loop when allocating 128kB
|
// ESP32 goes in a crash-loop when allocating 128kB
|
||||||
// see also https://github.com/espressif/esp-idf/issues/1934
|
// see also https://github.com/espressif/esp-idf/issues/1934
|
||||||
constexpr int n_pages = 12;
|
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(reg >= 0 && reg <= 7);
|
||||||
assert(delta >= -2 && delta <= 2);
|
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);
|
assert(MMR1 < 256);
|
||||||
|
#endif
|
||||||
|
|
||||||
MMR1 <<= 8;
|
MMR1 <<= 8;
|
||||||
|
|
||||||
|
|
2
config.h
2
config.h
|
@ -1,4 +1,4 @@
|
||||||
// (C) 2018-2023 by Folkert van Heusden
|
// (C) 2018-2023 by Folkert van Heusden
|
||||||
// Released under MIT license
|
// Released under MIT license
|
||||||
|
|
||||||
#define TURBO
|
// #define TURBO
|
||||||
|
|
38
console.cpp
38
console.cpp
|
@ -2,6 +2,7 @@
|
||||||
// Released under MIT license
|
// Released under MIT license
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <optional>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -14,11 +15,14 @@
|
||||||
#include "utils.h"
|
#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),
|
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()
|
console::~console()
|
||||||
|
@ -26,6 +30,8 @@ console::~console()
|
||||||
// done as well in subclasses but also here to
|
// done as well in subclasses but also here to
|
||||||
// stop lgtm.com complaining about it
|
// stop lgtm.com complaining about it
|
||||||
stop_thread();
|
stop_thread();
|
||||||
|
|
||||||
|
delete [] screen_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void console::start_thread()
|
void console::start_thread()
|
||||||
|
@ -70,7 +76,7 @@ int console::get_char()
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int console::wait_char(const int timeout_ms)
|
std::optional<char> console::wait_char(const int timeout_ms)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lck(input_lock);
|
std::unique_lock<std::mutex> lck(input_lock);
|
||||||
|
|
||||||
|
@ -86,7 +92,7 @@ int console::wait_char(const int timeout_ms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
void console::flush_input()
|
void console::flush_input()
|
||||||
|
@ -111,34 +117,34 @@ std::string console::read_line(const std::string & prompt)
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
char c = wait_char(500);
|
auto c = wait_char(250);
|
||||||
|
|
||||||
if (*stop_event == EVENT_TERMINATE)
|
if (*stop_event == EVENT_TERMINATE)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if (c == -1 || c == 255 /* ESP32 has unsigned char? */)
|
if (c.has_value() == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c == 13 || c == 10)
|
if (c.value() == 13 || c.value() == 10)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (c == 8 || c == 127) { // backspace
|
if (c.value() == 8 || c.value() == 127) { // backspace
|
||||||
if (!str.empty()) {
|
if (!str.empty()) {
|
||||||
str = str.substr(0, str.size() - 1);
|
str = str.substr(0, str.size() - 1);
|
||||||
|
|
||||||
emit_backspace();
|
emit_backspace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == 21) { // ^u
|
else if (c.value() == 21) { // ^u
|
||||||
for(size_t i=0; i<str.size(); i++)
|
for(size_t i=0; i<str.size(); i++)
|
||||||
emit_backspace();
|
emit_backspace();
|
||||||
|
|
||||||
str.clear();
|
str.clear();
|
||||||
}
|
}
|
||||||
else if (c >= 32) {
|
else if (c.value() >= 32) {
|
||||||
str += c;
|
str += c.value();
|
||||||
|
|
||||||
put_char(c);
|
put_char(c.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +192,7 @@ void console::put_char(const char c)
|
||||||
tx--;
|
tx--;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
screen_buffer[ty][tx++] = c;
|
screen_buffer[ty * t_width + tx++] = c;
|
||||||
|
|
||||||
if (tx == t_width) {
|
if (tx == t_width) {
|
||||||
tx = 0;
|
tx = 0;
|
||||||
|
@ -199,11 +205,11 @@ void console::put_char(const char c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ty == t_height) {
|
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--;
|
ty--;
|
||||||
|
|
||||||
memset(screen_buffer[t_height - 1], ' ', t_width);
|
memset(&screen_buffer[(t_height - 1) * t_width], ' ', t_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
console.h
12
console.h
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <optional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -15,9 +16,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
constexpr const int t_width { 80 };
|
|
||||||
constexpr const int t_height { 25 };
|
|
||||||
|
|
||||||
class console
|
class console
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -36,7 +34,9 @@ protected:
|
||||||
|
|
||||||
bool stop_thread_flag { false };
|
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 tx { 0 };
|
||||||
uint8_t ty { 0 };
|
uint8_t ty { 0 };
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ protected:
|
||||||
virtual void put_char_ll(const char c) = 0;
|
virtual void put_char_ll(const char c) = 0;
|
||||||
|
|
||||||
public:
|
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();
|
virtual ~console();
|
||||||
|
|
||||||
void start_thread();
|
void start_thread();
|
||||||
|
@ -55,7 +55,7 @@ public:
|
||||||
|
|
||||||
bool poll_char();
|
bool poll_char();
|
||||||
int get_char();
|
int get_char();
|
||||||
int wait_char(const int timeout_ms);
|
std::optional<char> wait_char(const int timeout_ms);
|
||||||
std::string read_line(const std::string & prompt);
|
std::string read_line(const std::string & prompt);
|
||||||
void flush_input();
|
void flush_input();
|
||||||
|
|
||||||
|
|
52
cpu.cpp
52
cpu.cpp
|
@ -71,7 +71,7 @@ std::tuple<double, double, uint64_t> cpu::get_mips_rel_speed()
|
||||||
{
|
{
|
||||||
uint64_t instr_count = get_instructions_executed_count();
|
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);
|
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 current_level = getPSW_spl();
|
||||||
|
|
||||||
// uint8_t start_level = current_level <= 3 ? 0 : current_level + 1;
|
// 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++) {
|
for(uint8_t i=start_level; i < 8; i++) {
|
||||||
auto interrupts = queued_interrupts.find(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)
|
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;
|
bool neg = mode == 4 || mode == 5;
|
||||||
|
|
||||||
if (word_mode == wm_word || reg >= 6 || mode == 6 || mode == 7)
|
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)
|
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;
|
const uint8_t operation = (instr >> 12) & 7;
|
||||||
|
|
||||||
if (operation == 0b000)
|
if (operation == 0b000)
|
||||||
return single_operand_instructions(instr);
|
return single_operand_instructions(instr);
|
||||||
|
|
||||||
|
const word_mode_t word_mode = instr & 0x8000 ? wm_byte : wm_word;
|
||||||
|
|
||||||
if (operation == 0b111) {
|
if (operation == 0b111) {
|
||||||
if (word_mode == wm_byte)
|
if (word_mode == wm_byte)
|
||||||
return false;
|
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_mode = (src >> 3) & 7;
|
||||||
const uint8_t src_reg = src & 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 = instr & 63;
|
||||||
const uint8_t dst_mode = (dst >> 3) & 7;
|
const uint8_t dst_mode = (dst >> 3) & 7;
|
||||||
const uint8_t dst_reg = dst & 7;
|
const uint8_t dst_reg = dst & 7;
|
||||||
|
@ -437,6 +429,8 @@ bool cpu::double_operand_instructions(const uint16_t instr)
|
||||||
|
|
||||||
switch(operation) {
|
switch(operation) {
|
||||||
case 0b001: { // MOV/MOVB Move Word/Byte
|
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)
|
if (word_mode == wm_byte && dst_mode == 0)
|
||||||
setRegister(dst_reg, int8_t(g_src.value.value())); // int8_t: sign extension
|
setRegister(dst_reg, int8_t(g_src.value.value())); // int8_t: sign extension
|
||||||
else {
|
else {
|
||||||
|
@ -452,6 +446,8 @@ bool cpu::double_operand_instructions(const uint16_t instr)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0b010: { // CMP/CMPB Compare Word/Byte
|
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);
|
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);
|
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
|
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);
|
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);
|
uint16_t result = (g_dst.value.value() & g_src.value.value()) & (word_mode == wm_byte ? 0xff : 0xffff);
|
||||||
|
|
||||||
setPSW_flags_nzv(result, word_mode);
|
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
|
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);
|
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
|
||||||
|
|
||||||
uint16_t result = g_dst.value.value() & ~g_src.value.value();
|
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
|
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);
|
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
|
||||||
|
|
||||||
uint16_t result = g_dst.value.value() | g_src.value.value();
|
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;
|
int dst_reg = instr & 7;
|
||||||
|
|
||||||
word_mode_t word_mode = wm_word;
|
setPC(getGAMAddress(dst_mode, dst_reg, wm_word).addr.value());
|
||||||
setPC(getGAMAddress(dst_mode, dst_reg, word_mode).addr.value());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1569,14 +1571,14 @@ bool cpu::misc_operations(const uint16_t instr)
|
||||||
// PUSH link
|
// PUSH link
|
||||||
pushStack(getRegister(link_reg));
|
pushStack(getRegister(link_reg));
|
||||||
|
|
||||||
|
b->addToMMR1(-2, 6);
|
||||||
|
|
||||||
// MOVE PC,link
|
// MOVE PC,link
|
||||||
setRegister(link_reg, getPC());
|
setRegister(link_reg, getPC());
|
||||||
|
|
||||||
// JMP dst
|
// JMP dst
|
||||||
setPC(dst_value);
|
setPC(dst_value);
|
||||||
|
|
||||||
b->addToMMR1(-2, 6);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1625,15 +1627,15 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bool mmr1_locked = b->getMMR0() & 0160000;
|
|
||||||
|
|
||||||
before_psw = getPSW();
|
before_psw = getPSW();
|
||||||
if (!mmr1_locked)
|
|
||||||
b->addToMMR1(-2, 6);
|
b->addToMMR1(-2, 6);
|
||||||
|
|
||||||
before_pc = getPC();
|
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
|
// make sure the trap vector is retrieved from kernel space
|
||||||
|
@ -2163,8 +2165,10 @@ void cpu::step_a()
|
||||||
if ((b->getMMR0() & 0160000) == 0)
|
if ((b->getMMR0() & 0160000) == 0)
|
||||||
b->clearMMR1();
|
b->clearMMR1();
|
||||||
|
|
||||||
if (any_queued_interrupts && check_queued_interrupts())
|
if (any_queued_interrupts && check_queued_interrupts()) {
|
||||||
return; // documentation
|
if ((b->getMMR0() & 0160000) == 0)
|
||||||
|
b->clearMMR1();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu::step_b()
|
void cpu::step_b()
|
||||||
|
|
BIN
images/KEK-ESP32-VT510.jpg
Normal file
BIN
images/KEK-ESP32-VT510.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
BIN
images/KEK-linux-frame.jpg
Normal file
BIN
images/KEK-linux-frame.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
BIN
images/KEK-linux.mp4
Normal file
BIN
images/KEK-linux.mp4
Normal file
Binary file not shown.
BIN
images/KEK-sha2017badge.jpg
Normal file
BIN
images/KEK-sha2017badge.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
21
tty.cpp
21
tty.cpp
|
@ -45,6 +45,14 @@ uint8_t tty::readByte(const uint16_t addr)
|
||||||
return v;
|
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)
|
uint16_t tty::readWord(const uint16_t addr)
|
||||||
{
|
{
|
||||||
const int reg = (addr - PDP11TTY_BASE) / 2;
|
const int reg = (addr - PDP11TTY_BASE) / 2;
|
||||||
|
@ -69,12 +77,8 @@ uint16_t tty::readWord(const uint16_t addr)
|
||||||
|
|
||||||
vtemp = ch | (parity(ch) << 7);
|
vtemp = ch | (parity(ch) << 7);
|
||||||
|
|
||||||
if (chars.empty() == false) {
|
if (chars.empty() == false)
|
||||||
registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] |= 128;
|
notify_rx();
|
||||||
|
|
||||||
if (registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] & 64)
|
|
||||||
b->getCpu()->queue_interrupt(4, 060);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (addr == PDP11TTY_TPS) {
|
else if (addr == PDP11TTY_TPS) {
|
||||||
|
@ -96,10 +100,7 @@ void tty::operator()()
|
||||||
|
|
||||||
chars.push_back(c->get_char());
|
chars.push_back(c->get_char());
|
||||||
|
|
||||||
registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] |= 128;
|
notify_rx();
|
||||||
|
|
||||||
if (registers[(PDP11TTY_TKS - PDP11TTY_BASE) / 2] & 64)
|
|
||||||
b->getCpu()->queue_interrupt(4, 060);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
myusleep(100000);
|
myusleep(100000);
|
||||||
|
|
2
tty.h
2
tty.h
|
@ -35,6 +35,8 @@ private:
|
||||||
std::thread *th { nullptr };
|
std::thread *th { nullptr };
|
||||||
std::atomic_bool stop_flag { false };
|
std::atomic_bool stop_flag { false };
|
||||||
|
|
||||||
|
void notify_rx();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
tty(console *const c, bus *const b);
|
tty(console *const c, bus *const b);
|
||||||
virtual ~tty();
|
virtual ~tty();
|
||||||
|
|
Loading…
Add table
Reference in a new issue