This commit is contained in:
folkert van heusden 2023-04-07 23:09:36 +02:00
parent e10124a550
commit 2b6de27c35
Signed by untrusted user who does not match committer: folkert
GPG key ID: 6B6455EDFEED3BD1
21 changed files with 341 additions and 145 deletions

View file

@ -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
View file

@ -0,0 +1 @@
../RP2040/rp2040.h

1
RP2040/config.h Symbolic link
View file

@ -0,0 +1 @@
../config.h

1
RP2040/main.ino Symbolic link
View file

@ -0,0 +1 @@
../ESP32/main.ino

View file

@ -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

View file

@ -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
View file

@ -0,0 +1 @@
../win32.h

38
bus.cpp
View file

@ -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
View file

@ -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 };

View file

@ -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
}
}

View file

@ -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
View file

@ -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
View file

@ -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;

View file

@ -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()));

View file

@ -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;

View file

@ -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()()

View file

@ -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:

View file

@ -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
View file

@ -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
View file

@ -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();

View file

@ -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);