components/
screen.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Components for the Screen.
6//!
7//! Buffer Size
8//! -----------
9//!
10//! Displays can receive a large amount of data and having larger transfer buffers
11//! optimizes the number of bus writes.
12//!
13//! As memory is limited on some MCUs, the `components::screen_buffer_size``
14//! macro allows users to define the size of the screen buffer.
15//!
16//! Usage
17//! -----
18//!
19//! // Screen
20//! ```rust
21//! let screen =
22//!     components::screen::ScreenComponent::new(board_kernel, tft, None)
23//!         .finalize(components::screen_component_static!(40960));
24//! ```
25//!
26//! // Screen with Setup
27//! ```rust
28//! let screen =
29//!     components::screen::ScreenComponent::new(board_kernel, tft, Some(tft))
30//!         .finalize(components::screen_component_static!(40960));
31//! ```
32
33use capsules_extra::screen::Screen;
34use capsules_extra::screen_shared::ScreenShared;
35use core::mem::MaybeUninit;
36use kernel::capabilities;
37use kernel::component::Component;
38use kernel::create_capability;
39use kernel::hil;
40
41#[macro_export]
42macro_rules! screen_component_static {
43    ($s:literal $(,)?) => {{
44        let buffer = kernel::static_buf!([u8; $s]);
45        let screen = kernel::static_buf!(capsules_extra::screen::Screen);
46
47        (buffer, screen)
48    };};
49}
50
51pub type ScreenComponentType = capsules_extra::screen::Screen<'static>;
52
53pub struct ScreenComponent<const SCREEN_BUF_LEN: usize> {
54    board_kernel: &'static kernel::Kernel,
55    driver_num: usize,
56    screen: &'static dyn kernel::hil::screen::Screen<'static>,
57    screen_setup: Option<&'static dyn kernel::hil::screen::ScreenSetup<'static>>,
58}
59
60impl<const SCREEN_BUF_LEN: usize> ScreenComponent<SCREEN_BUF_LEN> {
61    pub fn new(
62        board_kernel: &'static kernel::Kernel,
63        driver_num: usize,
64        screen: &'static dyn kernel::hil::screen::Screen,
65        screen_setup: Option<&'static dyn kernel::hil::screen::ScreenSetup>,
66    ) -> ScreenComponent<SCREEN_BUF_LEN> {
67        ScreenComponent {
68            board_kernel,
69            driver_num,
70            screen,
71            screen_setup,
72        }
73    }
74}
75
76impl<const SCREEN_BUF_LEN: usize> Component for ScreenComponent<SCREEN_BUF_LEN> {
77    type StaticInput = (
78        &'static mut MaybeUninit<[u8; SCREEN_BUF_LEN]>,
79        &'static mut MaybeUninit<Screen<'static>>,
80    );
81    type Output = &'static Screen<'static>;
82
83    fn finalize(self, static_input: Self::StaticInput) -> Self::Output {
84        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
85        let grant_screen = self.board_kernel.create_grant(self.driver_num, &grant_cap);
86
87        let buffer = static_input.0.write([0; SCREEN_BUF_LEN]);
88
89        let screen = static_input.1.write(Screen::new(
90            self.screen,
91            self.screen_setup,
92            buffer,
93            grant_screen,
94        ));
95
96        kernel::hil::screen::Screen::set_client(self.screen, screen);
97        if let Some(screen_setup) = self.screen_setup {
98            kernel::hil::screen::ScreenSetup::set_client(screen_setup, screen);
99        }
100
101        screen
102    }
103}
104
105#[macro_export]
106macro_rules! screen_shared_component_static {
107    ($s:literal, $S:ty $(,)?) => {{
108        let buffer = kernel::static_buf!([u8; $s]);
109        let screen = kernel::static_buf!(capsules_extra::screen_shared::ScreenShared<$S>);
110
111        (buffer, screen)
112    };};
113}
114
115pub type ScreenSharedComponentType<S> = capsules_extra::screen_shared::ScreenShared<'static, S>;
116
117pub struct ScreenSharedComponent<
118    const SCREEN_BUF_LEN: usize,
119    S: hil::screen::Screen<'static> + 'static,
120> {
121    board_kernel: &'static kernel::Kernel,
122    driver_num: usize,
123    screen: &'static S,
124    apps_regions: &'static [capsules_extra::screen_shared::AppScreenRegion],
125}
126
127impl<const SCREEN_BUF_LEN: usize, S: hil::screen::Screen<'static>>
128    ScreenSharedComponent<SCREEN_BUF_LEN, S>
129{
130    pub fn new(
131        board_kernel: &'static kernel::Kernel,
132        driver_num: usize,
133        screen: &'static S,
134        apps_regions: &'static [capsules_extra::screen_shared::AppScreenRegion],
135    ) -> ScreenSharedComponent<SCREEN_BUF_LEN, S> {
136        ScreenSharedComponent {
137            board_kernel,
138            driver_num,
139            screen,
140            apps_regions,
141        }
142    }
143}
144
145impl<const SCREEN_BUF_LEN: usize, S: hil::screen::Screen<'static>> Component
146    for ScreenSharedComponent<SCREEN_BUF_LEN, S>
147{
148    type StaticInput = (
149        &'static mut MaybeUninit<[u8; SCREEN_BUF_LEN]>,
150        &'static mut MaybeUninit<ScreenShared<'static, S>>,
151    );
152    type Output = &'static ScreenShared<'static, S>;
153
154    fn finalize(self, static_input: Self::StaticInput) -> Self::Output {
155        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
156        let grant_screen = self.board_kernel.create_grant(self.driver_num, &grant_cap);
157
158        let buffer = static_input.0.write([0; SCREEN_BUF_LEN]);
159
160        let screen = static_input.1.write(ScreenShared::new(
161            self.screen,
162            grant_screen,
163            buffer,
164            self.apps_regions,
165        ));
166
167        kernel::hil::screen::Screen::set_client(self.screen, screen);
168
169        screen
170    }
171}