Skip to content

Commit 3ca9a7c

Browse files
zelenskiCS107E BOT
authored andcommitted
lab6 release
commit 7c3ddae14be4ad1a40a113727e6d019fbe4362f4 Author: Julie Zelenski <[email protected]> Date: Mon Nov 4 09:18:51 2024 -0800 lab6 release
1 parent 5183d9c commit 3ca9a7c

File tree

5 files changed

+257
-1
lines changed

5 files changed

+257
-1
lines changed

_data/unreleased.csv

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ permalink,title,released
22
"/assignments/assign6/","Assignment 6: Graphics Library and Console",false
33
"/assignments/assign7/","Assignment 7: System Monitor with Interrupts",false
44
"/project/","Final Project",false
5-
"/labs/lab6/","Lab 6: Drawing into the Framebuffer",false
65
"/labs/lab7/","Lab 7: Mango Pi, Interrupted",false
76
"/labs/projectlab1/","Lab 8: Project Team Meeting 1",false
87
"/labs/projectlab2/","Lab 9: Project Team Meeting 2",false

labs/lab6/README.md

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
---
2+
released: true
3+
permalink: /labs/lab6/
4+
title: 'Lab 6: Drawing into the Framebuffer'
5+
attribution: Lab written by Philip Levis and Pat Hanrahan, updated by Julie Zelenski
6+
toc: true
7+
readings: |
8+
[Prelab](/labs/lab6/#prelab-preparation) to prep before lab.
9+
---
10+
{% comment %}
11+
Task list to copy/paste when creating PR for this lab:
12+
13+
__Before releasing lab6:__
14+
- [ ] Review writeup/code/checkin questions (instructor)
15+
- [ ] Walk through (SL)
16+
- [ ] Followup on issues from previous quarter postmortem (issue #403)
17+
18+
__To prep for lab6:__
19+
- [ ] Confirm lab has working monitors with HDMI cables (aim for 1 for every 2 students)
20+
21+
{% endcomment %}
22+
23+
24+
## Goals
25+
26+
For your next assignment, you will implement library of simple graphics routines and use them to implement a text console for your shell. The goal of this lab is to review concepts and code in preparation.
27+
28+
During this lab you will:
29+
30+
- Connect your Pi's HDMI port to a monitor and generate video
31+
- Write code to allocate framebuffer memory and make changes to the pixel data
32+
- Review C syntax for pointers to multi-dimensional arrays
33+
- Read and understand fonts and the representation of characters
34+
35+
## Prelab preparation
36+
To prepare for lab, do the following:
37+
38+
- Bring your Mango Pi and complete parts kit to lab. You do not need your PS/2 keyboard for lab6, it can stay home. (You will use the keyboard for assign6 though)
39+
- Lab6 and assign6 use an HDMI display. This can be any computer monitor, tv, or projector that accepts HDMI input.
40+
- Our lab room has a dozen monitors and you are welcome to come to lab anytime to use them. The monitors are to remain in lab for all to share. __Do not take our cables or monitors out of the lab room__.
41+
- If you have access to an HDMI-capable display elsewhere, give it a try! We have confirmed the reference library's support for HDMI output on a smattering of monitors. We expect it should work on others as well, but are a little wary about possibility of lurking bug or corner case that has yet to surface. Please let us know if you run into trouble and we can help diagnose.
42+
43+
## Lab exercises
44+
45+
### 0. Pull lab starter code
46+
47+
Change to your local `mycode` repo and pull in the lab starter code:
48+
49+
```console
50+
$ cd ~/cs107e_home/mycode
51+
$ git checkout dev
52+
$ git pull code-mirror lab6-starter
53+
```
54+
### 1. Confirm video
55+
56+
Find an available monitor in lab, connect the monitor to power, and turn it on.
57+
Connect its HDMI cable to the mini-HDMI port on your Mango Pi.
58+
59+
Change to the directory `lab6/grid` and build and run the grid program using
60+
`make run`. The monitor should display a grid of white lines on a black background.
61+
62+
Everyone should connect their Pi to a monitor and confirm the grid display.
63+
For the rest of the lab, 2-3 partners can share one Pi/monitor.
64+
65+
### 2. The `fb` module
66+
67+
You will implement the `fb` module to handle allocating the framebuffer memory
68+
and coordinating with the lower-level `de` and `hdmi` modules to control
69+
the hardware peripherals that display the framebuffer pixels on the screen.
70+
71+
#### Review code of modules `de` and `hdmi`
72+
Our reference libmango provides the implementation of the `de` (Display Engine)
73+
and `hdmi` modules.
74+
Peruse the module interfaces [$CS107E/include/de.h](/header#de) and [$CS107E/include/hdmi.h](/header#hdmi). You
75+
'll note that the modules export a tiny number of functions.
76+
We wrote those modules to support exactly and only the very specific features needed for our system.
77+
78+
Do a brief skim over the the implementation in files
79+
[$CS107E/src/de.c](/src#de) and [$CS107E/src/hdmi.c](/src#hdmi). You will not modify this code and
80+
do not need to make deep dive into it. Your `fb` module will interact with
81+
the `de` and `hdmi` modules through limited public functions documented in the header files.
82+
83+
#### Initializing the framebuffer
84+
85+
Change to the directory `lab6/fb`. The directory contains these files:
86+
87+
```console
88+
$ ls
89+
Makefile fb.c main.c
90+
```
91+
The file `fb.c` contains code to initialize the framebuffer. The `fb` module
92+
declares a struct to hold the module-level state. This struct has four fields:
93+
94+
95+
- `width`, `height`: width/height of framebuffer in pixels
96+
- `depth`: number of bytes per pixel (always 4 in our system)
97+
- `framebuffer`: base address of the framebuffer memory
98+
99+
Review the code in the `fb_init` function. Discuss with your tablemates and
100+
try to answer the questions below.
101+
102+
1. How are total bytes calculated when allocating the framebuffer?
103+
2. What is the color of the pixels in the newly created framebuffer?
104+
3. How does the framebuffer coordinate with the `hdmi` module to set the sceen size?
105+
4. How does the framebuffer communicate with the `de` module to draw the pixels on screen?
106+
5. What kind of changes will be needed for the `fb` module to support double-buffering (i.e. separate front/back buffers)?
107+
108+
If you do not feel confident about your answers or do not agree, please ask us to help resolve!
109+
110+
111+
### 2. Draw pixels
112+
In directory `lab6/grid`, open the `grid.c` file in your text editor and modify the program in the following ways:
113+
114+
1. Change the grid code to draw horizontal lines in red and vertical lines in yellow.
115+
*Remember from lecture that the B (blue) in BGRA is the lowest byte.*
116+
117+
2. Change the grid code to draw a checkerboard pattern
118+
(alternating filled red and yellow squares). Hint: define a helper function
119+
that draws a filled rectangle.
120+
121+
> __Here be dragons__ One critical fact to keep in mind when working with the framebuffer memory is that C does no bounds-checking on array indexes.
122+
Writing to an index
123+
outside the bounds of the framebuffer will simply overwrite data at the inappropriate location.
124+
Such as transgression can create a strange variety of symptoms, including corrupting the framebuffer image
125+
and/or locking up the pipeline to the display hardware. Should you encounter seemingly bizarre results
126+
when writing the framebuffer, review how your code accesses its memory. (Note: redzone
127+
protection can be lifesaver. The malloc module of the reference library has it enabled, if you did not do the extension yourself.)
128+
{: .callout-danger }
129+
130+
Show off your crisp looking squares to your tablemates!
131+
132+
### 3. Multi-dimensional arrays
133+
134+
Pointers are ubiquitous in systems programming in C and one of the most
135+
difficult concepts to master. Just when you are getting the hang of pointers
136+
and one-dimensional arrays, now we're adding multi-dimensioned arrays into the
137+
mix. The goal of this lab exercise is to review pointers and multi-dimensional
138+
arrays in preparation for your next assignment.
139+
140+
One convenient way to represent images is with a two-dimensional array.
141+
Treating it as a 2D array can be easier than explicitly calculating offsets
142+
into a one-dimensional array.
143+
144+
To start, here is a quick self-test:
145+
146+
* What is the difference between the following two declarations?
147+
Think about what operations are valid on `a` versus `b`. Also
148+
think about what memory is allocated.
149+
150+
char *a = "Hello, world\n";
151+
char b[] = "Hello, world\n";
152+
153+
* What is the difference between the following two declarations?
154+
155+
int *p[2];
156+
int (*c)[2];
157+
158+
You may find the **[cdecl tool](http://cdecl.org/)** helpful in demystifying a complex C declaration.
159+
160+
Inspect the code in `lab6/pointers/pointers.c`. Compile the program using
161+
`make`, run it on your Pi, and interpret the results. Ask questions about
162+
anything that doesn't make sense to you and be sure your understanding matches the results.
163+
164+
### 4. Fonts
165+
166+
A major part of your assignment will be to draw text on the screen.
167+
In order to do this, you need a *font*. Each character in the font is a little
168+
picture that represents the glyph to draw.
169+
170+
![Font](images/Apple2e.bmp){: .zoom .w-100}
171+
172+
This famous font was used by the original Apple IIe. We chose it to
173+
provide that extra-special retro touch for your graphical console.
174+
175+
Review the file [$CS107E/src/font.c](/src#font). It declares a `font_t` struct for representing a font and
176+
defines the variable `font_default`:
177+
178+
```
179+
/* from font.c */
180+
typedef struct {
181+
unsigned char first_char, last_char;
182+
int glyph_width, glyph_height;
183+
uint8_t pixel_data[];
184+
} font_t;
185+
186+
static const font_t font_default = {
187+
.first_char = 0x21, .last_char = 0x7F,
188+
.glyph_width = 14, .glyph_height = 16,
189+
.pixel_data = {
190+
0x03, 0x00, 0x33, 0x00, 0xcc, 0x00, 0xc0, 0x3c,
191+
0x00, 0x30, 0x00, 0x30, 0x00, 0xc0, 0x03, 0x00,
192+
...
193+
0x3f, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
194+
0x00, 0x00, 0x00, 0x00
195+
}
196+
};
197+
```
198+
199+
The pixel data for the character glyphs is stored as a bitmap. In a bitmap,
200+
each pixel is represented by a single bit. If the bit is 'on', the pixel is to
201+
be drawn in the foreground color; if 'off', the pixel is set to the background
202+
color. We use a bitmap rather than full RGBA because it takes much less (32
203+
times less) memory. This makes the font data much smaller, and hence faster to
204+
upload to your Pi.
205+
206+
Below is a pictorial representation of `font_default` using green to display
207+
each 'on' pixel in the bitmap. (click the image to see larger version):
208+
209+
![Font](images/apple2e-line.bmp){: .zoom .w-100}
210+
211+
The font bitmap stores the character glyphs in a single line. The leftmost glyph is for the
212+
character '`!`', whose ASCII value is 33 (0x21), the neighboring glyph is for
213+
character '`"`' (ASCII 34) and so on ending with rightmost character ASCII
214+
value 127 (0x7f) Delete, whose glyph is a little checkerboard. The font bitmap
215+
contains glyphs for 95 total characters, from ASCII 33 to 127.
216+
217+
Each glyph is the same size: 14 pixels wide and 16 pixels tall. This is termed
218+
a *fixed-width* font.
219+
220+
The bitmap is stored using an array of `uint8_t`
221+
values. For example, the first two bytes in the array are `0x03, 0x00`. Group
222+
the 8 bits from the first byte and 6 bits from the second into the 14-bit
223+
sequence `0b00000011000000`. These 14 bits correspond to the top row of the
224+
first glyph, the exclamation point. The bits indicate the vertical line for
225+
the exclamation point is 2 pixels wide and positioned in the center.
226+
227+
Each line of the bitmap is 1330 pixels long (95 characters * 14 pixels wide),
228+
and requires 1330 bits. If each glyph is 16 pixels tall, how many total
229+
bytes are in the `pixel_data` array?
230+
231+
Look carefully at the function `font_get_glyph()` in `font.c` which copies a
232+
single glyph from the font bitmap into a buffer.
233+
234+
* Trace the operation of `font_get_glyph` for ASCII character `&` (ascii hex
235+
0x26)? At what locations in `pixel_data` does it look to find the appropriate
236+
bits?
237+
238+
Now change to the directory `lab6/banner` and review the code in `banner.c`.
239+
This program calls `font_get_glyph` to store the glyph image into `buf`. The
240+
code then wants to go on to access `buf` as a 2-d array through the variable
241+
named `img`, but `img` is missing its declaration and initialization. Read and
242+
follow the instructions marked `TODO:` to fix this issue. Compile and run and
243+
you'll get an ascii banner that prints letters to the terminal using your Pi's
244+
font - neat!
245+
246+
247+
## Finishing
248+
249+
### Check in as you go
250+
Please touch base with us during lab to ask your questions and confirm your understanding. We are here to help,
251+
let us know of any challenges or confusions we can help resolve with you!
252+
253+
### Submit exit form
254+
Before leaving, submit the [lab exit form](https://forms.gle/EWGy15v4ySBE4uM17) to let us how the lab went for you and note any issues needing followup. The key goals for this lab are to leave with a good understanding of the layout of the framebuffer memory and feel ready for starting on Assignment 6.
255+
256+
Note that all HDMI monitors and cables must remain in lab for all to use. Do not take them from lab.
257+

labs/lab6/images/Apple2e.bmp

149 KB
Binary file not shown.

labs/lab6/images/apple2e-line.bmp

203 KB
Binary file not shown.

labs/lab6/images/pifb.png

60.2 KB
Loading

0 commit comments

Comments
 (0)