From 5c8f75a5cdfcff444558df1fb91ec9deea5e349f Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 27 Feb 2019 10:56:24 +0100 Subject: [PATCH] panel: implemented serial protocol used at LCM --- emu/util.c | 48 ++++++++++++++- panel/Makefile | 2 +- panel/panel6.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 202 insertions(+), 3 deletions(-) diff --git a/emu/util.c b/emu/util.c index b6ef53f..6f187d9 100644 --- a/emu/util.c +++ b/emu/util.c @@ -1,7 +1,12 @@ -#include "pdp6.h" +#include +#include +#include + +#include #include #include + void strtolower(char *s) { @@ -85,3 +90,44 @@ win: freeaddrinfo(result); return sockfd; } + +void +serve(int port, void (*handlecon)(int, void*), void *arg) +{ + int sockfd, confd; + socklen_t len; + struct sockaddr_in server, client; + int x; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(sockfd < 0){ + perror("error: socket"); + return; + } + + x = 1; + setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&x, sizeof x); + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(port); + if(bind(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0){ + perror("error: bind"); + return; + } + listen(sockfd, 5); + len = sizeof(client); + while(confd = accept(sockfd, (struct sockaddr*)&client, &len), + confd >= 0) + handlecon(confd, arg); + perror("error: accept"); + return; +} + +void +nodelay(int fd) +{ + int flag = 1; + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); +} diff --git a/panel/Makefile b/panel/Makefile index e79c5ae..f82fa2f 100644 --- a/panel/Makefile +++ b/panel/Makefile @@ -1,4 +1,4 @@ -SRC=panel6.c +SRC=panel6.c ../emu/util.c # clang #CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \ # -Wno-bitwise-op-parentheses diff --git a/panel/panel6.c b/panel/panel6.c index c2f50b2..7bf8656 100644 --- a/panel/panel6.c +++ b/panel/panel6.c @@ -5,6 +5,10 @@ #include #include #include +#include +#include + +#include "../emu/util.h" #define nelem(a) (sizeof(a)/sizeof(a[0])) #define nil NULL @@ -117,6 +121,14 @@ setlights(uchar b, Element *l, int n) l[i].state = !!(b & 1 << 7-i); } +void +setlights_(uchar b, Element *l, int n) +{ + int i; + for(i = 0; i < n; i++) + l[i].state = !!(b & 1 << 5-i); +} + void set18lights(uchar *b, Element *l) { @@ -146,6 +158,18 @@ getswitches(Element *sw, int n, int state) return b; } +uchar +getswitches_(Element *sw, int n, int state) +{ + uchar b; + int i; + b = 0; + for(i = 0; i < n; i++) + b |= (uchar)(sw[i].state == state) << 5-i; + return b; +} + + uchar get18switches(uchar *b, Element *sw) { @@ -324,6 +348,133 @@ findlayout(int *w, int *h) *h = oppanel.pos.y + oppanel.surf->h; } +void +talkserial(int fd) +{ + int i, n; + char c, buf[32]; + + while(1){ + misc_l[3].state = misc_sw[0].state; + misc_l[4].state = misc_sw[1].state; + misc_l[5].state = misc_sw[2].state; + misc_l[6].state = misc_sw[3].state; + + /* Send switches to CPU */ + n = 0; + buf[n++] = getswitches_(data_sw, 6, 1); + buf[n++] = getswitches_(data_sw+6, 6, 1); + buf[n++] = getswitches_(data_sw+12, 6, 1); + buf[n++] = getswitches_(data_sw+18, 6, 1); + buf[n++] = getswitches_(data_sw+24, 6, 1); + buf[n++] = getswitches_(data_sw+30, 6, 1); + buf[n++] = getswitches_(ma_sw, 6, 1); + buf[n++] = getswitches_(ma_sw+6, 6, 1); + buf[n++] = getswitches_(ma_sw+12, 6, 1); + buf[n++] = getswitches_(keys, 6, 2); + buf[n++] = getswitches_(keys, 6, 1); + c = 0; + c |= (keys[6].state == 2)<<3; + c |= (keys[6].state == 1)<<2; + c |= (keys[7].state == 2)<<1; + c |= (keys[7].state == 1)<<0; + buf[n++] = c; + c = 0; + c |= (misc_sw[1].state == 1)<<3; + c |= (misc_sw[0].state == 1)<<2; + c |= (misc_sw[3].state == 1)<<1; + c |= (misc_sw[2].state == 1)<<0; + buf[n++] = c; + // TODO: speed knobs + buf[n++] = 0; + for(i = 0; i < n; i++) + if(buf[i] != 077) + buf[i] |= 0100; + buf[n++] = '\r'; + write(fd, buf, n); + + + /* Read lights from CPU if we get any */ + if(hasinput(fd)){ + if(read(fd, &c, 1) != 1) + break; + if(c >= '0' && c <= '7'){ + if(readn(fd, buf, 3)) + break; + + switch(c){ + case '0': + setlights_(buf[0], ir_l, 6); + setlights_(buf[1], ir_l+6, 6); + setlights_(buf[2], ir_l+12, 6); + break; + case '1': + setlights_(buf[0], mi_l, 6); + setlights_(buf[1], mi_l+6, 6); + setlights_(buf[2], mi_l+12, 6); + break; + case '2': + setlights_(buf[0], mi_l+18, 6); + setlights_(buf[1], mi_l+24, 6); + setlights_(buf[2], mi_l+30, 6); + break; + case '3': + setlights_(buf[0], pc_l, 6); + setlights_(buf[1], pc_l+6, 6); + setlights_(buf[2], pc_l+12, 6); + break; + case '4': + setlights_(buf[0], ma_l, 6); + setlights_(buf[1], ma_l+6, 6); + setlights_(buf[2], ma_l+12, 6); + break; + case '5': + misc_l[2].state = !!(buf[0] & 040); // run + setlights_(buf[0]<<2, pih_l, 4); + setlights_(buf[1], pih_l+4, 3); + break; + case '6': + misc_l[1].state = !!(buf[0] & 040); // stop + setlights_(buf[0]<<2, pir_l, 4); + setlights_(buf[1], pir_l+4, 3); + break; + case '7': + misc_l[0].state = !!(buf[0] & 040); // pi + setlights_(buf[0]<<2, pio_l, 4); + setlights_(buf[1], pio_l+4, 3); + break; + } + } + } + } +} + +void +handlenetwork(int fd, void *x) +{ + nodelay(fd); + talkserial(fd); + close(fd); +} + +void* +servethread(void *x) +{ + serve(2000, handlenetwork, nil); +} + +void* +openserial(void *x) +{ + int fd; + + fd = open("/tmp/panel", O_RDWR); + if(fd < 0) + err("Couldn't open serial connection"); + talkserial(fd); + close(fd); +} + void* talki2c(void *x) { @@ -515,7 +666,9 @@ main(int argc, char *argv[]) extra_l = e; e += 1; - pthread_create(&comthread, nil, talki2c, nil); +// pthread_create(&comthread, nil, talki2c, nil); + pthread_create(&comthread, nil, servethread, nil); +// pthread_create(&comthread, nil, talkserial, nil); for(;;){ while(SDL_PollEvent(&ev))