Chars in C (PI5)e: Unterschied zwischen den Versionen
| Zeile 152: | Zeile 152: | ||
* <syntaxhighlight lang="C" inline>u32 x0</syntaxhighlight> and <syntaxhighlight lang="C" inline>u32 y0</syntaxhighlight> are the x and y coordinates on the screen where the character should start. | * <syntaxhighlight lang="C" inline>u32 x0</syntaxhighlight> and <syntaxhighlight lang="C" inline>u32 y0</syntaxhighlight> are the x and y coordinates on the screen where the character should start. | ||
Pointer to the Character in the Font Array: | '''Pointer to the Character in the Font Array:''' | ||
<syntaxhighlight lang="C">unsigned char *sym = font[(unsigned char)c];</syntaxhighlight> | <syntaxhighlight lang="C">unsigned char *sym = font[(unsigned char)c];</syntaxhighlight> | ||
* <syntaxhighlight lang="C" inline>unsigned char *sym</syntaxhighlight> is a pointer to the 8x8 pixel pattern of the character. | * <syntaxhighlight lang="C" inline>unsigned char *sym</syntaxhighlight> is a pointer to the 8x8 pixel pattern of the character. | ||
* <syntaxhighlight lang="C" inline>font[(unsigned char)c]</syntaxhighlight> accesses the corresponding character pattern in the font array. Each character is represented by an 8x8 pixel pattern. | * <syntaxhighlight lang="C" inline>font[(unsigned char)c]</syntaxhighlight> accesses the corresponding character pattern in the font array. Each character is represented by an 8x8 pixel pattern. | ||
Outer Loop: Iterate through Rows: | '''Outer Loop: Iterate through Rows:''' | ||
<syntaxhighlight lang="C">for (u32 i = 0; i < FONT_HEIGHT; i++)</syntaxhighlight> | <syntaxhighlight lang="C">for (u32 i = 0; i < FONT_HEIGHT; i++)</syntaxhighlight> | ||
This loop iterates through each row of the 8x8 pixel pattern. | This loop iterates through each row of the 8x8 pixel pattern. | ||
* <syntaxhighlight lang="C" inline>u32 i</syntaxhighlight> is the current row in the pixel pattern (from 0 to 7). | * <syntaxhighlight lang="C" inline>u32 i</syntaxhighlight> is the current row in the pixel pattern (from 0 to 7). | ||
Inner Loop: Iterate through Columns: | '''Inner Loop: Iterate through Columns:''' | ||
<syntaxhighlight lang="C">for (u32 j = 0; j < FONT_WIDTH; j++)</syntaxhighlight> | <syntaxhighlight lang="C">for (u32 j = 0; j < FONT_WIDTH; j++)</syntaxhighlight> | ||
This loop iterates through each column of the current row. | This loop iterates through each column of the current row. | ||
* <syntaxhighlight lang="C" inline>u32 j</syntaxhighlight> is the current column in the pixel pattern (from 0 to 7). | * <syntaxhighlight lang="C" inline>u32 j</syntaxhighlight> is the current column in the pixel pattern (from 0 to 7). | ||
Check if the Bit is Set: | '''Check if the Bit is Set:''' | ||
<syntaxhighlight lang="C">u32 check = (sym[i] >> (7 - j)) & 1;</syntaxhighlight> | <syntaxhighlight lang="C">u32 check = (sym[i] >> (7 - j)) & 1;</syntaxhighlight> | ||
* <syntaxhighlight lang="C" inline>sym[i]</syntaxhighlight> loads the byte of the current row. | * <syntaxhighlight lang="C" inline>sym[i]</syntaxhighlight> loads the byte of the current row. | ||
| Zeile 173: | Zeile 173: | ||
* <syntaxhighlight lang="C" inline>& 1</syntaxhighlight> masks all other bits except the lowest bit. The result is either 1 (bit set) or 0 (bit not set). | * <syntaxhighlight lang="C" inline>& 1</syntaxhighlight> masks all other bits except the lowest bit. The result is either 1 (bit set) or 0 (bit not set). | ||
Set the Drawing Color: | '''Set the Drawing Color:''' | ||
<syntaxhighlight lang="C">if (check == 1) | <syntaxhighlight lang="C">if (check == 1) | ||
{ | { | ||
| Zeile 182: | Zeile 182: | ||
DrawColor = BackColor; | DrawColor = BackColor; | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
If check is 1, it means the bit is set, and we set the drawing color (DrawColor) to the foreground color (FrontColor). | * If check is 1, it means the bit is set, and we set the drawing color (DrawColor) to the foreground color (FrontColor). | ||
If check is 0, we set the drawing color to the background color (BackColor). | * If check is 0, we set the drawing color to the background color (BackColor). | ||
Draw the Pixel: | '''Draw the Pixel:''' | ||
<syntaxhighlight lang="C">DrawPixel(x0 + j, y0 + i);</syntaxhighlight> | <syntaxhighlight lang="C">DrawPixel(x0 + j, y0 + i);</syntaxhighlight> | ||
* <syntaxhighlight lang="C" inline>DrawPixel</syntaxhighlight> draws the pixel at the position <syntaxhighlight lang="C" inline>(x0 + j, y0 + i)</syntaxhighlight>. | * <syntaxhighlight lang="C" inline>DrawPixel</syntaxhighlight> draws the pixel at the position <syntaxhighlight lang="C" inline>(x0 + j, y0 + i)</syntaxhighlight>. | ||
Version vom 21. August 2024, 13:23 Uhr
Drawing Characters on the Raspberry Pi
After we have implemented a function to set individual pixels, we now want to teach the Raspberry Pi to display text on the screen. Texts consist of characters that the computer does not inherently know. Similar to a human, the computer must first "learn" what each character looks like before it can display it. These characters are defined in a specific code that the computer understands. One of the most widely used codes is the ANSI character code.
The ANSI Character Code
The ANSI character code we use here is an extension of the original ASCII code. While ASCII originally used only 7 bits per character, ANSI extends this to 8 bits, which corresponds to one byte. The ANSI code was developed when computers needed to communicate over networks and ensure that both sides used the same characters. The first 128 characters in the ANSI code match the ASCII code, but characters 128 to 255 can vary depending on the code page used.
Here, we use "Codepage 437", which was originally developed by IBM for MS-DOS computers and is still used in the Windows command line today.
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x0 | NULL | ☺ | ☻ | ♥ | ♦ | ♣ | ♠ | • | ◘ | ○ | ◙ | ♂ | ♀ | ♪ | ♫ | ☼ |
| 0x1 | ► | ◄ | ↕ | ‼ | ¶ | § | ▬ | ↨ | ↑ | ↓ | → | ← | ∟ | ↔ | ▲ | ▼ |
| 0x2 | Space | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
| 0x3 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
| 0x4 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
| 0x5 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
| 0x6 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
| 0x7 | p | q | r | s | t | u | v | w | x | y | z | { | } | ~ | DEL | |
| 0x8 | Ç | ü | é | â | ä | à | å | ç | ê | ë | è | ï | î | ì | Ä | Å |
| 0x9 | É | æ | Æ | ô | ö | ò | û | ù | ÿ | Ö | Ü | ¢ | £ | ¥ | ₧ | ƒ |
| 0xA | á | í | ó | ú | ñ | Ñ | ª | º | ¿ | ⌐ | ¬ | ½ | ¼ | ¡ | « | » |
| 0xB | ░ | ▒ | ▓ | │ | ┤ | ╡ | ╢ | ╖ | ╕ | ╣ | ║ | ╗ | ╝ | ╜ | ╛ | ┐ |
| 0xC | └ | ┴ | ┬ | ├ | ─ | ┼ | ╞ | ╟ | ╚ | ╔ | ╩ | ╦ | ╠ | ═ | ╬ | ╧ |
| 0xD | ╨ | ╤ | ╥ | ╙ | ╘ | ╒ | ╓ | ╪ | ┘ | ┌ | █ | ▄ | ▌ | ▐ | ▀ | |
| 0xE | α | ß | Γ | π | Σ | σ | µ | τ | Φ | Θ | Ω | δ | ∞ | φ | ε | ∩ |
| 0xF | ≡ | ± | ≥ | ≤ | ⌠ | ⌡ | ÷ | ≈ | ° | • | · | √ | ⁿ | ² | ■ |
Creating a Font
To enable the computer to display characters, we need to show it how each character looks. We create a kind of database in which each character is described as an 8x8 pixel pattern.
For example, the file that describes these characters might look like this:
/* 8x8 FONT by Satyria */
/* Dimensions */
#define FONT_WIDTH 8
#define FONT_HEIGHT 8
#define FONT_MAX 256
unsigned char font[256][8] = {
// Data
// 0 NULL
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
},
// 65 A
{
0b00011000,
0b00111100,
0b00111100,
0b01100110,
0b01111110,
0b11000011,
0b11000011,
0b00000000
},
// 66 B
{
0b11111100,
0b01100110,
0b01100110,
0b01111100,
0b01100110,
0b01100110,
0b11111100,
0b00000000
},
// More characters...
};
In this example, the character "A" is described as an 8x8 pixel pattern, with each byte representing a row of the pattern. Each bit in this byte represents a pixel: a set bit (1) means the pixel is drawn in the foreground color, while an unset bit (0) means the pixel is drawn in the background color.
I have saved my font example as "ms8x8font.fon" in the include directory.
Drawing Characters on the Screen: DrawChar Function
The DrawChar function draws a single character at a specific position on the screen. Here is the complete code for the function:
void DrawChar(char c, u32 x0, u32 y0)
{
unsigned char *sym = font[(unsigned char)c];
for (u32 i = 0; i < FONT_HEIGHT; i++)
{
for (u32 j = 0; j < FONT_WIDTH; j++)
{
u32 check = (sym[i] >> (7 - j)) & 1;
if (check == 1)
{
DrawColor = FrontColor;
}
else
{
DrawColor = BackColor;
}
DrawPixel(x0 + j, y0 + i);
}
}
}
Explanation of the Function
Function Header:
void DrawChar(char c, u32 x0, u32 y0)
voidmeans the function does not return a value.char cis the character to be drawn.u32 x0andu32 y0are the x and y coordinates on the screen where the character should start.
Pointer to the Character in the Font Array:
unsigned char *sym = font[(unsigned char)c];
unsigned char *symis a pointer to the 8x8 pixel pattern of the character.font[(unsigned char)c]accesses the corresponding character pattern in the font array. Each character is represented by an 8x8 pixel pattern.
Outer Loop: Iterate through Rows:
for (u32 i = 0; i < FONT_HEIGHT; i++)
This loop iterates through each row of the 8x8 pixel pattern.
u32 iis the current row in the pixel pattern (from 0 to 7).
Inner Loop: Iterate through Columns:
for (u32 j = 0; j < FONT_WIDTH; j++)
This loop iterates through each column of the current row.
u32 jis the current column in the pixel pattern (from 0 to 7).
Check if the Bit is Set:
u32 check = (sym[i] >> (7 - j)) & 1;
sym[i]loads the byte of the current row.>> (7 - j)shifts the bits to the right so that the bit we want to check is at the lowest position.& 1masks all other bits except the lowest bit. The result is either 1 (bit set) or 0 (bit not set).
Set the Drawing Color:
if (check == 1)
{
DrawColor = FrontColor;
}
else
{
DrawColor = BackColor;
}
- If check is 1, it means the bit is set, and we set the drawing color (DrawColor) to the foreground color (FrontColor).
- If check is 0, we set the drawing color to the background color (BackColor).
Draw the Pixel:
DrawPixel(x0 + j, y0 + i);
DrawPixeldraws the pixel at the position(x0 + j, y0 + i).x0 + jgives the x-coordinate of the current pixel.y0 + igives the y-coordinate of the current pixel.
Summary
The DrawChar function iterates through the 8x8 pixel pattern of a character and draws each pixel at the corresponding position on the screen. The color of the pixel depends on whether the corresponding bit in the pixel pattern is set or not.
You can download the source code as a ZIP file from the following link: https://www.satyria.de/arm/sources/C/chars.zip.