Add some code
This commit is contained in:
187
src/main.rs
Normal file
187
src/main.rs
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use cortex_m_rt::entry;
|
||||||
|
use microbit::{
|
||||||
|
board::Board,
|
||||||
|
display::blocking::Display,
|
||||||
|
hal::{
|
||||||
|
timer::Timer,
|
||||||
|
pac::twim0::frequency::FREQUENCY_A,
|
||||||
|
prelude::*,
|
||||||
|
twim::Twim,
|
||||||
|
uarte,
|
||||||
|
uarte::{Baudrate, Parity},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use panic_rtt_target as _;
|
||||||
|
use rtt_target::{rprintln, rtt_init_print};
|
||||||
|
use core::fmt::Write;
|
||||||
|
use heapless::{Vec};
|
||||||
|
|
||||||
|
mod serial_setup;
|
||||||
|
use serial_setup::UartePort;
|
||||||
|
|
||||||
|
const SCREEN_SIZE: usize = 5;
|
||||||
|
const CLEAN_DISPLAY: [[u8; 5]; 5] = [
|
||||||
|
[0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0],
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Direction, clockwise
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum Direction {
|
||||||
|
UP,
|
||||||
|
RIGHT,
|
||||||
|
DOWN,
|
||||||
|
LEFT,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Direction {
|
||||||
|
fn right(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::UP => Self::RIGHT,
|
||||||
|
Self::RIGHT => Self::DOWN,
|
||||||
|
Self::DOWN => Self::LEFT,
|
||||||
|
Self::LEFT => Self::UP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::UP => Self::LEFT,
|
||||||
|
Self::RIGHT => Self::UP,
|
||||||
|
Self::DOWN => Self::RIGHT,
|
||||||
|
Self::LEFT => Self::DOWN,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
struct Position {
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Food {
|
||||||
|
position: Position
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Food {
|
||||||
|
fn regenerate(&mut self) {
|
||||||
|
// TODO rand this
|
||||||
|
self.position = Position { x: 3, y: 3 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Snake {
|
||||||
|
body: Vec<Position, 32>,
|
||||||
|
direction: Direction,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Snake {
|
||||||
|
fn new(start: Position, direction: Direction) -> Self {
|
||||||
|
let mut body: Vec<Position, 32> = Vec::new();
|
||||||
|
body.push(start).unwrap();
|
||||||
|
Self { body, direction }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, button_a: bool, button_b: bool, food: &mut Food) {
|
||||||
|
// update direction
|
||||||
|
if button_a {
|
||||||
|
self.direction = self.direction.left();
|
||||||
|
}
|
||||||
|
|
||||||
|
if button_b {
|
||||||
|
self.direction = self.direction.right();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update snake
|
||||||
|
let mut new_head = self.body[0].clone();
|
||||||
|
match self.direction {
|
||||||
|
// some bound checking
|
||||||
|
Direction::DOWN => new_head.y = (self.body[0].y + 1) % SCREEN_SIZE,
|
||||||
|
Direction::RIGHT => new_head.x = (self.body[0].x + 1) % SCREEN_SIZE,
|
||||||
|
Direction::UP => {
|
||||||
|
let next = (self.body[0].x, (self.body[0].y as isize) - 1);
|
||||||
|
if next.1 < 0 {
|
||||||
|
new_head.y = 4;
|
||||||
|
} else {
|
||||||
|
new_head.y -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Direction::LEFT => {
|
||||||
|
let next = ((self.body[0].x as isize) - 1, self.body[0].y);
|
||||||
|
if next.0 < 0 {
|
||||||
|
new_head.x = 4;
|
||||||
|
} else {
|
||||||
|
new_head.x -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// add new_head
|
||||||
|
let mut new_body: Vec<Position, 32> = Vec::new();
|
||||||
|
new_body.push(new_head);
|
||||||
|
self.body
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|body_part| new_body.push(body_part));
|
||||||
|
self.body = new_body;
|
||||||
|
|
||||||
|
// remove tail element
|
||||||
|
if self.body[0] != food.position {
|
||||||
|
self.body.pop();
|
||||||
|
food.regenerate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
rtt_init_print!();
|
||||||
|
|
||||||
|
let board = Board::take().unwrap();
|
||||||
|
let mut timer = Timer::new(board.TIMER0);
|
||||||
|
let mut display = Display::new(board.display_pins);
|
||||||
|
let _i2c = { Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };
|
||||||
|
let mut uart = {
|
||||||
|
let serial = uarte::Uarte::new(
|
||||||
|
board.UARTE0,
|
||||||
|
board.uart.into(),
|
||||||
|
Parity::EXCLUDED,
|
||||||
|
Baudrate::BAUD115200,
|
||||||
|
);
|
||||||
|
UartePort::new(serial)
|
||||||
|
};
|
||||||
|
|
||||||
|
let button_a = board.buttons.button_a;
|
||||||
|
let button_b = board.buttons.button_b;
|
||||||
|
|
||||||
|
let mut snake = Snake::new(Position { x: 1, y: 1 }, Direction::RIGHT);
|
||||||
|
let mut food = Food { position: Position { x: 2, y: 2 }};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// update snake
|
||||||
|
let is_a_pressed = button_a.is_low().unwrap();
|
||||||
|
let is_b_pressed = button_b.is_low().unwrap();
|
||||||
|
snake.update(is_a_pressed, is_b_pressed, &mut food);
|
||||||
|
|
||||||
|
// print some debug to uart
|
||||||
|
writeln!(uart, "Direction: {:?}\r", snake.direction);
|
||||||
|
|
||||||
|
// update screen
|
||||||
|
let mut display_matrix = CLEAN_DISPLAY;
|
||||||
|
for element in snake.body.iter() {
|
||||||
|
writeln!(uart, "Element: {:?}\r", element);
|
||||||
|
display_matrix[element.y][element.x] = 1;
|
||||||
|
}
|
||||||
|
display_matrix[food.position.y][food.position.x] = 1;
|
||||||
|
|
||||||
|
display.show(&mut timer, display_matrix, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/serial_setup.rs
Normal file
46
src/serial_setup.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use embedded_hal::blocking::serial as bserial;
|
||||||
|
use embedded_hal::serial;
|
||||||
|
use microbit::hal::uarte::{Error, Instance, Uarte, UarteRx, UarteTx};
|
||||||
|
|
||||||
|
static mut TX_BUF: [u8; 1] = [0; 1];
|
||||||
|
static mut RX_BUF: [u8; 1] = [0; 1];
|
||||||
|
|
||||||
|
pub struct UartePort<T: Instance>(UarteTx<T>, UarteRx<T>);
|
||||||
|
|
||||||
|
impl<T: Instance> UartePort<T> {
|
||||||
|
pub fn new(serial: Uarte<T>) -> UartePort<T> {
|
||||||
|
let (tx, rx) = serial
|
||||||
|
.split(unsafe { &mut TX_BUF }, unsafe { &mut RX_BUF })
|
||||||
|
.unwrap();
|
||||||
|
UartePort(tx, rx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> fmt::Write for UartePort<T> {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
self.0.write_str(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> serial::Write<u8> for UartePort<T> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn write(&mut self, b: u8) -> nb::Result<(), Self::Error> {
|
||||||
|
self.0.write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||||
|
self.0.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> bserial::write::Default<u8> for UartePort<T> {}
|
||||||
|
|
||||||
|
impl<T: Instance> serial::Read<u8> for UartePort<T> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||||
|
self.1.read()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user