embedded-hal

This commit is contained in:
Alex Janka 2023-03-15 12:02:34 +11:00
parent 94228978eb
commit e1ac328ce6
2 changed files with 60 additions and 15 deletions

View file

@ -29,6 +29,8 @@ agb_fixnum = { version = "0.13.0", path = "../agb-fixnum" }
bare-metal = "1" bare-metal = "1"
modular-bitfield = "0.11" modular-bitfield = "0.11"
rustc-hash = { version = "1", default-features = false } rustc-hash = { version = "1", default-features = false }
embedded-hal = "0.2.7"
nb = "1.1"
[package.metadata.docs.rs] [package.metadata.docs.rs]
default-target = "thumbv6m-none-eabi" default-target = "thumbv6m-none-eabi"

View file

@ -1,41 +1,67 @@
use core::ops::Deref; use core::ops::{Deref, DerefMut};
use crate::memory_mapped::MemoryMapped; use embedded_hal::serial::{Read, Write};
use crate::{memory_mapped::MemoryMapped, println};
const SIODATA8: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_012A) }; const SIODATA8: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_012A) };
const SIOCNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0128) }; const SIOCNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0128) };
const RCNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0134) }; const RCNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0134) };
#[derive(Debug)]
pub enum LinkPortError { pub enum LinkPortError {
GbaErrorBit, GbaErrorBit,
Blocked,
} }
pub struct LinkPortUart; pub struct LinkPortUart;
impl LinkPortUart { impl LinkPortUart {
pub fn init(rate: BaudRate) -> Self { pub fn init(rate: BaudRate, with_interrupts: bool, clear_to_send: bool) -> Self {
println!("begin init");
RCNT.set(0x0); RCNT.set(0x0);
SIOCNT.set(SioControlReg::default_uart().with_baud(rate).into()); println!("have set rcnt");
SIOCNT.set(0x0);
let reg: u16 = SioControlReg::default_uart()
.with_baud(rate)
.with_interrupts(with_interrupts)
.with_cts(clear_to_send)
.into();
SIOCNT.set(reg);
println!("have set siocnt to {reg:#X}/{reg:#b}");
Self Self
} }
}
pub fn read(&mut self) -> Result<u8, LinkPortError> { impl Read<u8> for LinkPortUart {
type Error = LinkPortError;
fn read(&mut self) -> Result<u8, nb::Error<LinkPortError>> {
match SioControlReg::from(SIOCNT.get()) { match SioControlReg::from(SIOCNT.get()) {
v if *v.error => Err(LinkPortError::GbaErrorBit), v if *v.error => Err(nb::Error::Other(LinkPortError::GbaErrorBit)),
v if *v.recv_empty => Err(LinkPortError::Blocked), v if *v.recv_empty => Err(nb::Error::WouldBlock),
_ => Ok((SIODATA8.get() & 0xFF) as u8), _ => Ok((SIODATA8.get() & 0xFF) as u8),
} }
} }
}
pub fn write(&mut self, data: u8) -> Result<(), LinkPortError> { impl Write<u8> for LinkPortUart {
match SioControlReg::from(SIOCNT.get()) { type Error = LinkPortError;
v if *v.error => Err(LinkPortError::GbaErrorBit),
v if *v.send_full => Err(LinkPortError::Blocked), fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
_ => { match self.flush() {
SIODATA8.set(data as u16); Ok(_) => {
SIODATA8.set(word as u16);
Ok(()) Ok(())
} }
Err(e) => Err(e),
}
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
match SioControlReg::from(SIOCNT.get()) {
v if *v.error => Err(nb::Error::Other(LinkPortError::GbaErrorBit)),
v if *v.send_full => Err(nb::Error::WouldBlock),
_ => Ok(()),
} }
} }
} }
@ -104,6 +130,7 @@ impl SioControlReg {
recv_empty: BoolField(false), recv_empty: BoolField(false),
error: BoolField(false), error: BoolField(false),
data_8bit: BoolField(true), data_8bit: BoolField(true),
// fifo_enabled: BoolField(true),
fifo_enabled: BoolField(true), fifo_enabled: BoolField(true),
parity_enabled: BoolField(false), parity_enabled: BoolField(false),
tx_enabled: BoolField(true), tx_enabled: BoolField(true),
@ -117,6 +144,16 @@ impl SioControlReg {
self.baud_rate = rate; self.baud_rate = rate;
self self
} }
fn with_interrupts(mut self, interrupts: bool) -> Self {
*self.irq_enable = interrupts;
self
}
fn with_cts(mut self, clear_to_send: bool) -> Self {
*self.flow_control = clear_to_send;
self
}
} }
impl From<SioControlReg> for u16 { impl From<SioControlReg> for u16 {
@ -127,7 +164,7 @@ impl From<SioControlReg> for u16 {
| u16::from(value.send_full) << 4 | u16::from(value.send_full) << 4
| u16::from(value.recv_empty) << 5 | u16::from(value.recv_empty) << 5
| u16::from(value.error) << 6 | u16::from(value.error) << 6
| u16::from(value.data_8bit) << 7 | u16::from(value.data_8bit) << 7 // bit start
| u16::from(value.fifo_enabled) << 8 | u16::from(value.fifo_enabled) << 8
| u16::from(value.parity_enabled) << 9 | u16::from(value.parity_enabled) << 9
| u16::from(value.tx_enabled) << 10 | u16::from(value.tx_enabled) << 10
@ -167,6 +204,12 @@ impl Deref for BoolField {
} }
} }
impl DerefMut for BoolField {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl From<BoolField> for u16 { impl From<BoolField> for u16 {
fn from(value: BoolField) -> Self { fn from(value: BoolField) -> Self {
if *value { if *value {