From 800614fcc52fc9347d1ba189d679c04c88f02b3f Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 27 Feb 2019 13:10:37 +0100 Subject: [PATCH] emu: implemented serial protocol --- emu/Makefile | 8 +- emu/apr.c | 1 + emu/dt.c | 22 ++-- emu/main_serial.c | 309 ++++++++++++++++++++++++++++++++++++++++++++++ emu/util.h | 7 ++ panel/panel6.c | 48 +++++-- 6 files changed, 376 insertions(+), 19 deletions(-) create mode 100644 emu/main_serial.c create mode 100644 emu/util.h diff --git a/emu/Makefile b/emu/Makefile index 4d32bdf..4bfb9f6 100644 --- a/emu/Makefile +++ b/emu/Makefile @@ -1,4 +1,4 @@ -SRC=main.c util.c cmd.c apr.c mem.c tty.c pt.c dc.c dt.c netmem.c ../tools/pdp6common.c +SRC=util.c cmd.c apr.c mem.c tty.c pt.c dc.c dt.c netmem.c ../tools/pdp6common.c H=pdp6.h ../tools/pdp6common.h # clang #CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \ @@ -9,8 +9,10 @@ SDLFLAGS=`sdl-config --cflags` `pkg-config SDL_image --cflags` LIBS=`sdl-config --libs` `pkg-config SDL_image --libs` -lpthread -pdp6: $(SRC) $(H) - $(CC) -o $@ $(CFLAGS) $(SDLFLAGS) $(SRC) $(LIBS) +pdp6: main.c $(SRC) $(H) + $(CC) -o $@ $(CFLAGS) $(SDLFLAGS) main.c $(SRC) $(LIBS) +pdp6_s: main_serial.c $(SRC) $(H) + $(CC) -o $@ $(CFLAGS) $(SDLFLAGS) main_serial.c $(SRC) $(LIBS) test_dc: test_dc.c dc.c $(H) $(CC) -o $@ $(CFLAGS) test_dc.c dc.c diff --git a/emu/apr.c b/emu/apr.c index b94eade..bacb129 100644 --- a/emu/apr.c +++ b/emu/apr.c @@ -181,6 +181,7 @@ stepone(Apr *apr) // TODO This is WIP +// TODO: can't set switches with real panel connected #define EXDEPREGS \ X(ir)\ diff --git a/emu/dt.c b/emu/dt.c index c4bb4ca..0562d35 100644 --- a/emu/dt.c +++ b/emu/dt.c @@ -217,7 +217,7 @@ enum #define UTE_ACTIVE_ERROR (!UT_ALL && prev.rw_state == RW_ACTIVE && (BM_SYNC || DATA_SYNC)) //#define debug(...) printf(__VA_ARGS__) -#define debug(...) 0 +#define debug(...) #define PRINT1 \ printf("%c%02o(%o,%02o,%d)", dt->rw_state == RW_ACTIVE ? '+' : dt->rw_state == RW_RQ ? '-' : ' ', \ @@ -422,9 +422,10 @@ dt_tp2(Dt551 *dt) dt->ut_jb_done_flag = 1; /* test checksum. NB: manual says should be 0 * TODO: not sure about ACTIVE */ - if(prev.rw_state == RW_ACTIVE && dt->lb != 077) -debug("CHECKSUM ERR\n"), + if(prev.rw_state == RW_ACTIVE && dt->lb != 077){ +debug("CHECKSUM ERR\n"); dt->ut_info_error = 1; // 3-13 + } } /* Job done after block mark */ @@ -437,9 +438,10 @@ debug("CHECKSUM ERR\n"), dt->rw_state = RW_NULL; } /* Catch invalid mark code */ - if(UTE_ERROR) -debug("TRACK ERROR\n"), + if(UTE_ERROR){ +debug("TRACK ERROR\n"); dt->ut_info_error = 1; // 3-15 + } /* Stop activity once job gets done */ if(!prev.ut_jb_done_flag && dt->ut_jb_done_flag) // 3-8 @@ -479,9 +481,10 @@ dt_tp4(Dt551 *dt) dt->rwb |= dctk(dt->dc, DEVNO, REV); if(UTE_DC_DISCONNECT) dt->ut_incomp_block = 1; // 3-17 - }else -debug("Getting LB\n"), + }else{ +debug("Getting LB\n"); dt->rwb |= dt->lb; + } // 3-6 if(REV) dt->rwb = dt->rwb>>3 & 07 | dt->rwb<<3 & 070; @@ -526,9 +529,10 @@ dtcycle(void *p) // UTE_SW_ERROR; 3-16 if(!UTE_UNIT_OK || - dt->ut_btm_switch != UT_WRTM) -debug("ILL op %d %d %d\n", nunits, dt->ut_btm_switch, UT_WRTM), + dt->ut_btm_switch != UT_WRTM){ +debug("ILL op %d %d %d\n", nunits, dt->ut_btm_switch, UT_WRTM); dt->ut_illegal_op = 1; + } if(!UTE_UNIT_OK){ dt->ut_go = 0; // 3-3 return; diff --git a/emu/main_serial.c b/emu/main_serial.c new file mode 100644 index 0000000..4d0ab0d --- /dev/null +++ b/emu/main_serial.c @@ -0,0 +1,309 @@ +#include "pdp6.h" +#include +#include +#include "args.h" + +char *argv0; + +FILE *debugfp; +int dotrace; + +void +trace(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if(dotrace){ + fprintf(debugfp, " "); + vfprintf(debugfp, fmt, ap); + } + va_end(ap); +} + +void +debug(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(debugfp, fmt, ap); + va_end(ap); +} + +void +err(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +// TODO: get rid of this +void updatepanel(Apr *apr) {} + +u32 +getms(void) +{ + // TODO + return 0; +} + +#define KEYPULSE(k) (apr->k && !oldapr.k) + +void +talkserial(int fd, Apr *apr, Ptr *ptr) +{ + Apr oldapr; + char buf[32]; + int n; + + while(1){ + if(apr == nil) + return; + oldapr = *apr; + + /* Read switch and key state */ + if(readn(fd, buf, 15)) + break; + apr->data = 0; + apr->data |= ((word)buf[0]&077) << 30; + apr->data |= ((word)buf[1]&077) << 24; + apr->data |= ((word)buf[2]&077) << 18; + apr->data |= ((word)buf[3]&077) << 12; + apr->data |= ((word)buf[4]&077) << 6; + apr->data |= ((word)buf[5]&077) << 0; + apr->mas = 0; + apr->mas |= ((word)buf[6]&077) << 12; + apr->mas |= ((word)buf[7]&077) << 6; + apr->mas |= ((word)buf[8]&077) << 0; + + apr->key_start = !!(buf[10] & 040); + apr->key_readin = !!(buf[9] & 040); + apr->key_inst_cont = !!(buf[10] & 020); + apr->key_mem_cont = !!(buf[9] & 020); + apr->key_inst_stop = !!(buf[10] & 010); + apr->key_mem_stop = !!(buf[9] & 010); + apr->key_io_reset = !!(buf[10] & 4); + apr->key_exec = !!(buf[9] & 4); + apr->key_dep = !!(buf[10] & 2); + apr->key_dep_nxt = !!(buf[9] & 2); + apr->key_ex = !!(buf[10] & 1); + apr->key_ex_nxt = !!(buf[9] & 1); + apr->key_rd_off = !!(buf[11] & 010); + apr->key_rd_on = !!(buf[11] & 4); + apr->key_pt_rd = !!(buf[11] & 2); + apr->key_pt_wr = !!(buf[11] & 1); + + apr->sw_addr_stop = !!(buf[12] & 010); + apr->sw_repeat = !!(buf[12] & 4); + apr->sw_mem_disable = !!(buf[12] & 2); + apr->sw_power = !!(buf[12] & 1); + + // TODO: buf[13] is a speed knob + // buf[14] is CR + + if(apr->sw_power){ + if(KEYPULSE(key_start) || KEYPULSE(key_readin) || + KEYPULSE(key_inst_cont) || KEYPULSE(key_mem_cont) || + KEYPULSE(key_io_reset) || KEYPULSE(key_exec) || + KEYPULSE(key_dep) || KEYPULSE(key_dep_nxt) || + KEYPULSE(key_ex) || KEYPULSE(key_ex_nxt)) + apr->extpulse |= EXT_KEY_MANUAL; + if(KEYPULSE(key_inst_stop)) + apr->extpulse |= EXT_KEY_INST_STOP; + if(ptr){ + if(KEYPULSE(key_rd_on)) + ptr_setmotor(ptr, 1); + if(KEYPULSE(key_rd_off)) + ptr_setmotor(ptr, 0); + } + } + + /* Send lights */ + // TODO: only send changes + n = 0; + buf[n++] = '0'; + buf[n++] = apr->ir>>12 & 077 | 0100; + buf[n++] = apr->ir>>6 & 077 | 0100; + buf[n++] = apr->ir>>0 & 077 | 0100; + buf[n++] = '1'; + buf[n++] = apr->mi>>30 & 077 | 0100; + buf[n++] = apr->mi>>24 & 077 | 0100; + buf[n++] = apr->mi>>18 & 077 | 0100; + buf[n++] = '2'; + buf[n++] = apr->mi>>12 & 077 | 0100; + buf[n++] = apr->mi>>6 & 077 | 0100; + buf[n++] = apr->mi>>0 & 077 | 0100; + buf[n++] = '3'; + buf[n++] = apr->pc>>12 & 077 | 0100; + buf[n++] = apr->pc>>6 & 077 | 0100; + buf[n++] = apr->pc>>0 & 077 | 0100; + buf[n++] = '4'; + buf[n++] = apr->ma>>12 & 077 | 0100; + buf[n++] = apr->ma>>6 & 077 | 0100; + buf[n++] = apr->ma>>0 & 077 | 0100; + buf[n++] = '5'; + buf[n++] = apr->run<<5 | apr->pih>>3 | 0100; + buf[n++] = (apr->pih&7)<<3 | 0100; + buf[n++] = 0100; + buf[n++] = '6'; + buf[n++] = apr->mc_stop<<5 | apr->pir>>3 | 0100; + buf[n++] = (apr->pir&7)<<3 | 0100; + buf[n++] = 0100; + buf[n++] = '7'; + buf[n++] = apr->pi_active<<5 | apr->pio>>3 | 0100; + buf[n++] = (apr->pio&7)<<3 | 0100; + buf[n++] = 0100; + writen(fd, buf, n); + } +} + +Thread *threads; + +void +addthread(Thread th) +{ + Thread *p; + p = malloc(sizeof(Thread)); + *p = th; + p->next = threads; + threads = p; +} + +void* +simthread(void *p) +{ + Thread *th; + + printf("[simthread] start\n"); + for(;;) + for(th = threads; th; th = th->next){ + th->cnt++; + if(th->cnt == th->freq){ + th->cnt = 0; + th->f(th->arg); + } + } + err("can't happen"); + return nil; +} + +Device *devlist; + +void +adddevice(Device *dev) +{ + dev->next = devlist; + devlist = dev; +}; + +Device* +getdevice(const char *name) +{ + Device *dev; + for(dev = devlist; dev; dev = dev->next) + if(strcmp(dev->name, name) == 0) + return dev; + return nil; +} + +void +showdevices(void) +{ + Device *dev; + for(dev = devlist; dev; dev = dev->next) + printf("%s %s\n", dev->name, dev->type); +} + + +void +dofile(const char *path) +{ + FILE *f; + if(f = fopen(path, "r"), f == nil){ + printf("Couldn't open file %s\n", path); + return; + } + cli(f); + fclose(f); +} + +void +quit(int code) +{ + int i; + Device *dev; + Membus *mbus; + + /* Detach all files */ + for(dev = devlist; dev; dev = dev->next) + if(dev->detach) + dev->detach(dev); + + /* Sync memory to disk */ + for(dev = devlist; dev; dev = dev->next){ + if(strcmp(dev->type, apr_ident) != 0) + continue; + + mbus = &((Apr*)dev)->membus; + for(i = 0; i < 16; i++) + if(mbus->cmem[i] && mbus->cmem[i]->sync) + mbus->cmem[i]->sync(mbus->cmem[i]); + } + +// putchar('\n'); + printf("\nquitting\n"); + exit(code); +} + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-t] [-d debugfile]\n", argv0); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + pthread_t cmd_thread, sim_thread; + const char *outfile; + int fd; + + Apr *apr; + Ptr *ptr; + + outfile = "/dev/null"; + ARGBEGIN{ + case 't': + dotrace = 1; + break; + case 'd': + outfile = EARGF(usage()); + break; + default: + usage(); + }ARGEND; + if(debugfp = fopen(outfile, "w"), debugfp == nil){ + fprintf(stderr, "Can't open %s\n", outfile); + exit(1); + } + + + dofile("init.ini"); + apr = (Apr*)getdevice("apr"); + ptr = (Ptr*)getdevice("ptr"); + + pthread_create(&sim_thread, nil, simthread, apr); + pthread_create(&cmd_thread, nil, cmdthread, nil); + + fd = dial("localhost", 2000); + if(fd < 0) + err("can't connect to panel"); + talkserial(fd, apr, ptr); + + return 0; +} diff --git a/emu/util.h b/emu/util.h new file mode 100644 index 0000000..9bf44b0 --- /dev/null +++ b/emu/util.h @@ -0,0 +1,7 @@ +void strtolower(char *s); +int hasinput(int fd); +int writen(int fd, void *data, int n); +int readn(int fd, void *data, int n); +int dial(const char *host, int port); +void serve(int port, void (*handlecon)(int, void*), void *arg); +void nodelay(int fd); diff --git a/panel/panel6.c b/panel/panel6.c index 7bf8656..e2401b7 100644 --- a/panel/panel6.c +++ b/panel/panel6.c @@ -227,6 +227,9 @@ ismouseover(Element *e, int x, int y) { Point p; + if(e->grid->panel == nil) + return 0; + p = xform(e->grid, e->pos); return x >= p.x && x <= p.x + e->surf[e->state]->w && y >= p.y && y <= p.y + e->surf[e->state]->h; @@ -262,6 +265,9 @@ drawelement(SDL_Surface *screen, Element *elt, int power) Point p; int s; + if(elt->grid->panel == nil) + return; + p = xform(elt->grid, elt->pos); r.x = p.x+0.5; r.y = p.y+0.5; @@ -348,6 +354,28 @@ findlayout(int *w, int *h) *h = oppanel.pos.y + oppanel.surf->h; } +/* Show only operator console */ +void +findlayout_small(int *w, int *h) +{ + SDL_Rect nopos = { -1, -1, -1, -1 }; + + indpanel1.pos = nopos; + indpanel2.pos = nopos; + iopanel.pos = nopos; + extrapanel.pos = nopos; + + iogrid.panel = nil; + indgrid1.panel = nil; + indgrid2.panel = nil; + extragrid.panel = nil; + + oppanel.pos = (SDL_Rect){ 0, 0, 0, 0 }; + + *w = oppanel.surf->w; + *h = oppanel.surf->h; +} + void talkserial(int fd) { @@ -395,7 +423,7 @@ talkserial(int fd) /* Read lights from CPU if we get any */ - if(hasinput(fd)){ + while(hasinput(fd)){ if(read(fd, &c, 1) != 1) break; if(c >= '0' && c <= '7'){ @@ -623,7 +651,8 @@ main(int argc, char *argv[]) extragrid = indgrid1; extragrid.panel = &extrapanel; - findlayout(&w, &h); +// findlayout(&w, &h); + findlayout_small(&w, &h); screen = SDL_SetVideoMode(w, h, 32, SDL_DOUBLEBUF); if(screen == nil) @@ -688,11 +717,16 @@ main(int argc, char *argv[]) } SDL_FillRect(screen, nil, SDL_MapRGBA(screen->format, 0xe6, 0xe6, 0xe6, 0xff)); - SDL_BlitSurface(indpanel1.surf, nil, screen, &indpanel1.pos); - SDL_BlitSurface(indpanel2.surf, nil, screen, &indpanel2.pos); - SDL_BlitSurface(extrapanel.surf, nil, screen, &extrapanel.pos); - SDL_BlitSurface(iopanel.surf, nil, screen, &iopanel.pos); - SDL_BlitSurface(oppanel.surf, nil, screen, &oppanel.pos); + if(indpanel1.pos.x >= 0) + SDL_BlitSurface(indpanel1.surf, nil, screen, &indpanel1.pos); + if(indpanel2.pos.x >= 0) + SDL_BlitSurface(indpanel2.surf, nil, screen, &indpanel2.pos); + if(extrapanel.pos.x >= 0) + SDL_BlitSurface(extrapanel.surf, nil, screen, &extrapanel.pos); + if(iopanel.pos.x >= 0) + SDL_BlitSurface(iopanel.surf, nil, screen, &iopanel.pos); + if(oppanel.pos.x >= 0) + SDL_BlitSurface(oppanel.surf, nil, screen, &oppanel.pos); for(i = 0, e = lamps; i < nelem(lamps); i++, e++) drawelement(screen, e, 1);