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

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
Show changes
Commits on Source (141)
Showing
with 679 additions and 234 deletions
#!/usr/bin/env bash
set -e
cargo build --release
arm-none-eabi-objcopy -O binary target/thumbv7em-none-eabi/release/$2 card10.bin
python c/bootloader/crc_patch.py card10.bin
echo "Copy this file to the device in USB Mass Storage mode:"
ls -l card10.bin
...@@ -29,4 +29,5 @@ firmware: ...@@ -29,4 +29,5 @@ firmware:
- apps - apps
- main.py - main.py
- menu.py - menu.py
- card10.cfg
expire_in: 1 week expire_in: 1 week
[submodule "c"] [submodule "card10-sys/firmware"]
path = c path = card10-sys/firmware
url = https://git.card10.badge.events.ccc.de/card10/firmware.git url = https://git.card10.badge.events.ccc.de/card10/firmware.git
From 93c318a284f7b0f3bce2046e1f631599190eaa10 Mon Sep 17 00:00:00 2001
From: Astro <astro@spaceboyz.net>
Date: Fri, 23 Aug 2019 19:44:45 +0200
Subject: [PATCH] feat(nix): add jailbreak arg
---
default.nix | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/default.nix b/default.nix
index dc9649bc..c49d0ab2 100644
--- a/default.nix
+++ b/default.nix
@@ -1,4 +1,8 @@
-with import <nixpkgs> {};
+{ pkgs ? import <nixpkgs> {},
+ jailbreak ? false,
+}:
+
+with pkgs;
let
py = python36;
@@ -12,6 +16,10 @@ let
sha256 = "15nkx0pa4lskwin84flpk8fsw3jqg6wic6v3s83syjqg76h6my61";
};
};
+ mesonOpt =
+ if jailbreak
+ then "-Djailbreak_card10=true"
+ else "";
in stdenv.mkDerivation rec {
name = "card10";
nativeBuildInputs = [
@@ -39,7 +47,7 @@ in stdenv.mkDerivation rec {
done
# Actually run the build.
- meson --cross-file card10-cross.ini "$build"
+ meson --cross-file card10-cross.ini ${mesonOpt} "$build"
ninja -C "$build" -j $NIX_BUILD_CORES
# Copy ELFs for debugging
--
2.22.0
From baef13b1adb6f7bf01a7dfd7f4f44a5a3e950b1d Mon Sep 17 00:00:00 2001
From: Astro <astro@spaceboyz.net>
Date: Thu, 5 Sep 2019 02:22:45 +0200
Subject: [PATCH] hack(epicardium): reduce init delay from 2s to 0.1s
---
epicardium/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/epicardium/main.c b/epicardium/main.c
index 51edbe93..7607d39d 100644
--- a/epicardium/main.c
+++ b/epicardium/main.c
@@ -32,7 +32,7 @@ int main(void)
epic_disp_print(10, 20, "Epicardium", 0xfe20, 0x0000);
epic_disp_print(off > 0 ? off : 0, 40, version_buf, 0xfe20, 0x0000);
epic_disp_update();
- mxc_delay(2000000);
+ mxc_delay(100000);
LOG_DEBUG("startup", "Initializing tasks ...");
--
2.22.1
This diff is collapsed.
[workspace] [workspace]
members = [ members = [
"l0dable", "card10-sys",
"card10-alloc",
"card10-l0dable",
"example", "example",
"rkanoid", "rkanoid",
"draw-image",
] ]
default-members = [ default-members = [
"example", "example",
"rkanoid", "rkanoid",
"draw-image",
] ]
[profile.release] [profile.release]
...@@ -16,3 +21,6 @@ debug = true ...@@ -16,3 +21,6 @@ debug = true
opt-level = "s" opt-level = "s"
lto = true lto = true
panic = "abort" panic = "abort"
[patch.crates-io]
alloc-cortex-m = { git = 'https://github.com/rust-embedded/alloc-cortex-m' }
# Rust support for the card10 CCCamp19 badge # Rust support for the card10 CCCamp19 badge
## Prepare your card10
**Jailbreaking is no longer necessary!**
Starting with firmware v1.9, running ELF binaries requires a
`/card10.cfg` with the following content:
```
execute_elf=true
```
## Prebuilt binaries ## Prebuilt binaries
By courtesy of this Gitlab's CI system, and NixOS, we build `.elf` By courtesy of this Gitlab's CI system, and NixOS, we build `.elf`
files for you drop into the `apps/` directory of your card10 badge. files for you drop into the `apps/` directory of your card10 badge.
Because running ELF binaries requires a jailbroken base firmware For each commit in this repository, we also build complete firmware
starting with v1.5, we build this one too. It includes this project's images with the required configuration and our example binaries.
Rust binaries.
https://git.card10.badge.events.ccc.de/astro/rust-card10/-/jobs https://git.card10.badge.events.ccc.de/astro/rust-card10/-/jobs
...@@ -40,31 +50,65 @@ firmware including the matching libc. ...@@ -40,31 +50,65 @@ firmware including the matching libc.
git submodule update --init --recursive git submodule update --init --recursive
``` ```
## Setup a Rust enabled firmware ## Build and run Rust loadables
To allow rust based apps on card10 you need a firmware which allows ### Setup
to run custom elf binaries on the core. This requires a custom build
with `-Djailbreak_card10=true` as bootstrapping flag.
Assuming that you installed all required dependencies mentioned in If you want to come up with your own rust based loadable crate a few
https://firmware.card10.badge.events.ccc.de/how-to-build.html this preparations are required:
should work as following:
```shell - Setup the new crate repository.
cd c/
./bootstrap -Djailbreak_card10=true - Add `card10-l0dable = "^0.1"` as a dependency to your new crate.
ninja -C build/
- Change the configuration of the default cargo release profile inside your
`Cargo.toml` file:
```
[profile.release]
opt-level = "s"
panic = "abort"
``` ```
And then copy `build/pycardium/pycardium_epicardium.bin` as - Create (or update) the `thumbv7em-none-eabi` target configuration at
`card10.bin` onto your badge. `$PROJECT/.cargo/config` with the following rustflags:
## Build and run Rust loadables ```
[target.thumbv7em-none-eabi]
rustflags = [
"-C", "linker=arm-none-eabi-gcc",
"-C", "link-args=-Tl0dable.ld -n -pie -fPIC",
"-C", "relocation-model=pic",
]
[build]
target = "thumbv7em-none-eabi"
```
- Ensure that your crate is marked as a `non_std` project and make
`card10-l0dable` aware of your custom main function. This should require
the following update to your `main.rs` file.
```main.rs
#![no_std]
#![no_main]
use card10_l0dable::main;
main!(main);
fn main() {}
```
### Compilation
To compile the project use the nightly toolchain and define the proper target.
```shell ```shell
cargo +nightly build --release --target thumbv7-none-eabi cargo +nightly build --release --target thumbv7em-none-eabi
``` ```
### Transfer to card10
Then copy the resulting executable from the target directory Then copy the resulting executable from the target directory
`target/thumbv7em-none-eabi/release/example` into the `target/thumbv7em-none-eabi/release/example` into the
`apps` directory of your badge. `apps` directory of your badge.
...@@ -74,29 +118,32 @@ extension (e.g `example` must be renamed as `example.elf`). ...@@ -74,29 +118,32 @@ extension (e.g `example` must be renamed as `example.elf`).
## Crates ## Crates
| Crate | Description | | Crate | Documentation | Description |
| ---- | --- | | ---- | --- | --- |
| l0dable | Helper crate for building l0dables | | card10-sys | [docs.rs][card10-sys] | Unsafe C bindings for l0dables |
| example | l0dable example | | card10-alloc | [docs.rs][card10-alloc] | alloc::* support for l0dables |
| rkanoid | Arkanoid clone | | card10-l0dable | [docs.rs][card10-l0dable] | High-level crate for building l0dables |
| example | | l0dable example |
| rkanoid | | Arkanoid clone |
| draw-image | | Example of drawing a static image to the display |
[card10-sys]: https://docs.rs/card10-sys/
[card10-alloc]: https://docs.rs/card10-alloc/
[card10-l0dable]: https://docs.rs/card10-l0dable/
## Misc ## Misc
### How to update the firmware bindings ### How to update the firmware bindings
1) Update the `c/` submodule to the latest firmware state. 1) Update the `card10-sys/firmware` submodule to the latest firmware state.
2) Rebuild the firmware as described above. 2) Rebuild the firmware as described above.
3) Run the following script from the project root directory 3) Run the following script from the project root directory
```shell ```shell
python c/epicardium/api/genapi.py -H c/epicardium/epicardium.h -c l0dable/src/client.c -s l0dable/src/server.c python card10-sys/firmware/epicardium/api/genapi.py -H card10-sys/firmware/epicardium/epicardium.h -c card10-sys/vendor/client.c -s card10-sys/vendor/server.c
``` ```
4) Rebuild your app :) 4) Rebuild your app :)
## TODO
- [ ] alloc
c @ c8dbb334
Subproject commit c8dbb334d9bfb99ddf0e9daacbe8b3ab88b60ed6
[package] [package]
edition = "2018"
name = "card10-l0dable" name = "card10-alloc"
version = "0.1.1" version = "0.1.1"
authors = ["Astro <astro@spaceboyz.net>", "Kloenk <me@kloenk.de>"] authors = ["Astro <astro@spaceboyz.net>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2018"
description = "Dynamic memory allocation for card10 l0dables"
repository = "https://git.card10.badge.events.ccc.de/astro/rust-card10" repository = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
homepage = "https://git.card10.badge.events.ccc.de/astro/rust-card10" homepage = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
documentation = "https://docs.rs/card10-alloc"
categories = ["no-std", "memory-management"]
keywords = [ keywords = [
"CCC", "CCC",
"CCCamp2019", "CCCamp2019",
...@@ -13,21 +19,7 @@ keywords = [ ...@@ -13,21 +19,7 @@ keywords = [
"card10", "card10",
"l0dable", "l0dable",
] ]
categories = ["no-std"]
description = """
make l0dables for the Card10 (CCCamp 2019) badge
"""
include = [
"**/*.rs",
"Cargo.toml",
"l0dable.ld",
"../c/",
]
[dependencies] [dependencies]
r0 = "0.2" alloc-cortex-m = "0.3"
panic-abort = "0.3" card10-sys = { path = "../card10-sys" }
[build-dependencies]
cc = "1.0"
bindgen = "0.51"
//! Support for dynamically allocated memory
//!
//! Reproduces l0dable hardware.c's `_sbrk()`
//!
//! Unfortunately, we cannot link `_sbrk()` directly because it
//! references the unwieldy `errno`.
//!
//! ## Example
//!
//! ```rust
//! #![no_std]
//! #![no_main]
//!
//! extern crate alloc;
//! use alloc::vec;
//! use card10_l0dable::*;
//!
//! main!(main);
//! fn main() {
//! // Pass stack headroom
//! card10_alloc::init(128 * 1024);
//! let mut xs = vec![];
//! xs.push(23);
//! }
//! ```
#![no_std]
#![feature(asm)]
#![feature(alloc_error_handler)]
use core::alloc::Layout;
use alloc_cortex_m::CortexMHeap;
use card10_sys as _;
#[global_allocator]
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
extern "C" {
static mut __heap_start: u32;
}
#[inline(always)]
fn sp() -> usize {
let mut value;
unsafe {
asm!("mov $0, sp" : "=r" (value) ::: "volatile");
}
value
}
/// Call this before using anything from `alloc`.
///
/// Consider the size of your stack-allocated variables for the
/// `stack_headroom` parameter.
///
/// Returns heap size
pub fn init(stack_headroom: usize) -> usize {
let start = unsafe { &__heap_start } as *const _ as usize;
let size = sp() - stack_headroom - start;
unsafe { ALLOCATOR.init(start, size); }
size
}
#[alloc_error_handler]
fn on_oom(_layout: Layout) -> ! {
panic!("OOM")
}
[package]
edition = "2018"
name = "card10-l0dable"
version = "0.3.0"
authors = [
"Astro <astro@spaceboyz.net>",
"Kloenk <me@kloenk.de>",
"Bruno Kirschner <bruno.kirschner@online.de>",
"Puzzlewolf <camp@nora.pink>",
"Raphael Nestler <raphael.nestler@gmail.com>",
"Danilo Bargen <mail@dbrgn.ch>",
"toon <toon@c3d2.de>",
"Sergey Pepyakin <sergei@parity.io>",
]
license = "MIT/Apache-2.0"
repository = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
homepage = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
keywords = [
"CCC",
"CCCamp2019",
"CCCamp19",
"card10",
"l0dable",
]
categories = ["no-std"]
description = "make l0dables for the Card10 (CCCamp 2019) badge"
documentation = "https://docs.rs/card10-l0dable"
[dependencies]
card10-sys = { path = "../card10-sys" }
embedded-graphics = "0.5"
File moved
File moved
/// Accelerometer, Gyroscope, Orientation
use core::{ use core::{
fmt::{self, Display, Write}, fmt::{self, Display, Write},
marker::PhantomData, marker::PhantomData,
mem::MaybeUninit, mem::MaybeUninit,
}; };
use crate::{bindings::*, errno}; use card10_sys::*;
pub trait SensorType { pub trait SensorType {
/// sensor_type in C, sensor_id in Python /// sensor_type in C, sensor_id in Python
...@@ -12,6 +14,7 @@ pub trait SensorType { ...@@ -12,6 +14,7 @@ pub trait SensorType {
fn convert_single(value: i16) -> f32; fn convert_single(value: i16) -> f32;
} }
#[derive(Debug)]
pub struct Accelerometer; pub struct Accelerometer;
impl SensorType for Accelerometer { impl SensorType for Accelerometer {
fn sensor_type() -> u32 { fn sensor_type() -> u32 {
...@@ -22,6 +25,7 @@ impl SensorType for Accelerometer { ...@@ -22,6 +25,7 @@ impl SensorType for Accelerometer {
} }
} }
#[derive(Debug)]
pub struct Gyroscope; pub struct Gyroscope;
impl SensorType for Gyroscope { impl SensorType for Gyroscope {
fn sensor_type() -> u32 { fn sensor_type() -> u32 {
...@@ -32,6 +36,7 @@ impl SensorType for Gyroscope { ...@@ -32,6 +36,7 @@ impl SensorType for Gyroscope {
} }
} }
#[derive(Debug)]
pub struct Orientation; pub struct Orientation;
impl SensorType for Orientation { impl SensorType for Orientation {
fn sensor_type() -> u32 { fn sensor_type() -> u32 {
...@@ -50,6 +55,10 @@ pub struct Sensor<S: SensorType> { ...@@ -50,6 +55,10 @@ pub struct Sensor<S: SensorType> {
} }
impl<S: SensorType> Sensor<S> { impl<S: SensorType> Sensor<S> {
/// Use one of:
/// - `BHI160::<Accelerometer>::start()`
/// - `BHI160::<Gyroscope>::start()`
/// - `BHI160::<Orientation>::start()`
fn new(stream_id: i32) -> Self { fn new(stream_id: i32) -> Self {
Self { Self {
stream_id, stream_id,
...@@ -118,7 +127,7 @@ pub struct SensorData<S> { ...@@ -118,7 +127,7 @@ pub struct SensorData<S> {
} }
impl<'a, S: SensorType> IntoIterator for &'a SensorData<S> { impl<'a, S: SensorType> IntoIterator for &'a SensorData<S> {
type Item = SensorDataItem; type Item = SensorDataItem<S>;
type IntoIter = SensorDataIter<'a, S>; type IntoIter = SensorDataIter<'a, S>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
...@@ -132,25 +141,26 @@ pub struct SensorDataIter<'a, S> { ...@@ -132,25 +141,26 @@ pub struct SensorDataIter<'a, S> {
} }
impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> { impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> {
type Item = SensorDataItem; type Item = SensorDataItem<S>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while self.pos < self.data.n { while self.pos < self.data.n {
self.pos += 1;
let vec = &self.data.buf[self.pos]; let vec = &self.data.buf[self.pos];
if vec.data_type != DATA_TYPE_VECTOR { if vec.data_type != DATA_TYPE_VECTOR {
writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).ok(); writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).ok();
continue; continue;
} }
let item = SensorDataItem { let item = SensorDataItem::<S> {
x: S::convert_single(vec.x), x_raw: vec.x,
y: S::convert_single(vec.y), y_raw: vec.y,
z: S::convert_single(vec.z), z_raw: vec.z,
status: vec.status, status: vec.status,
_kind: PhantomData,
}; };
self.pos += 1;
return Some(item); return Some(item);
} }
...@@ -159,11 +169,26 @@ impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> { ...@@ -159,11 +169,26 @@ impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SensorDataItem { pub struct SensorDataItem<S: SensorType> {
x: f32, pub x_raw: i16,
y: f32, pub y_raw: i16,
z: f32, pub z_raw: i16,
status: u8, pub status: u8,
_kind: PhantomData<S>,
}
impl<S: SensorType> SensorDataItem<S> {
pub fn get_x(&self) -> f32 {
S::convert_single(self.x_raw)
}
pub fn get_y(&self) -> f32 {
S::convert_single(self.y_raw)
}
pub fn get_z(&self) -> f32 {
S::convert_single(self.z_raw)
}
} }
#[repr(C)] #[repr(C)]
......
/// Enviromental sensor
use card10_sys::*;
use core::mem::uninitialized; use core::mem::uninitialized;
use super::bindings::*;
pub struct BME680; pub struct BME680;
pub type SensorData = bme680_sensor_data; pub type SensorData = bme680_sensor_data;
...@@ -7,7 +9,7 @@ pub type SensorData = bme680_sensor_data; ...@@ -7,7 +9,7 @@ pub type SensorData = bme680_sensor_data;
impl BME680 { impl BME680 {
pub fn start() -> Self { pub fn start() -> Self {
if unsafe { epic_bme680_init() } != 0 { if unsafe { epic_bme680_init() } != 0 {
panic!("Cannot start light sensor"); panic!("Cannot start BME680 sensor");
} }
BME680 BME680
} }
...@@ -24,6 +26,8 @@ impl BME680 { ...@@ -24,6 +26,8 @@ impl BME680 {
impl Drop for BME680 { impl Drop for BME680 {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { epic_bme680_deinit(); } unsafe {
epic_bme680_deinit();
}
} }
} }
use super::bindings::*; use card10_sys::*;
/// Button inputs
pub struct Buttons { pub struct Buttons {
state: u32, state: u32,
} }
impl Buttons { impl Buttons {
/// Read the current button state
pub fn read() -> Self { pub fn read() -> Self {
let mask = let mask = epic_button_BUTTON_LEFT_BOTTOM
epic_button_BUTTON_LEFT_BOTTOM | | epic_button_BUTTON_RIGHT_BOTTOM
epic_button_BUTTON_RIGHT_BOTTOM | | epic_button_BUTTON_LEFT_TOP
epic_button_BUTTON_LEFT_TOP | | epic_button_BUTTON_RIGHT_TOP
epic_button_BUTTON_RIGHT_TOP | | epic_button_BUTTON_RESET;
epic_button_BUTTON_RESET;
let state = unsafe { epic_buttons_read(mask as u8) }.into(); let state = unsafe { epic_buttons_read(mask as u8) }.into();
Buttons { state } Buttons { state }
} }
......
use super::bindings::*;
use super::framebuffer::FrameBuffer; use super::framebuffer::FrameBuffer;
use card10_sys::*;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C)] #[repr(C)]
...@@ -32,9 +32,7 @@ impl Color { ...@@ -32,9 +32,7 @@ impl Color {
pub fn rgb8(r8: u8, g8: u8, b8: u8) -> Self { pub fn rgb8(r8: u8, g8: u8, b8: u8) -> Self {
let c = let c =
((u16::from(r8) & 0xF8) << 8) | ((u16::from(r8) & 0xF8) << 8) | ((u16::from(g8) & 0xFA) << 3) | (u16::from(b8) & 0xF8);
((u16::from(g8) & 0xFA) << 3) |
(u16::from(b8) & 0xF8);
Color(c) Color(c)
} }
...@@ -51,7 +49,7 @@ impl Color { ...@@ -51,7 +49,7 @@ impl Color {
} }
pub fn g8(&self) -> u8 { pub fn g8(&self) -> u8 {
self.r() << 2 self.g() << 2
} }
pub fn b(&self) -> u8 { pub fn b(&self) -> u8 {
...@@ -59,7 +57,7 @@ impl Color { ...@@ -59,7 +57,7 @@ impl Color {
} }
pub fn b8(&self) -> u8 { pub fn b8(&self) -> u8 {
self.r() << 3 self.b() << 3
} }
} }
...@@ -77,63 +75,167 @@ pub enum FillStyle { ...@@ -77,63 +75,167 @@ pub enum FillStyle {
pub struct Display; pub struct Display;
#[repr(u8)]
pub enum Font {
Font8 = disp_font_name_DISP_FONT8 as u8,
Font12 = disp_font_name_DISP_FONT12 as u8,
Font16 = disp_font_name_DISP_FONT16 as u8,
Font20 = disp_font_name_DISP_FONT20 as u8,
Font24 = disp_font_name_DISP_FONT24 as u8,
}
/// Immediate mode routines
impl Display { impl Display {
pub const W: u16 = 160; pub const W: i16 = 160;
pub const H: u16 = 80; pub const H: i16 = 80;
pub const FONT_W: u16 = 14; pub const FONT_W: i16 = 14;
pub const FONT_H: u16 = 20; pub const FONT_H: i16 = 20;
/// Open the display, return an instance
pub fn open() -> Self { pub fn open() -> Self {
unsafe { epic_disp_open(); } unsafe {
epic_disp_open();
}
Display Display
} }
/// Write Epicardium's framebuffer to the display
pub fn update(&self) { pub fn update(&self) {
unsafe { epic_disp_update(); } unsafe {
epic_disp_update();
}
} }
/// Clear everything with a solid `color`
pub fn clear(&self, color: Color) { pub fn clear(&self, color: Color) {
unsafe { epic_disp_clear(color.0); } unsafe {
epic_disp_clear(color.0);
}
} }
/// Print text
///
/// s must be 0-terminated /// s must be 0-terminated
pub fn print(&self, x: u16, y: u16, s: &[u8], fg: Color, bg: Color) { pub fn print(&self, x: i16, y: i16, s: &[u8], fg: Color, bg: Color) {
unsafe { unsafe {
epic_disp_print(x, y, s.as_ptr(), fg.0, bg.0); epic_disp_print(x, y, s.as_ptr(), fg.0, bg.0);
} }
} }
pub fn pixel(&self, x: u16, y: u16, color: Color) { /// Print text with a selected font
///
/// s must be 0-terminated
pub fn print_adv(&self, font: Font, x: i16, y: i16, s: &[u8], fg: Color, bg: Color) {
unsafe {
epic_disp_print_adv(font as u8, x, y, s.as_ptr(), fg.0, bg.0);
}
}
/// Set a pixel
pub fn pixel(&self, x: i16, y: i16, color: Color) {
unsafe { unsafe {
epic_disp_pixel(x, y, color.0); epic_disp_pixel(x, y, color.0);
} }
} }
pub fn line(&self, x1: u16, y1: u16, x2: u16, y2: u16, color: Color, linestyle: LineStyle, pixelsize: u16) { /// Draw a line
pub fn line(
&self,
x1: i16,
y1: i16,
x2: i16,
y2: i16,
color: Color,
linestyle: LineStyle,
pixelsize: u16,
) {
unsafe { unsafe {
epic_disp_line(x1, y1, x2, y2, color.0, linestyle as u32, pixelsize); epic_disp_line(x1, y1, x2, y2, color.0, linestyle as u32, pixelsize);
} }
} }
pub fn rect(&self, x1: u16, y1: u16, x2: u16, y2: u16, color: Color, fillstyle: FillStyle, pixelsize: u16) { pub fn rect(
&self,
x1: i16,
y1: i16,
x2: i16,
y2: i16,
color: Color,
fillstyle: FillStyle,
pixelsize: u16,
) {
unsafe { unsafe {
epic_disp_rect(x1, y1, x2, y2, color.0, fillstyle as u32, pixelsize); epic_disp_rect(x1, y1, x2, y2, color.0, fillstyle as u32, pixelsize);
} }
} }
pub fn circ(&self, x: u16, y: u16, rad: u16, color: Color, fillstyle: FillStyle, pixelsize: u16) { /// Draw a circle
pub fn circ(
&self,
x: i16,
y: i16,
rad: u16,
color: Color,
fillstyle: FillStyle,
pixelsize: u16,
) {
unsafe { unsafe {
epic_disp_circ(x, y, rad, color.0, fillstyle as u32, pixelsize); epic_disp_circ(x, y, rad, color.0, fillstyle as u32, pixelsize);
} }
} }
pub fn framebuffer<'d>(&'d self) -> FrameBuffer<'d> { /// Obtain a handle for a framebuffer.
///
/// Don't use `display.send()` but `framebuffer.send()` as long as
/// it is in use.
pub fn framebuffer<'d>(&'d mut self) -> FrameBuffer<'d> {
FrameBuffer::uninitialized(self) FrameBuffer::uninitialized(self)
} }
} }
impl Drop for Display { impl Drop for Display {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { epic_disp_close(); } unsafe {
} epic_disp_close();
}
}
}
/// Convenience text display
///
/// Requires `card10_alloc::init()` and `extern crate alloc;`
#[macro_export]
macro_rules! display {
($disp: expr, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr) => ({
use alloc::format;
let s = format!(concat!($fmt, "\0"));
$disp.print($x, $y, s.as_bytes(), $fg, $bg);
});
($disp: expr, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr, $($arg: tt)*) => ({
use alloc::format;
let s = format!(concat!($fmt, "\0"), $($arg)*);
$disp.print($x, $y, s.as_bytes(), $fg, $bg);
});
}
/// Convenience text display with selected font
///
/// Requires `card10_alloc::init()` and `extern crate alloc;`
#[macro_export]
macro_rules! display_adv {
($disp: expr, $font: tt, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr) => ({
use alloc::format;
use card10_l0dable::Font;
let s = format!(concat!($fmt, "\0"));
$disp.print_adv(Font::$font, $x, $y, s.as_bytes(), $fg, $bg);
});
($disp: expr, $font: tt, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr, $($arg: tt)*) => ({
use alloc::format;
let s = format!(concat!($fmt, "\0"), $($arg)*);
$disp.print_adv(Font::$font, $x, $y, s.as_bytes(), $fg, $bg);
});
} }
...@@ -37,7 +37,7 @@ impl<'a> fmt::Write for FmtBuffer<'a> { ...@@ -37,7 +37,7 @@ impl<'a> fmt::Write for FmtBuffer<'a> {
} }
} }
/// 256 bytes ought to be enough for any string /// 255 bytes ought to be enough for any C string
pub fn str_to_cstr(s: &str) -> [u8; 256] { pub fn str_to_cstr(s: &str) -> [u8; 256] {
let mut buf: [u8; 256] = unsafe { uninitialized() }; let mut buf: [u8; 256] = unsafe { uninitialized() };
let mut fmt = FmtBuffer::new(buf.as_mut()); let mut fmt = FmtBuffer::new(buf.as_mut());
......