Skip to main content
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,
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<Color = Display::Color> + 'static,
55    RL: blinksy::layout::Layout2d + 'static,
56>(
57    #[allow(unused_variables, reason = "`spawner` is unused when `alloc` is disabled")]
58    spawner: embassy_executor::Spawner,
59    mut drivers: Drivers<
60        System,
61        KeyScan,
62        Debounce,
63        Encoder,
64        Rgb,
65        Storage,
66        Split,
67        Ble,
68        Usb,
69        Display,
70        Mouse,
71    >,
72    hooks: H,
73    mut opts: crate::config::RktkOpts<DC, RL>,
74) {
75    #[cfg(feature = "rrp-log")]
76    {
77        debug!("log init");
78        critical_section::with(|_| unsafe {
79            let _ = log::set_logger_racy(&logger::RRP_LOGGER);
80            log::set_max_level_racy(log::LevelFilter::Info);
81        });
82    }
83
84    info!("Booting rktk");
85
86    drivers
87        .system
88        .double_reset_usb_boot(Duration::from_millis(opts.config.rktk.double_tap_threshold))
89        .await;
90
91    let mut hooks = hooks.destructure();
92
93    sjoin::join!(
94        spawner,
95        async {
96            initializers::init_mouse(&mut drivers.mouse, opts.config).await;
97            let ((wireless, wireless_task), (usb, usb_task)) =
98                initializers::init_reporters(drivers.ble_builder, drivers.usb_builder).await;
99
100            sjoin::join!(
101                spawner,
102                async {
103                    let hand = opts.hand.unwrap_or(Hand::Left);
104                    crate::utils::display_state!(Hand, Some(hand));
105
106                    let role =
107                        initializers::init_split(opts.config, drivers.split, &usb, &wireless).await;
108
109                    hooks
110                        .common
111                        .on_init(
112                            hand,
113                            &mut drivers.keyscan,
114                            drivers.mouse.as_mut(),
115                            drivers.storage.as_mut(),
116                        )
117                        .await;
118
119                    crate::utils::display_state!(Master, Some(role.is_master()));
120
121                    match role {
122                        initializers::KeyboardRoleRes::Master { sender, receiver, task } => {
123                            info!("Master start");
124                            sjoin::join!(
125                                spawner,
126                                async {
127                                    let config_store =
128                                        master::utils::init_storage(drivers.storage).await;
129
130                                    if KeyScan::CALIBRATION_SIZE > 0
131                                        && let Some(ref store) = config_store
132                                    {
133                                        let mut buf =
134                                            [0u8; crate::config::CONST_CONFIG.buffer.calibration];
135                                        if let Ok(()) = store.read_calibration::<{ crate::config::CONST_CONFIG.buffer.calibration }>(&mut buf).await {
136                                                if drivers.keyscan.load_calibration(&buf[..KeyScan::CALIBRATION_SIZE]).is_err() {
137                                                    rktk_log::error!("Failed to load calibration data into keyscan driver");
138                                                } else {
139                                                    rktk_log::info!("Calibration data loaded successfully");
140                                                }
141                                            }
142                                    }
143
144                                    let state = master::utils::load_state(
145                                        &opts.config.key_manager,
146                                        &config_store,
147                                        opts.keymap,
148                                    )
149                                    .await;
150
151                                    hooks
152                                        .master
153                                        .on_master_init(
154                                            &mut drivers.keyscan,
155                                            drivers.mouse.as_mut(),
156                                        )
157                                        .await;
158
159                                    join(
160                                        join5(
161                                            master::report::report_task(
162                                                opts.config,
163                                                &drivers.system,
164                                                &state,
165                                                &config_store,
166                                                &wireless,
167                                                &usb,
168                                                hooks.master,
169                                            ),
170                                            master::handle_slave::start(
171                                                opts.config,
172                                                hand,
173                                                receiver,
174                                            ),
175                                            master::handle_keyboard::start(
176                                                opts.config,
177                                                hand,
178                                                drivers.keyscan,
179                                                &mut drivers.debounce,
180                                                &config_store,
181                                            ),
182                                            master::handle_mouse::start(opts.config, drivers.mouse),
183                                            master::handle_encoder::start(&mut drivers.encoder),
184                                        ),
185                                        async {
186                                            #[cfg(feature = "rrp")]
187                                            master::rrp_server::start(
188                                                opts.config,
189                                                &usb,
190                                                &wireless,
191                                                &state,
192                                                &config_store,
193                                            )
194                                            .await;
195                                        },
196                                    )
197                                    .await;
198                                },
199                                rgb::start::<RL, _>(
200                                    opts.config,
201                                    drivers.rgb,
202                                    hooks.rgb,
203                                    Some(sender)
204                                ),
205                                async move {
206                                    if let Some(task) = task {
207                                        task.await;
208                                    }
209                                }
210                            );
211                        }
212                        initializers::KeyboardRoleRes::Slave { sender, receiver, task } => {
213                            debug!("Slave start");
214                            sjoin::join!(
215                                spawner,
216                                async move {
217                                    slave::start(
218                                        opts.config,
219                                        sender,
220                                        receiver,
221                                        drivers.keyscan,
222                                        &mut drivers.debounce,
223                                        drivers.mouse,
224                                        hooks.slave,
225                                    )
226                                    .await
227                                },
228                                rgb::start::<RL, _>(opts.config, drivers.rgb, hooks.rgb, None),
229                                async move {
230                                    if let Some(task) = task {
231                                        task.await;
232                                    }
233                                }
234                            );
235                        }
236                    }
237                },
238                async {
239                    if let Some(usb_task) = usb_task {
240                        usb_task.await
241                    }
242                },
243                async {
244                    if let Some(wireless_task) = wireless_task {
245                        wireless_task.await
246                    }
247                }
248            );
249        },
250        async move {
251            if let Some(mut display) = drivers.display {
252                display::start(&mut display, &mut opts.display).await;
253            }
254        }
255    );
256}