Chars in C (PI5)e: Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
Die Seite wurde neu angelegt: „== 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…“
 
Zeile 187: Zeile 187:
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>.
<syntaxhighlight lang="C" inline>x0 + j</syntaxhighlight> gives the x-coordinate of the current pixel.
* <syntaxhighlight lang="C" inline>x0 + j</syntaxhighlight> gives the x-coordinate of the current pixel.
<syntaxhighlight lang="C" inline>y0 + i</syntaxhighlight> gives the y-coordinate of the current pixel.
* <syntaxhighlight lang="C" inline>y0 + i</syntaxhighlight> gives the y-coordinate of the current pixel.
 
== Summary ==
== 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.
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.
You can download the source code as a ZIP file from the following link: https://www.satyria.de/arm/sources/C/chars.zip.

Version vom 21. August 2024, 13:22 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)
  • void means the function does not return a value.
  • char c is the character to be drawn.
  • u32 x0 and u32 y0 are 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 *sym is 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 i is 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 j is 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.
  • & 1 masks 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);
  • DrawPixel draws the pixel at the position (x0 + j, y0 + i).
  • x0 + j gives the x-coordinate of the current pixel.
  • y0 + i gives 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.