split into hardware dependent / independent
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.vscode
|
||||||
|
.embuild
|
||||||
|
target
|
||||||
|
Cargo.lock
|
||||||
4
gem-remotes-esp32/.gitignore
vendored
4
gem-remotes-esp32/.gitignore
vendored
@ -1,4 +0,0 @@
|
|||||||
/.vscode
|
|
||||||
/.embuild
|
|
||||||
/target
|
|
||||||
/Cargo.lock
|
|
||||||
@ -28,6 +28,7 @@ experimental = ["esp-idf-svc/experimental"]
|
|||||||
embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"]
|
embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
gem-remotes-lib = { path = "../gem-remotes-lib" }
|
||||||
log = { version = "0.4", default-features = false, features = ["max_level_trace"] }
|
log = { version = "0.4", default-features = false, features = ["max_level_trace"] }
|
||||||
esp-idf-svc = { version = "0.49", default-features = false }
|
esp-idf-svc = { version = "0.49", default-features = false }
|
||||||
esp32-nimble = "0.7.0"
|
esp32-nimble = "0.7.0"
|
||||||
|
|||||||
@ -8,8 +8,13 @@ use bitflags::bitflags;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::dispatch::{Dispatch, RecvQ, SendQ};
|
use gem_remotes_lib::{
|
||||||
use crate::commands::{Button, Commands};
|
Dispatch,
|
||||||
|
DispatchRecvQ,
|
||||||
|
DispatchSendQ,
|
||||||
|
Commands,
|
||||||
|
Button,
|
||||||
|
};
|
||||||
|
|
||||||
// TODO HARDWARE: test these values to see if they are suitable
|
// TODO HARDWARE: test these values to see if they are suitable
|
||||||
const BLE_MIN_INTERVAL: u16 = 24; // x 1.25ms
|
const BLE_MIN_INTERVAL: u16 = 24; // x 1.25ms
|
||||||
@ -41,8 +46,8 @@ const BLE_BUTTON_RELEASE: u8 = 0;
|
|||||||
const BLE_BUTTON_PRESS: u8 = 1;
|
const BLE_BUTTON_PRESS: u8 = 1;
|
||||||
|
|
||||||
pub struct BleServer {
|
pub struct BleServer {
|
||||||
send_q: SendQ,
|
send_q: DispatchSendQ,
|
||||||
recv_q: RecvQ,
|
recv_q: DispatchRecvQ,
|
||||||
svc_flags: SvcFlags,
|
svc_flags: SvcFlags,
|
||||||
dev_name: String,
|
dev_name: String,
|
||||||
|
|
||||||
@ -205,7 +210,7 @@ impl BleServer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_bluetooth_cmd(sender: &SendQ, args: &mut OnWriteArgs, cmd: Commands) {
|
fn on_bluetooth_cmd(sender: &DispatchSendQ, args: &mut OnWriteArgs, cmd: Commands) {
|
||||||
let v = args.recv_data();
|
let v = args.recv_data();
|
||||||
// receiving incorrect data isn't fatal, but being unable to send events is.
|
// receiving incorrect data isn't fatal, but being unable to send events is.
|
||||||
let attempt = match cmd {
|
let attempt = match cmd {
|
||||||
@ -264,7 +269,7 @@ fn set_device_security(dev: &mut BLEDevice) {
|
|||||||
.resolve_rpa();
|
.resolve_rpa();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_server_callbacks(server: &mut BLEServer, sender: SendQ) {
|
fn set_server_callbacks(server: &mut BLEServer, sender: DispatchSendQ) {
|
||||||
server.on_connect(move |server, clntdesc| {
|
server.on_connect(move |server, clntdesc| {
|
||||||
// Print connected client data
|
// Print connected client data
|
||||||
info!("client connected: {:?}", clntdesc);
|
info!("client connected: {:?}", clntdesc);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const BUTTON_HOLD_TIME_MS: u64 = 500;
|
const BUTTON_HOLD_TIME_MS: u64 = 1_200;
|
||||||
const STOP_SAFETY_TIME_MS: u64 = 2000;
|
const STOP_SAFETY_TIME_MS: u64 = 2_000;
|
||||||
const PAIR_TIME_MS: u64 = 10000; //180000; TODO:Debug go back to 3 minutes from 10s
|
const PAIR_TIME_MS: u64 = 30_000;
|
||||||
|
|
||||||
// Crates used in release
|
// Crates used in release
|
||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
@ -10,20 +10,23 @@ use futures_lite::future;
|
|||||||
use std::panic;
|
use std::panic;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use gem_remotes_lib::{
|
||||||
|
Commands,
|
||||||
|
Controller,
|
||||||
|
Dispatch,
|
||||||
|
};
|
||||||
|
|
||||||
// Debug modules
|
// Debug modules
|
||||||
mod test_console;
|
mod test_console;
|
||||||
|
|
||||||
// Release modules
|
// Release modules
|
||||||
mod commands;
|
|
||||||
mod dispatch;
|
|
||||||
mod motor_controller;
|
|
||||||
mod motor_driver;
|
mod motor_driver;
|
||||||
mod message_timer;
|
mod message_timer;
|
||||||
mod ble_server;
|
mod ble_server;
|
||||||
mod pair_button_driver;
|
mod pair_button_driver;
|
||||||
|
|
||||||
use crate::message_timer::MessageTimer;
|
use crate::message_timer::MessageTimer;
|
||||||
use crate::commands::Commands;
|
//use crate::commands::Commands;
|
||||||
|
|
||||||
//TODO: limit switch driver, would be good in long run if it checked limit switches periodically (every 1s?) to ensure they are still functioning
|
//TODO: limit switch driver, would be good in long run if it checked limit switches periodically (every 1s?) to ensure they are still functioning
|
||||||
|
|
||||||
@ -67,14 +70,14 @@ async fn main_loop() -> Result<()> {
|
|||||||
info!("Entering main loop");
|
info!("Entering main loop");
|
||||||
|
|
||||||
// Create dispatch early so it can outlive most other things
|
// Create dispatch early so it can outlive most other things
|
||||||
let mut dp = dispatch::Dispatch::new();
|
let mut dp = Dispatch::new();
|
||||||
|
|
||||||
// Debug Drivers (TODO DEBUG: remove debug)
|
// Debug Drivers (TODO DEBUG: remove debug)
|
||||||
let motor_driver = motor_driver::MotorDriverDebug::new();
|
let motor_driver = motor_driver::MotorDriverDebug::new();
|
||||||
|
|
||||||
// Setup of various drivers that need to out-live the executor
|
// Setup of various drivers that need to out-live the executor
|
||||||
let m_chan = motor_controller::Controller::prepare_controller(&mut dp);
|
let m_chan = Controller::prepare_controller(&mut dp);
|
||||||
let mut motor_control = motor_controller::Controller::new(m_chan, dp.get_cmd_channel(), motor_driver.get_endpoint());
|
let mut motor_control = Controller::new(m_chan, dp.get_cmd_channel(), motor_driver.get_endpoint());
|
||||||
// Setup callback timers
|
// Setup callback timers
|
||||||
let mut button_timer = MessageTimer::<Commands, Commands>::new_on_dispatch(
|
let mut button_timer = MessageTimer::<Commands, Commands>::new_on_dispatch(
|
||||||
Commands::ButtonTimerRestart,
|
Commands::ButtonTimerRestart,
|
||||||
|
|||||||
@ -6,8 +6,10 @@ use core::time::Duration;
|
|||||||
use async_channel::{Receiver, Sender};
|
use async_channel::{Receiver, Sender};
|
||||||
use futures_lite::FutureExt;
|
use futures_lite::FutureExt;
|
||||||
|
|
||||||
use crate::dispatch::Dispatch;
|
use gem_remotes_lib::{
|
||||||
use crate::commands::Commands;
|
Commands,
|
||||||
|
Dispatch
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum State {
|
enum State {
|
||||||
|
|||||||
@ -2,34 +2,26 @@
|
|||||||
|
|
||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use async_channel::{unbounded, Receiver, Sender};
|
use async_channel::unbounded;
|
||||||
|
use gem_remotes_lib::{MotorCommands, MotorRecvQ, MotorSendQ};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub enum Commands {
|
|
||||||
StartUp,
|
|
||||||
StartDown,
|
|
||||||
Stop
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type SendQ = Sender<Commands>;
|
|
||||||
pub type RecvQ = Receiver<Commands>;
|
|
||||||
|
|
||||||
pub struct MotorDriverDebug{
|
pub struct MotorDriverDebug{
|
||||||
endpoint: SendQ, // Endpoint to hand to dispatch or anyone else sending commands here.
|
endpoint: MotorSendQ, // Endpoint to hand to dispatch or anyone else sending commands here.
|
||||||
recv_q: RecvQ,
|
recv_q: MotorRecvQ,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Debug / example version of Motor Driver.
|
/// Debug / example version of Motor Driver.
|
||||||
impl MotorDriverDebug {
|
impl MotorDriverDebug {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (s,r) = unbounded();
|
let (s,r) = unbounded(); // TODO: reserve a reasonable amount for all unbounded?
|
||||||
MotorDriverDebug {
|
MotorDriverDebug {
|
||||||
endpoint: s,
|
endpoint: s,
|
||||||
recv_q: r,
|
recv_q: r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_endpoint(&self) -> SendQ {
|
pub fn get_endpoint(&self) -> MotorSendQ {
|
||||||
self.endpoint.clone()
|
self.endpoint.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,11 +32,11 @@ impl MotorDriverDebug {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_cmd(&self, cmd: Commands) -> Result<()> {
|
async fn handle_cmd(&self, cmd: MotorCommands) -> Result<()> {
|
||||||
match cmd {
|
match cmd {
|
||||||
Commands::StartUp => {self.start_up().await?;}
|
MotorCommands::StartUp => {self.start_up().await?;}
|
||||||
Commands::StartDown => {self.start_down().await?;}
|
MotorCommands::StartDown => {self.start_down().await?;}
|
||||||
Commands::Stop => {self.stop().await?;}
|
MotorCommands::Stop => {self.stop().await?;}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -62,3 +54,7 @@ impl MotorDriverDebug {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: we should fix panic to ensure that we shut down motors before rebooting ESP!
|
||||||
|
// Maybe by getting another endpoint and passing it to the panic handler? Add a different command that doesn't just stop, but stops and stops processing any new commands.
|
||||||
@ -4,8 +4,10 @@ use async_channel::Sender;
|
|||||||
use esp_idf_svc::timer::EspTaskTimerService;
|
use esp_idf_svc::timer::EspTaskTimerService;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
use crate::commands::Commands;
|
use gem_remotes_lib::{
|
||||||
use crate::dispatch::Dispatch;
|
Commands,
|
||||||
|
Dispatch,
|
||||||
|
};
|
||||||
|
|
||||||
type SendQ = Sender<Commands>;
|
type SendQ = Sender<Commands>;
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ impl PairButtonDriver {
|
|||||||
debug!("Waiting on pairing button presses");
|
debug!("Waiting on pairing button presses");
|
||||||
loop {
|
loop {
|
||||||
//TO DO: Watch for incoming pair button presses from the PIC and/or hardware buttons
|
//TO DO: Watch for incoming pair button presses from the PIC and/or hardware buttons
|
||||||
async_timer.after(Duration::from_millis(10000)).await?; // no need to panic on test console driver timer failure
|
async_timer.after(Duration::from_millis(10_000)).await?; // no need to panic on test console driver timer failure
|
||||||
//When we find a press, send PicRecvPair
|
//When we find a press, send PicRecvPair
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,10 +24,15 @@ use ::{
|
|||||||
},
|
},
|
||||||
core::time::Duration,
|
core::time::Duration,
|
||||||
};
|
};
|
||||||
use crate::commands::{Button, Commands};
|
|
||||||
use async_channel::Sender;
|
use async_channel::Sender;
|
||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
|
|
||||||
|
use gem_remotes_lib::{
|
||||||
|
Button,
|
||||||
|
Commands
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Command)]
|
#[derive(Command)]
|
||||||
pub enum Menu{//<'a> {
|
pub enum Menu{//<'a> {
|
||||||
/// Simulate the PIC controller sending aus n Up character
|
/// Simulate the PIC controller sending aus n Up character
|
||||||
|
|||||||
11
gem-remotes-lib/Cargo.toml
Normal file
11
gem-remotes-lib/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "gem-remotes-lib"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.86"
|
||||||
|
async-channel = "2.3.1"
|
||||||
|
log = "0.4.22"
|
||||||
|
strum = "0.26.3"
|
||||||
|
strum_macros = "0.26.4"
|
||||||
@ -46,14 +46,6 @@ pub enum Commands {
|
|||||||
EraseBleBonds,
|
EraseBleBonds,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
|
||||||
/*pub struct Button;
|
|
||||||
|
|
||||||
impl Button {
|
|
||||||
pub const PRESSED: u8 = 0x1;
|
|
||||||
pub const RELEASED: u8 = 0x0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Button {
|
pub enum Button {
|
||||||
Released = 0,
|
Released = 0,
|
||||||
@ -1,3 +1,6 @@
|
|||||||
|
/// Acts as a queue multiplexer. Accepts messages from entities that have taken an endpoint, and
|
||||||
|
/// broadcasts them to any entity that has subscribed for them.
|
||||||
|
|
||||||
|
|
||||||
use std::mem::discriminant;
|
use std::mem::discriminant;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -8,15 +11,15 @@ use strum::EnumCount;
|
|||||||
use crate::commands::{Commands, CmdType};
|
use crate::commands::{Commands, CmdType};
|
||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
|
|
||||||
pub type SendQ = Sender<Commands>;
|
pub type DispatchSendQ = Sender<Commands>;
|
||||||
pub type RecvQ = Receiver<Commands>;
|
pub type DispatchRecvQ = Receiver<Commands>;
|
||||||
|
|
||||||
//TODO: Making this generic over a <C> for commands would make it a useful small event handler.
|
//TODO: Making this generic over a <C> for commands would make it a useful small event handler.
|
||||||
|
|
||||||
pub struct Dispatch {
|
pub struct Dispatch {
|
||||||
callbacks: HashMap<CmdType, Vec<SendQ> >,
|
callbacks: HashMap<CmdType, Vec<DispatchSendQ> >,
|
||||||
recv: RecvQ, // Channel to listen to incomming commands
|
recv: DispatchRecvQ, // Channel to listen to incomming commands
|
||||||
endpoint: SendQ, // Endpoint to clone to hand to other modules, so that they can send commands
|
endpoint: DispatchSendQ, // Endpoint to clone to hand to other modules, so that they can send commands
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatch {
|
impl Dispatch {
|
||||||
@ -28,7 +31,7 @@ impl Dispatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a channel receiver that will get callbacks for all commands in the listen_for vec.
|
/// Get a channel receiver that will get callbacks for all commands in the listen_for vec.
|
||||||
pub fn get_callback_channel(&mut self, listen_for: &Vec<Commands>) -> RecvQ {
|
pub fn get_callback_channel(&mut self, listen_for: &Vec<Commands>) -> DispatchRecvQ {
|
||||||
let (send, rec) = unbounded(); // TODO: these could be bounded instead, as these calls are all non-blocking.
|
let (send, rec) = unbounded(); // TODO: these could be bounded instead, as these calls are all non-blocking.
|
||||||
for cmd in listen_for {
|
for cmd in listen_for {
|
||||||
let callback_list = self.callbacks.get_mut(&discriminant(&cmd));
|
let callback_list = self.callbacks.get_mut(&discriminant(&cmd));
|
||||||
@ -49,7 +52,7 @@ impl Dispatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a channel sender that will send commands to this dispatcher
|
/// Get a channel sender that will send commands to this dispatcher
|
||||||
pub fn get_cmd_channel(&self) -> SendQ {
|
pub fn get_cmd_channel(&self) -> DispatchSendQ {
|
||||||
self.endpoint.clone()
|
self.endpoint.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
45
gem-remotes-lib/src/lib.rs
Normal file
45
gem-remotes-lib/src/lib.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
/// Business logic (independent of hardware) for Gem Remotes ESP32 controller
|
||||||
|
|
||||||
|
// Modules in this crate
|
||||||
|
pub mod commands;
|
||||||
|
pub mod dispatch;
|
||||||
|
pub mod motor_controller;
|
||||||
|
|
||||||
|
// Re-published items
|
||||||
|
pub use commands::{
|
||||||
|
Button,
|
||||||
|
Commands
|
||||||
|
};
|
||||||
|
pub use motor_controller::{
|
||||||
|
AutoMode,
|
||||||
|
Controller,
|
||||||
|
LimitState,
|
||||||
|
MotorCommands,
|
||||||
|
MotorRecvQ,
|
||||||
|
MotorSendQ,
|
||||||
|
};
|
||||||
|
pub use dispatch::{
|
||||||
|
Dispatch,
|
||||||
|
DispatchSendQ,
|
||||||
|
DispatchRecvQ,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Test Code for whole module
|
||||||
|
|
||||||
|
pub fn add(left: u64, right: u64) -> u64 {
|
||||||
|
left + right
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let result = add(2, 2);
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,14 +2,12 @@
|
|||||||
/// command messages.
|
/// command messages.
|
||||||
|
|
||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
//use async_channel::Receiver;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use async_channel::{Receiver, Sender};
|
||||||
use crate::commands::{Commands, Button};
|
use crate::commands::{Commands, Button};
|
||||||
use crate::motor_driver::Commands as MotorCommands;
|
use crate::dispatch::{Dispatch, DispatchRecvQ, DispatchSendQ};
|
||||||
use crate::motor_driver::SendQ as MotorSendQ;
|
|
||||||
use crate::dispatch::{Dispatch, RecvQ, SendQ};
|
|
||||||
|
|
||||||
|
// The main internal state of the controller, representing the current control method of the motors.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum ControllerStates {
|
enum ControllerStates {
|
||||||
Stopped,
|
Stopped,
|
||||||
@ -18,9 +16,19 @@ enum ControllerStates {
|
|||||||
AutoUp,
|
AutoUp,
|
||||||
GoingDown,
|
GoingDown,
|
||||||
AutoDown,
|
AutoDown,
|
||||||
//TODO: AutoUp and AutoDown
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum MotorCommands {
|
||||||
|
StartUp,
|
||||||
|
StartDown,
|
||||||
|
Stop
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type MotorSendQ = Sender<MotorCommands>;
|
||||||
|
pub type MotorRecvQ = Receiver<MotorCommands>;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum AutoMode {
|
pub enum AutoMode {
|
||||||
Disallowed = 0,
|
Disallowed = 0,
|
||||||
@ -37,15 +45,15 @@ pub enum LimitState {
|
|||||||
|
|
||||||
pub struct Controller {
|
pub struct Controller {
|
||||||
state: ControllerStates,
|
state: ControllerStates,
|
||||||
recv: RecvQ,
|
recv: DispatchRecvQ,
|
||||||
send: SendQ,
|
send: DispatchSendQ,
|
||||||
motor_q: MotorSendQ,
|
motor_q: MotorSendQ,
|
||||||
auto_mode: AutoMode,
|
auto_mode: AutoMode,
|
||||||
limit_state: LimitState,
|
limit_state: LimitState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Controller {
|
impl Controller {
|
||||||
pub fn new(recv: RecvQ, send: SendQ, motor_q: MotorSendQ) -> Self {
|
pub fn new(recv: DispatchRecvQ, send: DispatchSendQ, motor_q: MotorSendQ) -> Self {
|
||||||
Controller {
|
Controller {
|
||||||
state: ControllerStates::Stopping,
|
state: ControllerStates::Stopping,
|
||||||
recv: recv,
|
recv: recv,
|
||||||
@ -58,7 +66,7 @@ impl Controller {
|
|||||||
|
|
||||||
/// Tell the message dispatch which messages we are interested in receiving, and get
|
/// Tell the message dispatch which messages we are interested in receiving, and get
|
||||||
/// a callback channel that receives those messages.
|
/// a callback channel that receives those messages.
|
||||||
pub fn prepare_controller(dp: &mut Dispatch) -> RecvQ {
|
pub fn prepare_controller(dp: &mut Dispatch) -> DispatchRecvQ {
|
||||||
let cmds = vec![
|
let cmds = vec![
|
||||||
Commands::PicRecvUp{data: Button::Released},
|
Commands::PicRecvUp{data: Button::Released},
|
||||||
Commands::PicRecvDown{data: Button::Released},
|
Commands::PicRecvDown{data: Button::Released},
|
||||||
Reference in New Issue
Block a user