Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 4-fix-card10-l0dable-on-crates-io
  • 5-implement-client-c-in-plain-rust
  • api
  • build-from-root
  • master
  • no-str_to_cstr
  • card10-alloc-0.1.0
  • card10-alloc-0.1.1
  • card10-l0dable-0.2.0
  • card10-l0dable-0.3.0
  • card10-sys-1.10.0
  • card10-sys-1.9.0
12 results

Target

Select target project
  • astro/rust-card10
  • rnestler/rust-card10
  • dbrgn/rust-card10
  • toon/rust-card10
  • mwall/rust-card10
  • puzzlewolf/rust-card10
  • rnd/rust-card10
  • lilpep/rust-card10
  • rafael/rust-card10
  • squeed/rust-card10
  • arist/rust-card10
11 results
Select Git revision
  • 4-fix-card10-l0dable-on-crates-io
  • 5-implement-client-c-in-plain-rust
  • build-from-root
  • master
4 results
Show changes
use super::bindings::*;
pub fn set(status: bool) {
unsafe { epic_vibra_set(status.into()); }
}
pub fn vibrate(millis: i32) {
unsafe { epic_vibra_vibrate(millis); }
}
target remote :3333
define reset
mon mww 0x40000004 0x80000000
end
# print demangled symbols by default
set print asm-demangle on
monitor arm semihosting enable
load
{ stdenv, makeWrapper, openocd, fetchFromGitHub, autoreconfHook, git, which }:
let
maxim-openocd = openocd.overrideAttrs (oa: {
name = "maxim-openocd";
src = fetchFromGitHub {
owner = "maximmbed";
repo = "openocd";
rev = "e71ac88c9dbfa4ee1405d7a86376119dcc887ed1";
sha256 = "18yc1wyclmjxqg6jilfcm60hi01pgqc4dilsmksqbhg23m6x4ycw";
fetchSubmodules = true;
};
nativeBuildInputs = oa.nativeBuildInputs ++ [
autoreconfHook
git
which
];
enableParallelBuilding = true;
});
card10-scripts = stdenv.mkDerivation {
name = "card10-scripts";
src = ./c/openocd/scripts;
dontBuild = true;
installPhase = ''
mkdir -p $out/share/openocd
cp -ar . $out/share/openocd/scripts
'';
};
in
stdenv.mkDerivation {
name = "openocd-card10";
src = maxim-openocd;
phases = [ "unpackPhase" "installPhase" ];
buildInputs = [ makeWrapper maxim-openocd card10-scripts ];
installPhase = ''
mkdir -p $out/bin
makeWrapper ${maxim-openocd}/bin/openocd $out/bin/openocd-card10 \
--add-flags "-f ${card10-scripts}/share/openocd/scripts/interface/cmsis-dap.cfg" \
--add-flags "-f ${card10-scripts}/share/openocd/scripts/target/max32665.cfg"
'';
}
{ python3Packages }:
python3Packages.buildPythonPackage rec {
pname = "crc16";
version = "0.1.1";
src = python3Packages.fetchPypi {
inherit pname version;
sha256 = "15nkx0pa4lskwin84flpk8fsw3jqg6wic6v3s83syjqg76h6my61";
};
}
{ pkgs ? import <nixpkgs> {},
cFirmware ? (import ./firmware.nix { inherit pkgs; }).firmware,
rustL0dables ? (import ./default.nix {}).l0dables,
}:
with pkgs;
stdenv.mkDerivation {
name = "card10-firmware";
buildInputs = [ cFirmware rustL0dables ];
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp -r ${cFirmware}/card10/* $out/
chmod u+w $out/apps
cp ${rustL0dables}/apps/* $out/apps/
cat << EOF > $out/card10.cfg
execute_elf=true
EOF
'';
}
...@@ -5,7 +5,9 @@ version = "0.0.0" ...@@ -5,7 +5,9 @@ version = "0.0.0"
authors = ["Astro <astro@spaceboyz.net>"] authors = ["Astro <astro@spaceboyz.net>"]
[dependencies] [dependencies]
l0dable = { path = "../l0dable" } card10-l0dable = { path = "../card10-l0dable" }
card10-alloc = { path = "../card10-alloc" }
embedded-graphics = "0.5"
[build-dependencies] [build-dependencies]
cc = "1.0" cc = "1.0"
......
#![no_std] #![no_std]
#![no_main] #![no_main]
extern crate alloc;
use core::fmt::Write; use core::fmt::Write;
use l0dable::*; use card10_l0dable::{*, framebuffer::*};
use embedded_graphics::{
prelude::*,
primitives::Circle,
};
pub const BALL_RADIUS: u16 = 4; pub const BALL_RADIUS: u32 = 4;
pub const PADDLE_SPACE: u16 = 32; pub const PADDLE_SPACE: u32 = 32;
pub const BLOCK_W: u16 = 16; pub const PADDLE_HEIGHT: u32 = 6;
pub const BLOCK_H: u16 = 10; pub const PADDLE_SPEED: u32 = 4;
pub const BLOCKS_X: u16 = Display::W / BLOCK_W; pub const BLOCK_W: u32 = 16;
pub const BLOCKS_Y: u16 = (Display::H - PADDLE_SPACE) / BLOCK_H; pub const BLOCK_H: u32 = 10;
pub const BLOCKS_X: u32 = Display::W as u32 / BLOCK_W;
pub const BLOCKS_Y: u32 = (Display::H as u32 - PADDLE_SPACE) / BLOCK_H;
pub const LED_INTERVAL: u64 = 70;
pub struct Blocks { pub struct Blocks {
blocks: [[Option<Color>; BLOCKS_X as usize]; BLOCKS_Y as usize], blocks: [[Option<RawColor>; BLOCKS_X as usize]; BLOCKS_Y as usize],
} }
impl Blocks { impl Blocks {
...@@ -28,7 +36,7 @@ impl Blocks { ...@@ -28,7 +36,7 @@ impl Blocks {
let mut buf = [0, 0, 0, 0]; let mut buf = [0, 0, 0, 0];
trng::read(&mut buf); trng::read(&mut buf);
if buf[0] <= rand_max { if buf[0] <= rand_max {
*block = Some(Color::rgb8( *block = Some(RawColor::rgb8(
0x80 | buf[1], 0x80 | buf[1],
0x80 | buf[2], 0x80 | buf[2],
0x80 | buf[3], 0x80 | buf[3],
...@@ -41,18 +49,18 @@ impl Blocks { ...@@ -41,18 +49,18 @@ impl Blocks {
result result
} }
pub fn collides(&mut self, x: u16, y: u16) -> bool { pub fn collides(&mut self, x: u32, y: u32) -> Option<RawColor> {
let col = (x / BLOCK_W) as usize; let col = x / BLOCK_W;
let line = (y / BLOCK_H) as usize; let line = y / BLOCK_H;
if line >= BLOCKS_Y.into() || col >= BLOCKS_X.into() { if line >= BLOCKS_Y || col >= BLOCKS_X {
return false; return None;
} }
match self.blocks[line][col] { match self.blocks[line as usize][col as usize] {
Some(_) => { Some(color) => {
self.blocks[line][col] = None; self.blocks[line as usize][col as usize] = None;
true Some(color)
} }
None => false, None => None,
} }
} }
...@@ -61,9 +69,6 @@ impl Blocks { ...@@ -61,9 +69,6 @@ impl Blocks {
} }
} }
const PADDLE_HEIGHT: u16 = 6;
const PADDLE_SPEED: u16 = 4;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
enum Direction { enum Direction {
/// Up Right /// Up Right
...@@ -77,7 +82,7 @@ enum Direction { ...@@ -77,7 +82,7 @@ enum Direction {
} }
impl Direction { impl Direction {
fn motion(&self, x: &mut u16, y: &mut u16) { fn motion(&self, x: &mut u32, y: &mut u32) {
use Direction::*; use Direction::*;
match self { match self {
UR => { UR => {
...@@ -163,117 +168,166 @@ enum GameResult { ...@@ -163,117 +168,166 @@ enum GameResult {
} }
fn game(level: u16, mut score: u32) -> GameResult { fn game(level: u16, mut score: u32) -> GameResult {
let start_time = time(); let start_time = Seconds::time();
let display = Display::open(); let mut display = Display::open();
let mut fb = display.framebuffer();
let accel = BHI160::<Accelerometer>::start().unwrap();
let mut accel_x = 0;
let mut leds = [LEDColor::RGB(0, 0, 0); 6];
let mut last_led_tick = MilliSeconds::time();
let mut paddle = Display::W / 2; let mut paddle = Display::W as u32 / 2;
let paddle_size = 18 - (2 * level).min(14); let paddle_size = 18 - (2 * level as u32).min(14);
let mut ball_x = paddle; let mut ball_x = paddle;
let mut ball_y = Display::H - PADDLE_HEIGHT - BALL_RADIUS; let mut ball_y = Display::H as u32 - PADDLE_HEIGHT - BALL_RADIUS;
let mut ball_direction = Direction::UR; let mut ball_direction = Direction::UR;
let mut blocks = Blocks::generate((0x3F + 0x10 * level).min(0xff) as u8); let mut blocks = Blocks::generate((0x3F + 0x10 * level).min(0xff) as u8);
// Clear screen
draw_rect(&mut fb, 0, 0, Display::W as u16 - 1, Display::H as u16 - 1, RawColor::black());
// Draw Blocks
for (lineno, line) in blocks.blocks.iter_mut().enumerate() {
let lineno = lineno as u32;
for (colno, block) in line.iter_mut().enumerate() {
block.map(|color| {
let colno = colno as u32;
draw_rect(&mut fb, (colno * BLOCK_W) as u16, (lineno * BLOCK_H) as u16,
((colno + 1) * BLOCK_W - 1) as u16, ((lineno + 1) * BLOCK_H - 1) as u16,
color);
// TODO: spacing?
});
}
}
for tick in 0.. { for tick in 0.. {
for data in &accel.read().unwrap() {
accel_x = (17.0 * data.get_x()) as i32;
}
let input = Buttons::read(); let input = Buttons::read();
let old_paddle = paddle; let old_paddle = paddle;
if input.left_bottom() { if input.left_bottom() {
paddle -= PADDLE_SPEED; paddle = paddle.saturating_sub(PADDLE_SPEED);
paddle = paddle.max(paddle_size);
} }
if input.right_bottom() { if input.right_bottom() {
paddle += PADDLE_SPEED; paddle += PADDLE_SPEED;
paddle = paddle.min(Display::W - paddle_size)
} }
let paddle_moving = paddle != old_paddle; if accel_x < 0 {
paddle += -accel_x as u32;
} else if accel_x > 0 {
paddle = paddle.saturating_sub(accel_x as u32);
}
paddle = paddle
.max(paddle_size)
.min(Display::W as u32 - paddle_size);
if input.left_top() { if input.left_top() {
exit(0); exit(0);
} }
let mut check_finish = false; let mut check_finish = false;
let speed_steps = 2 + (time() - start_time) / 15; let speed_steps = 2 + (Seconds::time() - start_time).0 / 15;
let speed_steps = (speed_steps >> 1) + let speed_steps = (speed_steps >> 1) +
(speed_steps & tick & 1); (speed_steps & tick & 1);
for _ in 0..speed_steps { for _ in 0..speed_steps {
ball_direction.motion(&mut ball_x, &mut ball_y); ball_direction.motion(&mut ball_x, &mut ball_y);
if (ball_direction.is_left() && ball_x <= BALL_RADIUS) || if (ball_direction.is_left() && ball_x <= BALL_RADIUS) ||
(ball_direction.is_right() && ball_x >= Display::W - BALL_RADIUS) { (ball_direction.is_right() && ball_x >= Display::W as u32 - BALL_RADIUS) {
// Bounce on left/right border // Bounce on left/right border
ball_direction.bounce(Bounce::Vertical); ball_direction.bounce(Bounce::Vertical);
vibra::vibrate(10); vibra::vibrate(5);
} }
if ball_direction.is_up() && ball_y <= BALL_RADIUS { if ball_direction.is_up() && ball_y <= BALL_RADIUS {
// Bounce on top border // Bounce on top border
ball_direction.bounce(Bounce::Horizontal); ball_direction.bounce(Bounce::Horizontal);
vibra::vibrate(10); vibra::vibrate(5);
} }
if ball_direction.is_down() && if ball_direction.is_down() &&
ball_y >= Display::H - PADDLE_HEIGHT - BALL_RADIUS && ball_y >= Display::H as u32 - PADDLE_HEIGHT - BALL_RADIUS &&
ball_x >= paddle - paddle_size && ball_x >= paddle - paddle_size &&
ball_x <= paddle + paddle_size { ball_x <= paddle + paddle_size {
// Bounce on paddle // Bounce on paddle
if paddle_moving && input.left_bottom() { if paddle < old_paddle {
ball_direction = Direction::UL; ball_direction = Direction::UL;
vibra::vibrate(50); vibra::vibrate(20);
} else if paddle_moving && input.right_bottom() { } else if paddle > old_paddle {
ball_direction = Direction::UR; ball_direction = Direction::UR;
vibra::vibrate(50); vibra::vibrate(20);
} else { } else {
ball_direction.bounce(Bounce::Horizontal); ball_direction.bounce(Bounce::Horizontal);
vibra::vibrate(20); vibra::vibrate(10);
} }
} }
if ball_y >= Display::H - BALL_RADIUS { if ball_y >= Display::H as u32 - BALL_RADIUS {
return GameResult::Over(score); return GameResult::Over(score);
} }
if blocks.collides(ball_x - BALL_RADIUS, ball_y) || let collision_v = blocks.collides(ball_x - BALL_RADIUS, ball_y)
blocks.collides(ball_x + BALL_RADIUS, ball_y) { .or_else(|| blocks.collides(ball_x + BALL_RADIUS, ball_y));
if let Some(color) = collision_v {
ball_direction.bounce(Bounce::Vertical); ball_direction.bounce(Bounce::Vertical);
score += 3; score += 3;
// paddle_size += 2; // paddle_size += 2;
check_finish = true; check_finish = true;
vibra::vibrate(60); vibra::vibrate(15);
leds[0] = LEDColor::RGB(color.r8(), color.g8(), color.b8());
} }
if blocks.collides(ball_x, ball_y - BALL_RADIUS) || let collision_h = blocks.collides(ball_x, ball_y - BALL_RADIUS)
blocks.collides(ball_x, ball_y + BALL_RADIUS) { .or_else(|| blocks.collides(ball_x, ball_y + BALL_RADIUS));
if let Some(color) = collision_h {
ball_direction.bounce(Bounce::Horizontal); ball_direction.bounce(Bounce::Horizontal);
score += 2; score += 2;
// paddle_size += 1; // paddle_size += 1;
check_finish = true; check_finish = true;
vibra::vibrate(40); vibra::vibrate(15);
leds[0] = LEDColor::RGB(color.r8(), color.g8(), color.b8());
} }
} }
if check_finish && blocks.is_finished() { if check_finish && blocks.is_finished() {
return GameResult::LevelFinish(score + 100); return GameResult::LevelFinish(score + 100);
} }
display.clear(Color::black()); // Empty blocks
// Paddle
display.rect(
paddle - paddle_size, Display::H - PADDLE_HEIGHT,
paddle + paddle_size, Display::H - 1,
Color::rgb8(0x7f, 0xff, 0x7f), FillStyle::Filled, 1
);
// Ball
display.circ(
ball_x, ball_y, BALL_RADIUS,
Color::rgb8(0x7f, 0x7f, 0xff), FillStyle::Filled, 1
);
// Blocks
for (lineno, line) in blocks.blocks.iter_mut().enumerate() { for (lineno, line) in blocks.blocks.iter_mut().enumerate() {
let lineno = lineno as u16; let lineno = lineno as u32;
for (colno, block) in line.iter_mut().enumerate() { for (colno, block) in line.iter_mut().enumerate() {
block.map(|color| { block.or_else(|| {
let colno = colno as u16; let colno = colno as u32;
display.rect( draw_rect(&mut fb, (colno * BLOCK_W) as u16, (lineno * BLOCK_H) as u16,
colno * BLOCK_W, ((colno + 1) * BLOCK_W - 1) as u16, ((lineno + 1) * BLOCK_H - 1) as u16,
lineno * BLOCK_H, RawColor::black());
(colno + 1) * BLOCK_W - 1, None
(lineno + 1) * BLOCK_H - 1, });
color, FillStyle::Filled, 1 }
}
// Space below blocks
draw_rect(&mut fb, 0, (BLOCK_H * BLOCKS_Y) as u16,
Display::W as u16, Display::H as u16, RawColor::black());
// Paddle
draw_rect(&mut fb,
(paddle - paddle_size) as u16, Display::H as u16 - PADDLE_HEIGHT as u16,
(paddle + paddle_size) as u16, Display::H as u16 - 1,
RawColor::rgb8(0x7f, 0xff, 0x7f));
// Ball
fb.draw(
Circle::new((ball_x, ball_y).into(), BALL_RADIUS)
.fill(Some(RawColor::rgb8(0x7f, 0x7f, 0xff)))
); );
fb.send();
update_rgb_leds(|index| {
if index < 6 {
leds[(5 - index) as usize]
} else {
leds[(index - 5) as usize]
}
}); });
let now = MilliSeconds::time();
if last_led_tick.0 + LED_INTERVAL <= now.0 {
for i in 1..leds.len() {
leds[leds.len() - i] = leds[leds.len() - i - 1];
} }
leds[0] = LEDColor::RGB(0, 0, 0);
last_led_tick = now;
} }
display.update();
} }
unreachable!() unreachable!()
} }
...@@ -281,10 +335,10 @@ fn game(level: u16, mut score: u32) -> GameResult { ...@@ -281,10 +335,10 @@ fn game(level: u16, mut score: u32) -> GameResult {
fn title_screen() { fn title_screen() {
let display = Display::open(); let display = Display::open();
display.clear(Color::red()); display.clear(Color::red());
display.print(30, 15, b"Rkanoid\0", Color::white(), Color::red()); display_adv!(display, Font24, Display::W / 2 - 60, 14, Color::white(), Color::red(), "Rkanoid");
display.print(30, 30, b"in Rust\0", Color::white(), Color::red()); display_adv!(display, Font20, Display::W / 2 - 49, 40, Color::white(), Color::red(), "in Rust");
display.print(20, 45, b"by Astro\0", Color::white(), Color::red()); display_adv!(display, Font16, Display::W / 2 - 44, 64, Color::white(), Color::red(), "by Astro");
display.print(Display::W - 2 * Display::FONT_W, Display::H - Display::FONT_H, b"Go\0", Color::yellow(), Color::blue()); display!(display, Display::W - 2 * Display::FONT_W, Display::H - Display::FONT_H + 3, Color::yellow(), Color::blue(), "Go");
display.update(); display.update();
while !Buttons::read().right_bottom() {} while !Buttons::read().right_bottom() {}
} }
...@@ -292,13 +346,11 @@ fn title_screen() { ...@@ -292,13 +346,11 @@ fn title_screen() {
fn game_over(score: u32) -> bool { fn game_over(score: u32) -> bool {
let display = Display::open(); let display = Display::open();
display.clear(Color::red()); display.clear(Color::red());
display.print(30, 0, b"Rkanoid\0", Color::white(), Color::red()); display!(display, 30, 0, Color::white(), Color::red(), "Rkanoid");
display.print(0, 25, b"Game over!\0", Color::white(), Color::red()); display!(display, 0, 25, Color::white(), Color::red(), "Game over!");
let mut score_str = [0u8; 32]; display!(display, 0, 60, Color::white(), Color::red(), "Score {}", score);
write!(FmtBuffer::new(&mut score_str), "Score {}\0", score).unwrap(); display!(display, 0, 0, Color::yellow(), Color::blue(), "Q");
display.print(0, 60, &score_str, Color::white(), Color::red()); display!(display, Display::W - Display::FONT_W, Display::H - 2 * Display::FONT_H, Color::yellow(), Color::blue(), "S");
display.print(0, 0, b"Q\0", Color::yellow(), Color::blue());
display.print(Display::W - Display::FONT_W, Display::H - 2 * Display::FONT_H, b"S\0", Color::yellow(), Color::blue());
display.update(); display.update();
loop { loop {
let buttons = Buttons::read(); let buttons = Buttons::read();
...@@ -314,15 +366,11 @@ fn game_over(score: u32) -> bool { ...@@ -314,15 +366,11 @@ fn game_over(score: u32) -> bool {
fn level_finish(level: u16, score: u32) -> bool { fn level_finish(level: u16, score: u32) -> bool {
let display = Display::open(); let display = Display::open();
display.clear(Color::red()); display.clear(Color::red());
display.print(30, 0, b"Rkanoid\0", Color::white(), Color::red()); display!(display, 30, 0, Color::white(), Color::red(), "Rkanoid");
let mut level_str = [0u8; 32]; display!(display, 0, 25, Color::white(), Color::red(), "Lvl {} done!", level + 1);
write!(FmtBuffer::new(&mut level_str), "Lvl {} done!\0", level + 1).unwrap(); display!(display, 20, 60, Color::white(), Color::red(), "Score {}", score);
display.print(0, 25, &level_str, Color::white(), Color::red()); display!(display, 0, 60, Color::yellow(), Color::blue(), "Q");
let mut score_str = [0u8; 32]; display!(display, Display::W - Display::FONT_W, Display::H - 2 * Display::FONT_H, Color::yellow(), Color::blue(), "S");
write!(FmtBuffer::new(&mut score_str), "Score {}\0", score).unwrap();
display.print(0, 60, &score_str, Color::white(), Color::red());
display.print(0, 0, b"Q\0", Color::yellow(), Color::blue());
display.print(Display::W - Display::FONT_W, Display::H - 2 * Display::FONT_H, b"S\0", Color::yellow(), Color::blue());
display.update(); display.update();
loop { loop {
let buttons = Buttons::read(); let buttons = Buttons::read();
...@@ -337,13 +385,16 @@ fn level_finish(level: u16, score: u32) -> bool { ...@@ -337,13 +385,16 @@ fn level_finish(level: u16, score: u32) -> bool {
main!(main); main!(main);
fn main() { fn main() {
card10_alloc::init(128 * 1024);
title_screen(); title_screen();
let mut quit = false; let mut quit = false;
let mut level = 0; let mut level = 0;
let mut score = 0; let mut score = 0;
while !quit { while !quit {
match game(level, score) { let game_result = game(level, score);
update_rgb_leds(|_| LEDColor::RGB(0, 0, 0));
match game_result {
GameResult::LevelFinish(new_score) => { GameResult::LevelFinish(new_score) => {
let again = level_finish(level, new_score); let again = level_finish(level, new_score);
quit = !again; quit = !again;
...@@ -359,3 +410,15 @@ fn main() { ...@@ -359,3 +410,15 @@ fn main() {
} }
} }
} }
fn draw_rect(fb: &mut FrameBuffer, x1: u16, y1: u16, x2: u16, y2: u16, color: RawColor) {
let x1 = x1.max(0).min(Display::W as u16 - 1);
let x2 = x2.max(0).min(Display::W as u16 - 1);
let y1 = y1.max(0).min(Display::H as u16 - 1);
let y2 = y2.max(0).min(Display::H as u16 - 1);
for y in y1..=y2 {
for x in x1..=x2 {
fb[(x, y)] = color;
}
}
}
{ pkgs ? import <nixpkgs> {} }: { pkgs ? import <nixpkgs> {} }:
with pkgs; with pkgs;
with import ./default.nix; with import ./default.nix {};
stdenv.mkDerivation { stdenv.mkDerivation {
name = "env"; name = "env";
...@@ -10,14 +10,11 @@ stdenv.mkDerivation { ...@@ -10,14 +10,11 @@ stdenv.mkDerivation {
glibc_multi glibc_multi
rust rust
pkgsCross.arm-embedded.stdenv.cc pkgsCross.arm-embedded.stdenv.cc
openocd
]; ];
# Set Environment Variables LIBCLANG_PATH="${llvmPackages.libclang}/lib";
RUST_BACKTRACE = 1;
shellHook = '' shellHook = ''
export LIBCLANG_PATH=${llvmPackages.libclang}/lib export CPATH="${glibc_multi.dev}/include:${stdenv.cc.cc}/lib/gcc/$(cc -dumpmachine)/${lib.getVersion pkgsCross.arm-embedded.stdenv.cc.cc}/include"
echo "Run 'cd example && cargo build --release'" echo "Run 'cargo build --release'"
''; '';
} }