112 lines
3.7 KiB
Rust
112 lines
3.7 KiB
Rust
const BUTTON_HOLD_TIME_MS: u64 = 500;
|
|
const STOP_SAFETY_TIME_MS: u64 = 2000;
|
|
|
|
// Crates used in release
|
|
use log::*; //{trace, debug, info, warn, error}
|
|
use anyhow::Result;
|
|
use async_executor::Executor;
|
|
use futures_lite::future;
|
|
use std::panic;
|
|
use std::ops::Deref;
|
|
|
|
// Debug modules
|
|
mod test_console;
|
|
|
|
// Release modules
|
|
mod commands;
|
|
mod dispatch;
|
|
mod motor_controller;
|
|
mod motor_driver;
|
|
mod message_timer;
|
|
mod ble_server;
|
|
|
|
use crate::message_timer::MessageTimer;
|
|
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
|
|
|
|
fn main() {
|
|
// Do basic initialization
|
|
esp_idf_svc::sys::link_patches();
|
|
esp_idf_svc::log::EspLogger::initialize_default();
|
|
|
|
// Set log level based on compiler flags
|
|
#[cfg(debug_assertions)]
|
|
log::set_max_level(log::LevelFilter::Trace);
|
|
#[cfg(not(debug_assertions))]
|
|
log::set_max_level(log::LevelFilter::Info);
|
|
|
|
// Set panic to use error! instead of write! (as we will potentially log errors)
|
|
panic::set_hook(Box::new(|panic_info| {
|
|
let (filename, line) =
|
|
panic_info.location().map(|loc| (loc.file(), loc.line()))
|
|
.unwrap_or(("<unknown>", 0));
|
|
|
|
let cause = panic_info.payload().downcast_ref::<String>().map(String::deref);
|
|
|
|
let cause = cause.unwrap_or_else(||
|
|
panic_info.payload().downcast_ref::<&str>().map(|s| *s)
|
|
.unwrap_or("<cause unknown>")
|
|
);
|
|
|
|
error!("A panic occurred at {}:{}: {}", filename, line, cause);
|
|
}));
|
|
|
|
// Start up our main loop
|
|
match future::block_on(main_loop()) {
|
|
Ok(_) => {error!("Exited main loop with no errors, but this should not happen."); panic!();}
|
|
Err(e) => {error!("Exited main loop with error {}", e); panic!();}
|
|
};
|
|
}
|
|
|
|
async fn main_loop() -> Result<()> {
|
|
info!("Entering main loop");
|
|
|
|
// Create dispatch early so it can outlive most other things
|
|
let mut dp = dispatch::Dispatch::new();
|
|
|
|
// Debug Drivers (TODO DEBUG: remove debug)
|
|
let motor_driver = motor_driver::MotorDriverDebug::new();
|
|
|
|
// Setup of various drivers that need to out-live the executor
|
|
let m_chan = motor_controller::Controller::prepare_controller(&mut dp);
|
|
let mut motor_control = motor_controller::Controller::new(m_chan, dp.get_cmd_channel(), motor_driver.get_endpoint());
|
|
// Setup callback timers
|
|
let mut button_timer = MessageTimer::<Commands, Commands>::new_on_dispatch(
|
|
Commands::ButtonTimerRestart,
|
|
Commands::ButtonTimerClear,
|
|
Commands::ButtonTimerExpired,
|
|
BUTTON_HOLD_TIME_MS,
|
|
&mut dp);
|
|
let mut stopping_timer = MessageTimer::<Commands, Commands>::new_on_dispatch(
|
|
Commands::StopTimerRestart,
|
|
Commands::StopTimerClear,
|
|
Commands::StopTimerExpired,
|
|
STOP_SAFETY_TIME_MS,
|
|
&mut dp);
|
|
let ble_server = ble_server::BleServer::new(&mut dp);
|
|
|
|
let executor = Executor::new();
|
|
let mut tasks:Vec<_> = Vec::new();
|
|
|
|
//Queue Up debug tasks (TODO DEBUG: remove debug)
|
|
let cli_endpoint = dp.get_cmd_channel();
|
|
tasks.push(executor.spawn(test_console::start_cli(cli_endpoint)));
|
|
|
|
// Queueu up our async tasks
|
|
tasks.push(executor.spawn(motor_control.run()));
|
|
tasks.push(executor.spawn(button_timer.run()));
|
|
tasks.push(executor.spawn(stopping_timer.run()));
|
|
tasks.push(executor.spawn(ble_server.run()));
|
|
tasks.push(executor.spawn(motor_driver.run()));
|
|
tasks.push(executor.spawn(dp.cmd_loop()));
|
|
|
|
//Once we have all our tasks, await on them all to run them in parallel.
|
|
for task in tasks {
|
|
executor.run(task).await?;
|
|
}
|
|
|
|
info!("exiting main loop");
|
|
Ok(())
|
|
}
|