Skip to content

Commit

Permalink
looks like a plan
Browse files Browse the repository at this point in the history
  • Loading branch information
LuckyTurtleDev committed May 15, 2023
1 parent c2fcbde commit c01f51f
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 17 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use bincode::{Decode, Encode};
mod cards;
pub use cards::*;


//todo:
// new structure
// event + game + keep alive message


#[derive(Debug, Clone, Decode, Encode)]
pub enum MessageToPc {
ConnectionResponse
Expand Down
2 changes: 2 additions & 0 deletions pc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ sdl2_static_link = ["tetra/sdl2_static_link"]
sdl2_bundled = ["tetra/sdl2_bundled"]

[dependencies]
anyhow = "1.0.71"
bincode = { version = "2.0.0-rc.3", features = ["derive"] }
log = "0.4.17"
m3-macro = { version = "0.1.0", path = "../macro" }
m3-map = { version = "0.1.0", path = "../map" }
m3-models = { version = "0.1.0", path = "../models" }
Expand Down
149 changes: 132 additions & 17 deletions pc/src/usb.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,136 @@
use anyhow::Context;
use bincode::error::DecodeError;
use m3_models::{MessageToPc, MessageToPyBadge};
use serialport::available_ports;
use std::time::Duration;

pub(crate) fn init() {
let ports = available_ports().unwrap();
println!("{ports:?}");
for port in ports {
let mut port = serialport::new(port.port_name, 9600)
.timeout(Duration::from_millis(10))
use serialport::{available_ports, SerialPort, SerialPortInfo};
use std::{
iter,
sync::mpsc::{Receiver, Sender, TryRecvError},
thread,
time::Duration
};

struct Player {
receiver: Receiver<anyhow::Result<MessageToPc>>,
sender: Sender<MessageToPyBadge>,
port_name: String
}

#[derive(Default)]
struct Players {
player1: Option<Player>,
player2: Option<Player>,
player3: Option<Player>,
player4: Option<Player>,
///uart devices, wich where not classificated as pybadge yets
possible_players: Vec<Player>
}

impl Players {
fn iter(&self) -> impl Iterator<Item = &Player> {
iter::once(&self.player1)
.chain(iter::once(&self.player2))
.chain(iter::once(&self.player3))
.chain(iter::once(&self.player4))
.flat_map(|f| f.as_ref())
}

pub(crate) fn init() -> Players {
let players = Players::default();
let mut ports = available_ports().unwrap();
println!("avaibale ports: {ports:?}");
ports.retain(|port| {
!players
.iter()
.any(|player| player.port_name == port.port_name)
});
let mut possible_players: Vec<Player> = Vec::new();
for port in ports {
let (sender_to_pc, receiver_to_pc) = std::sync::mpsc::channel();
let (sender_to_pybadge, receiver_to_pydage) = std::sync::mpsc::channel();
let possible_player = Player {
receiver: receiver_to_pc,
sender: sender_to_pybadge,
port_name: port.port_name.clone()
};
possible_players.push(possible_player);
thread::spawn(move || {
let sender_to_pc: Sender<anyhow::Result<MessageToPc>> = sender_to_pc;
let receiver_to_pydage: Receiver<MessageToPyBadge> = receiver_to_pydage;
let pybadge = Pybadge::init(port).unwrap();
loop {
match receiver_to_pydage.try_recv() {
Err(err) => match err {
TryRecvError::Empty => {}
TryRecvError::Disconnected => panic!("channel disconnected") //or should I just break?
},
Ok(message) => pybadge.write(&message)
}
if let Some(message) = pybadge.try_next_event() {
sender_to_pc.send(Ok(message));
}
}
});
}
Players {
player1: None,
player2: None,
player3: None,
player4: None,
possible_players
}
}

//poll player events
fn poll(&mut self) {
todo!()
}
}

pub(crate) struct Pybadge {
port: Box<dyn SerialPort>,
buf: Vec<u8>
}

impl Pybadge {
fn init(port: SerialPortInfo) -> anyhow::Result<Self> {
let mut port = serialport::new(port.port_name, 960)
.timeout(Duration::from_secs(1))
.open()
.expect("Failed to open port");
let data = bincode::encode_to_vec(
MessageToPyBadge::ConnectionRequest,
bincode::config::standard()
)
.unwrap();
port.write_all(&data).unwrap();
println!("{data:?}");
.with_context(|| "Failed to open port")?;
Ok(Pybadge {
port,
buf: Vec::new()
})
}

fn try_next_event(&mut self) -> Option<MessageToPc> {
match bincode::decode_from_slice(&self.buf, bincode::config::standard()) {
Ok((event, len)) => {
self.buf.drain(..len);
return event;
},
Err(err) => {
match err {
//we need to wait for more data first
DecodeError::UnexpectedEnd { .. } => {},
_ => panic!("Could not decode message\n {}", err)
}
}
};
let mut buffer = [0_u8; 16];
let len = self.port.read(&mut buffer).unwrap();
if len != 0 { //if it even possibel to get len 0? Since it does blocking wait for messages
let mut new_data: Vec<u8> =
buffer[..len].iter().map(|f| f.to_owned()).collect();
println!("recieve data: {new_data:?}");
self.buf.append(&mut new_data);
}
None
}

fn write(&mut self, message: &MessageToPyBadge) {
let data = bincode::encode_to_vec(message, bincode::config::standard()).unwrap();
println!("send {data:?}");
self.port.write_all(&data).unwrap();
}
}

0 comments on commit c01f51f

Please sign in to comment.