chiark / gitweb /
initial hostside thingum
authorian <ian>
Sun, 2 Jan 2005 17:32:13 +0000 (17:32 +0000)
committerian <ian>
Sun, 2 Jan 2005 17:32:13 +0000 (17:32 +0000)
hostside/.cvsignore [new file with mode: 0644]
hostside/Makefile [new file with mode: 0644]
hostside/hostside.h [new file with mode: 0644]
hostside/main.c [new file with mode: 0644]
hostside/nmra.c [new file with mode: 0644]
hostside/serialio.c [new file with mode: 0644]

diff --git a/hostside/.cvsignore b/hostside/.cvsignore
new file mode 100644 (file)
index 0000000..f34b991
--- /dev/null
@@ -0,0 +1 @@
+hostside
diff --git a/hostside/Makefile b/hostside/Makefile
new file mode 100644 (file)
index 0000000..7a975c2
--- /dev/null
@@ -0,0 +1,16 @@
+#
+
+TARGETS=       hostside
+CFLAGS=                -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes \
+               -Wpointer-arith -Wwrite-strings $(OPTIMISE)
+OPTIMISE=      -O2
+
+all:           $(TARGETS)
+
+hostside:      serialio.o nmra.o main.o
+               $(CC) $(CFLAGS) -o $@ $+
+
+%.c:           hostside.h
+
+clean:
+               rm -f *.o $(TARGETS)
diff --git a/hostside/hostside.h b/hostside/hostside.h
new file mode 100644 (file)
index 0000000..279bae8
--- /dev/null
@@ -0,0 +1,17 @@
+/**/
+
+#ifndef HOSTSIDE_H
+#define HOSTSIDE_H
+
+typedef unsigned char Byte;
+
+#define COMMAND_ENCODED_MAX 16
+#define NMRA_PACKET_MAX ((COMMAND_ENCODED_MAX*7 - 14) / 8)
+
+void nmra_transmit(const Byte *nmra_packet, int length);
+
+void sysfatal(const char *m);
+void serial_open(const char *device);
+void command_transmit(const Byte *command, int length);
+
+#endif /*HOSTSIDE_H*/
diff --git a/hostside/main.c b/hostside/main.c
new file mode 100644 (file)
index 0000000..820197a
--- /dev/null
@@ -0,0 +1,34 @@
+/**/
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "hostside.h"
+
+int main(int argc, const char **argv) {
+  int l, i;
+  char hbuf[3], *ep;
+  Byte nmra[NMRA_PACKET_MAX];
+  
+  assert(argc==3);
+  serial_open(argv[1]);
+
+  l= strlen(argv[2]);
+  assert(!(l&1));
+  l >>= 1;
+  assert(l<=NMRA_PACKET_MAX);
+
+  for (i=0; i<l; i++) {
+    hbuf[0]= argv[2][i*2];
+    hbuf[1]= argv[2][i*2+1];
+    hbuf[2]= 0;
+    nmra[l]= strtoul(hbuf,&ep,16);
+    assert(ep==&hbuf[2]);
+  }
+
+  nmra_transmit(nmra,l);
+
+  return 0;
+}
diff --git a/hostside/nmra.c b/hostside/nmra.c
new file mode 100644 (file)
index 0000000..a0d3b81
--- /dev/null
@@ -0,0 +1,41 @@
+/**/
+
+#include <assert.h>
+
+#include "hostside.h"
+
+void nmra_transmit(const Byte *nmra_packet, int length) {
+  Byte encoded[COMMAND_ENCODED_MAX], *encp;
+  unsigned working;
+  int working_bits;
+
+  assert(length <= NMRA_PACKET_MAX);
+  encp= encoded;
+  working= 0xfffc;   /* 16-bit temp register.  Top working_bits bits   */
+  working_bits= 14;  /*  are some data bits to encode, rest are clear. */
+  for (;;) {
+    assert(working_bits >= 0);
+    if (working_bits < 7) {
+      if (length > 0) {
+       /* plonk new data bits just to right of old data bits */
+       working |= (*nmra_packet++ << (8-working_bits));
+       length--;
+       working_bits += 8;
+      } else if (!working_bits) {
+       /* all done */
+       break;
+      } else {
+       /* pad with exactly enough 1 bits to make up the encoded byte */
+       working |= 0xffU << (8-working_bits);
+       working_bits= 7;
+      }
+    }
+    assert(encp < encoded + COMMAND_ENCODED_MAX);
+    *encp++= (working_bits >> 8) & 0xfe; /* top 7 bits, shifted left one */
+    working_bits -= 7;
+  }
+  assert(encp > encoded);
+  encp[-1] |= 0x01; /* `end of command' bit */
+
+  command_transmit(encoded, encp - encoded);
+}
diff --git a/hostside/serialio.c b/hostside/serialio.c
new file mode 100644 (file)
index 0000000..5502a21
--- /dev/null
@@ -0,0 +1,39 @@
+/**/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "hostside.h"
+
+static int serial_fd= -1;
+
+void sysfatal(const char *m) { perror(m); exit(12); }
+
+void serial_open(const char *device) {
+  assert(serial_fd==-1);
+
+  serial_fd= open(device,O_RDWR);
+  if (serial_fd<0) sysfatal(device);
+}
+
+void command_transmit(const Byte *command, int length) {
+  int r;
+  assert(length <= COMMAND_ENCODED_MAX);
+
+  while (length > 0) {
+    r= write(serial_fd, command, length);
+    if (r==-1) {
+      if (errno == EINTR) continue;
+      sysfatal("command_transmit");
+    }
+    assert(r<=length);
+    command += r;
+    length -= r;
+  }
+}