]> mj.ucw.cz Git - home-hw.git/blob - protab/matrix/matrix.c
Merge branch 'master' of ssh://git.ucw.cz/home/mj/GIT/home-hw
[home-hw.git] / protab / matrix / matrix.c
1 #include <libopencm3/stm32/rcc.h>
2 #include <libopencm3/stm32/gpio.h>
3
4 #include <string.h>
5
6 typedef unsigned char byte;
7
8 static void wait(void)
9 {
10         for (int i=0; i<7200; i++)
11                 asm volatile ("");
12 }
13
14 static void set_reg(int reg, int data)
15 {
16         data |= reg << 8;
17
18         gpio_clear(GPIOB, GPIO13);
19         wait();
20
21         for (int mask=0x8000; mask; mask >>= 1) {
22                 if (data & mask)
23                         gpio_set(GPIOB, GPIO12);
24                 else
25                         gpio_clear(GPIOB, GPIO12);
26                 wait();
27                 gpio_set(GPIOB, GPIO14);
28                 wait();
29                 gpio_clear(GPIOB, GPIO14);
30                 wait();
31         }
32
33         gpio_set(GPIOB, GPIO13);
34         wait();
35 }
36
37 byte display[8];
38
39 #if 0
40 static unsigned char smile[8] = {
41         0x66,   /* .##..##. */
42         0x66,   /* .##..##. */
43         0x00,   /* ........ */
44         0x18,   /* ...##... */
45         0x00,   /* ........ */
46         0xc3,   /* ##....## */
47         0x66,   /* .##..##. */
48         0x3c,   /* ..####.. */
49 };
50 #endif
51
52 static void refresh_display(void)
53 {
54         for (int i=1; i<=8; i++)
55                 set_reg(i, display[8-i]);
56 }
57
58 static signed char dirs[4][2] = {{1,0}, {0,-1}, {-1,0}, {0,1}};
59
60 static byte snake_dir;
61 #define SNAKE_MAX 65
62 static byte snake[SNAKE_MAX][2];
63 static byte snake_tail, snake_head;
64 static byte food[2];
65 static unsigned int rng_state = 0xdeadbeef;
66
67 static byte buttons[2];
68
69 static void gen_food(void)
70 {
71         food[0] = (rng_state >> 28) & 7;
72         food[1] = (rng_state >> 20) & 7;
73         rng_state *= 0x3771cadb;
74 }
75
76 static void snake_init(void)
77 {
78         snake[0][0] = 0;
79         snake[0][1] = 0;
80         snake_dir = 3;
81         snake_tail = 0;
82         snake_head = 1;
83         gen_food();
84 }
85
86 static void snake_show(void)
87 {
88         memset(display, 0, 8);
89         for (int i=snake_tail; i != snake_head; i = (i+1) % SNAKE_MAX)
90                 display[snake[i][0]] |= 1 << snake[i][1];
91         display[food[0]] |= 1 << food[1];
92         refresh_display();
93 }
94
95 static void snake_step(void)
96 {
97         if (buttons[0])
98                 snake_dir = (snake_dir+3) % 4;
99         else if (buttons[1])
100                 snake_dir = (snake_dir+1) % 4;
101
102         int hi = (snake_head + SNAKE_MAX - 1) % SNAKE_MAX;
103         int x = snake[hi][0] + dirs[snake_dir][0];
104         int y = snake[hi][1] + dirs[snake_dir][1];
105
106         if (x < 0 || x > 7 || y < 0 || y > 7)
107                 return;
108
109         snake[snake_head][0] = x;
110         snake[snake_head][1] = y;
111         snake_head = (snake_head + 1) % SNAKE_MAX;
112
113         if (x == food[0] && y == food[1])
114                 gen_food();
115         else
116                 snake_tail = (snake_tail + 1) % SNAKE_MAX;
117
118         snake_show();
119 }
120
121 int main(void)
122 {
123         rcc_clock_setup_in_hse_8mhz_out_72mhz();
124         rcc_periph_clock_enable(RCC_GPIOA);
125         rcc_periph_clock_enable(RCC_GPIOB);
126         rcc_periph_clock_enable(RCC_GPIOC);
127
128         // PC13 = BluePill LED
129         gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
130
131         // PB12 = display DIN
132         // PB13 = display CS*
133         // PB14 = display CLK
134         gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12 | GPIO13 | GPIO14);
135         gpio_clear(GPIOB, GPIO12);
136         gpio_set(GPIOB, GPIO13);
137         gpio_clear(GPIOB, GPIO14);
138
139         // PA0 = left button
140         // PA1 = right button
141         gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0 | GPIO1);
142         gpio_set(GPIOA, GPIO0 | GPIO1);
143
144         refresh_display();
145         set_reg(9, 0);
146         set_reg(10, 0); // intensity
147         set_reg(11, 7);
148         set_reg(13, 0); // test
149         set_reg(12, 1); // shutdown
150
151         snake_init();
152         snake_show();
153
154         for (;;) {
155                 buttons[0] = buttons[1] = 0;
156                 for (int i=0; i<1000000; i++) {
157                         if (!gpio_get(GPIOA, GPIO0))
158                                 buttons[0] = 1;
159                         if (!gpio_get(GPIOA, GPIO1))
160                                 buttons[1] = 1;
161                         asm volatile ("");
162                 }
163
164                 gpio_toggle(GPIOC, GPIO13);
165                 snake_step();
166         }
167 }