use crate::common::PixelAddressRange;
use crate::register::Subpage;
#[doc(hidden)]
#[macro_export]
macro_rules! address_enum_ops {
($typ:ident) => {
impl ::core::ops::Add<$typ> for $typ {
type Output = u16;
fn add(self, other: $typ) -> Self::Output {
self as u16 + other as u16
}
}
impl ::core::ops::Add<&$typ> for $typ {
type Output = u16;
fn add(self, other: &$typ) -> Self::Output {
self as u16 + *other as u16
}
}
impl ::core::ops::Add<$typ> for &$typ {
type Output = u16;
fn add(self, other: $typ) -> Self::Output {
*self as u16 + other as u16
}
}
impl ::core::ops::Add<&$typ> for &$typ {
type Output = u16;
fn add(self, other: &$typ) -> Self::Output {
*self as u16 + *other as u16
}
}
impl ::core::ops::Sub<$typ> for $typ {
type Output = u16;
fn sub(self, other: $typ) -> Self::Output {
self as u16 - other as u16
}
}
impl ::core::ops::Sub<&$typ> for $typ {
type Output = u16;
fn sub(self, other: &$typ) -> Self::Output {
self as u16 - *other as u16
}
}
impl ::core::ops::Sub<$typ> for &$typ {
type Output = u16;
fn sub(self, other: $typ) -> Self::Output {
*self as u16 - other as u16
}
}
impl ::core::ops::Sub<&$typ> for &$typ {
type Output = u16;
fn sub(self, other: &$typ) -> Self::Output {
*self as u16 - *other as u16
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! expose_member {
($name:ident, $typ:ty) => {
fn $name(&self) -> $typ {
self.$name
}
};
(&$name:ident, $typ:ty) => {
fn $name(&self) -> &$typ {
&self.$name
}
};
}
pub(crate) trait Buffer {
fn advance(&mut self, cnt: usize);
fn get_u8(&mut self) -> u8;
fn get_i8(&mut self) -> i8;
fn get_u16(&mut self) -> u16;
fn get_i16(&mut self) -> i16;
}
impl Buffer for &[u8] {
fn advance(&mut self, cnt: usize) {
*self = &self[cnt..];
}
fn get_u8(&mut self) -> u8 {
let (byte, rest) = self.split_at(1);
*self = rest;
u8::from_be_bytes([byte[0]])
}
fn get_i8(&mut self) -> i8 {
let (byte, rest) = self.split_at(1);
*self = rest;
i8::from_be_bytes([byte[0]])
}
fn get_u16(&mut self) -> u16 {
let (bytes, rest) = self.split_at(2);
*self = rest;
u16::from_be_bytes([bytes[0], bytes[1]])
}
fn get_i16(&mut self) -> i16 {
let (bytes, rest) = self.split_at(2);
*self = rest;
i16::from_be_bytes([bytes[0], bytes[1]])
}
}
pub trait Sealed {}
pub(crate) fn is_bit_set<B>(value: B, index: usize) -> bool
where
B: num_traits::PrimInt + num_traits::Unsigned,
{
(value & (B::one() << index)) > B::zero()
}
pub(crate) fn i16_from_bits(mut bytes: &[u8], num_bits: u8) -> i16 {
let num = match bytes.len() {
1 => i16::from(bytes.get_i8()),
_ => bytes.get_i16(),
};
let shift_amount = 16 - num_bits;
(num << shift_amount) >> shift_amount
}
#[derive(Clone, Copy, Debug)]
pub struct SubpageInterleave<
const STRIDE_LENGTH: u16,
const NUM_STRIDES: u16,
const PIXEL_START_ADDRESS: u16,
> {
stride_count: u16,
base_address: u16,
}
impl<const STRIDE_LENGTH: u16, const NUM_STRIDES: u16, const PIXEL_START_ADDRESS: u16>
SubpageInterleave<STRIDE_LENGTH, NUM_STRIDES, PIXEL_START_ADDRESS>
{
pub(crate) fn new(subpage: Subpage) -> Self {
let starting_address: u16 = match subpage {
Subpage::Zero => PIXEL_START_ADDRESS,
Subpage::One => PIXEL_START_ADDRESS + STRIDE_LENGTH,
};
Self {
stride_count: 0,
base_address: starting_address,
}
}
}
impl<const STRIDE_LENGTH: u16, const NUM_STRIDES: u16, const PIXEL_START_ADDRESS: u16>
core::iter::Iterator for SubpageInterleave<STRIDE_LENGTH, NUM_STRIDES, PIXEL_START_ADDRESS>
{
type Item = PixelAddressRange;
fn next(&mut self) -> Option<Self::Item> {
match self.stride_count.cmp(&NUM_STRIDES) {
core::cmp::Ordering::Less => {
let next_value = PixelAddressRange {
start_address: (self.base_address + self.stride_count * STRIDE_LENGTH).into(),
buffer_offset: (self.stride_count * STRIDE_LENGTH * 2) as usize,
length: (STRIDE_LENGTH * 2) as usize,
};
self.stride_count += 1;
Some(next_value)
}
_ => None,
}
}
}
#[cfg(test)]
mod test {
use super::Buffer;
#[test]
fn buffer_advance() {
let data = b"\xde\xad\xbe\xef";
let mut buf = &data[..];
assert_eq!(buf, &data[..]);
buf.advance(1);
assert_eq!(buf, &data[1..]);
buf.advance(2);
assert_eq!(buf, &data[3..]);
}
#[test]
fn buffer_get_u8() {
let data = b"\xde\xad\xbe\xef";
let mut buf = &data[..];
let v = buf.get_u8();
assert_eq!(v, 0xde);
assert_eq!(buf, &data[1..]);
}
#[test]
fn buffer_get_i8() {
let data = b"\xde\xad\xbe\xef";
let mut buf = &data[..];
let v = buf.get_i8();
assert_eq!(v, -34);
assert_eq!(buf.len(), 3);
assert_eq!(buf, &data[1..]);
}
#[test]
fn buffer_get_u16() {
let data = b"\xde\xad\xbe\xef";
let mut buf = &data[..];
let v = buf.get_u16();
assert_eq!(v, 0xdead);
assert_eq!(buf.len(), 2);
assert_eq!(buf, &data[2..]);
}
#[test]
fn buffer_get_i16() {
let data = b"\xde\xad\xbe\xef";
let mut buf = &data[..];
let v = buf.get_i16();
assert_eq!(v, -8531);
assert_eq!(buf.len(), 2);
assert_eq!(buf, &data[2..]);
}
#[test]
fn is_bit_set() {
for n in 0..16 {
let value: u16 = 1 << n;
assert!(
super::is_bit_set(value, n),
"is_bit_set was incorrect for bit {}",
n
);
}
}
#[test]
fn i16_from_bits() {
assert_eq!(super::i16_from_bits(b"\x00\xff", 8), -1);
assert_eq!(super::i16_from_bits(b"\x03\xff", 10), -1);
assert_eq!(super::i16_from_bits(b"\xf0\xff", 8), -1);
assert_eq!(super::i16_from_bits(b"\xf3\xff", 10), -1);
}
}