From 1ede729f42a98ab91f0bd3f3f3f3b7751af15369 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 18 Oct 2016 16:04:43 +0300 Subject: [PATCH] dropped in the dos stuff --- .gitignore | 2 + Makefile.dos | 24 ++++ src/dos/main.c | 97 +++++++++++++++ src/dos/serial.c | 363 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/unix/main.c | 4 +- 5 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 Makefile.dos create mode 100644 src/dos/main.c create mode 100644 src/dos/serial.c diff --git a/.gitignore b/.gitignore index a2793a8..714eb15 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *.o +*.obj *.swp *.d smouse +*.exe diff --git a/Makefile.dos b/Makefile.dos new file mode 100644 index 0000000..44c1b2f --- /dev/null +++ b/Makefile.dos @@ -0,0 +1,24 @@ +obj = main.obj serial.obj device.obj dev_smag.obj vmath.obj +bin = smouse.exe + +def = -dM_PI=3.141592653589793 +opt = -5 -fp5 -otexan -oh -oi -ei +dbg = -d1 + +incpath = -Isrc + +CC = wcc386 +CFLAGS = $(dbg) $(opt) $(def) -zq -bt=dos $(incpath) +LD = wlink +RM = del + +$(bin): $(obj) + *$(LD) debug all name $@ system dos4g file { $(obj) } $(LDFLAGS) + +.c: src;src/dos + +.c.obj: .autodepend + $(CC) -fo=$@ $(CFLAGS) $[* + +clean: .symbolic + $(RM) *.obj diff --git a/src/dos/main.c b/src/dos/main.c new file mode 100644 index 0000000..3945cd0 --- /dev/null +++ b/src/dos/main.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include "serial.h" +#include "device.h" +#include "vmath.h" + +void init_gfx(void); +void destroy_gfx(void); +int handle_dev_event(device_event *ev); + +vec3_t pos = {0, 0, -6}; +quat_t rot = {0, 0, 0, 1}; /* that's 1 + 0i + 0j + 0k */ + +static struct device *dev; + +int main(void) +{ + int devfd; + + register_all(); + set_port("COM1"); + + if(!(dev = dev_init(0))) { + fprintf(stderr, "failed to initialize 6dof serial device at COM1\n"); + return 1; + } + if((devfd = dev->start()) == -1) { + return 1; + } + + init_gfx(); + + for(;;) { + device_event ev; + + if(kbhit() && getch() == 27) { + break; + } + + while(dev->getevent(&ev)) { + handle_dev_event(&ev); + } + + /* redisplay */ + } + + dev->stop(); + dev_destroy(); + destroy_gfx(); + return 0; +} + +void init_gfx(void) +{ +} + +void destroy_gfx(void) +{ +} + +#define TX(ev) ((ev)->motion.motion[0]) +#define TY(ev) ((ev)->motion.motion[1]) +#define TZ(ev) ((ev)->motion.motion[2]) +#define RX(ev) ((ev)->motion.motion[3]) +#define RY(ev) ((ev)->motion.motion[4]) +#define RZ(ev) ((ev)->motion.motion[5]) + +int handle_dev_event(device_event *ev) +{ + switch(ev->type) { + case DEV_EV_MOTION: + printf("t: %5d %5d %5d - r: %5d %5d %5d\n", TX(ev), TY(ev), TZ(ev), + RX(ev), RY(ev), RZ(ev)); + if(RX(ev) | RY(ev) | RZ(ev)) { + float axis_len = sqrt(RX(ev) * RX(ev) + RY(ev) * RY(ev) + RZ(ev) * RZ(ev)); + if(axis_len != 0.0) { + rot = quat_rotate(rot, axis_len * 0.001, -RX(ev) / axis_len, + -RY(ev) / axis_len, -RZ(ev) / axis_len); + } + } + + pos.x += TX(ev) * 0.001; + pos.y += TY(ev) * 0.001; + pos.z += TZ(ev) * 0.001; + break; + + case DEV_EV_BUTTON: + if(ev->button.pressed) { + pos = v3_cons(0, 0, -6); + rot = quat_cons(1, 0, 0, 0); + } + break; + } + + return 0; +} diff --git a/src/dos/serial.c b/src/dos/serial.c new file mode 100644 index 0000000..55a863d --- /dev/null +++ b/src/dos/serial.c @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "serial.h" + +#define UART1_BASE 0x3f8 +#define UART2_BASE 0x2f8 +#define UART1_IRQ 4 +#define UART2_IRQ 3 + +#define UART_DATA 0 +#define UART_INTR 1 +#define UART_DIVLO 0 +#define UART_DIVHI 1 +#define UART_FIFO 2 +#define UART_IID 2 +#define UART_LCTL 3 +#define UART_MCTL 4 +#define UART_LSTAT 5 +#define UART_MSTAT 6 + +/* interrupt enable register bits */ +#define INTR_RECV 1 +#define INTR_SEND 2 +#define INTR_LSTAT 4 +#define INTR_DELTA 8 + +/* fifo control register bits */ +#define FIFO_ENABLE 0x01 +#define FIFO_RECV_CLEAR 0x02 +#define FIFO_SEND_CLEAR 0x04 +#define FIFO_DMA 0x08 +#define FIFO_TRIG_4 0x40 +#define FIFO_TRIG_8 0x80 +#define FIFO_TRIG_14 0xc0 + +/* interrupt id register bits */ +#define IID_PENDING 0x01 +#define IID_ID0 0x02 +#define IID_ID1 0x04 +#define IID_ID2 0x08 +#define IID_FIFO_EN 0xc0 + +#define IID_SOURCE 0xe + +#define IID_DELTA 0 +#define IID_SEND 0x2 +#define IID_RECV 0x4 +#define IID_FIFO 0xc +#define IID_STATUS 0x6 + +/* line control register bits */ +#define LCTL_BITS_8 0x03 +#define LCTL_STOP_2 0x04 +#define LCTL_DLAB 0x80 +#define LCTL_8N1 LCTL_BITS_8 +#define LCTL_8N2 (LCTL_BITS_8 | LCTL_STOP_2) + +/* modem control register bits */ +#define MCTL_DTR 0x01 +#define MCTL_RTS 0x02 +#define MCTL_OUT1 0x04 +#define MCTL_OUT2 0x08 +#define MCTL_LOOP 0x10 + +/* line status register bits */ +#define LST_DRDY 0x01 +#define LST_ERR_OVER 0x02 +#define LST_ERR_PARITY 0x04 +#define LST_ERR_FRAME 0x08 +#define LST_ERR_BRK 0x10 +#define LST_TREG_EMPTY 0x20 +#define LST_TIDLE 0x40 +#define LST_ERROR 0x80 + +/* modem status register bits */ +#define MST_DELTA_CTS 0x01 +#define MST_DELTA_DSR 0x02 +#define MST_TERI 0x04 +#define MST_DELTA_DCD 0x08 +#define MST_CTS 0x10 +#define MST_DSR 0x20 +#define MST_RING 0x40 +#define MST_DCD 0x80 + +/* interrupt controller stuff */ +#define PIC1_CMD_PORT 0x20 +#define PIC1_DATA_PORT 0x21 +#define PIC2_CMD_PORT 0xa0 +#define PIC2_DATA_PORT 0xa1 +#define OCW2_EOI 0x20 + +#define COM_FMT_8N1 LCTL_8N1 +#define COM_FMT_8N2 LCTL_8N2 + +struct serial_port { + int base, intr; + int blocking; + + char inbuf[256]; + int inbuf_ridx, inbuf_widx; +}; + +#define BNEXT(x) (((x) + 1) & 0xff) +#define BEMPTY(b) (b##_ridx == b##_widx) + +static void ser_putc(int uart_base, char c); +static void ser_puts(int uart_base, const char *s); +static int ser_getc(int uart_base); +static int have_recv(int base); +static void __interrupt __far recv_intr(void); + +static struct serial_port ports[2]; +static int num_open; + +static int uart_base[] = {UART1_BASE, UART2_BASE}; +static int uart_irq[] = {UART1_IRQ, UART2_IRQ}; + +static void (__interrupt __far *prev_recv_intr)(void); + + +int ser_open(const char *port, int baud, unsigned int mode) +{ + unsigned char ctl; + unsigned short div = 115200 / baud; + int i, pidx, base, intr, fd; + unsigned int fmt; + + if(toupper(port[0]) != 'C' || toupper(port[1]) != 'O' || toupper(port[2]) != 'M' + || !isdigit(port[3])) { + fprintf(stderr, "ser_open: invalid com port: %s\n", port); + return -1; + } + pidx = port[3] - '0'; + if(pidx < 1 || pidx > 2) { + fprintf(stderr, "ser_open: invalid com port: %d\n", pidx); + return -1; + } + + if(ports[pidx].base) { + fprintf(stderr, "ser_open: port %d already open!\n", pidx); + return -1; + } + memset(ports + pidx, 0, sizeof ports[pidx]); + + base = uart_base[pidx]; + intr = uart_irq[pidx] | 8; + + if(mode & SER_8N2) { + fmt = COM_FMT_8N2; + } else { + fmt = COM_FMT_8N1; + } + + _disable(); + if(!prev_recv_intr) { + prev_recv_intr = _dos_getvect(intr); + _dos_setvect(intr, recv_intr); + } + /* unmask the appropriate interrupt */ + outp(PIC1_DATA_PORT, inp(PIC1_DATA_PORT) & ~(1 << uart_irq[pidx])); + + outp(base + UART_LCTL, LCTL_DLAB); + outp(base + UART_DIVLO, div & 0xff); + outp(base + UART_DIVHI, (div >> 8) & 0xff); + outp(base + UART_LCTL, fmt); /* fmt should be LCTL_8N1, LCTL_8N2 etc */ + outp(base + UART_FIFO, FIFO_ENABLE | FIFO_SEND_CLEAR | FIFO_RECV_CLEAR); + outp(base + UART_MCTL, MCTL_DTR | MCTL_RTS | MCTL_OUT2); + outp(base + UART_INTR, INTR_RECV); + + _enable(); + + ports[pidx].base = base; + ports[pidx].intr = intr; + ports[pidx].blocking = 1; + ++num_open; + return pidx; +} + +void ser_close(int fd) +{ + if(--num_open == 0) { + _disable(); + outp(ports[fd].base + UART_INTR, 0); + outp(ports[fd].base + UART_MCTL, 0); + _dos_setvect(ports[fd].intr, prev_recv_intr); + prev_recv_intr = 0; + _enable(); + } + + ports[fd].base = 0; +} + +int ser_block(int fd) +{ + ports[fd].blocking = 1; + return 0; +} + +int ser_nonblock(int fd) +{ + ports[fd].blocking = 0; + return 0; +} + +int ser_pending(int fd) +{ + return !BEMPTY(ports[fd].inbuf); +} + +/* if msec < 0: wait for ever */ +int ser_wait(int fd, long msec) +{ + int res; + while(!(res = ser_pending(fd))) { + delay(25); + if(msec >= 0) { + if((msec -= 25) < 0) msec = 0; + } + } + return res; +} + +static int can_send(int fd) +{ + int base = ports[fd].base; + return inp(base + UART_LSTAT) & LST_TREG_EMPTY; +} + +static void ser_putc(int fd, char c) +{ + int base = ports[fd].base; + while(!can_send(fd)); + while((inp(base + UART_MSTAT) & MST_CTS) == 0); + outp(base + UART_DATA, c); +} + +static void ser_puts(int fd, const char *s) +{ + int base = ports[fd].base; + while(*s) { + ser_putc(fd, *s++); + } +} + +static int ser_getc(int fd) +{ + struct serial_port *p = ports + fd; + int have, c = -1; + + if(p->blocking) { + while(!(have = ser_pending(fd))); + } else { + have = ser_pending(fd); + } + + if(have) { + c = p->inbuf[p->inbuf_ridx]; + p->inbuf_ridx = BNEXT(p->inbuf_ridx); + } + return c; +} + +int ser_write(int fd, const char *buf, int count) +{ + int n = count; + while(n--) { + ser_putc(fd, *buf++); + } + return count; +} + +int ser_read(int fd, char *buf, int count) +{ + int c, n = 0; + while(n < count && (c = ser_getc(fd)) != -1) { + *buf++ = c; + ++n; + } + return n; +} + +void ser_printf(int fd, const char *fmt, ...) +{ + static char buf[128]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + + ser_puts(fd, buf); +} + +char *ser_getline(int fd, char *buf, int bsz) +{ + static char linebuf[512]; + static int widx; + int i, rd, size, offs; + + size = sizeof linebuf - widx; + while(size && (rd = ser_read(fd, linebuf + widx, size)) > 0) { + widx += rd; + size -= rd; + } + + linebuf[widx] = 0; + + for(i=0; i= bsz ? bsz - 1 : i; + memcpy(buf, linebuf, size); + buf[size] = 0; + + offs = i + 1; + memmove(linebuf, linebuf + offs, widx - offs); + widx -= offs; + return buf; + } + } + return 0; +} + +static int have_recv(int base) +{ + unsigned short stat = inp(base + UART_LSTAT); + if(stat & LST_ERROR) { + fprintf(stderr, "receive error\n"); + abort(); + } + return stat & LST_DRDY; +} + +static void __interrupt __far recv_intr() +{ + int i, idreg, c; + + for(i=0; i<2; i++) { + int base = uart_base[i]; + struct serial_port *p = ports + i; + + while(((idreg = inp(base + UART_IID)) & IID_PENDING) == 0) { + while(have_recv(base)) { + c = inp(base + UART_DATA); + + p->inbuf[p->inbuf_widx] = inp(base + UART_DATA); + p->inbuf_widx = BNEXT(p->inbuf_widx); + + if(p->inbuf_widx == p->inbuf_ridx) { + /* we overflowed, drop the oldest */ + p->inbuf_ridx = BNEXT(p->inbuf_ridx); + } + } + } + } + + outp(PIC1_CMD_PORT, OCW2_EOI); +} diff --git a/src/unix/main.c b/src/unix/main.c index a936a74..0e92c8e 100644 --- a/src/unix/main.c +++ b/src/unix/main.c @@ -97,6 +97,8 @@ int main(void) } end: + dev->stop(); + dev_destroy(); destroy_gfx(); XCloseDisplay(dpy); return 0; @@ -154,7 +156,7 @@ int create_gfx(int xsz, int ysz) XSetWMProtocols(dpy, win, &wm_del_win, 1); - set_window_title("libspnav cube"); + set_window_title("spacemouse cube"); class_hint.res_name = "cube"; class_hint.res_class = "cube"; -- 1.7.10.4