diff --git a/ESP32/esp32.cpp b/ESP32/esp32.cpp new file mode 100644 index 0000000..c909131 --- /dev/null +++ b/ESP32/esp32.cpp @@ -0,0 +1,28 @@ +#include + +std::string read_terminal_line(const std::string & prompt) +{ + Serial.print(prompt.c_str()); + Serial.print(F(">")); + + std::string str; + + for(;;) { + if (Serial.available()) { + char c = Serial.read(); + + if (c == 13 || c == 10) + break; + + if (c >= 32 && c < 127) { + str += c; + + Serial.print(c); + } + } + } + + Serial.println(F("")); + + return str; +} diff --git a/ESP32/esp32.h b/ESP32/esp32.h new file mode 100644 index 0000000..a943c2a --- /dev/null +++ b/ESP32/esp32.h @@ -0,0 +1,3 @@ +#include + +std::string read_terminal_line(const std::string & prompt); diff --git a/ESP32/main.ino b/ESP32/main.ino index 20ce156..4ab3447 100644 --- a/ESP32/main.ino +++ b/ESP32/main.ino @@ -1,14 +1,20 @@ // (C) 2018-2022 by Folkert van Heusden // Released under Apache License v2.0 #include +#include #include #include +#include +#include +#include +#include -#include "memory.h" #include "cpu.h" +#include "error.h" +#include "esp32.h" +#include "memory.h" #include "tty.h" #include "utils.h" -#include "error.h" #define NEOPIXELS_PIN 25 @@ -44,6 +50,8 @@ void setBootLoader(bus *const b) { } void panel(void *p) { + Serial.println(F("panel task started")); + bus *const b = reinterpret_cast(p); cpu *const c = b->getCpu(); @@ -78,6 +86,168 @@ void panel(void *p) { } } +SemaphoreHandle_t terminal_mutex = xSemaphoreCreateMutex(); + +TaskHandle_t wifi_task { nullptr }; + +char terminal[25][80]; +uint8_t tx = 0, ty = 0; + +void delete_first_line() { + memmove(&terminal[0][0], &terminal[1][0], sizeof(terminal[1])); + memset(&terminal[24][0], ' ', sizeof(terminal[24])); +} + +void telnet_terminal(void *p) { + bus *const b = reinterpret_cast(p); + + Serial.println(F("telnet_terminal task started")); + + for(;;) { + char c { 0 }; + + xQueueReceive(b->getTerminalQueue(), &c, portMAX_DELAY); + + Serial.println(F("queue recv")); + + xSemaphoreTake(terminal_mutex, portMAX_DELAY); + + Serial.println(F("got mutex")); + + if (c == 13 || c == 10) { + tx = 0; + + ty++; + if (ty == 25) { + delete_first_line(); + ty--; + } + } + else { + terminal[ty][tx] = c; + + tx++; + + if (tx == 80) { + tx = 0; + + ty++; + if (ty == 25) { + delete_first_line(); + ty--; + } + } + } + + xSemaphoreGive(terminal_mutex); + + Serial.println(F("notify task")); + + xTaskNotify(wifi_task, 0, eNoAction); + } +} + +void wifi(void *p) { + Serial.println(F("wifi task started")); + + uint32_t ulNotifiedValue = 0; + + int fd = socket(AF_INET, SOCK_STREAM, 0); + + struct sockaddr_in server { 0 }; + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(23); + + if (bind(fd, (struct sockaddr *)&server, sizeof(server)) == -1) + Serial.println(F("bind failed")); + + if (listen(fd, 3) == -1) + Serial.println(F("listen failed")); + + struct pollfd fds[] = { { fd, POLLIN, 0 } }; + + std::vector clients; + + for(;;) { + int rc = poll(fds, 1, 10); + + if (rc == 1) { + int client = accept(fd, nullptr, nullptr); + if (client != -1) + clients.push_back(client); + } + + if (xTaskNotifyWait(0, 0, &ulNotifiedValue, 100 / portMAX_DELAY) != pdTRUE) + continue; + + Serial.println(F("got notification")); + + xSemaphoreTake(terminal_mutex, portMAX_DELAY); + + Serial.println(F("send to clients")); + + for(size_t i=0; iadd_tty(tty_); + Serial.print(F("Starting panel (on CPU 0, main emulator runs on CPU ")); + Serial.print(xPortGetCoreID()); + Serial.println(F(")")); + xTaskCreatePinnedToCore(&panel, "panel", 2048, b, 5, nullptr, 0); + + memset(terminal, ' ', sizeof(terminal)); + xTaskCreatePinnedToCore(&telnet_terminal, "telnet", 2048, b, 5, nullptr, 0); + + xTaskCreatePinnedToCore(&wifi, "wifi", 2048, b, 5, &wifi_task, 0); + + setup_wifi_stations(); + Serial.println(F("Load RK05")); b->add_rk05(new rk05("", b)); setBootLoader(b); @@ -119,11 +301,6 @@ void setup() { Serial.flush(); - Serial.print(F("Starting panel (on CPU 0, main emulator runs on CPU ")); - Serial.print(xPortGetCoreID()); - Serial.println(F(")")); - xTaskCreatePinnedToCore(&panel, "panel", 2048, b, 5, nullptr, 0); - Serial.println(F("Press to start")); for(;;) { diff --git a/ESP32/platformio.ini b/ESP32/platformio.ini index f4f2b04..6045e70 100644 --- a/ESP32/platformio.ini +++ b/ESP32/platformio.ini @@ -16,5 +16,5 @@ monitor_speed = 115200 upload_speed = 1000000 lib_deps = greiman/SdFat@^2.1.2 fastled/FastLED@^3.5.0 -build_flags = -std=c++14 -Ofast -DESP32=1 +build_flags = -std=gnu++17 -Ofast -DESP32=1 build_unflags = -std=gnu++11 -Os diff --git a/bus.cpp b/bus.cpp index b84b0b0..9325496 100644 --- a/bus.cpp +++ b/bus.cpp @@ -31,6 +31,10 @@ bus::bus() : c(nullptr), tm11(nullptr), rk05_(nullptr), rx02_(nullptr), tty_(nul } CPUERR = MMR2 = MMR3 = PIR = CSR = 0; + +#if defined(ESP32) + queue = xQueueCreate(10, sizeof(char)); +#endif } bus::~bus() @@ -438,7 +442,12 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons if (value) { #if defined(ESP32) - Serial.print(char(value & 127)); + char c = value & 127; + + Serial.print(c); + + if (xQueueSend(queue, &c, portMAX_DELAY) != pdTRUE) + Serial.println(F("queue fail")); #else printf("%c", value & 127); #endif diff --git a/bus.h b/bus.h index 0b352d6..bd05c5e 100644 --- a/bus.h +++ b/bus.h @@ -33,6 +33,10 @@ private: uint16_t MMR2 { 0 }, MMR3 { 0 }, CPUERR { 0 }, PIR { 0 }, CSR { 0 }; +#if defined(ESP32) + QueueHandle_t queue { nullptr }; +#endif + public: bus(); ~bus(); @@ -47,6 +51,10 @@ public: cpu *getCpu() { return this -> c; } +#if defined(ESP32) + QueueHandle_t & getTerminalQueue() { return queue; } +#endif + uint16_t read(const uint16_t a, const bool word_mode, const bool use_prev=false); uint16_t readByte(const uint16_t a) { return read(a, true); } uint16_t readWord(const uint16_t a); diff --git a/rk05.cpp b/rk05.cpp index d9b5e91..7c0f2a7 100644 --- a/rk05.cpp +++ b/rk05.cpp @@ -5,6 +5,7 @@ #include "bus.h" #include "error.h" +#include "esp32.h" #include "gen.h" #include "rk05.h" #include "utils.h" @@ -42,27 +43,10 @@ rk05::rk05(const std::string & file, bus *const b) : b(b) sd.ls("/", LS_DATE | LS_SIZE | LS_R); - std::string selected_file; - while(Serial.available()) Serial.read(); - Serial.print(F("Enter filename: ")); - - for(;;) { - if (Serial.available()) { - char c = Serial.read(); - - if (c == 13 || c == 10) - break; - - if (c >= 32 && c < 127) { - selected_file += c; - - Serial.print(c); - } - } - } + std::string selected_file = read_terminal_line("Enter filename: "); Serial.print(F("Opening file: ")); Serial.println(selected_file.c_str());