components/
lpm013m126.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//! Component for the Japan Display LPM013M126 display.
6//!
7//! Usage
8//! -----
9//!
10//! ```rust
11//! // Optional
12//! let spi_device = static_init!(
13//!     VirtualSpiMasterDevice<'static, nrf52840::spi::SPIM>,
14//!     VirtualSpiMasterDevice::new(
15//!         mux_spi,
16//!         &nrf52840_peripherals.gpio_port[Pin::P0_05], // CS pin
17//!     ),
18//! );
19//! let display
20//!     = components::lpm013m126::Lpm013m126Component::new(
21//!         disp_pin,
22//!         extcomin_pin,
23//!         alarm_mux,
24//!     )
25//!     .finalize(
26//!         components::lpm013m126_component_static!(
27//!             nrf52840::rtc::Rtc<'static>,
28//!             nrf52840::gpio::GPIOPin,
29//!             VirtualSpiMasterDevice<'static, nrf52840::spi::SPIM>,
30//!             spi_mux,
31//!             cs_pin,
32//!         )
33//!     );
34//! display.initialize().unwrap();
35//! // wait for `ScreenClient::screen_is_ready` callback
36//! ```
37
38use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
39use capsules_core::virtualizers::virtual_spi::{MuxSpiMaster, VirtualSpiMasterDevice};
40use capsules_extra::lpm013m126::Lpm013m126;
41use core::mem::MaybeUninit;
42use kernel::component::Component;
43use kernel::hil::spi::{SpiMaster, SpiMasterDevice};
44use kernel::hil::time::Alarm;
45use kernel::hil::{self, gpio};
46
47/// Setup static space for the driver and its requirements.
48#[macro_export]
49macro_rules! lpm013m126_component_static {
50    ($A:ty, $P:ty, $S:ty $(,)?) => {{
51        let alarm = kernel::static_buf!(
52            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
53        );
54        let buffer = kernel::static_buf!([u8; capsules_extra::lpm013m126::BUF_LEN]);
55        let spi_device = kernel::static_buf!(
56            capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>
57        );
58        let lpm013m126 = kernel::static_buf!(
59            capsules_extra::lpm013m126::Lpm013m126<
60                'static,
61                VirtualMuxAlarm<'static, $A>,
62                $P,
63                VirtualSpiMasterDevice<'static, $S>,
64            >
65        );
66
67        (alarm, buffer, spi_device, lpm013m126)
68    }};
69}
70
71pub struct Lpm013m126Component<A, P, S>
72where
73    A: 'static + Alarm<'static>,
74    P: 'static + gpio::Pin,
75    S: 'static + SpiMaster<'static>,
76{
77    spi: &'static MuxSpiMaster<'static, S>,
78    chip_select: S::ChipSelect,
79    disp: &'static P,
80    extcomin: &'static P,
81    alarm_mux: &'static MuxAlarm<'static, A>,
82}
83
84impl<A, P, S> Lpm013m126Component<A, P, S>
85where
86    A: 'static + Alarm<'static>,
87    P: 'static + gpio::Pin,
88    S: 'static + SpiMaster<'static>,
89{
90    pub fn new<I: kernel::hil::spi::cs::IntoChipSelect<S::ChipSelect, hil::spi::cs::ActiveHigh>>(
91        spi: &'static MuxSpiMaster<'static, S>,
92
93        chip_select: I,
94        disp: &'static P,
95        extcomin: &'static P,
96        alarm_mux: &'static MuxAlarm<'static, A>,
97    ) -> Self {
98        Self {
99            spi,
100            chip_select: chip_select.into_cs(),
101            disp,
102            extcomin,
103            alarm_mux,
104        }
105    }
106}
107
108impl<A, P, S> Component for Lpm013m126Component<A, P, S>
109where
110    A: 'static + Alarm<'static>,
111    P: 'static + gpio::Pin,
112    S: 'static + SpiMaster<'static>,
113{
114    type StaticInput = (
115        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
116        &'static mut MaybeUninit<[u8; capsules_extra::lpm013m126::BUF_LEN]>,
117        &'static mut MaybeUninit<VirtualSpiMasterDevice<'static, S>>,
118        &'static mut MaybeUninit<
119            Lpm013m126<'static, VirtualMuxAlarm<'static, A>, P, VirtualSpiMasterDevice<'static, S>>,
120        >,
121    );
122    type Output = &'static Lpm013m126<
123        'static,
124        VirtualMuxAlarm<'static, A>,
125        P,
126        VirtualSpiMasterDevice<'static, S>,
127    >;
128
129    fn finalize(self, s: Self::StaticInput) -> Self::Output {
130        let lpm013m126_alarm = s.0.write(VirtualMuxAlarm::new(self.alarm_mux));
131        lpm013m126_alarm.setup();
132
133        let buffer = s.1.write([0; capsules_extra::lpm013m126::BUF_LEN]);
134
135        let spi_device =
136            s.2.write(VirtualSpiMasterDevice::new(self.spi, self.chip_select));
137        spi_device.setup();
138
139        let lpm013m126 = s.3.write(
140            Lpm013m126::new(
141                spi_device,
142                self.extcomin,
143                self.disp,
144                lpm013m126_alarm,
145                buffer,
146            )
147            .unwrap(),
148        );
149        spi_device.set_client(lpm013m126);
150        lpm013m126_alarm.set_alarm_client(lpm013m126);
151        // Because this capsule uses multiple deferred calls internally, this
152        // takes care of registering the deferred calls as well. Thus there is
153        // no need to explicitly call
154        // `kernel::deferred_call::DeferredCallClient::register`.
155        lpm013m126.setup().unwrap();
156        lpm013m126
157    }
158}