2023-04-16 17:58:10 +00:00
|
|
|
mod serial_config;
|
|
|
|
|
|
|
|
use numtoa::NumToA;
|
|
|
|
|
2023-04-15 09:45:21 +00:00
|
|
|
use core::future::Future;
|
|
|
|
|
2023-08-25 12:14:35 +00:00
|
|
|
use embassy_rp::bind_interrupts;
|
|
|
|
use embassy_rp::peripherals::USB;
|
|
|
|
use embassy_rp::usb::{Driver, InterruptHandler};
|
2023-04-15 09:45:21 +00:00
|
|
|
|
|
|
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
|
|
|
use embassy_usb::{Builder, Config, UsbDevice};
|
|
|
|
|
2023-04-16 17:58:10 +00:00
|
|
|
pub use serial_config::SerialConfig;
|
|
|
|
|
2023-04-15 09:45:21 +00:00
|
|
|
static mut DEVICE_DESCRIPTOR_BUFFER: [u8; 256] = [0; 256];
|
|
|
|
static mut CONFIG_DESCRIPTOR_BUFFER: [u8; 256] = [0; 256];
|
|
|
|
static mut BOS_DESCRIPTOR_BUFFER: [u8; 256] = [0; 256];
|
|
|
|
static mut MSOS_DESCRIPTOR_BUFFER: [u8; 256] = [0; 256];
|
|
|
|
static mut CONTROL_BUFFER: [u8; 64] = [0; 64];
|
|
|
|
static mut STATE: Option<State<'static>> = None;
|
|
|
|
static mut USB: Option<UsbDevice<'static, Driver<'static, USB>>> = None;
|
|
|
|
|
2023-08-23 10:38:50 +00:00
|
|
|
pub trait Sender {
|
|
|
|
async fn send_msg(&mut self, msg: &str);
|
|
|
|
|
|
|
|
async fn send_number<T, I>(&mut self, i: T, base: I)
|
|
|
|
where
|
|
|
|
T: NumToA<I>;
|
|
|
|
}
|
|
|
|
|
2023-08-25 12:14:35 +00:00
|
|
|
bind_interrupts!(struct Irqs {
|
|
|
|
USBCTRL_IRQ => InterruptHandler<USB>;
|
|
|
|
});
|
|
|
|
|
2023-04-15 09:45:21 +00:00
|
|
|
pub struct Serial<'a> {
|
|
|
|
class: CdcAcmClass<'a, Driver<'a, USB>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Serial<'static> {
|
2023-08-25 11:38:30 +00:00
|
|
|
pub async fn new(
|
|
|
|
usb: USB,
|
|
|
|
serial_config: SerialConfig<'static>,
|
|
|
|
) -> (Serial<'static>, impl Future<Output = !>) {
|
2023-04-15 09:45:21 +00:00
|
|
|
// Create the driver, from the HAL.
|
2023-08-25 12:14:35 +00:00
|
|
|
let driver = Driver::new(usb, Irqs);
|
2023-04-15 09:45:21 +00:00
|
|
|
|
|
|
|
// Create embassy-usb Config
|
2023-04-16 17:58:10 +00:00
|
|
|
let mut config = Config::new(
|
|
|
|
serial_config.vendor_id as u16,
|
|
|
|
serial_config.product_id as u16,
|
|
|
|
);
|
|
|
|
config.manufacturer = Some(serial_config.manufacturer);
|
|
|
|
config.product = Some(serial_config.product);
|
|
|
|
config.serial_number = Some(serial_config.serial_number);
|
2023-04-15 09:45:21 +00:00
|
|
|
config.max_power = 100;
|
|
|
|
config.max_packet_size_0 = 64;
|
|
|
|
|
|
|
|
// Required for windows compatiblity.
|
|
|
|
// https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
|
|
|
|
config.device_class = 0xEF;
|
|
|
|
config.device_sub_class = 0x02;
|
|
|
|
config.device_protocol = 0x01;
|
|
|
|
config.composite_with_iads = true;
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
STATE = Some(State::new());
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut builder = Builder::new(
|
|
|
|
driver,
|
|
|
|
config,
|
|
|
|
unsafe { &mut DEVICE_DESCRIPTOR_BUFFER },
|
|
|
|
unsafe { &mut CONFIG_DESCRIPTOR_BUFFER },
|
|
|
|
unsafe { &mut BOS_DESCRIPTOR_BUFFER },
|
|
|
|
unsafe { &mut MSOS_DESCRIPTOR_BUFFER },
|
|
|
|
unsafe { &mut CONTROL_BUFFER },
|
|
|
|
);
|
|
|
|
|
|
|
|
// Create classes on the builder.
|
|
|
|
let class = CdcAcmClass::new(&mut builder, unsafe { STATE.as_mut().unwrap() }, 64);
|
|
|
|
|
|
|
|
// Build the builder.
|
|
|
|
unsafe {
|
|
|
|
USB = Some(builder.build());
|
|
|
|
};
|
|
|
|
|
2023-08-25 11:38:30 +00:00
|
|
|
(Self { class }, Self::run_usb().await)
|
2023-04-15 09:45:21 +00:00
|
|
|
}
|
2023-04-16 12:19:09 +00:00
|
|
|
|
2023-08-25 11:38:30 +00:00
|
|
|
async fn run_usb() -> impl Future<Output = !> {
|
2023-04-16 12:19:09 +00:00
|
|
|
unsafe { USB.as_mut().unwrap().run() }
|
|
|
|
}
|
|
|
|
|
2023-04-16 17:58:10 +00:00
|
|
|
pub async fn send_msg(&mut self, s: &str) {
|
|
|
|
self.class.write_packet(s.as_bytes()).await.unwrap_or(());
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn send_number<T, I>(&mut self, i: T, base: I)
|
|
|
|
where
|
|
|
|
T: NumToA<I>,
|
|
|
|
{
|
|
|
|
let mut buf = [0; 256];
|
|
|
|
|
|
|
|
let s = i.numtoa_str(base, &mut buf);
|
|
|
|
|
|
|
|
self.send_msg(s).await;
|
2023-04-16 12:19:09 +00:00
|
|
|
}
|
2023-04-15 09:45:21 +00:00
|
|
|
}
|
2023-08-23 10:38:50 +00:00
|
|
|
|
|
|
|
impl Sender for Serial<'static> {
|
|
|
|
async fn send_msg(&mut self, msg: &str) {
|
|
|
|
self.send_msg(msg).await;
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn send_number<T, I>(&mut self, i: T, base: I)
|
|
|
|
where
|
|
|
|
T: NumToA<I>,
|
|
|
|
{
|
|
|
|
self.send_number(i, base).await;
|
|
|
|
}
|
|
|
|
}
|