Add simple SPI bus software simulation/example
authorMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 27 Feb 2019 22:38:27 +0000 (22:38 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 27 Feb 2019 22:38:27 +0000 (22:38 +0000)
tests/spi/spi.c [new file with mode: 0644]

diff --git a/tests/spi/spi.c b/tests/spi/spi.c
new file mode 100644 (file)
index 0000000..5d72d42
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Simple SPI bus software simulation/example
+ * Copyright (c) 2019, Matthew Mondor,
+ * ALL RIGHTS RESERVED.
+ *
+ * $ cc -Wall -o spi spi.c
+ * $ ./spi
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+
+typedef struct spi_dev spi_dev_t;
+struct spi_dev {
+       bool    asserted;
+       uint8_t sreg, inval, outval;
+       int     ticks;
+       void    (*func)(spi_dev_t *);
+};
+
+void   binary_print(uint8_t);
+void   spi_dev_init(spi_dev_t *, void (*)(spi_dev_t *));
+void   spi_assert(spi_dev_t *);
+void   spi_unassert(spi_dev_t *);
+void   spi_tick(uint8_t *, spi_dev_t *, int);
+
+
+void
+binary_print(uint8_t b)
+{
+       char buf[10], *r = buf;
+       int i;
+
+       *r++ = '%';
+       for (i = 7; i >= 0; i--)
+               *r++ = ((b & (1 << i)) != 0 ? '1' : '0');
+       *r = '\0';
+       (void)printf("0x%02x (%s)", b, buf);
+}
+
+void
+spi_dev_init(spi_dev_t *dev, void (*func)(spi_dev_t *))
+{
+
+       dev->asserted = false;
+       dev->sreg = dev->inval = dev->outval = 0;
+       dev->ticks = 8;
+       dev->func = func;
+}
+
+void
+spi_assert(spi_dev_t *dev)
+{
+
+       dev->asserted = true;
+}
+
+void
+spi_unassert(spi_dev_t *dev)
+{
+
+       dev->asserted = false;
+}
+
+/*
+ *             <-shift
+ *     /---------------
+ *     1 2 3 4 5 6 7 8 |<
+ *     1 2 3 4 5 6 7 8</ |
+ *     \-----------------
+ *             <-shift
+ */
+void
+spi_tick(uint8_t *sreg, spi_dev_t *dev, int ticks)
+{
+       int bit;
+
+       if (!dev->asserted)
+               return;
+
+       while (--ticks >= 0) {
+               /*
+                * >> 7 picks the most significant bit but also places it
+                * right (results in the value of that single bit).
+                * << 1 rotates all other bits left, also resulting in a 0 bit
+                * at the least significant position.
+                */
+               bit = dev->sreg >> 7;
+               dev->sreg = (dev->sreg << 1) | (*sreg >> 7);
+               *sreg = (*sreg << 1) | bit;
+
+               if (--dev->ticks == 0) {
+                       dev->ticks = 8;
+                       dev->func(dev);
+               }
+       }
+}
+
+
+void   spi_dev_func(spi_dev_t *);
+void
+spi_dev_func(spi_dev_t *dev)
+{
+
+       dev->sreg = dev->outval++;
+       dev->inval = dev->sreg;
+       dev->ticks = 8;
+
+       (void)printf("spi_dev_func() - inval = ");
+       binary_print(dev->inval);
+       (void)printf(", outval = ");
+       binary_print(dev->outval);
+       (void)printf("\n");
+}
+
+int
+main(void)
+{
+       spi_dev_t dev;
+       uint8_t sreg;
+
+       spi_dev_init(&dev, spi_dev_func);
+       dev.sreg = 0x00;
+       dev.outval = 0x21;
+
+       spi_assert(&dev);
+       sreg = 0x11;
+
+       (void)printf("master outval = ");
+       binary_print(sreg);
+       (void)printf("\n");
+
+       spi_tick(&sreg, &dev, 8);
+
+       (void)printf("master inval = ");
+       binary_print(sreg);
+       (void)printf("\n");
+
+       sreg = 0x00;
+
+       (void)printf("master outval = ");
+       binary_print(sreg);
+       (void)printf("\n");
+
+       spi_tick(&sreg, &dev, 8);
+
+       (void)printf("master inval = ");
+       binary_print(sreg);
+       (void)printf("\n");
+
+       spi_unassert(&dev);
+
+       exit(EXIT_SUCCESS);
+}
+