From 79ef7a3af8ea8aa7f70eed8f350c1d314e025d79 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 1 May 2016 00:12:29 +0200 Subject: [PATCH] experimented, fixed bugs, implemented basic tty --- Makefile | 2 +- apr.c | 49 +++++++++++------- io.c | 5 -- main.c | 32 ++++++++++++ mem | 36 +++++++++---- op_panel.png | Bin 20946 -> 20746 bytes pdp6.h | 14 ++++-- tty.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++ ttytest.s | 43 ++++++++++++++++ 9 files changed, 283 insertions(+), 38 deletions(-) delete mode 100644 io.c create mode 100644 tty.c create mode 100644 ttytest.s diff --git a/Makefile b/Makefile index c36da57..e6c5225 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SRC=main.c apr.c mem.c io.c +SRC=main.c apr.c mem.c tty.c # clang #CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \ # -Wno-bitwise-op-parentheses diff --git a/apr.c b/apr.c index 8f227e6..0acf261 100644 --- a/apr.c +++ b/apr.c @@ -1,5 +1,10 @@ #include "pdp6.h" #include "inst.h" +#include + +word iobus0, iobus1; +void (*iobusmap[128])(void); +u8 ioreq[128]; #define DBG_AR print("AR: %012llo\n", apr->ar) #define DBG_MB print("MB: %012llo\n", apr->mb) @@ -7,7 +12,7 @@ #define DBG_MA print("MA: %06o\n", apr->ma) #define DBG_IR print("IR: %06o\n", apr->ir) -int dotrace = 1; +int dotrace = 0; int pulsestepping = 0; Apr apr; @@ -158,7 +163,6 @@ swap(word *a, word *b) #define IOT_CONI (apr->ir_iot && apr->io_inst == CONI) #define IOT_CONSZ (apr->ir_iot && apr->io_inst == CONSZ) #define IOT_CONSO (apr->ir_iot && apr->io_inst == CONSO) -#define IOT_CONI (apr->ir_iot && apr->io_inst == CONI) #define IOT_BLK (apr->ir_iot && (apr->io_inst == BLKI || apr->io_inst == BLKO)) #define IOT_OUTGOING (apr->ir_iot && (apr->io_inst == DATAO || apr->io_inst == CONO)) #define IOT_STATUS (apr->ir_iot && \ @@ -172,7 +176,7 @@ decodeir(Apr *apr) apr->io_inst = apr->ir & 0700340; // 5-7 - iobus1 &= ~037777000000; + iobus1 &= ~037777000000LL; iobus1 |= apr->ir & H3 ? IOBUS_IOS3_1 : IOBUS_IOS3_0; iobus1 |= apr->ir & H4 ? IOBUS_IOS4_1 : IOBUS_IOS4_0; iobus1 |= apr->ir & H5 ? IOBUS_IOS5_1 : IOBUS_IOS5_0; @@ -253,7 +257,7 @@ void ar_cry(Apr *apr) { // 6-10 - apr->ar_cry0_xor_cry1 = AR_OV_SET && ~MEMAC; + apr->ar_cry0_xor_cry1 = AR_OV_SET && !MEMAC; } void @@ -341,7 +345,7 @@ recalc_req(void) req = 0; for(i = 0; i < 128; i++) req |= ioreq[i]; - iobus1 = iobus1&~0177 | req&0177; + iobus1 = iobus1&~0177LL | req&0177; } void @@ -421,7 +425,7 @@ relocate(Apr *apr) apr->rla += apr->rlr; // 7-2, 7-10 - membus0 &= ~0007777777761; + membus0 &= ~0007777777761LL; membus0 |= ma_fmc_select ? MEMBUS_MA_FMC_SEL1 : MEMBUS_MA_FMC_SEL0; membus0 |= (apr->ma&01777) << 4; membus0 |= ((word)apr->rla&017) << 14; @@ -1699,11 +1703,11 @@ pulse(fpt3){ apr->fe |= apr->sc; // 6-15 apr->sc = 0; // 6-15 // 6-3, 6-4 - if(apr->mb & F0) apr->mb |= 0377000000000; - else apr->mb &= ~0377000000000; + if(apr->mb & F0) apr->mb |= 0377000000000LL; + else apr->mb &= ~0377000000000LL; // 6-9, 6-4 - if(apr->ar & F0) apr->ar |= 0377000000000; - else apr->ar &= ~0377000000000; + if(apr->ar & F0) apr->ar |= 0377000000000LL; + else apr->ar &= ~0377000000000LL; nextpulse(apr, fpt4); // 6-23 } @@ -2076,8 +2080,6 @@ pulse(pi_sync){ nextpulse(apr, iat0); // 5-3 if(IA_NOT_INT) nextpulse(apr, apr->if1a ? it1 : at1); // 5-3 - /* no longer needed */ - apr->ia_inh = 0; } // 5-1 @@ -2411,6 +2413,9 @@ pulse(et1){ if(PI_RST) clear_pih(apr); // 8-4 + // 6-3 + if(apr->ir_acbm) + apr->mb &= apr->ar; // 6-8 if(apr->ir_boole && (apr->ir_boole_op == 06 || apr->ir_boole_op == 011 || @@ -2432,9 +2437,6 @@ pulse(et1){ if(HWT_AR_0 || IOT_STATUS || IOT_DATAI) apr->ar = 0; - // 6-3 - if(apr->ir_acbm) - apr->mb &= ~apr->ar; if(HWT_SWAP || FWT_SWAP || apr->inst == BLT) SWAPLTRT(apr->mb); @@ -3056,6 +3058,7 @@ aprmain(void *p) if(c == 'x') pulsestepping = 0; } + //usleep(50000); for(i = 0; i < apr->ncurpulses; i++) apr->clist[i](apr); @@ -3071,7 +3074,7 @@ aprmain(void *p) if(apr->extpulse & 2){ apr->extpulse &= ~2; apr->run = 0; - // cleared after PI SYNC + // hack: cleared when the pulse list was empty apr->ia_inh = 1; } @@ -3097,6 +3100,10 @@ aprmain(void *p) iobus1 &= ~IOBUS_PULSES; } if(iobus1 & IOBUS_IOB_RESET){ + int d; + for(d = 0; d < nelem(iobusmap); d++) + if(iobusmap[d]) + iobusmap[d](); iobus1 &= ~IOBUS_IOB_RESET; } @@ -3124,8 +3131,14 @@ aprmain(void *p) if(apr->mc_rq && !apr->mc_stop) nextpulse(apr, mc_non_exist_mem); // 7-9 } - if(i) - print("--------------\n"); + if(i){ + // wakepanel(); + trace("--------------\n"); + }else{ + /* no longer needed */ + apr->ia_inh = 0; + } + } print("power off\n"); return NULL; diff --git a/io.c b/io.c deleted file mode 100644 index ca7f7a6..0000000 --- a/io.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "pdp6.h" - -word iobus0, iobus1; -void (*iobusmap[128])(void); -u8 ioreq[128]; diff --git a/main.c b/main.c index ecef388..2110d8c 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include SDL_Surface *screen; @@ -669,6 +671,18 @@ mouse(int button, int state, int x, int y) } } +void +wakepanel(void) +{ + SDL_Event user_event; + + user_event.type = SDL_USEREVENT; + user_event.user.code = 1; + user_event.user.data1 = NULL; + user_event.user.data2 = NULL; + SDL_PushEvent(&user_event); +} + int main() { @@ -804,10 +818,25 @@ error: rim_maint_sw->r.y += extra_panel.y; initmem(); + inittty(); memset(&apr, 0xff, sizeof apr); apr.extpulse = 0; +/* int frm = 0; + time_t tm, tm2; + tm = time(nil);*/ for(;;){ +/* + frm++; + tm2 = time(nil); + if((tm2 - tm) > 5){ + print("fps: %f\n", (float)frm/(tm2-tm)); + tm = tm2; + frm = 0; + } +*/ +// usleep(1000); + while(SDL_PollEvent(&ev)) switch(ev.type){ case SDL_MOUSEMOTION: @@ -825,6 +854,9 @@ error: dumpmem(); SDL_Quit(); return 0; + case SDL_USEREVENT: + print("user\n"); + break; } setlights(apr.ir, ir_lght, 18); setlights(apr.mi, mi_lght, 36); diff --git a/mem b/mem index 1ce9ab0..63b9de9 100644 --- a/mem +++ b/mem @@ -1,11 +1,25 @@ -1000: 200000001011 -1001: 150000001012 -1002: 254200000000 -1003: 202400000000 -1004: 576400000000 -1005: 201600000000 -1006: 576200000000 -1007: 204500000000 -1010: 573300000000 -1011: 204600000000 -1012: 203400000000 +40: 254200000000 +41: 254200000000 +1000: 254000001102 +1101: 777700001000 +1102: 200740001101 +1103: 260740001112 +1104: 260740001120 +1105: 201000000012 +1106: 260740001120 +1107: 201000000141 +1110: 260740001120 +1111: 254200000000 +1112: 712240000000 +1113: 606000000040 +1114: 254000001112 +1115: 712040000000 +1116: 620000000200 +1117: 263740000000 +1120: 712240000001 +1121: 602040000020 +1122: 254000001120 +1123: 435000000200 +1124: 712140000000 +1125: 263740000000 +1126: 000000000141 diff --git a/op_panel.png b/op_panel.png index 95b8f671feb4e290b9ff03fc6b499b5b95209e9f..81717fffbb105cbca39d2a443dfa7b2710c5eeae 100644 GIT binary patch literal 20746 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 literal 20946 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 +#include +#include +#include +#include +#include +#include + +/* + * This device is not accurately modeled after the schematics. + */ + +#define TTY (0120>>2) + +typedef struct Tty Tty; +struct Tty +{ + uchar tto, tti; + bool tto_busy, tto_flag; + bool tti_busy, tti_flag; + int pia; + int fd; +}; +Tty tty; + +void +recalc_tty_req(void) +{ + u8 req; + req = tty.tto_flag || tty.tti_flag ? tty.pia : 0; + if(req != ioreq[TTY]){ + ioreq[TTY] = req; + recalc_req(); + } +} + +void* +ttythread(void *arg) +{ + int sockfd, newsockfd, portno, clilen; + char buf; + struct sockaddr_in serv_addr, cli_addr; + int n; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(sockfd < 0){ + perror("ERROR opening socket"); + exit(1); + } + memset(&serv_addr, 0, sizeof(serv_addr)); + portno = 6666; + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(portno); + if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){ + perror("ERROR on bind"); + exit(1); + } + listen(sockfd,5); + clilen = sizeof(cli_addr); + + pthread_t thread_id; + while(newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen)){ + printf("TTY attached\n"); + tty.fd = newsockfd; + while(n = read(tty.fd, &buf, 1), n > 0){ + tty.tti = buf|0200; + tty.tti_flag = 1; + recalc_tty_req(); + } + tty.fd = -1; + close(newsockfd); + } + if(newsockfd < 0){ + perror("ERROR on accept"); + exit(1); + } + return nil; +} + +static void +wake_tty(void) +{ + if(IOB_RESET){ + tty.pia = 0; + tty.tto_busy = 0; + tty.tto_flag = 0; + tty.tto = 0; + tty.tti_busy = 0; + tty.tti_flag = 0; + tty.tti = 0; + ioreq[TTY] = 0; + } + if(IOB_STATUS){ + if(tty.tti_busy) iobus0 |= F29; + if(tty.tti_flag) iobus0 |= F30; + if(tty.tto_busy) iobus0 |= F31; + if(tty.tto_flag) iobus0 |= F32; + iobus0 |= tty.pia & 7; + } + if(IOB_DATAI) + apr.ar = tty.tti; + if(IOB_CONO_CLEAR) + tty.pia = 0; + if(IOB_CONO_SET){ + if(iobus0 & F25) tty.tti_busy = 0; + if(iobus0 & F26) tty.tti_flag = 0; + if(iobus0 & F27) tty.tto_busy = 0; + if(iobus0 & F28) tty.tto_flag = 0; + if(iobus0 & F29) tty.tti_busy = 1; + if(iobus0 & F30) tty.tti_flag = 1; + if(iobus0 & F31) tty.tto_busy = 1; + if(iobus0 & F32) tty.tto_flag = 1; + tty.pia |= iobus0 & 7; + } + if(IOB_DATAO_CLEAR) + tty.tto = 0; + if(IOB_DATAO_SET){ + tty.tto = iobus0 & 0377; + tty.tto_busy = 1; + if(tty.tto & 0200 && tty.fd >= 0){ + tty.tto &= ~0200; + write(tty.fd, &tty.tto, 1); + } + tty.tto_busy = 0; + tty.tto_flag = 1; + } + recalc_tty_req(); +} + +void +inittty(void) +{ + pthread_t thread_id; + tty.fd = -1; + ioreq[TTY] = 0; + pthread_create(&thread_id, nil, ttythread, nil); + iobusmap[TTY] = wake_tty; +} diff --git a/ttytest.s b/ttytest.s new file mode 100644 index 0000000..d7b1bb6 --- /dev/null +++ b/ttytest.s @@ -0,0 +1,43 @@ +P=17 +TTY=120 + + +PDLLEN=100 + +.=40 + JRST 4, + JRST 4, + +.=1000 +ENTRY: JRST START +PDL: .=.+PDLLEN +SP: -PDLLEN,,PDL-1 + +START: + MOVE P,SP + PUSHJ P,GETCH + PUSHJ P,PUTCHR + MOVEI 0,"\n + PUSHJ P,PUTCHR + MOVEI 0,"a + PUSHJ P,PUTCHR + JRST 4, + +GETCH: + CONI TTY,0 + TRNN 0,40 + JRST .-2 + DATAI TTY,0 + TRZ 0,200 + POPJ P, + +PUTCHR: + CONI TTY,1 + TRNE 1,20 + JRST .-2 + IORI 0,200 + DATAO TTY,0 + POPJ P, + +STR: + "a