Skip to content

Commit

Permalink
theoretical it should work now; test it tomorrow
Browse files Browse the repository at this point in the history
  • Loading branch information
LuckyTurtleDev committed May 16, 2023
1 parent 1b932e8 commit a5a6cb3
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 57 deletions.
5 changes: 2 additions & 3 deletions models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use cards::*;

#[derive(Debug, Clone, Decode, Encode, PartialEq)]
pub enum Key {
Start
Start
}

#[derive(Debug, Clone, Decode, Encode, PartialEq)]
Expand All @@ -33,8 +33,7 @@ pub enum MessageToPc {

#[derive(Debug, Clone, Decode, Encode, PartialEq)]
pub enum ToPybadgeProtocol {
ConnectionRequest,
ConnectionConfirmation
ConnectionRequest
}

#[derive(Debug, Clone, Decode, Encode, PartialEq)]
Expand Down
9 changes: 6 additions & 3 deletions pc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use tetra::{

mod tiles;
use tiles::{MapBaseTile, Textures};
use usb::Players;

mod usb;

Expand All @@ -34,7 +35,8 @@ struct GameState {
textures: Textures,
grass_postion: Vec2,
grass_rotation: f32,
level: Option<Map>
level: Option<Map>,
players: Players
}

impl GameState {
Expand All @@ -44,7 +46,8 @@ impl GameState {
textures,
grass_postion: Vec2::default(),
grass_rotation: 0.0,
level: Some(LEVELS.first().unwrap().to_owned())
level: Some(LEVELS.first().unwrap().to_owned()),
players: usb::Players::init()
})
}
}
Expand Down Expand Up @@ -84,6 +87,7 @@ impl State for GameState {
//update the current state.
//is called 60 time pro seconds (alsong framerated does not drop)
fn update(&mut self, ctx: &mut Context) -> tetra::Result<()> {
let player_events = self.players.get_events();
//use delta time, to avoid that the logic is effected by frame drops
let time = get_delta_time(ctx); //use time
self.grass_postion.x += 0.1 * time.as_millis() as f32;
Expand All @@ -93,7 +97,6 @@ impl State for GameState {
}

fn main() -> tetra::Result {
let players = usb::Players::init();
my_env_logger_style::just_log();
info!("{:?}", LEVELS[0]);
ContextBuilder::new(format!("{CARGO_PKG_NAME} v{CARGO_PKG_VERSION}"), 1280, 720)
Expand Down
63 changes: 42 additions & 21 deletions pc/src/usb.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use anyhow::Context;
use bincode::error::DecodeError;
use m3_models::{MessageToPc, MessageToPyBadge, ToPcGameEvent};
use serialport::{available_ports, SerialPort, SerialPortInfo, ClearBuffer};
use log::{debug, info, trace};
use m3_models::{
MessageToPc, MessageToPyBadge, ToPcGameEvent, ToPcProtocol, ToPybadgeProtocol
};
use serialport::{available_ports, ClearBuffer, SerialPort, SerialPortInfo};
use std::{
iter,
sync::mpsc::{Receiver, Sender, TryRecvError},
thread,
time::Duration
Expand All @@ -17,19 +19,21 @@ struct Player {

#[derive(Default)]
pub(crate) struct Players {
players: [Option<Player>;4],
players: [Option<Player>; 4],
///uart devices, wich where not classificated as pybadge yets
possible_players: Vec<Player>
}

impl Players {

pub(crate) fn init() -> Players {
let players = Players::default();
let mut ports = available_ports().unwrap();
println!("avaibale ports: {ports:?}");
ports.retain(|port| {
!players.players.iter().flatten()
!players
.players
.iter()
.flatten()
.any(|player| player.port_name == port.port_name)
});
let mut possible_players: Vec<Player> = Vec::new();
Expand All @@ -45,9 +49,9 @@ impl Players {
thread::spawn(move || {
let sender_to_pc: Sender<MessageToPc> = sender_to_pc;
let receiver_to_pydage: Receiver<MessageToPyBadge> = receiver_to_pydage;
let mut pybadge = Pybadge::init(port).unwrap();
let mut pybadge = Pybadge::init(port).unwrap();
//clean connection
pybadge.port.clear(ClearBuffer::All);
pybadge.port.clear(ClearBuffer::All).unwrap();
loop {
match receiver_to_pydage.try_recv() {
Err(err) => match err {
Expand All @@ -58,38 +62,50 @@ impl Players {
}
if let Some(message) = pybadge.try_next_event() {
if message != MessageToPc::KeepAlive {
sender_to_pc.send(message);
sender_to_pc.send(message).unwrap();
}
}
}
});
}
Players {
players: [None,None,None,None],
players: [None, None, None, None],
possible_players
}
}

///get aviable player events.
///Element i of return value repsent player i.
///ELement is None if no pybade is connected for player i.
fn get_events(&mut self) -> [Option<Vec<ToPcGameEvent>>;4] {
pub fn get_events(&mut self) -> [Option<Vec<ToPcGameEvent>>; 4] {
if self.players.iter().any(|f| f.is_none()) {
!todo!()
//check if some of the serial ports a pybadge and it as player
let mut i: usize = 0;
for possible_player in self.possible_players.iter() {
if MessageToPc::Protocol(m3_models::ToPcProtocol::ConnectionResponse)
== possible_player.receiver.try_recv().unwrap()
{
break;
}
i += 1;
}
let new_player = self.possible_players.remove(i);
info!("connected with player at port {}", new_player.port_name);
*self.players.iter_mut().find(|f| f.is_some()).unwrap() = Some(new_player);
}
let mut events = [None, None, None, None];
for (i, player) in self.players.iter().enumerate(){
for (i, player) in self.players.iter().enumerate() {
if let Some(player) = player {
let mut events_of_player = Vec::new();
match player.receiver.try_recv(){
Ok(event) => match event{
match player.receiver.try_recv() {
Ok(event) => match event {
MessageToPc::GameEvent(event) => events_of_player.push(event),
MessageToPc::Protocol(protocol) => todo!(),
MessageToPc::KeepAlive => {},
MessageToPc::Protocol(_protocol) => todo!(),
MessageToPc::KeepAlive => {}
},
Err(err) => todo!(),
Err(err) => panic!("{err}")
}
events[i]= Some(events_of_player);
events[i] = Some(events_of_player);
}
}
events
Expand All @@ -98,17 +114,20 @@ impl Players {

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

impl Pybadge {
fn init(port: SerialPortInfo) -> anyhow::Result<Self> {
let port_name = port.port_name.clone();
let port = serialport::new(port.port_name, 960)
.timeout(Duration::from_secs(1))
.open()
.with_context(|| "Failed to open port")?;
Ok(Pybadge {
port,
port_name,
buf: Vec::new()
})
}
Expand All @@ -117,6 +136,7 @@ impl Pybadge {
match bincode::decode_from_slice(&self.buf, bincode::config::standard()) {
Ok((event, len)) => {
self.buf.drain(..len);
debug!("recieve message form {:?} {event:?}", self.port_name);
return event;
},
Err(err) => {
Expand All @@ -133,15 +153,16 @@ impl Pybadge {
//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:?}");
trace!("recieve data form {:?} {new_data:?}", self.port_name);
self.buf.append(&mut new_data);
}
None
}

fn write(&mut self, message: &MessageToPyBadge) {
debug!("send message to {:?} {:?}", &self.port_name, &message);
let data = bincode::encode_to_vec(message, bincode::config::standard()).unwrap();
println!("send {data:?}");
trace!("send data to {:?} {:?}", &self.port_name, data);
self.port.write_all(&data).unwrap();
}
}
40 changes: 10 additions & 30 deletions pybadge/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,6 @@ fn send_event(event: MessageToPc) {
usb::wirte(&buf[..len]);
}

/// wait for the pc to start handshake
/// Return err, if pc need more the 5s to finish handshake after starting shake
fn connect(usb_data: &mut Vec<u8, 128>, delay: &mut Delay) -> Result<(), ()> {
while read_events(usb_data)
.iter()
.any(|f| f == &MessageToPyBadge::ConnectionRequest)
{
delay.delay_ms(50_u16);
usb::read(usb_data);
}
send_event(MessageToPc::ConnectionResponse);
//timeout after 5 seconds
for _ in 0..100 {
delay.delay_ms(50_u16);
usb::read(usb_data);
if read_events(usb_data)
.iter()
.any(|f| f == &MessageToPyBadge::ConnectionConfirmation)
{
return Ok(());
}
}
Err(())
}

#[entry]
fn main() -> ! {
let mut usb_data = Vec::<u8, 128>::new();
Expand All @@ -78,12 +53,17 @@ fn main() -> ! {
display.clear(Color::BLACK).unwrap();
usb::init(pybadge.usb_builder);
//wait for connection with pc;
while connect(&mut usb_data, &mut pybadge.delay).is_err() {}
while read_events(&mut usb_data)
.iter()
.any(|f| f == &MessageToPyBadge::ConnectionRequest)
{
delay.delay_ms(50_u16);
usb::read(&mut usb_data);
}
send_event(MessageToPc::ConnectionResponse);
//Todo: do not throw away event, wihich are directly send after ConnectionRequest
loop {
send_event(MessageToPc::KeepAlive);
usb::read(&mut usb_data);
pybadge.red_led.on().unwrap();
pybadge.delay.delay_ms(1000_u16);
pybadge.red_led.off().unwrap();
pybadge.delay.delay_ms(1000_u16);
}
}

0 comments on commit a5a6cb3

Please sign in to comment.