use core::arch::asm;
use avr_oxide::concurrency::Isolated;
use avr_oxide::util::datatypes::{BitFieldAccess, BitIndex, BitMaskable};
pub struct IOSpaceU8<const IOADDR:u8>();
#[cfg(target_arch="avr")]
impl<const IOADDR:u8> IOSpaceU8<IOADDR> {
pub const fn get() -> Self {
IOSpaceU8()
}
pub fn set_c<const BIT: u8>(&mut self) {
if IOADDR <= avr_oxide::hardware::cpu::cpuregs::MAX_BIT_ADDRESSABLE {
unsafe {
asm!(
"sbi {ioaddr},{bit}",
bit = const BIT,
ioaddr = const IOADDR,
options(nostack,preserves_flags)
);
}
} else {
self.set(BitIndex::bit(BIT as usize))
}
}
pub fn clr_c<const BIT: u8>(&mut self) {
if IOADDR <= avr_oxide::hardware::cpu::cpuregs::MAX_BIT_ADDRESSABLE {
unsafe {
asm!(
"cbi {ioaddr},{bit}",
bit = const BIT,
ioaddr = const IOADDR,
options(nostack,preserves_flags)
);
}
} else {
self.clr(BitIndex::bit(BIT as usize))
}
}
pub fn is_set_c<const BIT: u8>(&self) -> bool {
if IOADDR <= avr_oxide::hardware::cpu::cpuregs::MAX_BIT_ADDRESSABLE {
let val: u8;
unsafe {
asm!(
"clr {reg_val}",
"sbic {ioaddr},{bit}",
"ldi {reg_val},0x01",
bit = const BIT,
ioaddr = const IOADDR,
reg_val = out(reg_upper) val,
options(nostack,preserves_flags)
);
}
val != 0
} else {
self.is_set(BitIndex::bit(BIT as usize))
}
}
pub fn is_clr_c<const BIT: u8>(&self) -> bool {
if IOADDR <= avr_oxide::hardware::cpu::cpuregs::MAX_BIT_ADDRESSABLE {
let val: u8;
unsafe {
asm!(
"clr {reg_val}",
"sbic {ioaddr},{bit}",
"ldi {reg_val},0x01",
bit = const BIT,
ioaddr = const IOADDR,
reg_val = out(reg_upper) val,
options(nostack,preserves_flags)
);
}
val != 0
} else {
self.is_clr(BitIndex::bit(BIT as usize))
}
}
}
#[cfg(target_arch="avr")]
impl<const IOADDR:u8> BitFieldAccess for IOSpaceU8<IOADDR> {
fn read_byte(&self) -> u8 {
let val: u8;
unsafe {
asm!(
"in {reg_val},{ioaddr}",
reg_val = out(reg) val,
ioaddr = const IOADDR,
options(nostack,preserves_flags)
);
}
val
}
fn write_byte(&mut self, val: u8) {
unsafe {
asm!(
"out {ioaddr},{reg_val}",
reg_val = in(reg) val,
ioaddr = const IOADDR,
options(nostack,preserves_flags)
);
}
}
fn is_set(&self, bit: BitIndex) -> bool {
let mut flag: u8;
flag = bit.positive_byte_mask();
unsafe {
asm!(
"in {reg_scratch},{ioaddr}",
"and {reg_flag},{reg_scratch}",
reg_scratch = out(reg) _,
reg_flag = inout(reg) flag,
ioaddr = const IOADDR,
options(nostack)
);
}
flag != 0
}
fn is_clr(&self, bit: BitIndex) -> bool {
let mut flag: u8;
flag = bit.positive_byte_mask();
unsafe {
asm!(
"in {reg_scratch},{ioaddr}",
"and {reg_flag},{reg_scratch}",
reg_scratch = out(reg) _,
reg_flag = inout(reg) flag,
ioaddr = const IOADDR,
options(nostack)
);
}
flag == 0
}
fn set_isolated<B: BitMaskable>(&mut self, _isotoken: Isolated, bits: B) {
let mask: u8 = bits.positive_byte_mask();
unsafe {
asm!(
"in {reg_scratch},{ioaddr}",
"or {reg_scratch},{reg_mask}",
"out {ioaddr},{reg_scratch}",
reg_scratch = out(reg) _,
reg_mask = in(reg) mask,
ioaddr = const IOADDR,
options(nostack)
);
}
}
fn set_all(&mut self) {
unsafe {
asm!(
"ldi {reg_scratch},0xff",
"out {ioaddr},{reg_scratch}",
reg_scratch = out(reg_upper) _,
ioaddr = const IOADDR,
options(nostack,preserves_flags)
)
}
}
fn clr_all(&mut self) {
unsafe {
asm!(
"out {ioaddr},r1", ioaddr = const IOADDR,
options(nostack,preserves_flags)
)
}
}
fn clr_isolated<B: BitMaskable>(&mut self, _isotoken: Isolated, bits: B) {
let mask: u8 = bits.positive_byte_mask();
unsafe {
asm!(
"in {reg_scratch},{ioaddr}",
"and {reg_scratch},{reg_mask}",
"out {ioaddr},{reg_scratch}",
reg_scratch = out(reg) _,
reg_mask = in(reg) mask,
ioaddr = const IOADDR,
options(nostack)
);
}
}
}
#[cfg(not(target_arch="avr"))]
impl<const IOADDR:u8> IOSpaceU8<IOADDR> {
pub const fn get() -> Self {
IOSpaceU8()
}
pub fn set_c<const BIT: u8>(&mut self) {
unimplemented!()
}
pub fn clr_c<const BIT: u8>(&mut self) {
unimplemented!()
}
pub fn is_set_c<const BIT: u8>(&self) -> bool {
unimplemented!()
}
pub fn is_clr_c<const BIT: u8>(&self) -> bool {
unimplemented!()
}
}
#[cfg(not(target_arch="avr"))]
impl<const IOADDR:u8> BitFieldAccess for IOSpaceU8<IOADDR> {
fn read_byte(&self) -> u8 {
unimplemented!()
}
fn write_byte(&mut self, val: u8) {
unimplemented!()
}
fn is_set(&self, bit: BitIndex) -> bool {
unimplemented!()
}
fn is_clr(&self, bit: BitIndex) -> bool {
unimplemented!()
}
fn set_isolated<B: BitMaskable>(&mut self, _isotoken: Isolated, bits: B) {
unimplemented!()
}
fn set_all(&mut self) {
unimplemented!()
}
fn clr_all(&mut self) {
unimplemented!()
}
fn clr_isolated<B: BitMaskable>(&mut self, _isotoken: Isolated, bits: B) {
unimplemented!()
}
}