1
0
mirror of https://github.com/aap/pdp6.git synced 2026-02-05 08:05:12 +00:00
Files
aap.pdp6/emu/main_serial.c

237 lines
5.2 KiB
C

#include "pdp6.h"
#include <stdarg.h>
#include "args.h"
#include <fcntl.h>
#include <termios.h>
// TODO: get rid of this
void updatepanel(Apr *apr) {}
void writeconsreg(Apr *apr, u32 addr, u32 data)
{ // stub
}
u32
readconsreg(Apr *apr, u32 addr)
{
// stub
return 0;
}
#define KEYPULSE(k) (apr->k && !oldapr.k)
void
talkserial(int fd, Apr *apr, Ptr *ptr)
{
struct termios ios;
Apr oldapr;
char c, buf[32];
int n, sw;
if(tcgetattr(fd, &ios) == 0){
cfsetispeed(&ios, B38400);
cfsetospeed(&ios, B38400);
cfmakeraw(&ios);
tcsetattr(fd, TCSANOW, &ios);
}
/* Synch to CR */
while(readn(fd, &c, 1) == 0, c != 015);
sw = 0;
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;
switch(sw){
case 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;
break;
case 1:
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;
break;
}
if(apr->sw_power == 0){
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
buf[5] = 0;
buf[6] = 0;
buf[7] = 0;
buf[9] = 0;
buf[10] = 0;
buf[11] = 0;
buf[13] = 0;
buf[14] = 0;
buf[15] = 0;
}
sw = !sw;
writen(fd, buf, n);
}
}
void
usage(void)
{
fprintf(stderr, "usage: %s [-t] [-d debugfile] [-p paneltty]\n", argv0);
exit(1);
}
int
threadmain(int argc, char *argv[])
{
const char *outfile;
const char *panelfile;
int fd;
Channel *cmdchans[2];
Task t;
Apr *apr;
Ptr *ptr;
outfile = "/dev/null";
panelfile = nil;
ARGBEGIN{
case 't':
dotrace = 1;
break;
case 'd':
outfile = EARGF(usage());
break;
case 'p':
panelfile = EARGF(usage());
break;
default:
usage();
}ARGEND;
if(debugfp = fopen(outfile, "w"), debugfp == nil){
fprintf(stderr, "Can't open %s\n", outfile);
exit(1);
}
rtcchan = chancreate(sizeof(RtcMsg), 20);
if(dofile("init.ini"))
defaultconfig();
apr = (Apr*)getdevice("apr");
ptr = (Ptr*)getdevice("ptr");
if(apr == nil || ptr == nil)
err("need APR, PTR");
cmdchans[0] = chancreate(sizeof(char*), 1);
cmdchans[1] = chancreate(sizeof(void*), 1);
t = (Task){ nil, readcmdchan, cmdchans, 10, 0 };
addtask(t);
threadcreate(simthread, nil);
threadcreate(cmdthread, cmdchans);
threadcreate(rtcthread, nil);
if(panelfile){
fd = open(panelfile, O_RDWR);
if(fd < 0)
err("Couldn't open %s", panelfile);
}else{
/* Just testing... */
fd = dial("localhost", 2000);
if(fd < 0)
err("can't connect to panel");
}
talkserial(fd, apr, ptr);
return 0;
}