components/
st77xx.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 ST77XX screen.
6//!
7//! Usage
8//! -----
9//! ```rust
10//!
11//! let bus = components::bus::SpiMasterBusComponent::new().finalize(
12//!     components::spi_bus_component_static!(
13//!         // spi type
14//!         nrf52840::spi::SPIM,
15//!         // chip select
16//!         &nrf52840::gpio::PORT[GPIO_D4],
17//!         // spi mux
18//!         spi_mux
19//!     ),
20//! );
21//!
22//! let tft = components::st77xx::ST77XXComponent::new(mux_alarm,
23//!                                                    bus,
24//!                                                    Some(&nrf52840::gpio::PORT[GPIO_D3]),
25//!                                                    Some(&nrf52840::gpio::PORT[GPIO_D2]),
26//!                                                    &capsules_extra::st77xx::ST7735).finalize(
27//!     components::st77xx_component_static!(
28//!         // bus type
29//!         capsules_extra::bus::SpiMasterBus<
30//!             'static,
31//!             VirtualSpiMasterDevice<'static, nrf52840::spi::SPIM>,
32//!         >,
33//!         // timer type
34//!         nrf52840::rtc::Rtc,
35//!         // pin type
36//!         nrf52::gpio::GPIOPin<'static>,
37//!     ),
38//! );
39//! ```
40
41use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
42use capsules_extra::bus::{self, BusAddr8};
43use capsules_extra::st77xx::{ST77XXScreen, ST77XX};
44use core::mem::MaybeUninit;
45use kernel::component::Component;
46use kernel::hil::gpio;
47use kernel::hil::time::{self, Alarm};
48
49// Setup static space for the objects.
50#[macro_export]
51macro_rules! st77xx_component_static {
52    ($B: ty, $A:ty, $P:ty $(,)?) => {{
53        let buffer = kernel::static_buf!([u8; capsules_extra::st77xx::BUFFER_SIZE]);
54        let sequence_buffer = kernel::static_buf!(
55            [capsules_extra::st77xx::SendCommand; capsules_extra::st77xx::SEQUENCE_BUFFER_SIZE]
56        );
57        let st77xx_alarm = kernel::static_buf!(
58            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
59        );
60        let st77xx = kernel::static_buf!(
61            capsules_extra::st77xx::ST77XX<
62                'static,
63                capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>,
64                $B,
65                $P,
66            >
67        );
68
69        (st77xx_alarm, st77xx, buffer, sequence_buffer)
70    };};
71}
72
73pub struct ST77XXComponent<
74    A: 'static + time::Alarm<'static>,
75    B: 'static + bus::Bus<'static, BusAddr8>,
76    P: 'static + gpio::Pin,
77> {
78    alarm_mux: &'static MuxAlarm<'static, A>,
79    bus: &'static B,
80    dc: Option<&'static P>,
81    reset: Option<&'static P>,
82    screen: &'static ST77XXScreen,
83}
84
85impl<
86        A: 'static + time::Alarm<'static>,
87        B: 'static + bus::Bus<'static, BusAddr8>,
88        P: 'static + gpio::Pin,
89    > ST77XXComponent<A, B, P>
90{
91    pub fn new(
92        alarm_mux: &'static MuxAlarm<'static, A>,
93        bus: &'static B,
94        dc: Option<&'static P>,
95        reset: Option<&'static P>,
96        screen: &'static ST77XXScreen,
97    ) -> ST77XXComponent<A, B, P> {
98        ST77XXComponent {
99            alarm_mux,
100            bus,
101            dc,
102            reset,
103            screen,
104        }
105    }
106}
107
108impl<
109        A: 'static + time::Alarm<'static>,
110        B: 'static + bus::Bus<'static, BusAddr8>,
111        P: 'static + gpio::Pin,
112    > Component for ST77XXComponent<A, B, P>
113{
114    type StaticInput = (
115        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
116        &'static mut MaybeUninit<ST77XX<'static, VirtualMuxAlarm<'static, A>, B, P>>,
117        &'static mut MaybeUninit<[u8; capsules_extra::st77xx::BUFFER_SIZE]>,
118        &'static mut MaybeUninit<
119            [capsules_extra::st77xx::SendCommand; capsules_extra::st77xx::SEQUENCE_BUFFER_SIZE],
120        >,
121    );
122    type Output = &'static ST77XX<'static, VirtualMuxAlarm<'static, A>, B, P>;
123
124    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
125        let st77xx_alarm = static_buffer.0.write(VirtualMuxAlarm::new(self.alarm_mux));
126        st77xx_alarm.setup();
127
128        let buffer = static_buffer
129            .2
130            .write([0; capsules_extra::st77xx::BUFFER_SIZE]);
131        let sequence_buffer = static_buffer.3.write(
132            [capsules_extra::st77xx::SendCommand::Nop;
133                capsules_extra::st77xx::SEQUENCE_BUFFER_SIZE],
134        );
135
136        let st77xx = static_buffer.1.write(ST77XX::new(
137            self.bus,
138            st77xx_alarm,
139            self.dc,
140            self.reset,
141            buffer,
142            sequence_buffer,
143            self.screen,
144        ));
145        self.bus.set_client(st77xx);
146        st77xx_alarm.set_alarm_client(st77xx);
147
148        st77xx
149    }
150}