use super::region::*;
use core::marker::PhantomData;
#[derive(Copy, Clone)]
pub struct Ptr<R: MemoryRegion> {
pub(crate) addr: u32,
pub(crate) _region: PhantomData<R>,
}
impl<R: MemoryRegion> Ptr<R> {
#[inline]
pub fn new(offset: u32) -> Self {
R::ptr(offset)
}
#[inline]
pub fn to_raw(self) -> u32 {
self.addr
}
#[inline]
pub fn to_raw_offset(self) -> u32 {
self.addr - R::BASE_ADDR
}
#[inline]
pub fn slice_length(self, length: u32) -> super::slice::Slice<R> {
super::slice::Slice::new_length(self, length)
}
}
impl<R: MemoryRegion + HostAccessible> Ptr<R> {
pub fn build_spi_write_header(self, into: &mut [u8; 3]) {
into[0] = (((self.addr >> 16) & 0b00111111) | 0b10000000) as u8;
into[1] = (self.addr >> 8) as u8;
into[2] = (self.addr >> 0) as u8;
}
pub fn build_spi_read_header(self, into: &mut [u8; 4]) {
into[0] = ((self.addr >> 16) & 0b00111111) as u8;
into[1] = (self.addr >> 8) as u8;
into[2] = (self.addr >> 0) as u8;
into[3] = 0; }
}
impl<R1: MemoryRegion, R2: MemoryRegion<Model = R1::Model>> core::cmp::PartialEq<Ptr<R2>>
for Ptr<R1>
{
fn eq(&self, other: &Ptr<R2>) -> bool {
self.addr == other.addr
}
}
impl<R: MemoryRegion> core::cmp::Eq for Ptr<R> {}
impl<R1: MemoryRegion, R2: MemoryRegion<Model = R1::Model>> core::cmp::PartialOrd<Ptr<R2>>
for Ptr<R1>
{
fn partial_cmp(&self, other: &Ptr<R2>) -> core::option::Option<core::cmp::Ordering> {
if self.addr == other.addr {
Some(core::cmp::Ordering::Equal)
} else if self.addr < other.addr {
Some(core::cmp::Ordering::Less)
} else {
Some(core::cmp::Ordering::Greater)
}
}
}
impl<R: MemoryRegion> core::cmp::Ord for Ptr<R> {
fn cmp(&self, other: &Ptr<R>) -> core::cmp::Ordering {
if self.addr == other.addr {
core::cmp::Ordering::Equal
} else if self.addr < other.addr {
core::cmp::Ordering::Less
} else {
core::cmp::Ordering::Greater
}
}
}
impl<R: MemoryRegion> core::ops::Add<i32> for Ptr<R> {
type Output = Self;
fn add(self, offset: i32) -> Self {
R::ptr(self.to_raw() + (offset as u32))
}
}
impl<R: MemoryRegion> core::ops::Add<u32> for Ptr<R> {
type Output = Self;
fn add(self, offset: u32) -> Self {
R::ptr(self.to_raw() + offset)
}
}
impl<R: MemoryRegion> core::ops::AddAssign<i32> for Ptr<R> {
fn add_assign(&mut self, offset: i32) {
*self = R::ptr(self.to_raw() + (offset as u32))
}
}
impl<R: MemoryRegion> core::ops::AddAssign<u32> for Ptr<R> {
fn add_assign(&mut self, offset: u32) {
*self = R::ptr(self.to_raw() + offset)
}
}
impl<R: MemoryRegion> core::ops::Sub<i32> for Ptr<R> {
type Output = Self;
fn sub(self, offset: i32) -> Self {
R::ptr(self.to_raw() - (offset as u32))
}
}
impl<R: MemoryRegion> core::ops::Sub<u32> for Ptr<R> {
type Output = Self;
fn sub(self, offset: u32) -> Self {
R::ptr(self.to_raw() - offset)
}
}
impl<R: MemoryRegion> core::ops::SubAssign<i32> for Ptr<R> {
fn sub_assign(&mut self, offset: i32) {
*self = R::ptr(self.to_raw() - (offset as u32))
}
}
impl<R: MemoryRegion> core::ops::SubAssign<u32> for Ptr<R> {
fn sub_assign(&mut self, offset: u32) {
*self = R::ptr(self.to_raw() - offset)
}
}
impl<R: MemoryRegion> core::fmt::Debug for Ptr<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"Ptr {{ addr: {:#010x?} /*{}*/ }}",
self.addr,
R::DEBUG_NAME
)
}
}
impl<R: MemoryRegion> core::fmt::Display for Ptr<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#010x?}", self.addr)
}
}