diff --git a/swuart/Makefile b/swuart/Makefile new file mode 100644 index 0000000..bd56ff6 --- /dev/null +++ b/swuart/Makefile @@ -0,0 +1,19 @@ +CC = mipsel-openwrt-linux-gcc +CFLAGS = -g -Wall -I../libubb/include +LDFLAGS = -static +LDLIBS = -L../libubb -lubb + +MAIN = swuart +OBJS = swuart.o + +.PHONY: all clean spotless + +all: $(MAIN) + +$(MAIN): $(OBJS) + +clean: + rm -f $(OBJS) + +spotless: clean + rm -f $(MAIN) diff --git a/swuart/swuart.c b/swuart/swuart.c new file mode 100644 index 0000000..4310be1 --- /dev/null +++ b/swuart/swuart.c @@ -0,0 +1,101 @@ +/* + * swuart/swuart.c - Software-implemented half-duplex UART for UBB + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include + +#include +#include + + +#define TX UBB_DAT2 + + + +static uint32_t tx_mask, rx_mask; +static int loops; + + +/* + * TX bit timing: + * + * bps loops nominal estimated measured error + * 1152200 202 8.696 us 8.673 us 8.67 us -0.3% + * 38400 619 26.042 us 26.062 us 26.04 us n/a + * 9600 2494 104.167 us 104.250 us 104.16 us n/a + * + * Estimated loop timing: 0.25+0.0417*loops + */ + +int swuart_open(uint32_t tx, uint32_t rx, int bps) +{ + if (ubb_open(0)) + return -1; + + loops = 24000000/bps-6; + tx_mask = tx; + rx_mask = rx; + + ubb_power(1); + OUT(tx); + CLR(tx); + IN(rx); + + return 0; +} + + +static void send(uint8_t *out, int out_size) +{ + const uint8_t *end = out+out_size; + unsigned pattern; + int i, j; + + while (out != end) { + pattern = 0x200 | (*out++ << 1); + for (i = 0; i != 10; i++) { + if (pattern & 1) + SET(tx_mask); + else + CLR(tx_mask); + pattern >>= 1; + for (j = 0; j != loops; j++); + } + } +} + + +int swuart_trx(void *out, int out_size, void *in, int in_size, int bit_wait) +{ + uint32_t icmr; + + icmr = ICMR; + ICMSR = 0xffffffff; + + send(out, out_size); + + ICMCR = ~icmr; + + return 0; +} + + +int main(int argc, char **argv) +{ + swuart_open(TX, 0, atoi(argv[1])); + while (1) { + swuart_trx("U ", 2, NULL, 0, 0); + usleep(100); + } + ubb_close(0); +}