2018-11-14 06:47:52 +11:00
|
|
|
#![no_std]
|
2018-12-16 14:35:57 +11:00
|
|
|
#![feature(start)]
|
|
|
|
#![feature(underscore_const_names)]
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! newtype {
|
|
|
|
($(#[$attr:meta])* $new_name:ident, $old_name:ident) => {
|
|
|
|
$(#[$attr])*
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct $new_name($old_name);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! const_assert {
|
|
|
|
($condition:expr) => {
|
|
|
|
#[deny(const_err)]
|
|
|
|
#[allow(dead_code)]
|
|
|
|
const _: usize = 0 - !$condition as usize;
|
|
|
|
};
|
|
|
|
}
|
2018-11-14 06:47:52 +11:00
|
|
|
|
2018-12-18 11:00:22 +11:00
|
|
|
/// Constructs an RGB value with a `const_assert!` that the input is in range.
|
2018-12-17 14:55:53 +11:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! const_rgb {
|
|
|
|
($r:expr, $g:expr, $b:expr) => {{
|
2018-12-18 11:00:22 +11:00
|
|
|
const_assert!($r <= 31);
|
|
|
|
const_assert!($g <= 31);
|
|
|
|
const_assert!($b <= 31);
|
2018-12-17 14:55:53 +11:00
|
|
|
Color::new($r, $g, $b)
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: kill this
|
|
|
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct VolatilePtr<T>(pub *mut T);
|
|
|
|
impl<T> VolatilePtr<T> {
|
|
|
|
pub unsafe fn read(&self) -> T {
|
|
|
|
core::ptr::read_volatile(self.0)
|
|
|
|
}
|
|
|
|
pub unsafe fn write(&self, data: T) {
|
|
|
|
core::ptr::write_volatile(self.0, data);
|
|
|
|
}
|
|
|
|
pub unsafe fn offset(self, count: isize) -> Self {
|
|
|
|
VolatilePtr(self.0.wrapping_offset(count))
|
|
|
|
}
|
2018-11-14 06:47:52 +11:00
|
|
|
}
|
|
|
|
|
2018-12-16 14:35:57 +11:00
|
|
|
newtype! {
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
Color, u16
|
|
|
|
}
|
|
|
|
|
2018-12-17 14:55:53 +11:00
|
|
|
impl Color {
|
|
|
|
/// Combines the Red, Blue, and Green provided into a single color value.
|
|
|
|
pub const fn new(red: u16, green: u16, blue: u16) -> Color {
|
|
|
|
Color(blue << 10 | green << 5 | red)
|
|
|
|
}
|
2018-12-16 14:35:57 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
newtype! {
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
DisplayControlSetting, u16
|
|
|
|
}
|
|
|
|
|
2018-12-17 14:55:53 +11:00
|
|
|
pub const DISPLAY_CONTROL: VolatilePtr<DisplayControlSetting> = VolatilePtr(0x0400_0000 as *mut DisplayControlSetting);
|
|
|
|
pub const JUST_MODE3: DisplayControlSetting = DisplayControlSetting(3);
|
|
|
|
pub const JUST_BG2: DisplayControlSetting = DisplayControlSetting(0b100_0000_0000);
|
|
|
|
pub const JUST_MODE3_AND_BG2: DisplayControlSetting = DisplayControlSetting(JUST_MODE3.0 | JUST_BG2.0);
|
2018-12-16 14:35:57 +11:00
|
|
|
|
|
|
|
pub struct Mode3;
|
|
|
|
impl Mode3 {
|
|
|
|
const SCREEN_WIDTH: isize = 240;
|
|
|
|
const PIXELS: VolatilePtr<Color> = VolatilePtr(0x600_0000 as *mut Color);
|
|
|
|
|
|
|
|
pub unsafe fn draw_pixel_unchecked(col: isize, row: isize, color: Color) {
|
|
|
|
Self::PIXELS.offset(col + row * Self::SCREEN_WIDTH).write(color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-17 14:55:53 +11:00
|
|
|
#[panic_handler]
|
|
|
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
|
|
|
loop {}
|
|
|
|
}
|
|
|
|
|
2018-11-14 06:47:52 +11:00
|
|
|
#[start]
|
|
|
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
|
|
|
unsafe {
|
2018-12-16 14:35:57 +11:00
|
|
|
DISPLAY_CONTROL.write(JUST_MODE3_AND_BG2);
|
2018-12-17 14:55:53 +11:00
|
|
|
Mode3::draw_pixel_unchecked(120, 80, const_rgb!(31, 0, 0));
|
|
|
|
Mode3::draw_pixel_unchecked(136, 80, const_rgb!(0, 31, 0));
|
|
|
|
Mode3::draw_pixel_unchecked(120, 96, const_rgb!(0, 0, 31));
|
2018-11-14 06:47:52 +11:00
|
|
|
loop {}
|
|
|
|
}
|
|
|
|
}
|