From 39caffd6e67fe568920d985bc0ba936898a077da Mon Sep 17 00:00:00 2001 From: Joerg Hoppe Date: Sat, 10 Aug 2019 10:19:05 +0200 Subject: [PATCH] Emulated DL11: stream interface parallel to RS232. demo: "dl11 rcv" and "dl11 wait" script extension cleanup --- 10.01_base/2_src/arm/unibus.cpp | 2 +- 10.01_base/2_src/arm/utils.cpp | 123 +++++++++- 10.01_base/2_src/arm/utils.hpp | 8 +- 10.02_devices/2_src/dl11w.cpp | 22 +- 10.02_devices/2_src/dl11w.hpp | 5 + 10.02_devices/2_src/rs232adapter.cpp | 215 ++++++++++++++++++ 10.02_devices/2_src/rs232adapter.hpp | 86 +++++++ 10.02_devices/3_test/dl11w/zdld.cmd | 16 +- 10.02_devices/3_test/rl02/ZRLJB1.BIC | Bin 0 -> 11730 bytes 10.03_app_demo/2_src/makefile | 4 + 10.03_app_demo/2_src/menu_buslatches.cpp | 2 +- .../2_src/menu_device_exercisers.cpp | 4 +- 10.03_app_demo/2_src/menu_devices.cpp | 93 +++++++- 10.03_app_demo/2_src/menu_interrupts.cpp | 4 +- 10.03_app_demo/2_src/menu_masterslave.cpp | 4 +- .../5_applications/cpu/cpu20hellodl11.cmd | 30 +++ .../5_applications/cpu/cpu20hellodl11.sh | 6 + 17 files changed, 587 insertions(+), 37 deletions(-) create mode 100644 10.02_devices/2_src/rs232adapter.cpp create mode 100644 10.02_devices/2_src/rs232adapter.hpp create mode 100644 10.02_devices/3_test/rl02/ZRLJB1.BIC create mode 100644 10.03_app_demo/5_applications/cpu/cpu20hellodl11.cmd create mode 100644 10.03_app_demo/5_applications/cpu/cpu20hellodl11.sh diff --git a/10.01_base/2_src/arm/unibus.cpp b/10.01_base/2_src/arm/unibus.cpp index b246a1e..4ee85d1 100644 --- a/10.01_base/2_src/arm/unibus.cpp +++ b/10.01_base/2_src/arm/unibus.cpp @@ -147,7 +147,7 @@ bool unibus_c::dma(enum unibus_c::arbitration_mode_enum arbitration_mode, bool b set_arbitration_mode(arbitration_mode); // changes PRU behaviour - timeout.start(0); // no timeout, just running timer + timeout.start_ns(0); // no timeout, just running timer unibusadapter->DMA(*dma_request, blocking, control, startaddr, buffer, wordcount); dmatime_ns = timeout.elapsed_ns(); diff --git a/10.01_base/2_src/arm/utils.cpp b/10.01_base/2_src/arm/utils.cpp index 5305c92..a3a0c10 100644 --- a/10.01_base/2_src/arm/utils.cpp +++ b/10.01_base/2_src/arm/utils.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -85,31 +86,38 @@ timeout_c::timeout_c() { uint64_t timeout_c::get_resolution_ns() { struct timespec res; clock_getres(CLOCK_MONOTONIC, &res); - return BILLION * res.tv_sec + res.tv_nsec ; + return BILLION * res.tv_sec + res.tv_nsec; } - -void timeout_c::start(uint64_t duration_ns) { +void timeout_c::start_ns(uint64_t duration_ns) { this->duration_ns = duration_ns; clock_gettime(CLOCK_MONOTONIC, &starttime); } +void timeout_c::start_us(uint64_t duration_us) { + start_ns(duration_us * 1000); +} + +void timeout_c::start_ms(uint64_t duration_ms) { + start_ns(duration_ms * MILLION); +} + uint64_t timeout_c::elapsed_ns(void) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - uint64_t result = (uint64_t)BILLION * (now.tv_sec - starttime.tv_sec) + (uint64_t)now.tv_nsec - starttime.tv_nsec; - return result ; + uint64_t result = (uint64_t) BILLION * (now.tv_sec - starttime.tv_sec) + + (uint64_t) now.tv_nsec - starttime.tv_nsec; + return result; } uint64_t timeout_c::elapsed_us(void) { - return elapsed_ns() / 1000 ; + return elapsed_ns() / 1000; } uint64_t timeout_c::elapsed_ms(void) { - return elapsed_ns() / MILLION ; + return elapsed_ns() / MILLION; } - bool timeout_c::reached() { return (elapsed_ns() > duration_ns); } @@ -264,3 +272,102 @@ struct timespec timespec_future_us(unsigned offset_us) { } */ +// decodes C escape sequences \char, \nnn octal, \xnn hex +// result string is smaller or same as "encoded", must have at least "ncoded" size +// return: true of OK, else false +static int digitval(char c) { + c = toupper(c); + if (c < '0') + return 0; // illegal + else if (c <= '9') + return c - '0'; + else if (c < 'A') + return 0; // illegal + else if (c <= 'F') + return c - 'A' + 10; + else + return 0; // illegal +} + +bool str_decode_escapes(char *result, unsigned result_size, char *encoded) { + int c ; + char *wp = result; // write pointer + char *rp = encoded; // read pointer + assert(result_size >= strlen(encoded)); + while (*rp) { + if (*rp != '\\') { + *wp++ = *rp++; // not escaped + continue; + } + // decode escapes + rp++; // eat backslash + int n = strspn(rp, "01234567"); // + if (n >= 1) { // \nnn given + // use max 3 digits for octal literal + c = digitval(*rp++) ; + if (n >= 2) + c = c * 8 + digitval(*rp++) ; + if (n >= 3) + c = c * 8 + digitval(*rp++) ; + *wp++ = (char) c; + continue; + } + switch (*rp) { + // literals allowed behind backslash + case '\'': + case '"': + case '?': + case '\\': + *wp++ = *rp++; + continue; + case 'a': + *wp++ = 0x07; // audible bell + rp++; + continue; + case 'b': + *wp++ = 0x08; // backspace + rp++; + continue; + case 'f': + *wp++ = 0x0c; // form feed - new page + rp++; + continue; + case 'n': + *wp++ = 0x0a; // line feed - new line + rp++; + continue; + case 'r': + *wp++ = 0x0d; // carriage return + rp++; + continue; + case 't': + *wp++ = 0x09; // horizontal tab + rp++; + continue; + case 'v': + *wp++ = 0x0b; // vertical tab + rp++; + continue; + case 'x': // hex: \xnn + rp++; // eat "x" + // in contrast to the standard, max 2 hex digits are evaualted, not arbitrary amount. + // this makes it easy to write "L 200" as "L\x20200". + // Else \xnnnn may eat following chars not meant as part of the hex sequence + // convert and skip arbitrary count of hex characters + n = strspn(rp, "0123456789aAbBcCdDeEfF"); + if (n < 1) + return false ; // no hexdigit after "x" + // use max 2 digits for hex literal + c = digitval(toupper(*rp++)) ; + if (n >= 2) + c = c * 16 + digitval(toupper(*rp++)) ; + // c = strtol(rp, &rp, 16) ; if unlimited hex chars + *wp++ = (char) c; + continue; + default: + return false; // unknown char behind backslash + } + } + *wp = 0; + return true; +} diff --git a/10.01_base/2_src/arm/utils.hpp b/10.01_base/2_src/arm/utils.hpp index 50321ed..fc08390 100644 --- a/10.01_base/2_src/arm/utils.hpp +++ b/10.01_base/2_src/arm/utils.hpp @@ -66,7 +66,9 @@ private: public: timeout_c(); uint64_t get_resolution_ns(void) ; - void start(uint64_t duration_ns); + void start_ns(uint64_t duration_ns); + void start_us(uint64_t duration_us) ; + void start_ms(uint64_t duration_ms) ; uint64_t elapsed_ns(void); uint64_t elapsed_us(void); uint64_t elapsed_ms(void); @@ -109,4 +111,8 @@ struct timespec timespec_add_us(struct timespec ts, unsigned us); // add microseconds to current time struct timespec timespec_future_us(unsigned offset_us); +// decodes C escape sequences \char, \nnn octal, \xnn hex +bool str_decode_escapes(char *result, unsigned result_size, char *encoded) ; + + #endif /* _UTILS_H_ */ diff --git a/10.02_devices/2_src/dl11w.cpp b/10.02_devices/2_src/dl11w.cpp index e112fb3..68e4622 100644 --- a/10.02_devices/2_src/dl11w.cpp +++ b/10.02_devices/2_src/dl11w.cpp @@ -48,6 +48,7 @@ #include "dl11w.hpp" #include "rs232.hpp" +#include "rs232adapter.hpp" //------------------------------------------------- @@ -114,6 +115,8 @@ slu_c::slu_c() : serialport.value = "ttyS2"; // labeled "UART2" on PCB baudrate.value = 9600; mode.value = "8N1"; + + rs232adapter.rs232 = &rs232; } slu_c::~slu_c() { @@ -124,6 +127,7 @@ bool slu_c::on_param_changed(parameter_c *param) { if (enabled.new_value) { // enable SLU: setup COM serial port // setup for BREAK and parity evaluation + rs232adapter.rcv_termios_error_encoding = true; if (rs232.OpenComport(serialport.value.c_str(), baudrate.value, mode.value.c_str(), true)) { ERROR("Can not open serial port %s", serialport.value.c_str()); @@ -136,7 +140,7 @@ bool slu_c::on_param_changed(parameter_c *param) { mode.readonly = true; INFO("Serial port %s opened", serialport.value.c_str()); - char buff[256] ; + char buff[256]; sprintf(buff, "Serial port %s opened\n\r", serialport.value.c_str()); rs232.cputs(buff); } else { @@ -225,7 +229,7 @@ void slu_c::set_xcsr_dati_value_and_INTR(void) { default: set_register_dati_value(reg_xcsr, val, __func__); } - + } void slu_c::eval_xcsr_dato_value(void) { @@ -342,7 +346,7 @@ void slu_c::on_init_changed(void) { void slu_c::worker_rcv(void) { timeout_c timeout; int n; - char buffer[BUFLEN + 1]; + unsigned char buffer[BUFLEN + 1]; // poll with frequency > baudrate, to see single bits //unsigned poll_periods_us = 1000000 / baudrate.value; @@ -366,7 +370,7 @@ void slu_c::worker_rcv(void) { // rcv_active: can only be set by polling the UART input GPIO pin? // at the moments, it is only sent on maintenance loopback xmt /* read serial data, if any */ - if (rs232.PollComport((unsigned char*) buffer, 1)) { + if (rs232adapter.byte_rcv_poll(buffer)) { pthread_mutex_lock(&on_after_rcv_register_access_mutex); // signal changes atomic against UNIBUS accesses rcv_or_err = rcv_fr_err = rcv_p_err = 0; if (rcv_done) // not yet cleared? overrun! @@ -376,12 +380,12 @@ void slu_c::worker_rcv(void) { If IGNPAR=0, PARMRK=1: error on received as \377 \0 \377 received as \377 \377 */ - n = rs232.PollComport((unsigned char*) buffer, 1); + n = rs232adapter.byte_rcv_poll(buffer); assert(n); // next char after 0xff escape immediately available if (buffer[0] == 0) { // error flags rcv_fr_err = rcv_p_err = 1; - n = rs232.PollComport((unsigned char*) buffer, 1); + n = rs232adapter.byte_rcv_poll(buffer); assert(n); // next char after 0xff 0 seq is data" rcv_buffer = buffer[0]; } else if (buffer[0] == 0xff) { // enocoded 0xff @@ -421,7 +425,7 @@ void slu_c::worker_xmt(void) { } // 2. transmit - rs232.SendByte(xmt_buffer); + rs232adapter.byte_xmt_sent(xmt_buffer); xmt_ready = 0; set_xcsr_dati_value_and_INTR(); if (xmt_maint) { // loop back: simulate data byte coming in @@ -437,7 +441,7 @@ void slu_c::worker_xmt(void) { pthread_mutex_lock(&on_after_xmt_register_access_mutex); if (xmt_maint) // put sent byte into rcv buffer, receiver will poll it - rs232.LoopbackByte(xmt_buffer); + rs232adapter.byte_loopback(xmt_buffer); xmt_ready = 1; set_xcsr_dati_value_and_INTR(); @@ -583,7 +587,7 @@ void ltc_c::worker(unsigned instance) { INFO("KW11 time resolution is < %u us", (unsigned )(global_time.get_resolution_ns() / 1000)); - global_time.start(0); + global_time.start_ns(0); global_next_edge_ns = global_time.elapsed_ns(); uint64_t global_edge_count = 0; while (!workers_terminate) { diff --git a/10.02_devices/2_src/dl11w.hpp b/10.02_devices/2_src/dl11w.hpp index 8e1fb04..7b61613 100644 --- a/10.02_devices/2_src/dl11w.hpp +++ b/10.02_devices/2_src/dl11w.hpp @@ -35,6 +35,8 @@ using namespace std; #include "unibusdevice.hpp" #include "parameter.hpp" #include "rs232.hpp" +#include "rs232adapter.hpp" + // socket console settings //#define IP_PORT 5001 @@ -98,7 +100,10 @@ enum slu_reg_index { class slu_c: public unibusdevice_c { private: rs232_c rs232; /// COM port interface +public: + rs232adapter_c rs232adapter; /// stream router + private: unibusdevice_register_t *reg_rcsr; unibusdevice_register_t *reg_rbuf; unibusdevice_register_t *reg_xcsr; diff --git a/10.02_devices/2_src/rs232adapter.cpp b/10.02_devices/2_src/rs232adapter.cpp new file mode 100644 index 0000000..fba66ae --- /dev/null +++ b/10.02_devices/2_src/rs232adapter.cpp @@ -0,0 +1,215 @@ +/* rs232adapter.cpp: route byte xmt/rcv interface to stream and RS232 + + Copyright (c) 2019, Joerg Hoppe + j_hoppe@t-online.de, www.retrocmp.com + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + 8-aug-2019 JH edit start + + This is a stream router. + - Main interface is a byte-port with sent/poll functions + - the bytestream can be routed to a RS232 object for TxD and RxD + - the bytestream can be routed to two streams: rcv/xmt + - for the xmt stream a pattern matcher is implemented, which search for strigns in the stream + + To be used to router DL11 RCV/XMT ports to RS232 and/or program functions + + + + + + stream_rcv stream_xmt upper end "STREAM" + \ / / \ + | | + | +---> ringbuffer "PATTERN" + | | + +--------------|----rs232.Poll()---< RxD "RS232" + | | + | +----rs232.Send()---> TxD + | | + | | + \ / / \ + byte_rcv_poll() byte_xmt_sent() lower end "BYTE" + + DL11 RCVR DL11 XMT DL11 + DATI DATO UNIBUS + + + + + // check RS232 or buffer for data bytes, + // which shall be "published" by DL11 RCVer + bool poll_receiver_input(unsigned char *rcvchar) { + if (input_queue.size()) { + // in character to send: has priority over RS232 input + *rcvchar = input_queue.pop() ; + return true ; + // should wait for one byte time before delivering next buffer char + } else + return rs232.PollComport(rcvchar, 1) ; + } + + + string pattern_buffer ; + string xmt_search // search expression in transmitter output + void send_transmitter_output(unsigned char xmtchar) { + + // show output on stdio ? + if (output_stream) + output_stream.out(xmtchar) ; + // save output in ring buffer + pattern_buffer += xmtchar ; + if (pattern_buffer.size() >= PATTERN_BUFFER_LEN) + pattern_buffer.erase(0,1) ; // delete first + // if search expression appears in pattern buffer: + if (pattern_buffer.find(xmt_search) !=std::string::npos ) { + // added char makes search found + + pattern_buffer.clear() ; + } + + } + + + demo: + + dl11 waitfor + dl11 waitfor 1000 @ + + dl11.xmt_monitor_clear() + dl11.xmt_monitor_pattern := + timeout.start_ms() + while(!timeout.reached && !dl11_xmt_monitor_pattern_match()) + sleep(1ms) ; + if (timeout. + + reached() { + // abort script + inputline_clearscript(); + } + + + -> will clear ringbuffer, montior dl11 output + + + + + + */ +#include +#include +#include +#include "rs232adapter.hpp" + +rs232adapter_c::rs232adapter_c() { + log_label = "ADP232"; + + rs232 = NULL; + stream_rcv = NULL; + stream_xmt = NULL; + rcv_termios_error_encoding = false; + rcv_decoder.clear(); + pattern_stream_data[0] = 0; + pattern[0] = 0; + pattern_found = false; + baudrate = 0; // default: no delay + rcv_baudrate_delay.start_us(0); // start with elapsed() == true" +} + +// BYTE interface: check for received char (from stream or RS232) +// Attention: must produce 0xff 0 sequences for termios encoded byte errors +// and 0xff 0xff for \ff +// If IGNPAR=0, PARMRK=1: error on received as \377 \0 +// \377 received as \377 \377 +bool rs232adapter_c::byte_rcv_poll(unsigned char *rcvchar) { + + pthread_mutex_lock(&mutex); + bool result = false; + // mixing input streams, with RS232 priority + + // loopback or part of previous 0xff,0xff sequence ? + int c = rcv_decoder.get(); + if (c != EOF) { + *rcvchar = c; + result = true; + } + if (!result && rs232) { + // rs2323 must be programmed to generate 0xff 0xff sequences + result = rs232->PollComport(rcvchar, 1); + } + + if (stream_rcv && !result) { + // deliver next char from stream delayed, with simulated baudrate + if (baudrate == 0 || rcv_baudrate_delay.reached()) { + int c = stream_rcv->get(); + if (c != EOF) { + *rcvchar = c; + if (rcv_termios_error_encoding && c == 0xff) { + // mark 2nd 0xff for output on next call + rcv_decoder.clear(); + rcv_decoder.put(0xff); + } + result = true; + if (baudrate != 0) + rcv_baudrate_delay.start_us(10 * MILLION / baudrate); // assume 10 bits per char + } + } + } + pthread_mutex_unlock(&mutex); + return result; +} + +void rs232adapter_c::byte_xmt_sent(unsigned char xmtchar) { + if (rs232) + rs232->SendByte(xmtchar); + if (stream_xmt) + stream_xmt->put(xmtchar); + // pattern ring buffer + unsigned n = strlen(pattern); + if (n) { + // put new chars at end of string + unsigned m = strlen(pattern_stream_data); + assert(m < pattern_max_len); + pattern_stream_data[m] = xmtchar; + pattern_stream_data[m + 1] = 0; + // only keep the last chars in buffer. + while ((m = strlen(pattern_stream_data)) > n) + // strip first char, should loop only once + memmove(pattern_stream_data, pattern_stream_data + 1, m); + if (strstr(pattern_stream_data, pattern)) + pattern_found = true; // user must clear + } +// pattern_buffer. +} + +void rs232adapter_c::byte_loopback(unsigned char xmtchar) { + // not a queue, only single char (DL11 loopback) + rcv_decoder.clear(); + rcv_decoder.put(xmtchar); + if (rcv_termios_error_encoding && xmtchar == 0xff) + rcv_decoder.put(0xff); + // fill intermediate buffer with seqeunce to receive +} + +void rs232adapter_c::set_pattern(char *pattern) { + strncpy(this->pattern, pattern, pattern_max_len); + pattern_found = false; + pattern_stream_data[0] = 0; +} + diff --git a/10.02_devices/2_src/rs232adapter.hpp b/10.02_devices/2_src/rs232adapter.hpp new file mode 100644 index 0000000..4728c7d --- /dev/null +++ b/10.02_devices/2_src/rs232adapter.hpp @@ -0,0 +1,86 @@ +/* rs232adapter.hpp: route byte xmt/rcv interface to stream and RS232 + + Copyright (c) 2019, Joerg Hoppe + j_hoppe@t-online.de, www.retrocmp.com + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + 8-aug-2019 JH edit start + */ + +#ifndef _RS232ADAPTER_HPP_ +#define _RS232ADAPTER_HPP_ + +#include +#include +#include +#include "utils.hpp" +#include "logsource.hpp" +#include "rs232.hpp" + +class rs232adapter_c: public logsource_c { +private: + // for loopback and to decode 0xff to 0xff,0xff + std::stringstream rcv_decoder; + + // last sequence of xmt data for pattern matching + static const int pattern_max_len = 256 ; + char pattern[pattern_max_len+1]; // if != "", this is search for + char pattern_stream_data[pattern_max_len+1]; + + // deliver rcv chars delayed by this "baudrate" + timeout_c rcv_baudrate_delay ; + +public: + + rs232adapter_c(); + + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + + unsigned baudrate ; // deliver rcv chars throttled by this "baudrate" + + // if true, an inject 0xff is delivered as 0xff,0xff. + // this is compatible with termios(3) encoding of error flags + // If IGNPAR=0, PARMRK=1: error on received as \377 \0 + // \377 received as \377 \377 + bool rcv_termios_error_encoding; + + /*** RS232 interface ***/ + rs232_c *rs232; // if assigned, routing to initialized RS232 port + + /*** BYTE interface ***/ + bool byte_rcv_poll(unsigned char *rcvchar); + void byte_xmt_sent(unsigned char xmtchar); + void byte_loopback(unsigned char xmtchar); + + /*** STREAM interface ***/ + std::istream *stream_rcv; // users sets this to a stream which producess chars + // may be a stringstream to inject characters + + std::ostream *stream_xmt; // users sets this to a stream in which + // chars are written to be transferred. + // may be "cout", or an stringstream + + /*** PATTERN detection ***/ + void set_pattern(char *pattern); + bool pattern_found; // switches ture on match, user must clear + +}; + +#endif // _RS232ADAPTER_HPP_ + diff --git a/10.02_devices/3_test/dl11w/zdld.cmd b/10.02_devices/3_test/dl11w/zdld.cmd index ca95ee2..55255b0 100644 --- a/10.02_devices/3_test/dl11w/zdld.cmd +++ b/10.02_devices/3_test/dl11w/zdld.cmd @@ -6,6 +6,7 @@ sd dl11 .input en dl11 +en kw11 pwr @@ -14,6 +15,19 @@ pwr m i +en rl +en rl0 +sd rl0 +p emulation_speed 10 +p runstopbutton 0 # released: "LOAD" +p powerswitch 1 # power on, now in "load" state +p image xxdp25.rl02 # mount image file + p runstopbutton 1 + m lp /root/10.02_devices/3_test/dl11w/ZDLDI0.BIN -.print Now start ZDLD at address 200 \ No newline at end of file +.print Now start ZDLD at address 200 +.print Or boot XXDP from DL, then execute "R ZDLDI0" +.print Set switch register with "D 176" +.print 100000 = HALT on error, 2000=error flags, 400= test BREAK, 100=disable KW11 +# d 176 100000 # HALT on error diff --git a/10.02_devices/3_test/rl02/ZRLJB1.BIC b/10.02_devices/3_test/rl02/ZRLJB1.BIC new file mode 100644 index 0000000000000000000000000000000000000000..aaa65ff7e5ac96dce02f48aa090f900f77634dfb GIT binary patch literal 11730 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 JzyJFZ_-_cb#-;!O literal 0 HcmV?d00001 diff --git a/10.03_app_demo/2_src/makefile b/10.03_app_demo/2_src/makefile index bded5b9..dbfdcda 100644 --- a/10.03_app_demo/2_src/makefile +++ b/10.03_app_demo/2_src/makefile @@ -105,6 +105,7 @@ OBJECTS = $(OBJDIR)/application.o \ $(OBJDIR)/mscp_server.o \ $(OBJDIR)/mscp_drive.o \ $(OBJDIR)/rs232.o \ + $(OBJDIR)/rs232adapter.o \ $(OBJDIR)/dl11w.o \ $(OBJDIR)/storagedrive.o \ $(OBJDIR)/storagecontroller.o \ @@ -240,6 +241,9 @@ $(OBJDIR)/mscp_drive.o : $(DEVICE_SRC_DIR)/mscp_drive.cpp $(DEVICE_SRC_DIR)/ms $(OBJDIR)/rs232.o : $(DEVICE_SRC_DIR)/rs232.cpp $(DEVICE_SRC_DIR)/rs232.hpp $(CC) $(CCFLAGS) $< -o $@ +$(OBJDIR)/rs232adapter.o : $(DEVICE_SRC_DIR)/rs232adapter.cpp $(DEVICE_SRC_DIR)/rs232adapter.hpp + $(CC) $(CCFLAGS) $< -o $@ + $(OBJDIR)/dl11w.o : $(DEVICE_SRC_DIR)/dl11w.cpp $(DEVICE_SRC_DIR)/dl11w.hpp $(CC) $(CCFLAGS) $< -o $@ diff --git a/10.03_app_demo/2_src/menu_buslatches.cpp b/10.03_app_demo/2_src/menu_buslatches.cpp index 8680f56..65c87f5 100644 --- a/10.03_app_demo/2_src/menu_buslatches.cpp +++ b/10.03_app_demo/2_src/menu_buslatches.cpp @@ -77,7 +77,7 @@ static bool buslatches_oscillate_pin(buslatches_wire_info_t *si, unsigned timeou timeout_c timeout; unsigned count; - timeout.start(1000000L * timeout_ms); + timeout.start_ms(timeout_ms); SIGINTcatchnext(); // high speed loop diff --git a/10.03_app_demo/2_src/menu_device_exercisers.cpp b/10.03_app_demo/2_src/menu_device_exercisers.cpp index 1eacc65..827965b 100644 --- a/10.03_app_demo/2_src/menu_device_exercisers.cpp +++ b/10.03_app_demo/2_src/menu_device_exercisers.cpp @@ -107,7 +107,7 @@ void application_c::menu_device_exercisers(void) { printf("e Examine all device registers\n"); printf("d Deposit octal val into UNIBUS address.\n"); printf("e Deposit octal val into UNIBUS address.\n"); - printf("dl c|s|f Debug log: Clear, Show on console, dump to File.\n"); + printf("dbg c|s|f Debug log: Clear, Show on console, dump to File.\n"); printf(" (file = %s)\n", logger->default_filepath.c_str()); printf("init Pulse UNIBUS INIT\n"); printf("pwr Simulate UNIBUS power cycle (ACLO/DCLO)\n"); @@ -124,7 +124,7 @@ void application_c::menu_device_exercisers(void) { unibus->init(); } else if (!strcasecmp(s_opcode, "pwr")) { unibus->powercycle(); - } else if (!strcasecmp(s_opcode, "dl") && n_fields == 2) { + } else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) { if (!strcasecmp(s_param[0], "c")) { logger->clear(); printf("Debug log cleared.\n"); diff --git a/10.03_app_demo/2_src/menu_devices.cpp b/10.03_app_demo/2_src/menu_devices.cpp index 84ab102..61f0af8 100644 --- a/10.03_app_demo/2_src/menu_devices.cpp +++ b/10.03_app_demo/2_src/menu_devices.cpp @@ -82,7 +82,7 @@ static void load_memory(enum unibus_c::arbitration_mode_enum arbitration_mode, "Loaded MACRO-11 listing from file \"%s\" into memory: %d words from %06o to %06o.\n", fname, membuffer->get_word_count(), firstaddr, lastaddr); if (entry_label == NULL) - printf(" No entry address label.\n") ; + printf(" No entry address label.\n"); else if (membuffer->entry_address != MEMORY_ADDRESS_INVALID) printf(" Entry address at \"%s\" label is %06o.\n", entry_label, membuffer->entry_address); @@ -99,11 +99,11 @@ static void load_memory(enum unibus_c::arbitration_mode_enum arbitration_mode, static void print_device(device_c *device) { unibusdevice_c *ubdevice = dynamic_cast(device); if (ubdevice) - printf("- %-12s Type %s, %s.\n",ubdevice->name.value.c_str(), - ubdevice->type_name.value.c_str(), ubdevice->get_unibus_resource_info()) ; + printf("- %-12s Type %s, %s.\n", ubdevice->name.value.c_str(), + ubdevice->type_name.value.c_str(), ubdevice->get_unibus_resource_info()); else - printf("- %-12s Type %s.\n",device->name.value.c_str(), - device->type_name.value.c_str()) ; + printf("- %-12s Type %s.\n", device->name.value.c_str(), + device->type_name.value.c_str()); } // CPU is enabled, act as ARBITRATION_MASTER @@ -120,11 +120,12 @@ void application_c::menu_devices(bool with_CPU) { unibusdevice_c *unibuscontroller = NULL; unsigned n_fields; char *s_choice; - char s_opcode[256], s_param[2][256]; + char s_opcode[256], s_param[3][256]; // with_CPU: the emulated CPU is answering BR and NPR requests. if (with_CPU) - arbitration_mode = unibus_c::ARBITRATION_MODE_MASTER; + arbitration_mode = unibus_c::ARBITRATION_MODE_NONE; +// arbitration_mode = unibus_c::ARBITRATION_MODE_MASTER; else arbitration_mode = unibus_c::ARBITRATION_MODE_CLIENT; @@ -156,6 +157,12 @@ void application_c::menu_devices(bool with_CPU) { uda_c *UDA50 = new uda_c(); // Create SLU+ LTC slu_c *DL11 = new slu_c(); + // to inject characters into DL11 receiver + std::stringstream dl11_rcv_stream(std::ios::app | std::ios::in | std::ios::out); + DL11->rs232adapter.stream_rcv = &dl11_rcv_stream; + DL11->rs232adapter.stream_xmt = NULL; // do not echo output to stdout + DL11->rs232adapter.baudrate = DL11->baudrate.value; // limit speed of injected chars + ltc_c *LTC = new ltc_c(); // //demo_regs.install(); @@ -225,7 +232,18 @@ void application_c::menu_devices(bool with_CPU) { printf("e Examine octal UNIBUS address.\n"); printf("d Deposit octal val into UNIBUS address.\n"); } - printf("dl c|s|f Debug log: Clear, Show on console, dump to File.\n"); + if (DL11->enabled.value) { + printf( + "dl11 rcv [] inject characters as if DL11 received them.\n"); + printf( + " Before output there's an optional pause of milliseconds.\n"); + printf( + " uses C-escapes: \"\\r\"= CR, \040 = space, etc.\n"); + printf( + "dl11 wait wait time until DL11 was ordered to transmit .\n"); + printf(" On timeout, script execution is terminated.\n"); + } + printf("dbg c|s|f Debug log: Clear, Show on console, dump to File.\n"); printf(" (file = %s)\n", logger->default_filepath.c_str()); printf("init Pulse UNIBUS INIT\n"); printf("pwr Simulate UNIBUS power cycle (ACLO/DCLO)\n"); @@ -235,14 +253,15 @@ void application_c::menu_devices(bool with_CPU) { printf("\n"); try { - n_fields = sscanf(s_choice, "%s %s %s", s_opcode, s_param[0], s_param[1]); + n_fields = sscanf(s_choice, "%s %s %s %s", s_opcode, s_param[0], s_param[1], + s_param[2]); if (!strcasecmp(s_opcode, "q")) { ready = true; } else if (!strcasecmp(s_opcode, "init")) { unibus->init(); } else if (!strcasecmp(s_opcode, "pwr")) { unibus->powercycle(); - } else if (!strcasecmp(s_opcode, "dl") && n_fields == 2) { + } else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) { if (!strcasecmp(s_param[0], "c")) { logger->clear(); printf("Debug log cleared.\n"); @@ -456,7 +475,61 @@ void application_c::menu_devices(bool with_CPU) { if (timeout) printf("Bus timeout at %06o.\n", mailbox->dma.cur_addr); // cur_addr now on last address in block + } else if (DL11->enabled.value && !strcasecmp(s_opcode, "dl11")) { + if ((n_fields == 3 || n_fields == 4) && !strcasecmp(s_param[0], "rcv")) { + // dl11 rcv [] + char buff[256]; + unsigned wait_ms; + timeout_c timeout; + char *s; + if (n_fields == 3) { + wait_ms = 0; + s = s_param[1]; + } else { + wait_ms = strtol(s_param[1], NULL, 10); + s = s_param[2]; + } + if (!str_decode_escapes(buff, sizeof(buff), s)) { + printf("Error in escape sequences.\n"); + inputline_init(); + continue; + } + timeout.wait_ms(wait_ms); + // let DL11 produce chars in 'buff' + pthread_mutex_lock(&DL11->rs232adapter.mutex); + dl11_rcv_stream.clear(); + dl11_rcv_stream.write(buff, strlen(buff)); // add endlessly to string + // dl11_rcv_stream.str(buff); + pthread_mutex_unlock(&DL11->rs232adapter.mutex); +// printf("AAA %d\n", (int)dl11_rcv_stream.get()) ; + } else if (n_fields == 4 && !strcasecmp(s_param[0], "wait")) { + // dl11 wait + timeout_c timeout, timeout2; + unsigned ms = strtol(s_param[1], NULL, 10); + char buff[256]; + if (!str_decode_escapes(buff, sizeof(buff), s_param[2])) { + printf("Error in escape sequences.\n"); + inputline_init(); + continue; + } + // while waiting echo to stdout, for diag + DL11->rs232adapter.stream_xmt = &cout; + DL11->rs232adapter.set_pattern(buff); + timeout.start_ms(ms); + while (!timeout.reached() && !DL11->rs232adapter.pattern_found) + timeout2.wait_ms(1); + DL11->rs232adapter.stream_xmt = NULL; // stop echo + if (!DL11->rs232adapter.pattern_found) { + printf( + "\nPDP-11 did not xmt \"%s\" over DL11 within %u ms, aborting script\n", + s_param[2], ms); + inputline_init(); + } + } else { + printf("Unknown DL11 command \"%s\"!\n", s_choice); + show_help = true; + } } else { printf("Unknown command \"%s\"!\n", s_choice); show_help = true; diff --git a/10.03_app_demo/2_src/menu_interrupts.cpp b/10.03_app_demo/2_src/menu_interrupts.cpp index 330ecdb..dba9b77 100644 --- a/10.03_app_demo/2_src/menu_interrupts.cpp +++ b/10.03_app_demo/2_src/menu_interrupts.cpp @@ -110,7 +110,7 @@ void application_c::menu_interrupts(void) { printf(" 0..%u possible.\n", (unsigned) test_controller->dma_channel_count); } - printf("dl c|s|f Debug log: Clear, Show on console, dump to File.\n"); + printf("dbg c|s|f Debug log: Clear, Show on console, dump to File.\n"); printf("pwr Simulate UNIBUS power cycle (ACLO/DCLO)\n"); printf("q Quit\n"); } @@ -227,7 +227,7 @@ void application_c::menu_interrupts(void) { &(dma_buffer->data.words[addr_from / 2]), wordcount); printf("DEPOSIT in slot %d started for %06o..%06o\n", dma_request->get_priority_slot(), addr_from, addr_to); - } else if (!strcasecmp(s_opcode, "dl") && n_fields == 2) { + } else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) { if (!strcasecmp(s_param[0], "c")) { logger->clear(); printf("Debug log cleared.\n"); diff --git a/10.03_app_demo/2_src/menu_masterslave.cpp b/10.03_app_demo/2_src/menu_masterslave.cpp index ce1412c..2a009d2 100644 --- a/10.03_app_demo/2_src/menu_masterslave.cpp +++ b/10.03_app_demo/2_src/menu_masterslave.cpp @@ -130,7 +130,7 @@ void application_c::menu_masterslave(enum unibus_c::arbitration_mode_enum arbitr printf("init Pulse UNIBUS INIT\n"); printf("pwr Simulate UNIBUS power cycle (ACLO/DCLO)\n"); printf( - "dl c|s|f Debug log: Clear, Show on console, dump to File.\n"); + "dbg c|s|f Debug log: Clear, Show on console, dump to File.\n"); printf(" (file = %s)\n", logger->default_filepath.c_str()); printf("i Info about address tables\n"); @@ -351,7 +351,7 @@ void application_c::menu_masterslave(enum unibus_c::arbitration_mode_enum arbitr unibus->mem_read(arbitration_mode, membuffer->data.words, 0, end_addr, &timeout); printf("Saving to file %s\n", s_param[0]); membuffer->save_binary(s_param[0], end_addr + 2); - } else if (!strcasecmp(s_opcode, "dl") && n_fields == 2) { + } else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) { if (!strcasecmp(s_param[0], "c")) { logger->clear(); printf("Debug log cleared.\n"); diff --git a/10.03_app_demo/5_applications/cpu/cpu20hellodl11.cmd b/10.03_app_demo/5_applications/cpu/cpu20hellodl11.cmd new file mode 100644 index 0000000..3ab7d72 --- /dev/null +++ b/10.03_app_demo/5_applications/cpu/cpu20hellodl11.cmd @@ -0,0 +1,30 @@ +# Inputfile for demo to execute "Hello world" +# Uses emulated CPU and (physical or emulated) DL11 +# Read in with command line option "demo --cmdfile ..." + +dc # "device with cpu" menu + +m i # emulate missing memory + +en dl11 # switch on emulated DL11 + +en cpu20 # switch on emulated 11/20 CPU +sd cpu20 # select + +m ll serial.lst # load test program + +p + +init + +.print Emulated PDP-11/20 CPU will now output "Hello world" +.print and enter a serial echo loop on DL11 at 177650. +.print Make sure physical CPU is disabled. + +.input + +p run 1 + +.print CPU20 started + + diff --git a/10.03_app_demo/5_applications/cpu/cpu20hellodl11.sh b/10.03_app_demo/5_applications/cpu/cpu20hellodl11.sh new file mode 100644 index 0000000..af74568 --- /dev/null +++ b/10.03_app_demo/5_applications/cpu/cpu20hellodl11.sh @@ -0,0 +1,6 @@ +# starts PDP11/20 emulation +# and executes a "Hello world" on an emualted DL11 card +# Main PDP-1120 must be HALTed +cd ~/10.03_app_demo/5_applications/cpu +~/10.03_app_demo/4_deploy/demo --arb 0 --verbose --debug --cmdfile cpu20hellodl11.cmd +