pros_sync/lib.rs
1//! Synchronous robot code trait for [pros-rs](https://crates.io/crates/pros).
2
3#![no_std]
4
5use pros_core::error::Result;
6
7/// A trait for robot code that runs without the async executor spun up.
8/// This trait isn't recommended. See `AsyncRobot` in [pros-async](https://crates.io/crates/pros-async) for the preferred trait to run robot code.
9pub trait SyncRobot {
10 /// Runs during the operator control period.
11 /// This function may be called more than once.
12 /// For that reason, do not use `Peripherals::take` in this function.
13 fn opcontrol(&mut self) -> Result {
14 Ok(())
15 }
16 /// Runs during the autonomous period.
17 fn auto(&mut self) -> Result {
18 Ok(())
19 }
20 /// Runs continuously during the disabled period.
21 fn disabled(&mut self) -> Result {
22 Ok(())
23 }
24 /// Runs once when the competition system is initialized.
25 fn comp_init(&mut self) -> Result {
26 Ok(())
27 }
28}
29
30#[doc(hidden)]
31#[macro_export]
32macro_rules! __gen_sync_exports {
33 ($rbt:ty) => {
34 pub static mut ROBOT: Option<$rbt> = None;
35
36 #[doc(hidden)]
37 #[no_mangle]
38 extern "C" fn opcontrol() {
39 <$rbt as $crate::SyncRobot>::opcontrol(unsafe {
40 ROBOT
41 .as_mut()
42 .expect("Expected initialize to run before opcontrol")
43 })
44 .unwrap();
45 }
46
47 #[doc(hidden)]
48 #[no_mangle]
49 extern "C" fn autonomous() {
50 <$rbt as $crate::SyncRobot>::auto(unsafe {
51 ROBOT
52 .as_mut()
53 .expect("Expected initialize to run before opcontrol")
54 })
55 .unwrap();
56 }
57
58 #[doc(hidden)]
59 #[no_mangle]
60 extern "C" fn disabled() {
61 <$rbt as $crate::SyncRobot>::disabled(unsafe {
62 ROBOT
63 .as_mut()
64 .expect("Expected initialize to run before opcontrol")
65 })
66 .unwrap();
67 }
68
69 #[doc(hidden)]
70 #[no_mangle]
71 extern "C" fn competition_initialize() {
72 <$rbt as $crate::SyncRobot>::comp_init(unsafe {
73 ROBOT
74 .as_mut()
75 .expect("Expected initialize to run before opcontrol")
76 })
77 .unwrap();
78 }
79 };
80}
81
82/// Allows your sync robot code to be executed by the pros kernel.
83/// If your robot struct implements Default then you can just supply this macro with its type.
84/// If not, you can supply an expression that returns your robot type to initialize your robot struct.
85/// The code that runs to create your robot struct will run in the initialize function in PROS.
86///
87/// Example of using the macro with a struct that implements Default:
88/// ```rust
89/// use pros::prelude::*;
90/// #[derive(Default)]
91/// struct ExampleRobot;
92/// impl SyncRobot for ExampleRobot {
93/// asnyc fn opcontrol(&mut self) -> pros::Result {
94/// println!("Hello, world!");
95/// Ok(())
96/// }
97/// }
98/// sync_robot!(ExampleRobot);
99/// ```
100///
101/// Example of using the macro with a struct that does not implement Default:
102/// ```rust
103/// use pros::prelude::*;
104/// struct ExampleRobot {
105/// x: i32,
106/// }
107/// impl SyncRobot for ExampleRobot {
108/// async fn opcontrol(&mut self) -> pros::Result {
109/// println!("Hello, world! {}", self.x);
110/// Ok(())
111/// }
112/// }
113/// impl ExampleRobot {
114/// pub fn new() -> Self {
115/// Self { x: 5 }
116/// }
117/// }
118/// sync_robot!(ExampleRobot, ExampleRobot::new());
119#[macro_export]
120macro_rules! sync_robot {
121 ($rbt:ty) => {
122 $crate::__gen_sync_exports!($rbt);
123
124 #[no_mangle]
125 extern "C" fn initialize() {
126 let robot = Default::default();
127 unsafe {
128 ROBOT = Some(robot);
129 }
130 }
131 };
132 ($rbt:ty, $init:expr) => {
133 $crate::__gen_sync_exports!($rbt);
134
135 #[no_mangle]
136 extern "C" fn initialize() {
137 let robot = $init;
138 unsafe {
139 ROBOT = Some(robot);
140 }
141 }
142 };
143}