From cd50bf9673b0adb9c1377a68dd88f3c059aaab60 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Tue, 11 Apr 2023 19:05:05 +1000 Subject: [PATCH] idk what i scrwed up --- agb/src/serial_link/mod.rs | 180 +++++++++++++++++++++++++++++++--- agb/src/serial_link/normal.rs | 148 ---------------------------- agb/src/serial_link/uart.rs | 168 ------------------------------- 3 files changed, 164 insertions(+), 332 deletions(-) delete mode 100644 agb/src/serial_link/normal.rs delete mode 100644 agb/src/serial_link/uart.rs diff --git a/agb/src/serial_link/mod.rs b/agb/src/serial_link/mod.rs index bad7df38..9775b2cf 100644 --- a/agb/src/serial_link/mod.rs +++ b/agb/src/serial_link/mod.rs @@ -1,16 +1,9 @@ -use self::uart::UartSioControl; -pub use self::{ - normal::{ClockSource, LinkPortNormal}, - uart::{BaudRate, LinkPortUart}, -}; -use crate::memory_mapped::MemoryMapped; use core::ops::{Deref, DerefMut}; -mod normal; -mod uart; +use embedded_hal::serial::{Read, Write}; + +use crate::{memory_mapped::MemoryMapped, println}; -// const SIODATA32LOW: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0120) }; -// const SIODATA32HIGH: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0122) }; const SIODATA8: MemoryMapped = unsafe { MemoryMapped::new(0x0400_012A) }; const SIOCNT: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0128) }; const RCNT: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0134) }; @@ -20,11 +13,76 @@ pub enum LinkPortError { GbaErrorBit, } -#[allow(dead_code)] -enum SioControlReg { - Normal, - Multi, - Uart(UartSioControl), +pub struct LinkPortUart; + +impl LinkPortUart { + pub fn init(rate: BaudRate, with_interrupts: bool, clear_to_send: bool) -> Self { + println!("begin init"); + RCNT.set(0x0); + 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 + } +} + +impl Read for LinkPortUart { + type Error = LinkPortError; + + fn read(&mut self) -> Result> { + match SioControlReg::from(SIOCNT.get()) { + v if *v.error => Err(nb::Error::Other(LinkPortError::GbaErrorBit)), + v if *v.recv_empty => Err(nb::Error::WouldBlock), + _ => Ok((SIODATA8.get() & 0xFF) as u8), + } + } +} + +impl Write for LinkPortUart { + type Error = LinkPortError; + + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + match self.flush() { + Ok(_) => { + SIODATA8.set(word as u16); + 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(()), + } + } +} + +pub enum BaudRate { + B9600 = 0b00, + B38400 = 0b01, + B57600 = 0b10, + B115200 = 0b11, +} + +impl From for BaudRate { + fn from(value: u16) -> Self { + match value { + 0b00 => Self::B9600, + 0b01 => Self::B38400, + 0b10 => Self::B57600, + 0b11 => Self::B115200, + _ => panic!("passed invalid value"), + } + } } pub enum SioMode { @@ -46,6 +104,96 @@ impl From for SioMode { } } +struct SioControlReg { + baud_rate: BaudRate, // 0-1 + flow_control: BoolField, // 2 + parity_odd: BoolField, // 3 + send_full: BoolField, // 4 + recv_empty: BoolField, // 5 + error: BoolField, // 6 + data_8bit: BoolField, // 7 + fifo_enabled: BoolField, // 8 + parity_enabled: BoolField, // 9 + tx_enabled: BoolField, // 10 + rx_enabled: BoolField, // 11 + mode: SioMode, // 12-13 + irq_enable: BoolField, // 14 +} + +impl SioControlReg { + fn default_uart() -> Self { + Self { + baud_rate: BaudRate::B9600, + flow_control: BoolField(false), + parity_odd: BoolField(false), + send_full: BoolField(false), + recv_empty: BoolField(false), + error: BoolField(false), + data_8bit: BoolField(true), + // fifo_enabled: BoolField(true), + fifo_enabled: BoolField(true), + parity_enabled: BoolField(false), + tx_enabled: BoolField(true), + rx_enabled: BoolField(true), + mode: SioMode::Uart, + irq_enable: BoolField(false), + } + } + + fn with_baud(mut self, rate: BaudRate) -> Self { + self.baud_rate = rate; + 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 for u16 { + fn from(value: SioControlReg) -> Self { + value.baud_rate as u16 + | u16::from(value.flow_control) << 2 + | u16::from(value.parity_odd) << 3 + | u16::from(value.send_full) << 4 + | u16::from(value.recv_empty) << 5 + | u16::from(value.error) << 6 + | u16::from(value.data_8bit) << 7 // bit start + | u16::from(value.fifo_enabled) << 8 + | u16::from(value.parity_enabled) << 9 + | u16::from(value.tx_enabled) << 10 + | u16::from(value.rx_enabled) << 11 + | (value.mode as u16) << 12 + | u16::from(value.irq_enable) << 14 + } +} + +impl From for SioControlReg { + fn from(value: u16) -> Self { + Self { + baud_rate: BaudRate::from(value & 0b11), + flow_control: (value & (1 << 2)).into(), + parity_odd: (value & (1 << 3)).into(), + send_full: (value & (1 << 4)).into(), + recv_empty: (value & (1 << 5)).into(), + error: (value & (1 << 6)).into(), + data_8bit: (value & (1 << 7)).into(), + fifo_enabled: (value & (1 << 8)).into(), + parity_enabled: (value & (1 << 9)).into(), + tx_enabled: (value & (1 << 10)).into(), + rx_enabled: (value & (1 << 11)).into(), + mode: ((value & (0b11 << 12)) >> 12).into(), + irq_enable: (value & (1 << 14)).into(), + } + } +} + pub struct BoolField(bool); impl Deref for BoolField { @@ -74,7 +222,7 @@ impl From for u16 { impl From for BoolField { fn from(value: u16) -> Self { - Self((value % 2) != 0) + Self(value != 0) } } diff --git a/agb/src/serial_link/normal.rs b/agb/src/serial_link/normal.rs deleted file mode 100644 index 46bb7d8c..00000000 --- a/agb/src/serial_link/normal.rs +++ /dev/null @@ -1,148 +0,0 @@ -use crate::println; - -use super::{BoolField, RCNT, SIOCNT}; - -pub struct LinkPortNormal; - -impl LinkPortNormal { - pub fn init(clock_source: ClockSource) -> Self { - println!("begin uart init"); - RCNT.set(0x0); - println!("have set rcnt"); - SIOCNT.set(0x0); - let reg: u16 = NormalSioControl::default() - .with_clock_source(clock_source) - .with_transfer_length(S) - .into(); - SIOCNT.set(reg); - println!("have set siocnt to {reg:#X}/{reg:#b}"); - Self - } -} - -pub(super) struct NormalSioControl { - clock_source: ClockSource, // 0 - clock_rate: InternalClock, // 1 - si_state: BoolField, // 2 - so_inactive: BoolField, // 3 - // 4-6 empty - start_bit: StartBit, // 7 - // 8-11 empty - transfer_length: TransferLength, // 12 - // 13 must be 0 - irq_enable: BoolField, // 14 -} - -impl NormalSioControl { - fn with_clock_source(mut self, source: ClockSource) -> Self { - self.clock_source = source; - self - } - - fn with_transfer_length(mut self, length: TransferLength) -> Self { - self.transfer_length = length; - self - } -} - -impl Default for NormalSioControl { - fn default() -> Self { - Self { - clock_source: ClockSource::Internal, - clock_rate: InternalClock::Khz256, - si_state: BoolField(false), - so_inactive: BoolField(false), - start_bit: StartBit::Inactive, - transfer_length: TransferLength::Bits32, - irq_enable: BoolField(false), - } - } -} - -impl From for u16 { - fn from(value: NormalSioControl) -> Self { - value.clock_source as u16 - | (value.clock_rate as u16) << 1 - | u16::from(value.si_state) << 2 - | u16::from(value.so_inactive) << 3 - | (value.start_bit as u16) << 7 - | (value.transfer_length as u16) << 12 - | u16::from(value.irq_enable) << 14 - } -} - -impl From for NormalSioControl { - fn from(value: u16) -> Self { - Self { - clock_source: (value & 1).into(), - clock_rate: (value & (1 << 1)).into(), - si_state: (value & (1 << 2)).into(), - so_inactive: (value & (1 << 3)).into(), - start_bit: (value & (1 << 7)).into(), - transfer_length: (value & (1 << 12)).into(), - irq_enable: (value & (1 << 14)).into(), - } - } -} - -pub enum ClockSource { - External = 0, - Internal = 1, -} - -impl From for ClockSource { - fn from(value: u16) -> Self { - match value % 2 { - 0 => ClockSource::External, - 1 => ClockSource::Internal, - _ => panic!(), - } - } -} - -pub enum InternalClock { - Khz256 = 0, - Mhz2 = 1, -} - -impl From for InternalClock { - fn from(value: u16) -> Self { - match value % 2 { - 0 => InternalClock::Khz256, - 1 => InternalClock::Mhz2, - _ => panic!(), - } - } -} - -// automatically reset when transfer complete -pub enum StartBit { - Inactive = 0, - Active = 1, -} - -impl From for StartBit { - fn from(value: u16) -> Self { - match value % 2 { - 0 => StartBit::Inactive, - 1 => StartBit::Active, - _ => panic!(), - } - } -} - -#[derive(PartialEq, Eq)] -pub enum TransferLength { - Bits8 = 0, - Bits32 = 1, -} - -impl From for TransferLength { - fn from(value: u16) -> Self { - match value % 2 { - 0 => TransferLength::Bits8, - 1 => TransferLength::Bits32, - _ => panic!(), - } - } -} diff --git a/agb/src/serial_link/uart.rs b/agb/src/serial_link/uart.rs deleted file mode 100644 index 644b1bb3..00000000 --- a/agb/src/serial_link/uart.rs +++ /dev/null @@ -1,168 +0,0 @@ -use embedded_hal::serial::{Read, Write}; - -use crate::println; - -use super::{BoolField, LinkPortError, SioMode, RCNT, SIOCNT, SIODATA8}; - -pub struct LinkPortUart; - -impl LinkPortUart { - pub fn init(rate: BaudRate, with_interrupts: bool, clear_to_send: bool) -> Self { - println!("begin uart init"); - RCNT.set(0x0); - println!("have set rcnt"); - SIOCNT.set(0x0); - let reg: u16 = UartSioControl::default() - .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 - } -} - -impl Read for LinkPortUart { - type Error = LinkPortError; - - fn read(&mut self) -> Result> { - match UartSioControl::from(SIOCNT.get()) { - v if *v.error => Err(nb::Error::Other(LinkPortError::GbaErrorBit)), - v if *v.recv_empty => Err(nb::Error::WouldBlock), - _ => Ok((SIODATA8.get() & 0xFF) as u8), - } - } -} - -impl Write for LinkPortUart { - type Error = LinkPortError; - - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { - match self.flush() { - Ok(_) => { - SIODATA8.set(word as u16); - Ok(()) - } - Err(e) => Err(e), - } - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - match UartSioControl::from(SIOCNT.get()) { - v if *v.error => Err(nb::Error::Other(LinkPortError::GbaErrorBit)), - v if *v.send_full => Err(nb::Error::WouldBlock), - _ => Ok(()), - } - } -} - -pub(super) struct UartSioControl { - baud_rate: BaudRate, // 0-1 - flow_control: BoolField, // 2 - parity_odd: BoolField, // 3 - send_full: BoolField, // 4 - recv_empty: BoolField, // 5 - error: BoolField, // 6 - data_8bit: BoolField, // 7 - fifo_enabled: BoolField, // 8 - parity_enabled: BoolField, // 9 - tx_enabled: BoolField, // 10 - rx_enabled: BoolField, // 11 - mode: SioMode, // 12-13 - irq_enable: BoolField, // 14 -} - -impl Default for UartSioControl { - fn default() -> Self { - Self { - baud_rate: BaudRate::B9600, - flow_control: BoolField(false), - parity_odd: BoolField(false), - send_full: BoolField(false), - recv_empty: BoolField(false), - error: BoolField(false), - data_8bit: BoolField(true), - fifo_enabled: BoolField(true), - parity_enabled: BoolField(false), - tx_enabled: BoolField(true), - rx_enabled: BoolField(true), - mode: SioMode::Uart, - irq_enable: BoolField(false), - } - } -} - -impl UartSioControl { - fn with_baud(mut self, rate: BaudRate) -> Self { - self.baud_rate = rate; - 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 for u16 { - fn from(value: UartSioControl) -> Self { - value.baud_rate as u16 - | u16::from(value.flow_control) << 2 - | u16::from(value.parity_odd) << 3 - | u16::from(value.send_full) << 4 - | u16::from(value.recv_empty) << 5 - | u16::from(value.error) << 6 - | u16::from(value.data_8bit) << 7 // bit start - | u16::from(value.fifo_enabled) << 8 - | u16::from(value.parity_enabled) << 9 - | u16::from(value.tx_enabled) << 10 - | u16::from(value.rx_enabled) << 11 - | (value.mode as u16) << 12 - | u16::from(value.irq_enable) << 14 - } -} - -impl From for UartSioControl { - fn from(value: u16) -> Self { - Self { - baud_rate: BaudRate::from(value & 0b11), - flow_control: (value & (1 << 2)).into(), - parity_odd: (value & (1 << 3)).into(), - send_full: (value & (1 << 4)).into(), - recv_empty: (value & (1 << 5)).into(), - error: (value & (1 << 6)).into(), - data_8bit: (value & (1 << 7)).into(), - fifo_enabled: (value & (1 << 8)).into(), - parity_enabled: (value & (1 << 9)).into(), - tx_enabled: (value & (1 << 10)).into(), - rx_enabled: (value & (1 << 11)).into(), - mode: ((value & (0b11 << 12)) >> 12).into(), - irq_enable: (value & (1 << 14)).into(), - } - } -} - -pub enum BaudRate { - B9600 = 0b00, - B38400 = 0b01, - B57600 = 0b10, - B115200 = 0b11, -} - -impl From for BaudRate { - fn from(value: u16) -> Self { - match value { - 0b00 => Self::B9600, - 0b01 => Self::B38400, - 0b10 => Self::B57600, - 0b11 => Self::B115200, - _ => panic!("passed invalid value"), - } - } -}