Skip to content

Project that convert different True Type fonts (TTF) into Zephyr fonts to be used by monochrome caracter Framebuffer (CFB) API for displays such as ssd1306

Notifications You must be signed in to change notification settings

jeronimoagullo/Zephyr-TTF-fonts-for-CFB

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zephyr TTF fonts for CFB

This project shows how to use True Type fonts (TTF) in Zephyr into Zephyr fonts to be used by monochrome caracter Framebuffer (CFB) API for displays such as ssd1306.

image

If you want to know everyting about CFB in Zephyr, you are in the correct repository!

🎯 Configure display - device tree and Kconfig

Device tree and shields

First of all, you need to have a displayed configured and ready to be used by the CFB API. In this project, I have selected the well-known ssd1306, which is a 128x64 OLED display.

image

This display is alredy implemented in Zephyr by a Shield named ssd1306_128x64 which is connected into a i2c node named arduino_i2c. The content of the shield can be found in the route zephyr/boards/shields/ssd1306/ssd1306_128x64.overlay, which contains the following device tree definition:

/ {
	chosen {
		zephyr,display = &sh1106_sh1106_128x64;
	};
};

&arduino_i2c {
	status = "okay";

	sh1106_sh1106_128x64: ssd1306@3c {
		compatible = "sinowealth,sh1106";
		reg = <0x3c>;
		width = <128>;
		height = <64>;
		segment-offset = <2>;
		page-offset = <0>;
		display-offset = <0>;
		multiplex-ratio = <63>;
		segment-remap;
		com-invdir;
		prechargep = <0x22>;
	};
};

In this shield, a node named sh1106_sh1106_128x64 is defined within node arduino_i2c with all required information for the CFB API such as the width, height and offset among others. Besides, a chosen is defined to facilitate the access to the display from the code as we will se later.

Thus, we can take advantage of this shield and speed up our development, which is one of the great features of Zephyr RTOS. However, probably, our board has not a i2c node whose alias is arduino_i2c. Then, we need to add a simple overlay to alias an i2c node of our board properly. In my case, I have used the i2c1 node adding:

arduino_i2c: &i2c1{
	status = "okay";
};

Now, we are ready to use the ssd1306 shield.

Kconfig - prj.conf file

Once the display is already defined at hardware level, we need to add the corresponding Kconfig variables into our prj.conf configuration file to compile and link the proper libraries for CFB API.

We need to include the following variables:

# display
CONFIG_DISPLAY=y

# CFB API
CONFIG_CHARACTER_FRAMEBUFFER=y
# needed for the k_malloc function used by cfb library
CONFIG_HEAP_MEM_POOL_SIZE=16384

# log
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=1
CONFIG_CFB_LOG_LEVEL_DBG=y

🖥️ Character Bufferframe (CFB) API functions

After the previous configuration, you can dive into programming code for the display.

Get display in our code

The first step is to get the pointer to our display. For this aim, you need to define a device struct pointer:

const struct device *display_device;

Then, you can use the DEVICE_DT_GET and DT_CHOSEN macros to get easily the device pointer based on the chosen name provided by the shield (check out the previous section for more info).

display_device = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));

Configure display

You must set the pixel format, wich can be done easily with display_set_pixel_format function:

if (display_set_pixel_format(display_device, PIXEL_FORMAT_MONO10) != 0) {
		if (display_set_pixel_format(display_device, PIXEL_FORMAT_MONO01) != 0) {
			LOG_ERR("Failed to set required pixel format");
		}
	}

Then, you initialize the framebuffer with cfb_framebuffer_init function passing the display pointer as parameter:

if (cfb_framebuffer_init(display_device)) {
	LOG_ERR("Framebuffer initialization failed!\n");
}

Get display information

You can get the display information by the cfb_get_display_parameter chaging the passing parameters. For example, the most relevant information can be get as following:

x_res = cfb_get_display_parameter(display_device, CFB_DISPLAY_WIDTH);
y_res = cfb_get_display_parameter(display_device, CFB_DISPLAY_HEIGH);
rows = cfb_get_display_parameter(display_device, CFB_DISPLAY_ROWS);
cols = cfb_get_display_parameter(display_device, CFB_DISPLAY_COLS);
ppt = cfb_get_display_parameter(display_device, CFB_DISPLAY_PPT);

// log display parameters
LOG_INF("Display parameters: x_res %d, y_res %d, ppt %d, rows %d, cols %d",
		x_res, y_res, ppt, rows, cols);

Display text

Finally, you are ready to display text into the display. Keep in mind that the display is handled by a framebuffer which is fulfilled before being displayed.

Firstly, you need to set the font that you want to use (remember you can get the total number of available fonts by cfb_get_numof_fonts function):

cfb_framebuffer_set_font(display_device, 0);

Before displaying information you need to clear the framebuffer:

cfb_framebuffer_clear(display_device, false);

Now, you can call cfb_print to display text. The arguments are the display pointer, the string to be displayed and the coordinates in which the string will be displayed, for example:

cfb_print(display_device, "Zephyr RTOS!!",0,0);

Once the framebuffer is ready, you must called the cfb_framebuffer_finalize function to set the framebuffer into the display to visualize it:

cfb_framebuffer_finalize(display_device);

image

🚀 Set your own True Type Fonts (TTF)

Once you know how the CFB library works, you can add your custom fonts by TTF. It is well-kown standard created by Apple and integrated today in almost all devices. You can get your favorite fonts from websites like dafont or directly from your PC.

In this project I have used 4 different fonts that can be found in the fonts folder. To add your TTF font, you just need to drop it into that folder and modify the CMakeLists.txt file with the following code:

# Set the include directory for the generated font headers
set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)

# Include cfb cmake script
include(${ZEPHYR_BASE}/cmake/cfb.cmake NO_POLICY_SCOPE)

# Generate the CFB fonts
generate_cfb_font_for_target(app fonts/04B.ttf ${gen_dir}/cfb_mono_04B.h 12 16 -s 12 --first 32 --last 126 --name cfb_custom)

The first line sets the gen_dir where the header generated with the fonts will be located (it can be found under build folder once the code is compiled). Then, you need to include the zephyr/cmake/cfb.cmake script, which executes the required python script that generate the CFB font from your TTF font.

The generate_cfb_font_for_target function has as parameters the relative path of the ttf font fonts/04B.ttf, the output path ${gen_dir}/cfb_mono_04B.h, the width and height in pixels (12 and 16 respectively), the font size (12 in this case) and the starting and end character set (from space to ~). Finally, you can specify a name for the font array, it is quite useful for two reasons. Firstly, it must be unique and the default value is based on the width and heigh, so if you have fonts with same sizes, it will arise an error. Secondly, because the order of the fonts (when you use the cfb_framebuffer_set_font function to set it) will be ordered by the name.

Finally, you can add the corresponding header (.h) file to your code and use your custom ttf font!!

🛠️ Build the project

Choose your board by running:

west build -b <your_board>

It was tested with STM32L4S5 board and SSD1306 OLED display. The display was configured by the corresponding shield. Then, run the following command:

west build -b b_l4s5i_iot01a -- -DSHIELD=ssd1306_128x64

⚡️ Flash

Flash it to your board with:

west flash

About

Project that convert different True Type fonts (TTF) into Zephyr fonts to be used by monochrome caracter Framebuffer (CFB) API for displays such as ssd1306

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published