#![no_std]
#![no_main]
use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::USB;
use embassy_rp::usb::{Driver, InterruptHandler};
use embassy_time::Timer;
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
use embassy_usb::driver::EndpointError;
use embassy_usb::{Builder, Config};
use rp2040_hal::rom_data::reset_to_usb_boot;
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
USBCTRL_IRQ => InterruptHandler<USB>;
});
#[embassy_executor::task]
pub async fn init() {
let p = embassy_rp::init(Default::default());
let driver = Driver::new(p.USB, Irqs);
let mut config = Config::new(65535u16, 65535u16);
config.manufacturer = Some("Jaydar");
config.product = Some("RP2040 Debug");
config.serial_number = Some("RP2040");
config.max_power = 100;
config.max_packet_size_0 = 64;
config.device_class = 0xEF;
config.device_sub_class = 0x02;
config.device_protocol = 0x01;
config.composite_with_iads = true;
let mut config_descriptor = [0; 256];
let mut bos_descriptor = [0; 256];
let mut control_buf = [0; 64];
let mut state = State::new();
let mut builder = Builder::new(
driver,
config,
&mut config_descriptor,
&mut bos_descriptor,
&mut [], &mut control_buf,
);
let class = CdcAcmClass::new(&mut builder, &mut state, 64);
let mut usb = builder.build();
let (mut usb_tx, mut usb_rx) = class.split();
let usb_fut = usb.run();
let usb_echo_fut = async {
let mut buf = [0; 64];
let mut message = [0; 128];
let mut idx = 0;
loop {
let n = match usb_rx.read_packet(&mut buf).await {
Ok(n) => n,
Err(EndpointError::Disabled) => break,
Err(_) => continue,
};
for &byte in &buf[..n] {
usb_tx.write_packet(&[byte]).await.ok();
if byte == b'\r' || byte == b'\n' {
if idx > 0 {
usb_tx.write_packet(b"\r\n").await.ok();
let is_boot = idx == 6
&& message[0] == b'r'
&& message[1] == b'e'
&& message[2] == b'b'
&& message[3] == b'o'
&& message[4] == b'o'
&& message[5] == b't';
let is_clear = idx == 5
&& message[0] == b'c'
&& message[1] == b'l'
&& message[2] == b'e'
&& message[3] == b'a'
&& message[4] == b'r';
if is_boot {
usb_tx.write_packet(b"Booting\r\n").await.ok();
Timer::after_secs(1).await;
reset_to_usb_boot(0, 0)
} else if is_clear {
usb_tx.write_packet(b"\x1b[2J\x1b[H").await.ok();
} else {
usb_tx.write_packet(&message[..idx]).await.ok();
usb_tx.write_packet(b" Hi\r\n").await.ok();
}
idx = 0;
}
} else {
if idx < message.len() {
message[idx] = byte;
idx += 1;
}
}
}
}
};
embassy_futures::join::join(usb_fut, usb_echo_fut).await;
}