RKTK API Docs RKTK Home Repo

rktk/task/
mod.rs

1//! Program entrypoint.
2
3use crate::{
4    config::Hand,
5    drivers::interface::{
6        debounce::DebounceDriver, display::DisplayDriver, encoder::EncoderDriver,
7        keyscan::KeyscanDriver, mouse::MouseDriver, rgb::RgbDriver, split::SplitDriver,
8        storage::StorageDriver, usb::UsbReporterDriverBuilder,
9        wireless::WirelessReporterDriverBuilder,
10    },
11    hooks::{AllHooks, Hooks},
12};
13use crate::{
14    drivers::{Drivers, interface::system::SystemDriver},
15    hooks::interface::*,
16    utils::sjoin,
17};
18use display::DisplayConfig;
19use embassy_futures::join::{join, join5};
20use embassy_time::Duration;
21use rktk_log::{debug, info};
22
23pub(crate) mod channels;
24// `display` module is public as internally used by macros
25pub mod display;
26mod initializers;
27#[cfg(feature = "rrp-log")]
28mod logger;
29mod master;
30mod rgb;
31mod slave;
32mod split_handler;
33
34/// Runs rktk with the given drivers and key configuration.
35///
36/// # Parameters
37/// - `drivers`: Drivers for the keyboard.
38/// - `hooks`: Hooks for the keyboard. See [`Hooks`] for detail.
39/// - `opts`: Other options such as keymap. See [`crate::config`] for detail.
40#[allow(clippy::type_complexity)]
41pub async fn start<
42    System: SystemDriver,
43    KeyScan: KeyscanDriver,
44    Debounce: DebounceDriver,
45    Encoder: EncoderDriver,
46    Rgb: RgbDriver,
47    Storage: StorageDriver,
48    Split: SplitDriver,
49    Ble: WirelessReporterDriverBuilder,
50    Usb: UsbReporterDriverBuilder,
51    Display: DisplayDriver,
52    Mouse: MouseDriver,
53    H: AllHooks,
54    DC: DisplayConfig + 'static,
55    RL: blinksy::layout::Layout2d + 'static,
56>(
57    #[allow(
58        unused_variables,
59        reason = "`spawner` is unused when `alloc` is disabled"
60    )]
61    spawner: embassy_executor::Spawner,
62    mut drivers: Drivers<
63        System,
64        KeyScan,
65        Debounce,
66        Encoder,
67        Rgb,
68        Storage,
69        Split,
70        Ble,
71        Usb,
72        Display,
73        Mouse,
74    >,
75    hooks: H,
76    mut opts: crate::config::RktkOpts<DC, RL>,
77) {
78    #[cfg(feature = "rrp-log")]
79    {
80        debug!("log init");
81        critical_section::with(|_| unsafe {
82            let _ = log::set_logger_racy(&logger::RRP_LOGGER);
83            log::set_max_level_racy(log::LevelFilter::Info);
84        });
85    }
86
87    info!("Booting rktk",);
88
89    drivers
90        .system
91        .double_reset_usb_boot(Duration::from_millis(opts.config.rktk.split_usb_timeout))
92        .await;
93
94    let mut hooks = hooks.destructure();
95
96    sjoin::join!(
97        spawner,
98        async {
99            initializers::init_mouse(&mut drivers.mouse, opts.config).await;
100            let ((wireless, wireless_task), (usb, usb_task)) =
101                initializers::init_reporters(drivers.ble_builder, drivers.usb_builder).await;
102
103            sjoin::join!(
104                spawner,
105                async {
106                    let hand = opts.hand.unwrap_or(Hand::Left);
107                    crate::utils::display_state!(Hand, Some(hand));
108
109                    let role =
110                        initializers::init_split(opts.config, drivers.split, &usb, &wireless).await;
111
112                    hooks
113                        .common
114                        .on_init(
115                            hand,
116                            &mut drivers.keyscan,
117                            drivers.mouse.as_mut(),
118                            drivers.storage.as_mut(),
119                        )
120                        .await;
121
122                    crate::utils::display_state!(Master, Some(role.is_master()));
123
124                    match role {
125                        initializers::KeyboardRoleRes::Master {
126                            sender,
127                            receiver,
128                            task,
129                        } => {
130                            info!("Master start");
131                            sjoin::join!(
132                                spawner,
133                                async {
134                                    let config_store =
135                                        master::utils::init_storage(drivers.storage).await;
136                                    let state = master::utils::load_state(
137                                        &opts.config.key_manager,
138                                        &config_store,
139                                        opts.keymap,
140                                    )
141                                    .await;
142
143                                    hooks
144                                        .master
145                                        .on_master_init(
146                                            &mut drivers.keyscan,
147                                            drivers.mouse.as_mut(),
148                                        )
149                                        .await;
150
151                                    join(
152                                        join5(
153                                            master::report::report_task(
154                                                opts.config,
155                                                &drivers.system,
156                                                &state,
157                                                &config_store,
158                                                &wireless,
159                                                &usb,
160                                                hooks.master,
161                                            ),
162                                            master::handle_slave::start(
163                                                opts.config,
164                                                hand,
165                                                receiver,
166                                            ),
167                                            master::handle_keyboard::start(
168                                                opts.config,
169                                                hand,
170                                                drivers.keyscan,
171                                                &mut drivers.debounce,
172                                            ),
173                                            master::handle_mouse::start(opts.config, drivers.mouse),
174                                            master::handle_encoder::start(&mut drivers.encoder),
175                                        ),
176                                        async {
177                                            #[cfg(feature = "rrp")]
178                                            master::rrp_server::start(
179                                                opts.config,
180                                                &usb,
181                                                &wireless,
182                                                &state,
183                                                &config_store,
184                                            )
185                                            .await;
186                                        },
187                                    )
188                                    .await;
189                                },
190                                rgb::start::<RL, _>(
191                                    opts.config,
192                                    drivers.rgb,
193                                    hooks.rgb,
194                                    Some(sender)
195                                ),
196                                async move {
197                                    if let Some(task) = task {
198                                        task.await;
199                                    }
200                                }
201                            );
202                        }
203                        initializers::KeyboardRoleRes::Slave {
204                            sender,
205                            receiver,
206                            task,
207                        } => {
208                            debug!("Slave start");
209                            sjoin::join!(
210                                spawner,
211                                async move {
212                                    slave::start(
213                                        opts.config,
214                                        sender,
215                                        receiver,
216                                        drivers.keyscan,
217                                        &mut drivers.debounce,
218                                        drivers.mouse,
219                                        hooks.slave,
220                                    )
221                                    .await
222                                },
223                                rgb::start::<RL, _>(opts.config, drivers.rgb, hooks.rgb, None),
224                                async move {
225                                    if let Some(task) = task {
226                                        task.await;
227                                    }
228                                }
229                            );
230                        }
231                    }
232                },
233                async {
234                    if let Some(usb_task) = usb_task {
235                        usb_task.await
236                    }
237                },
238                async {
239                    if let Some(wireless_task) = wireless_task {
240                        wireless_task.await
241                    }
242                }
243            );
244        },
245        async move {
246            if let Some(mut display) = drivers.display {
247                display::start(&mut display, &mut opts.display).await;
248            }
249        }
250    );
251}