#![no_std]
use core::convert::{From, Into};
use core::marker::PhantomData;
use core::slice::from_raw_parts_mut;
pub struct RegisterValue(usize);
impl From<u8> for RegisterValue {
fn from(value: u8) -> RegisterValue {
RegisterValue(value as usize)
}
}
impl From<u16> for RegisterValue {
fn from(value: u16) -> RegisterValue {
RegisterValue(value as usize)
}
}
impl From<u32> for RegisterValue {
fn from(value: u32) -> RegisterValue {
RegisterValue(value as usize)
}
}
impl From<RegisterValue> for u8 {
fn from(value: RegisterValue) -> u8 {
value.0 as u8
}
}
impl From<RegisterValue> for u16 {
fn from(value: RegisterValue) -> u16 {
value.0 as u16
}
}
impl From<RegisterValue> for u32 {
fn from(value: RegisterValue) -> u32 {
value.0 as u32
}
}
pub trait Field {
fn get_offset_length(&self) -> (usize, usize);
fn of(&self, value: usize) -> usize {
let (offset, length) = self.get_offset_length();
(value & ((1 << length) - 1)) << offset
}
}
pub enum NoField {}
impl Field for NoField {
fn get_offset_length(&self) -> (usize, usize) {
return (0, 0);
}
}
pub enum Bits {
Of(usize, usize),
}
impl Field for Bits {
fn get_offset_length(&self) -> (usize, usize) {
match self {
Bits::Of(offset, length) => (*offset, *length),
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct Register<T, U: Field = NoField> {
pub value: T,
u: PhantomData<U>,
}
impl<T, U: Field> From<T> for Register<T, U> {
fn from(value: T) -> Register<T, U> {
Register {
value,
u: PhantomData,
}
}
}
impl<'a, T, U: Field> Into<&'a mut [T]> for Register<T, U> {
fn into(mut self) -> &'a mut [T] {
unsafe { from_raw_parts_mut(&mut self.value, 1) }
}
}
impl<T, U> Register<T, U>
where
T: Into<RegisterValue> + From<RegisterValue> + Copy + Default,
U: Field,
{
pub fn new(value: T) -> Self {
Self {
value: value,
u: PhantomData,
}
}
pub fn of(u: U, value: T) -> Self {
let mut v = Self {
value: Default::default(),
u: PhantomData,
};
v.set(u, value);
v
}
pub fn get(&self, u: U) -> T {
let (offset, length) = u.get_offset_length();
let mask = ((1 << length) - 1) << offset;
RegisterValue((self.value.into().0 >> offset) & mask).into()
}
pub fn is_set(&self, u: U) -> bool {
self.get(u).into().0 > 0
}
pub fn set(&mut self, u: U, value: T) {
let (offset, length) = u.get_offset_length();
let mask = ((1 << length) - 1) << offset;
let to_set = self.value.into().0 & !mask;
let usize_value = value.into().0;
self.value = RegisterValue(to_set | (usize_value << offset) & mask).into();
}
pub fn reset(&mut self, u: U) {
let (offset, length) = u.get_offset_length();
let mask = ((1 << length) - 1) << offset;
let to_set = self.value.into().0 & !mask;
self.value = RegisterValue(to_set).into();
}
}
#[macro_export]
macro_rules! register_fields {
(
$(
$(#[$outer:meta])*
enum $name:ident {
$($field:ident = $offset:tt : $len:tt,)*
}
)*
) => {
$(
$(#[$outer])*
#[repr(usize)]
#[derive(Copy, Clone)]
enum $name {
$($field = $offset << 8 | $len,)*
}
impl Field for $name {
fn get_offset_length(&self) -> (usize, usize) {
(*self as usize >> 8, *self as usize & 0xFF)
}
}
)*
};
(
$(
$(#[$outer:meta])*
pub enum $name:ident {
$($field:ident = $offset:tt : $len:tt,)*
}
)*
) => {
$(
$(#[$outer])*
#[repr(usize)]
#[derive(Copy, Clone)]
pub enum $name {
$($field = $offset << 8 | $len,)*
}
impl Field for $name {
fn get_offset_length(&self) -> (usize, usize) {
(*self as usize >> 8, *self as usize & 0xFF)
}
}
)*
}
}