components/
led_matrix.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 matrices of LEDs.
6//!
7//! Usage
8//! -----
9//! ```rust
10//! let led_matrix = components::led_matrix::LedMatrixComponent::new(
11//!     mux_alarm,
12//!     components::led_line_component_static!(
13//!         nrf52833::gpio::GPIOPin,
14//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[0]],
15//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[1]],
16//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[2]],
17//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[3]],
18//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[4]],
19//!     ),
20//!     components::led_line_component_static!(
21//!         nrf52833::gpio::GPIOPin,
22//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[0]],
23//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[1]],
24//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[2]],
25//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[3]],
26//!         &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[4]],
27//!     ),
28//!     kernel::hil::gpio::ActivationMode::ActiveLow,
29//!     kernel::hil::gpio::ActivationMode::ActiveHigh,
30//!     60,
31//! )
32//! .finalize(components::led_matrix_component_static!(
33//!     nrf52833::gpio::GPIOPin,
34//!     nrf52::rtc::Rtc<'static>,
35//!     5,
36//!     5
37//! ));
38//! ```
39//!
40//! Single LED usage
41//! ----------------
42//!
43//! ```rust
44//! let led = components::led_matrix_led!(
45//!     nrf52::gpio::GPIOPin<'static>,
46//!     capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
47//!     led,
48//!     1,
49//!     2
50//! );
51//! ```
52//!
53//! Array LED usage
54//! ----------------
55//!
56//! ```rust
57//! let leds = components::led_matrix_leds!(
58//!     nrf52::gpio::GPIOPin<'static>,
59//!     capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
60//!     led,
61//!     (0, 0),
62//!     (1, 0),
63//!     (2, 0),
64//!     (3, 0),
65//!     (4, 0),
66//!     (0, 1)
67//!     // ...
68//! );
69//! ```
70//!
71
72use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
73use capsules_extra::led_matrix::LedMatrixDriver;
74use core::mem::MaybeUninit;
75use kernel::component::Component;
76use kernel::hil::gpio::{ActivationMode, Pin};
77use kernel::hil::time::Alarm;
78
79#[macro_export]
80macro_rules! led_matrix_component_static {
81    ($Pin:ty, $A: ty, $num_cols: literal, $num_rows: literal $(,)?) => {{
82        let buffer = kernel::static_buf!([u8; $num_cols * $num_rows / 8 + 1]);
83        let alarm = kernel::static_buf!(
84            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
85        );
86        let led = kernel::static_buf!(
87            capsules_extra::led_matrix::LedMatrixDriver<
88                'static,
89                $Pin,
90                capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>,
91            >
92        );
93
94        (alarm, led, buffer)
95    };};
96}
97
98#[macro_export]
99macro_rules! led_line_component_static {
100    ($Pin:ty, $($L:expr),+ $(,)?) => {{
101        use kernel::count_expressions;
102        use kernel::static_init;
103        const NUM_LEDS: usize = count_expressions!($($L),+);
104
105        static_init!(
106            [&'static $Pin; NUM_LEDS],
107            [
108                $(
109                    static_init!(
110                        &'static $Pin,
111                        $L
112                    )
113                ),+
114            ]
115        )
116    };};
117}
118
119#[macro_export]
120macro_rules! led_matrix_led {
121    ($Pin:ty, $A: ty, $led_matrix: expr, $col: expr, $row: expr) => {{
122        use capsules_extra::led_matrix::LedMatrixLed;
123        static_init!(
124            LedMatrixLed<'static, $Pin, $A>,
125            LedMatrixLed::new($led_matrix, $col, $row)
126        )
127    };};
128}
129
130#[macro_export]
131macro_rules! led_matrix_leds {
132    ($Pin:ty, $A: ty, $led_matrix: expr, $(($col: expr, $row: expr)),+) => {{
133        use capsules_extra::led_matrix::LedMatrixLed;
134        use kernel::count_expressions;
135
136        const NUM_LEDS: usize = count_expressions!($(($col, $row)),+);
137        let leds = static_init!(
138            [&LedMatrixLed<'static, $Pin, $A>; NUM_LEDS],
139            [$(
140                $crate::led_matrix_led! ($Pin, $A, $led_matrix, $col, $row)
141            ),+]
142        );
143        leds
144    };};
145}
146
147pub struct LedMatrixComponent<
148    L: 'static + Pin,
149    A: 'static + Alarm<'static>,
150    const NUM_COLS: usize,
151    const NUM_ROWS: usize,
152    const NUM_LED_BITS: usize,
153> {
154    alarm_mux: &'static MuxAlarm<'static, A>,
155    col: &'static [&'static L; NUM_COLS],
156    row: &'static [&'static L; NUM_ROWS],
157    col_active: ActivationMode,
158    row_active: ActivationMode,
159    refresh_rate: usize,
160}
161
162impl<
163        L: 'static + Pin,
164        A: 'static + Alarm<'static>,
165        const NUM_COLS: usize,
166        const NUM_ROWS: usize,
167        const NUM_LED_BITS: usize,
168    > LedMatrixComponent<L, A, NUM_COLS, NUM_ROWS, NUM_LED_BITS>
169{
170    pub fn new(
171        alarm_mux: &'static MuxAlarm<'static, A>,
172        col: &'static [&'static L; NUM_COLS],
173        row: &'static [&'static L; NUM_ROWS],
174        col_active: ActivationMode,
175        row_active: ActivationMode,
176        refresh_rate: usize,
177    ) -> Self {
178        Self {
179            alarm_mux,
180            col,
181            row,
182            col_active,
183            row_active,
184            refresh_rate,
185        }
186    }
187}
188
189impl<
190        L: 'static + Pin,
191        A: 'static + Alarm<'static>,
192        const NUM_COLS: usize,
193        const NUM_ROWS: usize,
194        const NUM_LED_BITS: usize,
195    > Component for LedMatrixComponent<L, A, NUM_COLS, NUM_ROWS, NUM_LED_BITS>
196{
197    type StaticInput = (
198        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
199        &'static mut MaybeUninit<LedMatrixDriver<'static, L, VirtualMuxAlarm<'static, A>>>,
200        &'static mut MaybeUninit<[u8; NUM_LED_BITS]>,
201    );
202    type Output = &'static LedMatrixDriver<'static, L, VirtualMuxAlarm<'static, A>>;
203
204    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
205        let led_alarm = static_buffer.0.write(VirtualMuxAlarm::new(self.alarm_mux));
206        led_alarm.setup();
207
208        let buffer = static_buffer.2.write([0; NUM_LED_BITS]);
209
210        let led_matrix = static_buffer.1.write(LedMatrixDriver::new(
211            self.col,
212            self.row,
213            buffer,
214            led_alarm,
215            self.col_active,
216            self.row_active,
217            self.refresh_rate,
218        ));
219
220        led_alarm.set_alarm_client(led_matrix);
221
222        led_matrix.init();
223
224        led_matrix
225    }
226}