hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
#[derive(Copy, Clone, PartialEq)]
pub enum PixelFormat {
    Rgb565,
    Rgb888,
    Rgba8888,
    Bgra8888,
    Xrgb8888,
    Yuv420,
    Yuv422,
}

pub fn bytes_per_pixel(fmt: PixelFormat) -> u8 {
    match fmt {
        PixelFormat::Rgb565 => 2,
        PixelFormat::Rgb888 => 3,
        PixelFormat::Rgba8888 | PixelFormat::Bgra8888 | PixelFormat::Xrgb8888 => 4,
        PixelFormat::Yuv420 => 1,
        PixelFormat::Yuv422 => 2,
    }
}

pub fn compute_stride(width: u32, fmt: PixelFormat) -> u32 {
    let bpp = bytes_per_pixel(fmt) as u32;
    let raw = width * bpp;
    (raw + 63) & !63
}

pub fn framebuffer_size(width: u32, height: u32, fmt: PixelFormat) -> usize {
    (compute_stride(width, fmt) * height) as usize
}

pub fn pixel_offset(x: u32, y: u32, stride_bytes: u32, fmt: PixelFormat) -> usize {
    (y * stride_bytes + x * bytes_per_pixel(fmt) as u32) as usize
}

pub fn write_pixel(fb: usize, x: u32, y: u32, stride_bytes: u32, fmt: PixelFormat, color: u32) {
    let off = pixel_offset(x, y, stride_bytes, fmt);
    let ptr = fb + off;
    match fmt {
        PixelFormat::Rgb565 => unsafe {
            core::ptr::write_volatile(ptr as *mut u16, color as u16);
        },
        PixelFormat::Rgb888 => unsafe {
            core::ptr::write_volatile(ptr as *mut u8, (color & 0xFF) as u8);
            core::ptr::write_volatile((ptr + 1) as *mut u8, ((color >> 8) & 0xFF) as u8);
            core::ptr::write_volatile((ptr + 2) as *mut u8, ((color >> 16) & 0xFF) as u8);
        },
        _ => unsafe {
            core::ptr::write_volatile(ptr as *mut u32, color);
        },
    }
}

pub fn clear(fb: usize, total_size: usize, val: u8) {
    let ptr = fb as *mut u8;
    let mut i = 0usize;
    while i < total_size {
        unsafe { core::ptr::write_volatile(ptr.add(i), val) };
        i += 1;
    }
}