|
@ -1,3 +1,4 @@ |
|
|
|
|
|
#include <libopencm3/cm3/systick.h> |
|
|
#include <libopencm3/stm32/rcc.h> |
|
|
#include <libopencm3/stm32/rcc.h> |
|
|
#include <libopencm3/stm32/gpio.h> |
|
|
#include <libopencm3/stm32/gpio.h> |
|
|
|
|
|
|
|
@ -5,6 +6,14 @@ |
|
|
|
|
|
|
|
|
typedef unsigned char byte; |
|
|
typedef unsigned char byte; |
|
|
|
|
|
|
|
|
|
|
|
static void delay_ms(unsigned int ms) |
|
|
|
|
|
{ |
|
|
|
|
|
systick_clear(); |
|
|
|
|
|
for (unsigned int i=0; i<ms; i++) |
|
|
|
|
|
while (!systick_get_countflag()) |
|
|
|
|
|
; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static void wait(void) |
|
|
static void wait(void) |
|
|
{ |
|
|
{ |
|
|
for (int i=0; i<7200; i++) |
|
|
for (int i=0; i<7200; i++) |
|
@ -34,10 +43,7 @@ static void set_reg(int reg, int data) |
|
|
wait(); |
|
|
wait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
byte display[8]; |
|
|
static byte display[8] = { |
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
|
static unsigned char smile[8] = { |
|
|
|
|
|
0x66, /* .##..##. */ |
|
|
0x66, /* .##..##. */ |
|
|
0x66, /* .##..##. */ |
|
|
0x66, /* .##..##. */ |
|
|
0x00, /* ........ */ |
|
|
0x00, /* ........ */ |
|
@ -47,7 +53,6 @@ static unsigned char smile[8] = { |
|
|
0x66, /* .##..##. */ |
|
|
0x66, /* .##..##. */ |
|
|
0x3c, /* ..####.. */ |
|
|
0x3c, /* ..####.. */ |
|
|
}; |
|
|
}; |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
static void refresh_display(void) |
|
|
static void refresh_display(void) |
|
|
{ |
|
|
{ |
|
@ -55,69 +60,6 @@ static void refresh_display(void) |
|
|
set_reg(i, display[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) |
|
|
int main(void) |
|
|
{ |
|
|
{ |
|
|
rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); |
|
|
rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); |
|
@ -136,10 +78,12 @@ int main(void) |
|
|
gpio_set(GPIOB, GPIO13); |
|
|
gpio_set(GPIOB, GPIO13); |
|
|
gpio_clear(GPIOB, GPIO14); |
|
|
gpio_clear(GPIOB, GPIO14); |
|
|
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
// PA0 = left button
|
|
|
// PA0 = left button
|
|
|
// PA1 = right button
|
|
|
// PA1 = right button
|
|
|
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0 | GPIO1); |
|
|
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0 | GPIO1); |
|
|
gpio_set(GPIOA, GPIO0 | GPIO1); |
|
|
gpio_set(GPIOA, GPIO0 | GPIO1); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
refresh_display(); |
|
|
refresh_display(); |
|
|
set_reg(9, 0); |
|
|
set_reg(9, 0); |
|
@ -148,20 +92,10 @@ int main(void) |
|
|
set_reg(13, 0); // test
|
|
|
set_reg(13, 0); // test
|
|
|
set_reg(12, 1); // shutdown
|
|
|
set_reg(12, 1); // shutdown
|
|
|
|
|
|
|
|
|
snake_init(); |
|
|
|
|
|
snake_show(); |
|
|
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
for (;;) { |
|
|
buttons[0] = buttons[1] = 0; |
|
|
gpio_clear(GPIOC, GPIO13); |
|
|
for (int i=0; i<1000000; i++) { |
|
|
delay_ms(100); |
|
|
if (!gpio_get(GPIOA, GPIO0)) |
|
|
gpio_set(GPIOC, GPIO13); |
|
|
buttons[0] = 1; |
|
|
delay_ms(500); |
|
|
if (!gpio_get(GPIOA, GPIO1)) |
|
|
|
|
|
buttons[1] = 1; |
|
|
|
|
|
asm volatile (""); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gpio_toggle(GPIOC, GPIO13); |
|
|
|
|
|
snake_step(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|