components/
lpm013m126.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Component for the Japan Display LPM013M126 display.
//!
//! Usage
//! -----
//!
//! ```rust
//! // Optional
//! let spi_device = static_init!(
//!     VirtualSpiMasterDevice<'static, nrf52840::spi::SPIM>,
//!     VirtualSpiMasterDevice::new(
//!         mux_spi,
//!         &nrf52840_peripherals.gpio_port[Pin::P0_05], // CS pin
//!     ),
//! );
//! let display
//!     = components::lpm013m126::Lpm013m126Component::new(
//!         disp_pin,
//!         extcomin_pin,
//!         alarm_mux,
//!     )
//!     .finalize(
//!         components::lpm013m126_component_static!(
//!             nrf52840::rtc::Rtc<'static>,
//!             nrf52840::gpio::GPIOPin,
//!             VirtualSpiMasterDevice<'static, nrf52840::spi::SPIM>,
//!             spi_mux,
//!             cs_pin,
//!         )
//!     );
//! display.initialize().unwrap();
//! // wait for `ScreenClient::screen_is_ready` callback
//! ```

use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use capsules_core::virtualizers::virtual_spi::{MuxSpiMaster, VirtualSpiMasterDevice};
use capsules_extra::lpm013m126::Lpm013m126;
use core::mem::MaybeUninit;
use kernel::component::Component;
use kernel::hil::spi::{SpiMaster, SpiMasterDevice};
use kernel::hil::time::Alarm;
use kernel::hil::{self, gpio};

/// Setup static space for the driver and its requirements.
#[macro_export]
macro_rules! lpm013m126_component_static {
    ($A:ty, $P:ty, $S:ty $(,)?) => {{
        let alarm = kernel::static_buf!(
            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
        );
        let buffer = kernel::static_buf!([u8; capsules_extra::lpm013m126::BUF_LEN]);
        let spi_device = kernel::static_buf!(
            capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>
        );
        let lpm013m126 = kernel::static_buf!(
            capsules_extra::lpm013m126::Lpm013m126<
                'static,
                VirtualMuxAlarm<'static, $A>,
                $P,
                VirtualSpiMasterDevice<'static, $S>,
            >
        );

        (alarm, buffer, spi_device, lpm013m126)
    }};
}

pub struct Lpm013m126Component<A, P, S>
where
    A: 'static + Alarm<'static>,
    P: 'static + gpio::Pin,
    S: 'static + SpiMaster<'static>,
{
    spi: &'static MuxSpiMaster<'static, S>,
    chip_select: S::ChipSelect,
    disp: &'static P,
    extcomin: &'static P,
    alarm_mux: &'static MuxAlarm<'static, A>,
}

impl<A, P, S> Lpm013m126Component<A, P, S>
where
    A: 'static + Alarm<'static>,
    P: 'static + gpio::Pin,
    S: 'static + SpiMaster<'static>,
{
    pub fn new<I: kernel::hil::spi::cs::IntoChipSelect<S::ChipSelect, hil::spi::cs::ActiveHigh>>(
        spi: &'static MuxSpiMaster<'static, S>,

        chip_select: I,
        disp: &'static P,
        extcomin: &'static P,
        alarm_mux: &'static MuxAlarm<'static, A>,
    ) -> Self {
        Self {
            spi,
            chip_select: chip_select.into_cs(),
            disp,
            extcomin,
            alarm_mux,
        }
    }
}

impl<A, P, S> Component for Lpm013m126Component<A, P, S>
where
    A: 'static + Alarm<'static>,
    P: 'static + gpio::Pin,
    S: 'static + SpiMaster<'static>,
{
    type StaticInput = (
        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
        &'static mut MaybeUninit<[u8; capsules_extra::lpm013m126::BUF_LEN]>,
        &'static mut MaybeUninit<VirtualSpiMasterDevice<'static, S>>,
        &'static mut MaybeUninit<
            Lpm013m126<'static, VirtualMuxAlarm<'static, A>, P, VirtualSpiMasterDevice<'static, S>>,
        >,
    );
    type Output = &'static Lpm013m126<
        'static,
        VirtualMuxAlarm<'static, A>,
        P,
        VirtualSpiMasterDevice<'static, S>,
    >;

    fn finalize(self, s: Self::StaticInput) -> Self::Output {
        let lpm013m126_alarm = s.0.write(VirtualMuxAlarm::new(self.alarm_mux));
        lpm013m126_alarm.setup();

        let buffer = s.1.write([0; capsules_extra::lpm013m126::BUF_LEN]);

        let spi_device =
            s.2.write(VirtualSpiMasterDevice::new(self.spi, self.chip_select));
        spi_device.setup();

        let lpm013m126 = s.3.write(
            Lpm013m126::new(
                spi_device,
                self.extcomin,
                self.disp,
                lpm013m126_alarm,
                buffer,
            )
            .unwrap(),
        );
        spi_device.set_client(lpm013m126);
        lpm013m126_alarm.set_alarm_client(lpm013m126);
        // Because this capsule uses multiple deferred calls internally, this
        // takes care of registering the deferred calls as well. Thus there is
        // no need to explicitly call
        // `kernel::deferred_call::DeferredCallClient::register`.
        lpm013m126.setup().unwrap();
        lpm013m126
    }
}