mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-04 06:01:35 +11:00
embedded-hal
This commit is contained in:
parent
94228978eb
commit
e1ac328ce6
|
@ -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"
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue