From: ian Date: Sun, 2 Jan 2005 17:32:13 +0000 (+0000) Subject: initial hostside thingum X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=10222d17dea76e3b64d9f395a49c7e6141a9f2cf;p=trains.git initial hostside thingum --- diff --git a/hostside/.cvsignore b/hostside/.cvsignore new file mode 100644 index 0000000..f34b991 --- /dev/null +++ b/hostside/.cvsignore @@ -0,0 +1 @@ +hostside diff --git a/hostside/Makefile b/hostside/Makefile new file mode 100644 index 0000000..7a975c2 --- /dev/null +++ b/hostside/Makefile @@ -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 index 0000000..279bae8 --- /dev/null +++ b/hostside/hostside.h @@ -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 index 0000000..820197a --- /dev/null +++ b/hostside/main.c @@ -0,0 +1,34 @@ +/**/ + +#include +#include +#include +#include + +#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 + +#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 index 0000000..5502a21 --- /dev/null +++ b/hostside/serialio.c @@ -0,0 +1,39 @@ +/**/ + +#include +#include +#include +#include +#include + +#include +#include + +#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; + } +}