Frame Buffer

#include <eglib/display/frame_buffer.h>

Configuration

frame_buffer_config_t

Configuration for frame buffer display.

eglib_Init_FrameBuffer() populates the values here.

Functions

These functions can be used exclusively with eglib_t initialized for frame buffer.

eglib_t * eglib_Init_FrameBuffer(eglib_t * eglib, frame_buffer_config_t * frame_buffer_config, const hal_t * hal_driver, void * hal_config_ptr, const display_t * display_driver, void * display_config_ptr)

Works similarly to eglib_Init(), but creates a frame buffer where data is written to, instead of directly to the display. The buffer is only sent to the display when eglib_FrameBuffer_Send() is called.

Using a frame buffer makes sense when:

  • You are using a display that does not support directly writing pixels to display memory (eg: sh1106_vdd1_2_4_v).

  • You have enough RAM.

  • You want to have faster refresh rates.

  • You want to avoid visual artifacts when drawing complex shapes.

You can not use a frame buffer only when you don’t have enough RAM available.

This function allocates the memory required for the buffer dynamically based on display_struct width, height and pixel format (width * height * bit depth / 8). This can be freed by frame_buffer_Free().

Parameters
  • eglib – Pointer to eglib_t to be initialized.

  • frame_buffer_config – Pointer to frame_buffer_config_t to be initialized.

  • hal_driver – Pointer to the HAL driver hal_t to use.

  • hal_config_ptr – Pointer to the HAL driver configuration. Please refer each HAL driver documentation for details.

  • display_driver – Pointer to the display driver display_t to use.

  • display_config_ptr – Pointer to the display driver configuration. Please refer each display driver documentation for details.

Returns

Pointer to an initialized eglib_t for the given HAL and display parameters. This reference must be used when using display specific functions, such as st7789_SetDisplayInversion().

void eglib_FrameBuffer_SendPartial(eglib_t * eglib, coordinate_t x, coordinate_t y, coordinate_t width, coordinate_t height)

Send part of the frame buffer to the display RAM.

eglib_FrameBuffer_Send(eglib)

Send the whole frame buffer to the display RAM.

void eglib_FrameBuffer_SendUpdated(eglib_t * eglib)

Send only updated parts of the frame buffer to the display RAM.

void frame_buffer_Free(eglib_t * eglib)

Free memory previously allocated by eglib_Init_FrameBuffer().

Examples

#include <eglib.h>
#include <eglib/hal/four_wire_spi/libopencm3_stm32f4.h>
#include <eglib/display/frame_buffer.h>
#include <eglib/display/sh1106.h>
#include <stdio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/spi.h>

int main(void) {
	eglib_t eglib;
	eglib_t *eglib_sh1106;

	sh1106_config_t sh1106_config = {
		// Display physical construction
		.width = 128,
		.height = 64,
		.segment_remap = SH1106_SEGMENT_REMAP_REVERSE,
		.common_pads_hardware_configuration = SH1106_COMMON_PADS_HARDWARE_CONFIGURATION_ALTERNATIVE,
		.common_output_scan_direction = SH1106_COMMON_OUTPUT_SCAN_DIRECTION_DESC,
		.display_offset = 0,
		.column_offset = 2,

		// Change period
		.pre_charge_period = 2,
		.dis_charge_period = 2,

		// VCOM deselect
		.vcom_deselect_level = 0x35,

		// Internal display clocks
		.clock_divide = 0,
		.oscillator_frequency = SH1106_OSCILLATOR_FREQUENCY_PLUS_50_PCT,

		// Charge Pump Regulator
		.dc_dc_enable = true,
		.dc_dc_voltage = SHH1106_DC_DC_8_0_V,
	};

	frame_buffer_config_t frame_buffer_config;

	four_wire_spi_libopencm3_stm32f4_config_t  four_wire_spi_libopencm3_stm32f4_config = {
		// rst
		.rcc_rst = RCC_GPIOA,
		.port_rst = GPIOA,
		.gpio_rst = GPIO4,
		// dc
		.rcc_dc = RCC_GPIOA,
		.port_dc = GPIOA,
		.gpio_dc = GPIO3,
		// cs
		.rcc_cs = RCC_GPIOA,
		.port_cs = GPIOA,
		.gpio_cs = GPIO2,
		// spi
		.rcc_spi = RCC_SPI1,
		.spi = SPI1,
		// sck
		.rcc_sck = RCC_GPIOA,
		.port_sck = GPIOA,
		.gpio_sck = GPIO5,
		// mosi
		.rcc_mosi = RCC_GPIOA,
		.port_mosi = GPIOA,
		.gpio_mosi = GPIO7,
	};

	rcc_clock_setup_pll(&rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_84MHZ]);

	eglib_sh1106 = eglib_Init_FrameBuffer(
		&eglib, &frame_buffer_config,
		&four_wire_spi_libopencm3_stm32f4, &four_wire_spi_libopencm3_stm32f4_config,
		&sh1106_vdd1_2_4_v, &sh1106_config
	);

	eglib_SetIndexColor(&eglib, 0, 0xFF, 0xFF, 0xFF);

	eglib_DrawLine(&eglib,0, 0, sh1106_config.width-1, sh1106_config.height-1);
	eglib_DrawLine(&eglib,0, sh1106_config.height-1, sh1106_config.width-1, 0);

	eglib_FrameBuffer_Send(&eglib);

	sh1106_Reverse(eglib_sh1106, true);
}