Skip to content

Commit d88279d

Browse files
committed
Document the lcd module
1 parent 3f2f7e6 commit d88279d

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

src/lcd/color.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1+
/// Represents a color with alpha, red, green, and blue channels.
12
#[derive(Debug, Clone, Copy)]
23
pub struct Color {
4+
/// The red channel.
35
pub red: u8,
6+
/// The green channel.
47
pub green: u8,
8+
/// The blue channel.
59
pub blue: u8,
10+
/// The alpha channel (0 is transparent, 255 is opaque).
611
pub alpha: u8,
712
}
813

914
impl Color {
15+
/// Creates a color from the passed RGB values. The alpha channel is set to 255 (opaque).
1016
pub fn rgb(red: u8, green: u8, blue: u8) -> Color {
1117
Self::rgba(red, green, blue, 255)
1218
}
1319

20+
/// Converts the color to RGB. The alpha channel is ignored.
1421
pub fn to_rgb(&self) -> u32 {
1522
(u32::from(self.red) << 16) | (u32::from(self.green) << 8) | u32::from(self.blue)
1623
}
1724

25+
/// Creates a color from the passed values.
1826
pub fn rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Color {
1927
Color {
2028
red: red,
@@ -24,6 +32,7 @@ impl Color {
2432
}
2533
}
2634

35+
/// Creates a color from the passed hex RGB value. The alpha channel is set to 255 (opaque).
2736
pub fn from_hex(color: u32) -> Color {
2837
assert_eq!(color >> (8 * 3), 0);
2938
Color {
@@ -34,18 +43,22 @@ impl Color {
3443
}
3544
}
3645

46+
/// Converts the color to RGB. The alpha channel is ignored.
3747
pub fn to_rgb888(&self) -> u32 {
3848
self.to_rgb()
3949
}
4050

51+
/// Creates a color from the passed RGB value. The alpha channel is set to 255 (opaque).
4152
pub fn from_rgb888(color: u32) -> Color {
4253
Color::from_hex(color)
4354
}
4455

56+
/// Converts the color to ARGB.
4557
pub fn to_argb8888(&self) -> u32 {
4658
(u32::from(self.alpha) << 24) | self.to_rgb888()
4759
}
4860

61+
/// Creates a color from the passed ARGB value.
4962
pub fn from_argb8888(color: u32) -> Color {
5063
Color {
5164
red: (color >> 16) as u8,
@@ -55,13 +68,15 @@ impl Color {
5568
}
5669
}
5770

71+
/// Converts the color to ARGB1555.
5872
pub fn to_argb1555(&self) -> u16 {
5973
(u16::from(self.alpha) & 0x80) << 8
6074
| (u16::from(self.red) & 0xf8) << 7
6175
| (u16::from(self.green) & 0xf8) << 2
6276
| (u16::from(self.blue) & 0xf8) >> 3
6377
}
6478

79+
/// Creates a color from the passed ARGB1555 value.
6580
pub fn from_argb1555(color: u16) -> Color {
6681
Color {
6782
alpha: ((color >> 8) & 0x80) as u8,
@@ -71,6 +86,7 @@ impl Color {
7186
}
7287
}
7388

89+
/// Creates a color from the passed HSV value.
7490
pub fn from_hsv(hue: i32, saturation: f32, value: f32) -> Color {
7591
let mut h = hue % 360;
7692
if h < 0 {

src/lcd/init.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
use super::Lcd;
22
use stm32f7::stm32f7x6::{LTDC, RCC};
33

4+
/// Initializes the LCD controller.
5+
///
6+
/// The SDRAM must be initialized before this function is called. See the
7+
/// [`init_sdram`] function for more information.
8+
///
9+
/// [`init_sdram`]: crate::init::init_sdram
410
pub fn init<'a>(ltdc: &'a mut LTDC, rcc: &mut RCC) -> Lcd<'a> {
511
use crate::lcd::{self, LAYER_1_START, LAYER_2_START};
612
const HEIGHT: u16 = lcd::HEIGHT as u16;

src/lcd/mod.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
//! Functions for accessing and writing text to the LCD.
2+
//!
3+
//! The display has two layers that are blended on top of each other, and a background layer
4+
//! with an uniform color.
5+
16
pub use self::color::Color;
27
pub use self::init::init;
38
pub use self::stdout::init as init_stdout;
@@ -10,18 +15,28 @@ pub mod stdout;
1015
mod color;
1116
mod init;
1217

18+
/// The height of the display in pixels.
1319
pub const HEIGHT: usize = 272;
20+
/// The width of the display in pixels.
1421
pub const WIDTH: usize = 480;
1522

23+
/// The number of bytes per pixel for layer 1.
1624
pub const LAYER_1_OCTETS_PER_PIXEL: usize = 4;
25+
/// The length of the layer 1 buffer in bytes.
1726
pub const LAYER_1_LENGTH: usize = HEIGHT * WIDTH * LAYER_1_OCTETS_PER_PIXEL;
27+
/// The number of bytes per pixel for layer 2.
1828
pub const LAYER_2_OCTETS_PER_PIXEL: usize = 2;
29+
/// The length of the layer 1 buffer in bytes.
1930
pub const LAYER_2_LENGTH: usize = HEIGHT * WIDTH * LAYER_2_OCTETS_PER_PIXEL;
2031

32+
/// Start address of the SDRAM where the framebuffers live.
2133
pub const SDRAM_START: usize = 0xC000_0000;
34+
/// Start address of the layer 1 framebuffer.
2235
pub const LAYER_1_START: usize = SDRAM_START;
36+
/// Start address of the layer 2 framebuffer.
2337
pub const LAYER_2_START: usize = SDRAM_START + LAYER_1_LENGTH;
2438

39+
/// Represents the LCD and provides methods to access both layers.
2540
pub struct Lcd<'a> {
2641
controller: &'a mut LTDC,
2742
layer_1_in_use: bool,
@@ -37,12 +52,14 @@ impl<'a> Lcd<'a> {
3752
}
3853
}
3954

55+
/// Sets the color of the background layer.
4056
pub fn set_background_color(&mut self, color: Color) {
4157
self.controller
4258
.bccr
4359
.modify(|_, w| unsafe { w.bc().bits(color.to_rgb()) });
4460
}
4561

62+
/// Returns a reference to layer 1.
4663
pub fn layer_1(&mut self) -> Option<Layer<FramebufferArgb8888>> {
4764
if self.layer_1_in_use {
4865
None
@@ -53,6 +70,7 @@ impl<'a> Lcd<'a> {
5370
}
5471
}
5572

73+
/// Returns a reference to layer 2.
5674
pub fn layer_2(&mut self) -> Option<Layer<FramebufferAl88>> {
5775
if self.layer_2_in_use {
5876
None
@@ -64,10 +82,15 @@ impl<'a> Lcd<'a> {
6482
}
6583
}
6684

85+
/// Represents a buffer of pixels.
6786
pub trait Framebuffer {
87+
/// Set the pixel at the specified coordinates to the specified color.
6888
fn set_pixel(&mut self, x: usize, y: usize, color: Color);
6989
}
7090

91+
/// A framebuffer in the ARGB8888 format.
92+
///
93+
/// It uses 8bits for alpha, red, green, and black respectively, totaling in 32bits per pixel.
7194
pub struct FramebufferArgb8888 {
7295
base_addr: usize,
7396
}
@@ -86,6 +109,10 @@ impl Framebuffer for FramebufferArgb8888 {
86109
}
87110
}
88111

112+
/// A framebuffer in the AL88 format.
113+
///
114+
/// There are 8bits for the alpha channel and 8 bits for specifying a color using a
115+
/// lookup table. Thus, each pixel is represented by 16bits.
89116
pub struct FramebufferAl88 {
90117
base_addr: usize,
91118
}
@@ -104,11 +131,15 @@ impl Framebuffer for FramebufferAl88 {
104131
}
105132
}
106133

134+
/// Represents a layer of the LCD controller.
107135
pub struct Layer<T> {
108136
framebuffer: T,
109137
}
110138

111139
impl<T: Framebuffer> Layer<T> {
140+
/// Fill the layer with horizontal stripes.
141+
///
142+
/// Useful for testing.
112143
pub fn horizontal_stripes(&mut self) {
113144
let colors = [
114145
0xffffff, 0xcccccc, 0x999999, 0x666666, 0x333333, 0x0, 0xff0000, 0x0000ff,
@@ -126,6 +157,9 @@ impl<T: Framebuffer> Layer<T> {
126157
}
127158
}
128159

160+
/// Fill the layer with vertical stripes.
161+
///
162+
/// Useful for testing.
129163
pub fn vertical_stripes(&mut self) {
130164
let colors = [
131165
0xcccccc, 0x999999, 0x666666, 0x333333, 0x0, 0xff0000, 0x0000ff, 0xffffff,
@@ -143,6 +177,9 @@ impl<T: Framebuffer> Layer<T> {
143177
}
144178
}
145179

180+
/// Clear all pixels.
181+
///
182+
/// This method sets each pixel to transparent or black, depending on the framebuffer format.
146183
pub fn clear(&mut self) {
147184
for i in 0..HEIGHT {
148185
for j in 0..WIDTH {
@@ -151,17 +188,20 @@ impl<T: Framebuffer> Layer<T> {
151188
}
152189
}
153190

191+
/// Sets the pixel at the specified coordinates to white.
154192
pub fn print_point_at(&mut self, x: usize, y: usize) {
155193
self.print_point_color_at(x, y, Color::from_hex(0xffffff));
156194
}
157195

196+
/// Sets the pixel at the specified coordinates to the specified color.
158197
pub fn print_point_color_at(&mut self, x: usize, y: usize, color: Color) {
159198
assert!(x < WIDTH);
160199
assert!(y < HEIGHT);
161200

162201
self.framebuffer.set_pixel(x, y, color);
163202
}
164203

204+
/// Creates a text writer on this layer.
165205
pub fn text_writer(&mut self) -> TextWriter<T> {
166206
TextWriter {
167207
layer: self,
@@ -171,13 +211,15 @@ impl<T: Framebuffer> Layer<T> {
171211
}
172212
}
173213

214+
/// Allows to print audio data.
174215
pub struct AudioWriter {
175216
next_pixel: usize,
176217
next_col: usize,
177218
prev_value: (usize, usize),
178219
}
179220

180221
impl AudioWriter {
222+
/// Creates a new audio writer starting at the left edge of the screen.
181223
pub fn new() -> Self {
182224
AudioWriter {
183225
next_pixel: 0,
@@ -186,11 +228,15 @@ impl AudioWriter {
186228
}
187229
}
188230

231+
/// Sets the next pixel on the layer.
232+
///
233+
/// Useful for testing.
189234
pub fn set_next_pixel<F: Framebuffer>(&mut self, layer: &mut Layer<F>, color: Color) {
190235
layer.print_point_color_at(self.next_pixel % WIDTH, self.next_pixel / WIDTH, color);
191236
self.next_pixel = (self.next_pixel + 1) % (HEIGHT * WIDTH);
192237
}
193238

239+
/// Sets the next column of the screen according to the passed audio data.
194240
pub fn set_next_col<F: Framebuffer>(&mut self, layer: &mut Layer<F>, value0: u32, value1: u32) {
195241
let value0 = value0 + 2u32.pow(15);
196242
let value0 = value0 as u16 as usize;
@@ -232,6 +278,10 @@ impl AudioWriter {
232278
}
233279
}
234280

281+
/// Allows writing text to the wrapped layer.
282+
///
283+
/// This struct implements the [fmt::Write](core::fmt::Write) trait, which makes it possible
284+
/// to use the `writeln!` macro with this struct.
235285
pub struct TextWriter<'a, T: Framebuffer + 'a> {
236286
layer: &'a mut Layer<T>,
237287
x_pos: usize,

src/lcd/stdout.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Initialize a LCD layer as standard output.
2+
13
use super::{FramebufferAl88, Layer, TextWriter};
24
use core::fmt;
35
use cortex_m::interrupt;
@@ -13,6 +15,10 @@ impl<'a> Stdout<'a> {
1315
}
1416
}
1517

18+
/// Initialize the passed layer as standard output.
19+
///
20+
/// Subsequent calls to [`print`](print) or [`println!`](println!) will then print
21+
/// to the layer.
1622
pub fn init(layer: Layer<FramebufferAl88>) {
1723
static mut LAYER: Option<Layer<FramebufferAl88>> = None;
1824

@@ -22,19 +28,32 @@ pub fn init(layer: Layer<FramebufferAl88>) {
2228
});
2329
}
2430

31+
/// Prints to the LCD screen, appending a newline.
32+
///
33+
/// The LCD stdout must be initialized. See the [`lcd::stdout::print`](lcd::stdout::print)
34+
/// function for more information.
2535
#[macro_export]
2636
macro_rules! println {
2737
($fmt:expr) => (print!(concat!($fmt, "\n")));
2838
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
2939
}
3040

41+
/// Prints to the LCD screen.
42+
///
43+
/// The LCD stdout must be initialized. See the [`lcd::stdout::print`](lcd::stdout::print)
44+
/// function for more information.
3145
#[macro_export]
3246
macro_rules! print {
3347
($($arg:tt)*) => ({
3448
$crate::lcd::stdout::print(format_args!($($arg)*));
3549
});
3650
}
3751

52+
/// Print to the standard output.
53+
///
54+
/// The easiest way to use this function is through the `write!`/`writeln` macros.
55+
///
56+
/// Panics if the standard output is not yet initialized.
3857
pub fn print(args: fmt::Arguments) {
3958
use core::fmt::Write;
4059
let mut uninitialized = false;
@@ -50,6 +69,7 @@ pub fn print(args: fmt::Arguments) {
5069
}
5170
}
5271

72+
/// Returns whether the [`init`](init) function has already been called.
5373
pub fn is_initialized() -> bool {
5474
let mut initialized = false;
5575
STDOUT.with(|stdout| {

0 commit comments

Comments
 (0)