]> mj.ucw.cz Git - home-hw.git/commitdiff
Matrix display & snake
authorMartin Mares <mj@ucw.cz>
Wed, 22 Jul 2020 15:55:21 +0000 (17:55 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 22 Jul 2020 15:55:21 +0000 (17:55 +0200)
protab/matrix/Makefile [new file with mode: 0644]
protab/matrix/matrix.c [new file with mode: 0644]

diff --git a/protab/matrix/Makefile b/protab/matrix/Makefile
new file mode 100644 (file)
index 0000000..4da665f
--- /dev/null
@@ -0,0 +1,6 @@
+ROOT=../..
+BINARY=matrix
+OBJS=matrix.o
+LIB_OBJS=
+
+include $(ROOT)/mk/bluepill.mk
diff --git a/protab/matrix/matrix.c b/protab/matrix/matrix.c
new file mode 100644 (file)
index 0000000..b4b368d
--- /dev/null
@@ -0,0 +1,167 @@
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+
+#include <string.h>
+
+typedef unsigned char byte;
+
+static void wait(void)
+{
+       for (int i=0; i<7200; i++)
+               asm volatile ("");
+}
+
+static void set_reg(int reg, int data)
+{
+       data |= reg << 8;
+
+       gpio_clear(GPIOB, GPIO13);
+       wait();
+
+       for (int mask=0x8000; mask; mask >>= 1) {
+               if (data & mask)
+                       gpio_set(GPIOB, GPIO12);
+               else
+                       gpio_clear(GPIOB, GPIO12);
+               wait();
+               gpio_set(GPIOB, GPIO14);
+               wait();
+               gpio_clear(GPIOB, GPIO14);
+               wait();
+       }
+
+       gpio_set(GPIOB, GPIO13);
+       wait();
+}
+
+byte display[8];
+
+#if 0
+static unsigned char smile[8] = {
+       0x66,   /* .##..##. */
+       0x66,   /* .##..##. */
+       0x00,   /* ........ */
+       0x18,   /* ...##... */
+       0x00,   /* ........ */
+       0xc3,   /* ##....## */
+       0x66,   /* .##..##. */
+       0x3c,   /* ..####.. */
+};
+#endif
+
+static void refresh_display(void)
+{
+       for (int i=1; i<=8; i++)
+               set_reg(i, display[8-i]);
+}
+
+static signed char dirs[4][2] = {{1,0}, {0,-1}, {-1,0}, {0,1}};
+
+static byte snake_dir;
+#define SNAKE_MAX 65
+static byte snake[SNAKE_MAX][2];
+static byte snake_tail, snake_head;
+static byte food[2];
+static unsigned int rng_state = 0xdeadbeef;
+
+static byte buttons[2];
+
+static void gen_food(void)
+{
+       food[0] = (rng_state >> 28) & 7;
+       food[1] = (rng_state >> 20) & 7;
+       rng_state *= 0x3771cadb;
+}
+
+static void snake_init(void)
+{
+       snake[0][0] = 0;
+       snake[0][1] = 0;
+       snake_dir = 3;
+       snake_tail = 0;
+       snake_head = 1;
+       gen_food();
+}
+
+static void snake_show(void)
+{
+       memset(display, 0, 8);
+       for (int i=snake_tail; i != snake_head; i = (i+1) % SNAKE_MAX)
+               display[snake[i][0]] |= 1 << snake[i][1];
+       display[food[0]] |= 1 << food[1];
+       refresh_display();
+}
+
+static void snake_step(void)
+{
+       if (buttons[0])
+               snake_dir = (snake_dir+3) % 4;
+       else if (buttons[1])
+               snake_dir = (snake_dir+1) % 4;
+
+       int hi = (snake_head + SNAKE_MAX - 1) % SNAKE_MAX;
+       int x = snake[hi][0] + dirs[snake_dir][0];
+       int y = snake[hi][1] + dirs[snake_dir][1];
+
+       if (x < 0 || x > 7 || y < 0 || y > 7)
+               return;
+
+       snake[snake_head][0] = x;
+       snake[snake_head][1] = y;
+       snake_head = (snake_head + 1) % SNAKE_MAX;
+
+       if (x == food[0] && y == food[1])
+               gen_food();
+       else
+               snake_tail = (snake_tail + 1) % SNAKE_MAX;
+
+       snake_show();
+}
+
+int main(void)
+{
+       rcc_clock_setup_in_hse_8mhz_out_72mhz();
+       rcc_periph_clock_enable(RCC_GPIOA);
+       rcc_periph_clock_enable(RCC_GPIOB);
+       rcc_periph_clock_enable(RCC_GPIOC);
+
+       // PC13 = BluePill LED
+       gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
+
+       // PB12 = display DIN
+       // PB13 = display CS*
+       // PB14 = display CLK
+       gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12 | GPIO13 | GPIO14);
+       gpio_clear(GPIOB, GPIO12);
+       gpio_set(GPIOB, GPIO13);
+       gpio_clear(GPIOB, GPIO14);
+
+       // PA0 = left button
+       // PA1 = right button
+       gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0 | GPIO1);
+       gpio_set(GPIOA, GPIO0 | GPIO1);
+
+       refresh_display();
+       set_reg(9, 0);
+       set_reg(10, 0); // intensity
+       set_reg(11, 7);
+       set_reg(13, 0); // test
+       set_reg(12, 1); // shutdown
+
+       snake_init();
+       snake_show();
+
+       for (;;) {
+               buttons[0] = buttons[1] = 0;
+               for (int i=0; i<1000000; i++) {
+                       if (!gpio_get(GPIOA, GPIO0))
+                               buttons[0] = 1;
+                       if (!gpio_get(GPIOA, GPIO1))
+                               buttons[1] = 1;
+                       asm volatile ("");
+               }
+
+               gpio_toggle(GPIOC, GPIO13);
+               snake_step();
+       }
+}