use core::convert::Infallible;
use crate::{
peripheral::{Peripheral, PeripheralRef},
peripherals::{usb_device::RegisterBlock, USB_DEVICE},
};
pub struct UsbSerialJtag<'d, T> {
usb_serial: PeripheralRef<'d, T>,
}
type Error = Infallible;
impl<'d, T> UsbSerialJtag<'d, T>
where
T: Instance,
{
pub fn new(usb_serial: impl Peripheral<P = T> + 'd) -> Self {
crate::into_ref!(usb_serial);
let mut dev = Self { usb_serial };
dev.usb_serial.disable_rx_interrupts();
dev.usb_serial.disable_tx_interrupts();
dev
}
pub fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error> {
let reg_block = self.usb_serial.register_block();
for chunk in data.chunks(64) {
unsafe {
for &b in chunk {
reg_block.ep1.write(|w| w.rdwr_byte().bits(b.into()))
}
reg_block.ep1_conf.write(|w| w.wr_done().set_bit());
while reg_block.ep1_conf.read().bits() & 0b011 == 0b000 {
}
}
}
Ok(())
}
pub fn write_byte_nb(&mut self, word: u8) -> nb::Result<(), Error> {
let reg_block = self.usb_serial.register_block();
if reg_block
.ep1_conf
.read()
.serial_in_ep_data_free()
.bit_is_set()
{
unsafe {
reg_block.ep1.write(|w| w.rdwr_byte().bits(word.into()));
}
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
pub fn flush_tx(&mut self) -> Result<(), Error> {
let reg_block = self.usb_serial.register_block();
reg_block.ep1_conf.write(|w| w.wr_done().set_bit());
while reg_block.ep1_conf.read().bits() & 0b011 == 0b000 {
}
Ok(())
}
pub fn flush_tx_nb(&mut self) -> nb::Result<(), Error> {
let reg_block = self.usb_serial.register_block();
reg_block.ep1_conf.write(|w| w.wr_done().set_bit());
if reg_block.ep1_conf.read().bits() & 0b011 == 0b000 {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
let reg_block = self.usb_serial.register_block();
if reg_block
.ep1_conf
.read()
.serial_out_ep_data_avail()
.bit_is_set()
{
let value = reg_block.ep1.read().rdwr_byte().bits();
Ok(value)
} else {
Err(nb::Error::WouldBlock)
}
}
pub fn listen_rx_packet_recv_interrupt(&mut self) {
let reg_block = self.usb_serial.register_block();
reg_block
.int_ena
.modify(|_, w| w.serial_out_recv_pkt_int_ena().set_bit());
}
pub fn unlisten_rx_packet_recv_interrupt(&mut self) {
let reg_block = self.usb_serial.register_block();
reg_block
.int_ena
.modify(|_, w| w.serial_out_recv_pkt_int_ena().clear_bit());
}
pub fn rx_packet_recv_interrupt_set(&mut self) -> bool {
let reg_block = unsafe { &*USB_DEVICE::PTR };
reg_block
.int_st
.read()
.serial_out_recv_pkt_int_st()
.bit_is_set()
}
pub fn reset_rx_packet_recv_interrupt(&mut self) {
let reg_block = unsafe { &*USB_DEVICE::PTR };
reg_block
.int_clr
.write(|w| w.serial_out_recv_pkt_int_clr().set_bit())
}
}
pub trait Instance {
fn register_block(&self) -> &RegisterBlock;
fn disable_tx_interrupts(&mut self) {
self.register_block()
.int_ena
.write(|w| w.serial_in_empty_int_ena().clear_bit());
self.register_block()
.int_clr
.write(|w| w.serial_in_empty_int_clr().set_bit())
}
fn disable_rx_interrupts(&mut self) {
self.register_block()
.int_ena
.write(|w| w.serial_out_recv_pkt_int_ena().clear_bit());
self.register_block()
.int_clr
.write(|w| w.serial_out_recv_pkt_int_clr().set_bit())
}
fn get_rx_fifo_count(&self) -> u16 {
let ep0_state = self.register_block().in_ep0_st.read();
let wr_addr = ep0_state.in_ep0_wr_addr().bits();
let rd_addr = ep0_state.in_ep0_rd_addr().bits();
(wr_addr - rd_addr).into()
}
fn get_tx_fifo_count(&self) -> u16 {
let ep1_state = self.register_block().in_ep1_st.read();
let wr_addr = ep1_state.in_ep1_wr_addr().bits();
let rd_addr = ep1_state.in_ep1_rd_addr().bits();
(wr_addr - rd_addr).into()
}
}
impl Instance for crate::peripherals::USB_DEVICE {
#[inline(always)]
fn register_block(&self) -> &RegisterBlock {
self
}
}
impl<T> core::fmt::Write for UsbSerialJtag<'_, T>
where
T: Instance,
{
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.write_bytes(s.as_bytes()).map_err(|_| core::fmt::Error)
}
}
impl<T> embedded_hal::serial::Read<u8> for UsbSerialJtag<'_, T>
where
T: Instance,
{
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.read_byte()
}
}
impl<T> embedded_hal::serial::Write<u8> for UsbSerialJtag<'_, T>
where
T: Instance,
{
type Error = Error;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.write_byte_nb(word)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
self.flush_tx_nb()
}
}