compiles
This commit is contained in:
parent
e10124a550
commit
2b6de27c35
21 changed files with 341 additions and 145 deletions
|
@ -6,26 +6,35 @@
|
|||
#include <atomic>
|
||||
#include <HardwareSerial.h>
|
||||
#include <LittleFS.h>
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
#include <SD.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
#include <WiFi.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(SHA2017)
|
||||
#include "console_shabadge.h"
|
||||
#else
|
||||
#elif !defined(BUILD_FOR_RP2040)
|
||||
#include "console_esp32.h"
|
||||
#endif
|
||||
#include "cpu.h"
|
||||
#include "debugger.h"
|
||||
#include "disk_backend.h"
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
#include "disk_backend_esp32.h"
|
||||
#include "disk_backend_nbd.h"
|
||||
#endif
|
||||
#include "error.h"
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
#include "esp32.h"
|
||||
#endif
|
||||
#include "gen.h"
|
||||
#include "kw11-l.h"
|
||||
#include "loaders.h"
|
||||
|
@ -41,6 +50,11 @@ constexpr const char SERIAL_CFG_FILE[] = "/serial.json";
|
|||
#define MAX_CFG_SIZE 1024
|
||||
StaticJsonDocument<MAX_CFG_SIZE> json_doc;
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
#define Serial_RS232 Serial2
|
||||
#else
|
||||
HardwareSerial Serial_RS232(1);
|
||||
#endif
|
||||
|
||||
bus *b = nullptr;
|
||||
cpu *c = nullptr;
|
||||
|
@ -57,9 +71,7 @@ std::atomic_bool *running { nullptr };
|
|||
|
||||
bool trace_output { false };
|
||||
|
||||
HardwareSerial Serial_RS232(2);
|
||||
|
||||
// std::atomic_bool on_wifi { false };
|
||||
typedef enum { DT_RK05, DT_RL02 } disk_type_t;
|
||||
|
||||
void console_thread_wrapper_panel(void *const c)
|
||||
{
|
||||
|
@ -109,8 +121,7 @@ bool save_serial_speed_configuration(const uint32_t bps)
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef enum { DT_RK05, DT_RL02 } disk_type_t;
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *> > > load_disk_configuration(console *const c)
|
||||
{
|
||||
File dataFile = LittleFS.open(NET_DISK_CFG_FILE, "r");
|
||||
|
@ -185,10 +196,15 @@ bool save_disk_configuration(const std::string & nbd_host, const int nbd_port, c
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef enum { BE_NETWORK, BE_SD } disk_backend_t;
|
||||
|
||||
std::optional<disk_backend_t> select_disk_backend(console *const c)
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
return BE_SD;
|
||||
#endif
|
||||
c->put_string("1. network (NBD), 2. local SD card, 9. abort");
|
||||
|
||||
int ch = -1;
|
||||
|
@ -235,6 +251,7 @@ std::optional<disk_type_t> select_disk_type(console *const c)
|
|||
return DT_RL02;
|
||||
}
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *> > > select_nbd_server(console *const c)
|
||||
{
|
||||
c->flush_input();
|
||||
|
@ -275,6 +292,7 @@ std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *>
|
|||
|
||||
return { };
|
||||
}
|
||||
#endif
|
||||
|
||||
// RK05, RL02 files
|
||||
std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *> > > select_disk_files(console *const c)
|
||||
|
@ -289,6 +307,8 @@ std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *>
|
|||
#if defined(SHA2017)
|
||||
if (!sd.begin(21, SD_SCK_MHZ(10)))
|
||||
sd.initErrorHalt();
|
||||
#elif defined(BUILD_FOR_RP2040)
|
||||
// SD.begin(cspin, SPI1); FIXME
|
||||
#else
|
||||
if (!sd.begin(SS, SD_SCK_MHZ(15)))
|
||||
sd.initErrorHalt();
|
||||
|
@ -317,6 +337,7 @@ std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *>
|
|||
if (fh.open(selected_file.c_str(), O_RDWR)) {
|
||||
fh.close();
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040) // FIXME
|
||||
disk_backend *temp = new disk_backend_esp32(selected_file);
|
||||
|
||||
if (!temp->begin()) {
|
||||
|
@ -333,6 +354,7 @@ std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *>
|
|||
|
||||
if (disk_type.value() == DT_RL02)
|
||||
return { { { }, { temp } } };
|
||||
#endif
|
||||
}
|
||||
|
||||
c->put_string_lf("open failed");
|
||||
|
@ -366,9 +388,11 @@ void configure_disk(console *const c)
|
|||
|
||||
std::optional<std::pair<std::vector<disk_backend *>, std::vector<disk_backend *> > > files;
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
if (backend == BE_NETWORK)
|
||||
files = select_nbd_server(cnsl);
|
||||
else // if (backend == BE_SD)
|
||||
#endif
|
||||
files = select_disk_files(cnsl);
|
||||
|
||||
if (files.has_value() == false)
|
||||
|
@ -380,6 +404,7 @@ void configure_disk(console *const c)
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
void set_hostname()
|
||||
{
|
||||
WiFi.setHostname("PDP-11");
|
||||
|
@ -459,14 +484,6 @@ void start_network(console *const c)
|
|||
c->put_string_lf(format("Local IP address: %s", WiFi.localIP().toString().c_str()));
|
||||
}
|
||||
|
||||
void set_tty_serial_speed(console *const c, const uint32_t bps)
|
||||
{
|
||||
Serial_RS232.begin(bps);
|
||||
|
||||
if (save_serial_speed_configuration(bps) == false)
|
||||
c->put_string_lf("Failed to store configuration file with serial settings");
|
||||
}
|
||||
|
||||
void recall_configuration(console *const c)
|
||||
{
|
||||
c->put_string_lf("Starting network...");
|
||||
|
@ -479,6 +496,15 @@ void recall_configuration(console *const c)
|
|||
set_disk_configuration(disk_configuration.value());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_tty_serial_speed(console *const c, const uint32_t bps)
|
||||
{
|
||||
Serial_RS232.begin(bps);
|
||||
|
||||
if (save_serial_speed_configuration(bps) == false)
|
||||
c->put_string_lf("Failed to store configuration file with serial settings");
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
@ -491,14 +517,25 @@ void setup()
|
|||
Serial.print(F("Size of int: "));
|
||||
Serial.println(sizeof(int));
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
Serial.print(F("CPU clock frequency (MHz): "));
|
||||
Serial.println(getCpuFrequencyMhz());
|
||||
#endif
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
LittleFSConfig cfg;
|
||||
cfg.setAutoFormat(false);
|
||||
|
||||
LittleFS.setConfig(cfg);
|
||||
#else
|
||||
if (!LittleFS.begin(true))
|
||||
Serial.println(F("LittleFS.begin() failed"));
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
Serial.print(F("Free RAM before init (decimal bytes): "));
|
||||
Serial.println(ESP.getFreeHeap());
|
||||
#endif
|
||||
|
||||
Serial.println(F("Init bus"));
|
||||
b = new bus();
|
||||
|
@ -516,16 +553,20 @@ void setup()
|
|||
Serial.print(bitrate);
|
||||
Serial.println(F("bps"));
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
Serial_RS232.begin(bitrate, hwSerialConfig, 16, 17);
|
||||
Serial_RS232.setHwFlowCtrlMode(0);
|
||||
#endif
|
||||
|
||||
Serial_RS232.println(F("\014Console enabled on TTY"));
|
||||
|
||||
std::vector<Stream *> serial_ports { &Serial_RS232, &Serial };
|
||||
#if defined(SHA2017)
|
||||
cnsl = new console_shabadge(&stop_event, b, serial_ports);
|
||||
#else
|
||||
#elif defined(ESP32)
|
||||
cnsl = new console_esp32(&stop_event, b, serial_ports, 80, 25);
|
||||
#elif defined(BUILD_FOR_RP2040)
|
||||
// FIXME
|
||||
#endif
|
||||
|
||||
Serial.println(F("Start line-frequency interrupt"));
|
||||
|
@ -543,8 +584,10 @@ void setup()
|
|||
|
||||
xTaskCreate(&console_thread_wrapper_io, "c-io", 2048, cnsl, 1, nullptr);
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
Serial.print(F("Free RAM after init: "));
|
||||
Serial.println(ESP.getFreeHeap());
|
||||
#endif
|
||||
|
||||
#if !defined(SHA2017)
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
|
1
ESP32/rp2040.h
Symbolic link
1
ESP32/rp2040.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../RP2040/rp2040.h
|
1
RP2040/config.h
Symbolic link
1
RP2040/config.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../config.h
|
1
RP2040/main.ino
Symbolic link
1
RP2040/main.ino
Symbolic link
|
@ -0,0 +1 @@
|
|||
../ESP32/main.ino
|
|
@ -1,17 +1,18 @@
|
|||
[platformio]
|
||||
default_envs = RP2040
|
||||
default_envs = BUILD_FOR_RP2040
|
||||
src_dir = .
|
||||
|
||||
[env:RP2040]
|
||||
[env:BUILD_FOR_RP2040]
|
||||
lib_ldf_mode = deep+
|
||||
src_filter = +<*> -<.git/> -<.svn/> -<example/> -<examples/> -<test/> -<tests/> -<build> -<player.cpp>
|
||||
platform = raspberrypi
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = pico
|
||||
framework = arduino
|
||||
board_build.core = earlephilhower
|
||||
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 -DRP2040=1 -ggdb3
|
||||
lib_deps = adafruit/Adafruit NeoPixel@^1.10.4
|
||||
bblanchon/ArduinoJson@^6.19.4
|
||||
build_flags = -std=gnu++17 -Ofast -DBUILD_FOR_RP2040=1 -ggdb3 -DPIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS
|
||||
#-D_GLIBCXX_USE_C99
|
||||
build_unflags = -std=gnu++14 -Os
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#if defined(RP2040)
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
#define USE_SDFAT
|
||||
#define SD_FAT_TYPE 1
|
||||
#include <SdFat.h>
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
#include <task.h>
|
||||
#endif
|
||||
|
|
1
RP2040/win32.h
Symbolic link
1
RP2040/win32.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../win32.h
|
38
bus.cpp
38
bus.cpp
|
@ -13,8 +13,10 @@
|
|||
#include "tm-11.h"
|
||||
#include "tty.h"
|
||||
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
#if defined(ESP32)
|
||||
#include <esp_debug_helpers.h>
|
||||
#endif
|
||||
|
||||
// ESP32 goes in a crash-loop when allocating 128kB
|
||||
// see also https://github.com/espressif/esp-idf/issues/1934
|
||||
|
@ -214,10 +216,19 @@ uint16_t bus::read(const uint16_t addr_in, const word_mode_t word_mode, const rm
|
|||
}
|
||||
|
||||
if (a == ADDR_LFC) { // line frequency clock and status register
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(lf_csr_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(lf_csr_lock);
|
||||
#endif
|
||||
|
||||
uint16_t temp = lf_csr;
|
||||
if (!peek_only) DOLOG(debug, false, "READ-I/O line frequency clock: %o", temp);
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(lf_csr_lock);
|
||||
#endif
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
@ -875,10 +886,17 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
|
|||
}
|
||||
|
||||
if (a == ADDR_LFC) { // line frequency clock and status register
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(lf_csr_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(lf_csr_lock);
|
||||
#endif
|
||||
|
||||
DOLOG(debug, true, "WRITE-I/O set line frequency clock/status register: %06o", value);
|
||||
lf_csr = value;
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(lf_csr_lock);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1047,14 +1065,32 @@ void bus::writeUnibusByte(const uint16_t a, const uint8_t v)
|
|||
|
||||
void bus::set_lf_crs_b7()
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(lf_csr_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(lf_csr_lock);
|
||||
#endif
|
||||
|
||||
lf_csr |= 128;
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(lf_csr_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t bus::get_lf_crs()
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(lf_csr_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(lf_csr_lock);
|
||||
#endif
|
||||
|
||||
return lf_csr;
|
||||
uint8_t rc = lf_csr;
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(lf_csr_lock);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
9
bus.h
9
bus.h
|
@ -14,6 +14,11 @@
|
|||
#include "rk05.h"
|
||||
#include "rl02.h"
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
#include "rp2040.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define ADDR_MMR0 0177572
|
||||
#define ADDR_MMR1 0177574
|
||||
#define ADDR_MMR2 0177576
|
||||
|
@ -93,7 +98,11 @@ private:
|
|||
|
||||
uint16_t MMR0 { 0 }, MMR1 { 0 }, MMR2 { 0 }, MMR3 { 0 }, CPUERR { 0 }, PIR { 0 }, CSR { 0 };
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
SemaphoreHandle_t lf_csr_lock { xSemaphoreCreateBinary() };
|
||||
#else
|
||||
std::mutex lf_csr_lock;
|
||||
#endif
|
||||
uint16_t lf_csr { 0 };
|
||||
|
||||
uint16_t microprogram_break_register { 0 };
|
||||
|
|
106
console.cpp
106
console.cpp
|
@ -9,11 +9,20 @@
|
|||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#include "rp2040.h"
|
||||
#include "console.h"
|
||||
#include "gen.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
void thread_wrapper_console(void *p)
|
||||
{
|
||||
console *const consolel = reinterpret_cast<console *>(p);
|
||||
|
||||
consolel->operator()();
|
||||
}
|
||||
#endif
|
||||
|
||||
console::console(std::atomic_uint32_t *const stop_event, bus *const b, const int t_width, const int t_height) :
|
||||
stop_event(stop_event),
|
||||
|
@ -21,7 +30,6 @@ console::console(std::atomic_uint32_t *const stop_event, bus *const b, const int
|
|||
t_width(t_width),
|
||||
t_height(t_height)
|
||||
{
|
||||
|
||||
screen_buffer = new char[t_width * t_height]();
|
||||
}
|
||||
|
||||
|
@ -38,13 +46,16 @@ void console::start_thread()
|
|||
{
|
||||
stop_thread_flag = false;
|
||||
|
||||
#if !defined(ESP32)
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xTaskCreate(&thread_wrapper_console, "console-l", 2048, this, 1, nullptr);
|
||||
#elif !defined(ESP32)
|
||||
th = new std::thread(std::ref(*this));
|
||||
#endif
|
||||
}
|
||||
|
||||
void console::stop_thread()
|
||||
{
|
||||
#if !defined(ESP32) && !defined(BUILD_FOR_RP2040)
|
||||
if (th) {
|
||||
stop_thread_flag = true;
|
||||
|
||||
|
@ -53,31 +64,84 @@ void console::stop_thread()
|
|||
|
||||
th = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool console::poll_char()
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(input_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(input_lock);
|
||||
#endif
|
||||
|
||||
return input_buffer.empty() == false;
|
||||
bool rc = input_buffer.empty() == false;
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(input_lock);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int console::get_char()
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(input_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(input_lock);
|
||||
#endif
|
||||
|
||||
if (input_buffer.empty())
|
||||
return -1;
|
||||
char c = -1;
|
||||
|
||||
char c = input_buffer.at(0);
|
||||
if (input_buffer.empty() == false) {
|
||||
c = input_buffer.at(0);
|
||||
|
||||
input_buffer.erase(input_buffer.begin() + 0);
|
||||
}
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(input_lock);
|
||||
#endif
|
||||
return c;
|
||||
}
|
||||
|
||||
std::optional<char> console::wait_char(const int timeout_ms)
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(input_lock, portMAX_DELAY);
|
||||
|
||||
bool triggered = input_buffer.empty() == false;
|
||||
|
||||
if (!triggered) {
|
||||
uint32_t start = millis();
|
||||
|
||||
while(!have_data && millis() - start < timeout_ms) {
|
||||
}
|
||||
|
||||
have_data = false; // FIXME
|
||||
|
||||
triggered = input_buffer.empty() == false;
|
||||
}
|
||||
|
||||
if (triggered) {
|
||||
int c = input_buffer.at(0);
|
||||
|
||||
input_buffer.erase(input_buffer.begin() + 0);
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(input_lock);
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(input_lock);
|
||||
#endif
|
||||
|
||||
return { };
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(input_lock);
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
@ -93,13 +157,22 @@ std::optional<char> console::wait_char(const int timeout_ms)
|
|||
}
|
||||
|
||||
return { };
|
||||
#endif
|
||||
}
|
||||
|
||||
void console::flush_input()
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(input_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(input_lock);
|
||||
#endif
|
||||
|
||||
input_buffer.clear();
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(input_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void console::emit_backspace()
|
||||
|
@ -155,6 +228,16 @@ std::string console::read_line(const std::string & prompt)
|
|||
|
||||
void console::debug(const std::string fmt, ...)
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
char buffer[128];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buffer, sizeof buffer, fmt.c_str(), ap);
|
||||
va_end(ap);
|
||||
|
||||
put_string_lf(buffer);
|
||||
#else
|
||||
char *buffer = nullptr;
|
||||
|
||||
va_list ap;
|
||||
|
@ -167,6 +250,7 @@ void console::debug(const std::string fmt, ...)
|
|||
put_string_lf(buffer);
|
||||
|
||||
free(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void console::put_char(const char c)
|
||||
|
@ -240,11 +324,21 @@ void console::operator()()
|
|||
else if (running_flag == false && c == 12) // ^l
|
||||
refresh_virtual_terminal();
|
||||
else {
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(input_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(input_lock);
|
||||
#endif
|
||||
|
||||
input_buffer.push_back(c);
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
have_data = true;
|
||||
|
||||
xSemaphoreGive(input_lock);
|
||||
#else
|
||||
have_data.notify_all();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,21 @@ class console
|
|||
{
|
||||
private:
|
||||
std::vector<char> input_buffer;
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
volatile bool have_data { false };
|
||||
SemaphoreHandle_t input_lock { xSemaphoreCreateBinary() };
|
||||
#else
|
||||
std::condition_variable have_data;
|
||||
std::mutex input_lock;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::atomic_uint32_t *const stop_event { nullptr };
|
||||
|
||||
bus *const b { nullptr };
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
std::thread *th { nullptr };
|
||||
#endif
|
||||
std::atomic_bool disk_read_activity_flag { false };
|
||||
std::atomic_bool disk_write_activity_flag { false };
|
||||
std::atomic_bool running_flag { false };
|
||||
|
|
34
cpu.cpp
34
cpu.cpp
|
@ -254,7 +254,11 @@ void cpu::setPSW_flags_nzv(const uint16_t value, const word_mode_t word_mode)
|
|||
|
||||
bool cpu::check_queued_interrupts()
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(qi_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(qi_lock);
|
||||
#endif
|
||||
|
||||
uint8_t current_level = getPSW_spl();
|
||||
|
||||
|
@ -275,24 +279,43 @@ bool cpu::check_queued_interrupts()
|
|||
|
||||
trap(v, i, true);
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(qi_lock);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
any_queued_interrupts = false;
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(qi_lock);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void cpu::queue_interrupt(const uint8_t level, const uint8_t vector)
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(qi_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(qi_lock);
|
||||
#endif
|
||||
|
||||
auto it = queued_interrupts.find(level);
|
||||
|
||||
it->second.insert(vector);
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
qi_cv = true;
|
||||
|
||||
xSemaphoreGive(qi_lock);
|
||||
#else
|
||||
|
||||
qi_cv.notify_all();
|
||||
#endif
|
||||
|
||||
any_queued_interrupts = true;
|
||||
|
||||
|
@ -1496,9 +1519,16 @@ bool cpu::misc_operations(const uint16_t instr)
|
|||
|
||||
case 0b0000000000000001: // WAIT
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
while(!qi_cv)
|
||||
vTaskDelay(10);
|
||||
|
||||
qi_cv = false; // FIXME
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(qi_lock);
|
||||
|
||||
qi_cv.wait(lck);
|
||||
#endif
|
||||
}
|
||||
|
||||
DOLOG(debug, false, "WAIT returned");
|
||||
|
@ -2201,7 +2231,7 @@ void cpu::step_b()
|
|||
|
||||
trap(010); // floating point nog niet geimplementeerd
|
||||
}
|
||||
catch(const int exception) {
|
||||
DOLOG(debug, true, "bus-trap during execution of command (%d)", exception);
|
||||
catch(const int exception_nr) {
|
||||
DOLOG(debug, true, "bus-trap during execution of command (%d)", exception_nr);
|
||||
}
|
||||
}
|
||||
|
|
5
cpu.h
5
cpu.h
|
@ -42,8 +42,13 @@ private:
|
|||
|
||||
// level, vector
|
||||
std::map<uint8_t, std::set<uint8_t> > queued_interrupts;
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
SemaphoreHandle_t qi_lock { xSemaphoreCreateBinary() };
|
||||
volatile bool qi_cv { false };
|
||||
#else
|
||||
std::mutex qi_lock;
|
||||
std::condition_variable qi_cv;
|
||||
#endif
|
||||
std::atomic_bool any_queued_interrupts { false };
|
||||
|
||||
std::set<uint16_t> breakpoints;
|
||||
|
|
89
debugger.cpp
89
debugger.cpp
|
@ -10,10 +10,10 @@
|
|||
#include "utils.h"
|
||||
|
||||
|
||||
#if defined(ESP32) || defined(RP2040)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
#if defined(ESP32)
|
||||
#include "esp32.h"
|
||||
#else
|
||||
#elif defined(BUILD_FOR_RP2040)
|
||||
#include "rp2040.h"
|
||||
#endif
|
||||
|
||||
|
@ -503,91 +503,6 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
|
|||
*cnsl->get_running_flag() = false;
|
||||
|
||||
c->reset();
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#if defined(ESP32) || defined(RP2040)
|
||||
else if (cmd == "cfgdisk") {
|
||||
configure_disk(cnsl);
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
else if (cmd == "cfgnet") {
|
||||
configure_network(cnsl);
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (cmd == "startnet") {
|
||||
start_network(cnsl);
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
else if (cmd == "quit" || cmd == "q") {
|
||||
#if defined(ESP32)
|
||||
ESP.restart();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
else if (cmd == "help" || cmd == "h" || cmd == "?") {
|
||||
cnsl->put_string_lf("disassemble/d - show current instruction (pc=/n=)");
|
||||
cnsl->put_string_lf("go - run until trap or ^e");
|
||||
#if !defined(ESP32) && !defined(RP2040)
|
||||
cnsl->put_string_lf("quit/q - stop emulator");
|
||||
#endif
|
||||
cnsl->put_string_lf("examine/e - show memory address (<b|w> <octal address> [<n>])");
|
||||
cnsl->put_string_lf("reset/r - reset cpu/bus/etc");
|
||||
cnsl->put_string_lf("single/s - run 1 instruction (implicit 'disassemble' command)");
|
||||
cnsl->put_string_lf("sbp/cbp/lbp - set/clear/list breakpoint(s)");
|
||||
cnsl->put_string_lf("trace/t - toggle tracing");
|
||||
cnsl->put_string_lf("strace - start tracing from address - invoke without address to disable");
|
||||
cnsl->put_string_lf("mmudump - dump MMU settings (PARs/PDRs)");
|
||||
cnsl->put_string_lf("setpc - set PC to value");
|
||||
cnsl->put_string_lf("setmem - set memory (a=) to value (v=), both in octal, one byte");
|
||||
cnsl->put_string_lf("toggle - set switch (s=, 0...15 (decimal)) of the front panel to state (t=, 0 or 1)");
|
||||
#if defined(ESP32)
|
||||
cnsl->put_string_lf("cfgnet - configure network (e.g. WiFi)");
|
||||
cnsl->put_string_lf("startnet - start network");
|
||||
#endif
|
||||
#if defined(ESP32) || defined(RP2040)
|
||||
cnsl->put_string_lf("cfgdisk - configure disk");
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
cnsl->put_string_lf("?");
|
||||
continue;
|
||||
}
|
||||
|
||||
c->emulation_start();
|
||||
|
||||
*cnsl->get_running_flag() = true;
|
||||
|
||||
while(*stop_event == EVENT_NONE) {
|
||||
if (!single_step)
|
||||
DOLOG(debug, false, "---");
|
||||
|
||||
c->step_a();
|
||||
|
||||
if (trace_start_addr != -1 && c->getPC() == trace_start_addr)
|
||||
tracing = true;
|
||||
|
||||
if (tracing || single_step)
|
||||
disassemble(c, single_step ? cnsl : nullptr, c->getPC(), false);
|
||||
|
||||
if (c->check_breakpoint() && !single_step) {
|
||||
cnsl->put_string_lf("Breakpoint");
|
||||
break;
|
||||
}
|
||||
|
||||
if (*stop_event == EVENT_INTERRUPT) {
|
||||
single_step = true;
|
||||
|
||||
*stop_event = EVENT_NONE;
|
||||
}
|
||||
}
|
||||
catch(const std::exception & e) {
|
||||
cnsl->put_string_lf(format("Exception caught: %s", e.what()));
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
#include <Arduino.h>
|
||||
#elif defined(_WIN32)
|
||||
#else
|
||||
|
@ -21,11 +21,11 @@
|
|||
{
|
||||
int e = errno;
|
||||
|
||||
#if !defined(_WIN32) && !defined(ESP32)
|
||||
#if !defined(_WIN32) && !defined(ESP32) && !defined(BUILD_FOR_RP2040)
|
||||
(void)endwin();
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
Serial.println(format);
|
||||
#else
|
||||
va_list ap;
|
||||
|
|
10
kw11-l.cpp
10
kw11-l.cpp
|
@ -10,10 +10,12 @@
|
|||
|
||||
#if defined(ESP32)
|
||||
#include "esp32.h"
|
||||
#elif defined(BUILD_FOR_RP2040)
|
||||
#include "rp2040.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
void thread_wrapper_kw11(void *p)
|
||||
{
|
||||
kw11_l *const kw11l = reinterpret_cast<kw11_l *>(p);
|
||||
|
@ -24,7 +26,7 @@ void thread_wrapper_kw11(void *p)
|
|||
|
||||
kw11_l::kw11_l(bus *const b, console *const cnsl) : b(b), cnsl(cnsl)
|
||||
{
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
xTaskCreate(&thread_wrapper_kw11, "kw11-l", 2048, this, 1, nullptr);
|
||||
#else
|
||||
th = new std::thread(std::ref(*this));
|
||||
|
@ -35,11 +37,11 @@ kw11_l::~kw11_l()
|
|||
{
|
||||
stop_flag = true;
|
||||
|
||||
#if !defined(ESP32)
|
||||
#if !defined(ESP32) && !defined(BUILD_FOR_RP2040)
|
||||
th->join();
|
||||
#endif
|
||||
|
||||
delete th;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kw11_l::operator()()
|
||||
|
|
2
kw11-l.h
2
kw11-l.h
|
@ -13,7 +13,9 @@ private:
|
|||
bus *const b { nullptr };
|
||||
console *const cnsl { nullptr };
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
std::thread * th { nullptr };
|
||||
#endif
|
||||
std::atomic_bool stop_flag { false };
|
||||
|
||||
public:
|
||||
|
|
2
log.cpp
2
log.cpp
|
@ -61,6 +61,7 @@ void closelog()
|
|||
|
||||
void dolog(const log_level_t ll, const char *fmt, ...)
|
||||
{
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
if (!lfh && logfile != nullptr) {
|
||||
#if !defined(ESP32)
|
||||
lfh = fopen(logfile, "a+");
|
||||
|
@ -113,6 +114,7 @@ void dolog(const log_level_t ll, const char *fmt, ...)
|
|||
|
||||
free(str);
|
||||
free(ts_str);
|
||||
#endif
|
||||
}
|
||||
|
||||
log_level_t parse_ll(const std::string & str)
|
||||
|
|
36
tty.cpp
36
tty.cpp
|
@ -20,19 +20,33 @@ const char * const regnames[] = {
|
|||
"puncher buffer"
|
||||
};
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
void thread_wrapper_tty(void *p)
|
||||
{
|
||||
tty *const t = reinterpret_cast<tty *>(p);
|
||||
|
||||
t->operator()();
|
||||
}
|
||||
#endif
|
||||
|
||||
tty::tty(console *const c, bus *const b) :
|
||||
c(c),
|
||||
b(b)
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xTaskCreate(&thread_wrapper_tty, "tty-l", 2048, this, 1, nullptr);
|
||||
#else
|
||||
th = new std::thread(std::ref(*this));
|
||||
#endif
|
||||
}
|
||||
|
||||
tty::~tty()
|
||||
{
|
||||
stop_flag = true;
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
th->join();
|
||||
delete th;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t tty::readByte(const uint16_t addr)
|
||||
|
@ -58,17 +72,19 @@ uint16_t tty::readWord(const uint16_t addr)
|
|||
const int reg = (addr - PDP11TTY_BASE) / 2;
|
||||
uint16_t vtemp = registers[reg];
|
||||
|
||||
if (addr == PDP11TTY_TKS) {
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(chars_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(chars_lock);
|
||||
#endif
|
||||
|
||||
if (addr == PDP11TTY_TKS) {
|
||||
bool have_char = chars.empty() == false;
|
||||
|
||||
vtemp &= ~128;
|
||||
vtemp |= have_char ? 128 : 0;
|
||||
}
|
||||
else if (addr == PDP11TTY_TKB) {
|
||||
std::unique_lock<std::mutex> lck(chars_lock);
|
||||
|
||||
if (chars.empty())
|
||||
vtemp = 0;
|
||||
else {
|
||||
|
@ -85,6 +101,10 @@ uint16_t tty::readWord(const uint16_t addr)
|
|||
vtemp |= 128;
|
||||
}
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(chars_lock);
|
||||
#endif
|
||||
|
||||
DOLOG(debug, true, "PDP11TTY read addr %o (%s): %d, 7bit: %d", addr, regnames[reg], vtemp, vtemp & 127);
|
||||
|
||||
registers[reg] = vtemp;
|
||||
|
@ -96,11 +116,19 @@ void tty::operator()()
|
|||
{
|
||||
while(!stop_flag) {
|
||||
if (c->poll_char()) {
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreTake(chars_lock, portMAX_DELAY);
|
||||
#else
|
||||
std::unique_lock<std::mutex> lck(chars_lock);
|
||||
#endif
|
||||
|
||||
chars.push_back(c->get_char());
|
||||
|
||||
notify_rx();
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
xSemaphoreGive(chars_lock);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
myusleep(100000);
|
||||
|
|
9
tty.h
9
tty.h
|
@ -29,10 +29,19 @@ class tty
|
|||
private:
|
||||
console *const c { nullptr };
|
||||
bus *const b { nullptr };
|
||||
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
SemaphoreHandle_t chars_lock { xSemaphoreCreateBinary() };
|
||||
#else
|
||||
std::mutex chars_lock;
|
||||
#endif
|
||||
std::vector<char> chars;
|
||||
|
||||
uint16_t registers[4] { 0 };
|
||||
|
||||
#if !defined(BUILD_FOR_RP2040)
|
||||
std::thread *th { nullptr };
|
||||
#endif
|
||||
std::atomic_bool stop_flag { false };
|
||||
|
||||
void notify_rx();
|
||||
|
|
22
utils.cpp
22
utils.cpp
|
@ -1,7 +1,7 @@
|
|||
// (C) 2018-2023 by Folkert van Heusden
|
||||
// Released under MIT license
|
||||
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
|||
#include <vector>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "rp2040.h"
|
||||
#include "win32.h"
|
||||
|
||||
|
||||
|
@ -31,6 +32,16 @@ void setBit(uint16_t & v, const int bit, const bool vb)
|
|||
|
||||
std::string format(const char *const fmt, ...)
|
||||
{
|
||||
#if defined(BUILD_FOR_RP2040)
|
||||
char buffer[128];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buffer, sizeof buffer, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return buffer;
|
||||
#else
|
||||
char *buffer = nullptr;
|
||||
va_list ap;
|
||||
|
||||
|
@ -42,11 +53,12 @@ std::string format(const char *const fmt, ...)
|
|||
free(buffer);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long get_ms()
|
||||
{
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
return millis();
|
||||
#else
|
||||
timeval tv;
|
||||
|
@ -60,7 +72,7 @@ unsigned long get_ms()
|
|||
|
||||
uint64_t get_us()
|
||||
{
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
return micros();
|
||||
#else
|
||||
timeval tv;
|
||||
|
@ -79,7 +91,7 @@ int parity(int v)
|
|||
|
||||
void myusleep(uint64_t us)
|
||||
{
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) || defined(BUILD_FOR_RP2040)
|
||||
for(;;) {
|
||||
uint64_t n_ms = us / 1000;
|
||||
|
||||
|
@ -143,7 +155,7 @@ std::vector<std::string> split(std::string in, std::string splitter)
|
|||
|
||||
void set_thread_name(std::string name)
|
||||
{
|
||||
#if !defined(ESP32)
|
||||
#if !defined(ESP32) && !defined(BUILD_FOR_RP2040)
|
||||
if (name.length() > 15)
|
||||
name = name.substr(0, 15);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue