diff --git a/rust/pico/src/main.rs b/rust/pico/src/main.rs index dd1433d..209b567 100644 --- a/rust/pico/src/main.rs +++ b/rust/pico/src/main.rs @@ -74,33 +74,73 @@ fn main() -> ! { )); // Set up the USB Communications Class Device driver - let mut _serial = SerialPort::new(&usb_bus); + let mut serial = SerialPort::new(&usb_bus); // Create a USB device with a fake VID and PID - let mut _usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) .manufacturer("Fake company") .product("Serial port") .serial_number("TEST") .device_class(2) // from: https://www.usb.org/defined-class-codes .build(); + let mut i = 0; + loop { info!("start!"); - // delay.delay_ms(1000); - // serial.write("test".as_bytes()); // serial_send(&mut serial, "test"); // delay.delay_ms(1000); + + i += 1; + + if i == 100 { + i = 0; + serial_send(&mut serial, "test"); + } + + delay.delay_ms(8); + + if usb_dev.poll(&mut [&mut serial]) { + + // let mut buf = [0u8; 64]; + + // match serial.read(&mut buf) { + // Err(_e) => { + // // Do nothing + // } + // Ok(0) => { + // // Do nothing + // } + // Ok(count) => { + // // Convert to upper case + // buf.iter_mut().take(count).for_each(|b| { + // b.make_ascii_uppercase(); + // }); + + // // Send back to the host + // let mut wr_ptr = &buf[..count]; + + // while !wr_ptr.is_empty() { + // match serial.write(wr_ptr) { + // Ok(len) => wr_ptr = &wr_ptr[len..], + // // On error, just drop unwritten data. + // // One possible error is Err(WouldBlock), meaning the USB + // // write buffer is full. + // Err(_) => break, + // }; + // } + // } + // } + } } } fn serial_send(serial: &mut SerialPort, msg: &str) { - let buf = [0u8; 64]; - // Send back to the host - let mut wr_ptr = &buf[..msg.len()]; + let mut wr_ptr = msg.as_bytes(); while !wr_ptr.is_empty() { match serial.write(wr_ptr) { diff --git a/rust/serial_reader/.vscode/launch.json b/rust/serial_reader/.vscode/launch.json new file mode 100644 index 0000000..d89ce87 --- /dev/null +++ b/rust/serial_reader/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'serial_reader'", + "cargo": { + "args": [ + "build", + "--bin=serial_reader", + "--package=serial_reader" + ], + "filter": { + "name": "serial_reader", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/rust/serial_reader/Cargo.toml b/rust/serial_reader/Cargo.toml index 30f1b73..478b70a 100644 --- a/rust/serial_reader/Cargo.toml +++ b/rust/serial_reader/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" serialport = "*" gtk = { version = "*", features = ["v3_24"] } anyhow = { version = "1.0", features = ["backtrace"] } +glib = "*" diff --git a/rust/serial_reader/src/main.rs b/rust/serial_reader/src/main.rs index d89d94a..729e16c 100644 --- a/rust/serial_reader/src/main.rs +++ b/rust/serial_reader/src/main.rs @@ -1,24 +1,25 @@ use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering::SeqCst; -// use std::thread::JoinHandle; use gtk::{prelude::*, TextView}; use gtk::{Application, ApplicationWindow}; use gtk::{Button, Entry, Orientation}; +use glib; + mod port; use port::*; static CONNECTED: AtomicBool = AtomicBool::new(false); -// static mut THREAD: Option> = None; +static mut PORT: Option = None; fn main() { let app = Application::builder() .application_id("org.example.HelloWorld") .build(); - app.connect_activate(|app| { + app.connect_activate(move |app| { // We create the main window. let window = ApplicationWindow::builder() .application(app) @@ -29,22 +30,39 @@ fn main() { let master_box = gtk::Box::new(Orientation::Vertical, 5); let top_bar_box = gtk::Box::new(Orientation::Horizontal, 5); - let pid = Entry::builder().text("0x27dd").editable(true).build(); let vid = Entry::builder().text("0x16c0").editable(true).build(); - let connect_button = Button::with_label("Connect"); + let serial_info = TextView::new(); top_bar_box.pack_end(&connect_button, true, true, 3); top_bar_box.pack_end(&vid, true, true, 3); top_bar_box.pack_end(&pid, true, true, 3); - let serial_info = TextView::new(); - master_box.pack_end(&serial_info, true, true, 3); master_box.pack_end(&top_bar_box, false, true, 3); - window.add(&master_box); + let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); + + std::thread::spawn(move || { + // loop forever + loop { + unsafe { + if let Some(port) = &mut PORT { + // handle incoming message + match port.read().unwrap() { + SerialReadResult::Message(msg) => { + if !msg.is_empty() { + tx.send(msg).unwrap(); + } + } + SerialReadResult::UtfConversion(err) => println!("{:?}", err), + SerialReadResult::Timeout => (), + } + } + } + } + }); connect_button.connect_clicked(move |_| { if !CONNECTED.load(SeqCst) { @@ -62,7 +80,7 @@ fn main() { }; let serialport_settings = SerialPortSettings { - baud_rate: 57600, + baud_rate: 9600, data_bits: DataBits::Eight, parity: Parity::None, stop_bits: StopBits::One, @@ -70,32 +88,27 @@ fn main() { timeout: Duration::from_millis(2500), }; - if let Ok(mut port) = Port::open(usb_id, serialport_settings) { + if let Ok(port) = Port::open(usb_id, serialport_settings) { CONNECTED.store(true, SeqCst); - - // unsafe { - // THREAD = Some(std::thread::spawn(move || { - - // loop forever - loop { - // handle incoming message - match port.read().unwrap() { - SerialReadResult::Message(msg) => { - let buffer = serial_info.buffer().unwrap(); - - buffer.insert(&mut buffer.end_iter(), &msg); - } - SerialReadResult::UtfConversion(err) => println!("{:?}", err), - SerialReadResult::Timeout => (), - } + unsafe { + PORT = Some(port); } - - // })); - // } } } }); + let buffer = serial_info.buffer().unwrap(); + + rx.attach(None, move |message| { + if !message.is_empty() { + buffer.insert(&mut buffer.end_iter(), &format!("{}\n", message)); + } + + glib::Continue(true) + }); + + window.add(&master_box); + // Don't forget to make all widgets visible. window.show_all(); }); diff --git a/rust/serial_reader/src/port.rs b/rust/serial_reader/src/port.rs index d5335d0..ed48f78 100644 --- a/rust/serial_reader/src/port.rs +++ b/rust/serial_reader/src/port.rs @@ -48,7 +48,7 @@ impl Port { #[allow(unused)] pub fn read(&mut self) -> Result { - let mut buf: Vec = (0..255).collect(); + let mut buf: Vec = vec![0; 256]; match self.serial_port.read(&mut buf[..]) { Ok(t) => match String::from_utf8(buf[0..t].to_vec()) {