mirror of
https://github.com/aap/pdp6.git
synced 2026-03-06 03:19:57 +00:00
emu: implemented serial protocol
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -181,6 +181,7 @@ stepone(Apr *apr)
|
||||
|
||||
|
||||
// TODO This is WIP
|
||||
// TODO: can't set switches with real panel connected
|
||||
|
||||
#define EXDEPREGS \
|
||||
X(ir)\
|
||||
|
||||
22
emu/dt.c
22
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;
|
||||
|
||||
309
emu/main_serial.c
Normal file
309
emu/main_serial.c
Normal file
@@ -0,0 +1,309 @@
|
||||
#include "pdp6.h"
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
#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;
|
||||
}
|
||||
7
emu/util.h
Normal file
7
emu/util.h
Normal file
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user