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::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    //
54    CH: CommonHooks,
55    MH: MasterHooks,
56    SH: SlaveHooks,
57    BH: RgbHooks,
58    //
59    DC: DisplayConfig + 'static,
60    RL: blinksy::layout::Layout2d + 'static,
61>(
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    mut hooks: Hooks<CH, MH, SH, BH>,
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    sjoin::join!(
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                async {
102                    let hand = opts.hand.unwrap_or(Hand::Left);
103                    crate::utils::display_state!(Hand, Some(hand));
104
105                    let role =
106                        initializers::init_split(opts.config, drivers.split, &usb, &wireless).await;
107
108                    hooks
109                        .common
110                        .on_init(
111                            hand,
112                            &mut drivers.keyscan,
113                            drivers.mouse.as_mut(),
114                            drivers.storage.as_mut(),
115                        )
116                        .await;
117
118                    crate::utils::display_state!(Master, Some(role.is_master()));
119
120                    match role {
121                        initializers::KeyboardRoleRes::Master {
122                            sender,
123                            receiver,
124                            task,
125                        } => {
126                            info!("Master start");
127                            sjoin::join!(
128                                async {
129                                    let config_store =
130                                        master::utils::init_storage(drivers.storage).await;
131                                    let state = master::utils::load_state(
132                                        &opts.config.key_manager,
133                                        &config_store,
134                                        opts.keymap,
135                                    )
136                                    .await;
137
138                                    hooks
139                                        .master
140                                        .on_master_init(
141                                            &mut drivers.keyscan,
142                                            drivers.mouse.as_mut(),
143                                        )
144                                        .await;
145
146                                    join(
147                                        join5(
148                                            master::report::report_task(
149                                                opts.config,
150                                                &drivers.system,
151                                                &state,
152                                                &config_store,
153                                                &wireless,
154                                                &usb,
155                                                hooks.master,
156                                            ),
157                                            master::handle_slave::start(
158                                                opts.config,
159                                                hand,
160                                                receiver,
161                                            ),
162                                            master::handle_keyboard::start(
163                                                opts.config,
164                                                hand,
165                                                drivers.keyscan,
166                                                &mut drivers.debounce,
167                                            ),
168                                            master::handle_mouse::start(opts.config, drivers.mouse),
169                                            master::handle_encoder::start(&mut drivers.encoder),
170                                        ),
171                                        async {
172                                            #[cfg(feature = "rrp")]
173                                            master::rrp_server::start(
174                                                opts.config,
175                                                &usb,
176                                                &wireless,
177                                                &state,
178                                                &config_store,
179                                            )
180                                            .await;
181                                        },
182                                    )
183                                    .await;
184                                },
185                                rgb::start::<RL, _>(
186                                    opts.config,
187                                    drivers.rgb,
188                                    hooks.rgb,
189                                    Some(sender)
190                                ),
191                                async move {
192                                    if let Some(task) = task {
193                                        task.await;
194                                    }
195                                }
196                            );
197                        }
198                        initializers::KeyboardRoleRes::Slave {
199                            sender,
200                            receiver,
201                            task,
202                        } => {
203                            debug!("Slave start");
204                            sjoin::join!(
205                                async move {
206                                    slave::start(
207                                        opts.config,
208                                        sender,
209                                        receiver,
210                                        drivers.keyscan,
211                                        &mut drivers.debounce,
212                                        drivers.mouse,
213                                        hooks.slave,
214                                    )
215                                    .await
216                                },
217                                rgb::start::<RL, _>(opts.config, drivers.rgb, hooks.rgb, None),
218                                async move {
219                                    if let Some(task) = task {
220                                        task.await;
221                                    }
222                                }
223                            );
224                        }
225                    }
226                },
227                async {
228                    if let Some(usb_task) = usb_task {
229                        usb_task.await
230                    }
231                },
232                async {
233                    if let Some(wireless_task) = wireless_task {
234                        wireless_task.await
235                    }
236                }
237            );
238        },
239        async move {
240            if let Some(mut display) = drivers.display {
241                display::start(&mut display, &mut opts.display).await;
242            }
243        }
244    );
245}