Skip to content

BSP — Board Support Package

The BSP (Board Support Package) is the Hardware Abstraction Layer of the Pibot CNC pendant firmware. It bridges the gap between the application layer (LVGL UI, CNC screens) and the physical hardware of each supported board variant. Every board target gets its own BSP component that implements a single, uniform initialization contract (board_init()), making the rest of the firmware board-agnostic.

The BSP owns:

  • Display controller initialization and LVGL integration (flush callback, tick timer, color-swap)
  • Touchscreen controller initialization and LVGL input-device wiring
  • Physical controls: rotary encoder, pushbuttons, 4-position switch, potentiometer
  • Backlight (PWM) control
  • Buzzer driver and tone sequencer
  • IO expander chips (I²C-attached GPIO extenders)
  • Communication buses (I²C, software SPI) shared between multiple peripherals
  • USB OTG serial host stack (Virtual COM Port adapters)
  • Analog sensor reading (ADC)
  • Custom LVGL event IDs for hardware controls
  • Screen-snapshot capture (pixel dump to file during LVGL flush)
  • Activity-manager integration (display wake-up on first touch/input)

BoardMCUDisplayInterfaceTouch ICExtra Inputs
dlc32_max_lcdESP32ST7796SPIFT6336U (I²C)—
esp32_2432s028rESP32ILI9341SPIXPT2046 (SW SPI)—
esp32_3248s035cESP32ST7796SPIGT911 (I²C)—
esp32_3248s035rESP32ST7796SPIXPT2046 (shared SPI)—
esp32s3_4827s043cESP32-S3ILI9485RGBGT911 (I²C)—
esp32s3_8048_touch_lcd_7ESP32-S3ST7262RGBGT911 (I²C)CH422G expander (SD-CS)
esp32s3_8048s043cESP32-S3ST7262RGBGT911 (I²C)—
esp32s3_8048s050cESP32-S3ST7262RGBGT911 (I²C)—
esp32s3_8048s070cESP32-S3ST7262RGBGT911 (I²C)—
esp32s3_bzm_tft35_gt911ESP32-S3ST7796SPIGT911 (I²C)—
esp32s3_hmi43v3ESP32-S3RM68120Intel 8080GT911 (I²C)—
esp32s3_zx3d50ce02s_usrc_4832ESP32-S3ST7796Intel 8080FT5x06 (I²C)—
fysetc_wifi_proESP32-S3———Headless (WiFi+SD only)
pibot_pendant_v1_0ESP32-S3ILI9341SPIXPT2046 (SW SPI)Encoder, Buttons, Switch, Potentiometer, Buzzer

get_lvgl_display()

get_lvgl_lock()

get_touch_indev()

BSP - Board Support Package

IO Expanders

CH422G (I²C)

TCA9554 (I²C)

board_init()

Backlight (PWM)

LVGL Integration

(flush_cb / tick / indev)

Control Events

(custom LVGL event IDs)

Activity Manager

(display wake-up)

Snapshot (pixel dump)

Display Drivers

SPI: ILI9341 / ST7796

I80: RM68120 / ST7796-i80

RGB: ILI9485 / ST7262 / EK9716

Touch Controllers

GT911 (I²C)

FT5x06 / FT6336U (I²C)

XPT2046 (SPI)

Physical Inputs (pibot)

Rotary Encoder (PCNT)

Buttons (GPIO)

4-pos Switch

Potentiometer (ADC)

Buses

I²C bus

Software SPI bus

Buzzer / Tone Sequencer

USB Serial Host

(CH9102 / PL2303 / STM32)

Analog Sensor (ADC)

Application Layer

(LVGL UI / CNC Screens)


Every board_init() follows this ordered sequence, with optional steps guarded by CMake feature flags:

LVGLPhysical InputsTouch ControllerDisplay DriverBacklightboard_init()ApplicationLVGLPhysical InputsTouch ControllerDisplay DriverBacklightboard_init()Applicationpibot_pendant_v1_0 onlyboard_init()activity_manager_init()backlight_configure() → set(0%)[spi/i80/rgb]_configure()bus_i2c_init() / bus_sw_spi_init()touch_xxx_configure()phy_encoder / phy_buttons / phy_switch / phy_potentiometerlv_init() + lv_display_create()register flush_cb / tick timer / indevcontrol_events_init()backlight_set(default %)ESP_OK

Three distinct display bus types are in use, each with a different LVGL flush strategy:

Boards: dlc32_max_lcd, esp32_2432s028r, esp32_3248s035c, esp32_3248s035r, esp32s3_bzm_tft35_gt911, pibot_pendant_v1_0

The SPI transfer is asynchronous via DMA. notify_lvgl_flush_ready is registered as the panel IO on_color_trans_done callback and fires from the SPI interrupt to signal LVGL that the frame buffer is free.

esp_lcd panel (SPI)flush_cbLVGLesp_lcd panel (SPI)flush_cbLVGLDMA transfer (async)lvgl_flush_cb(area, px_map)optional snapshot captureoptional RGB565 byte-swapesp_lcd_panel_draw_bitmap()on_color_trans_done ISRlv_display_flush_ready()

Boards: esp32s3_hmi43v3 (RM68120), esp32s3_zx3d50ce02s_usrc_4832 (ST7796-i80)

Uses the ESP-IDF I80 parallel-bus driver. A dedicated i80_flush_ready_cb is registered instead of the SPI transfer-done callback. The flush completes synchronously before LVGL is notified. See display_drivers_i80.md for the panel-specific API.

Boards: esp32s3_4827s043c, esp32s3_8048_touch_lcd_7, esp32s3_8048s043c, esp32s3_8048s050c, esp32s3_8048s070c

RGB panels stream continuously from a shared frame buffer. Tearing is prevented by synchronising the LVGL flush with the panel’s VSYNC signal using two binary semaphores:

RGB Panel DMAdisp_on_vsync_event (ISR)lvgl_flush_cbLVGLRGB Panel DMAdisp_on_vsync_event (ISR)lvgl_flush_cbLVGLrender complete → call flush_cbsnapshot / byte-swapxSemaphoreGive(sem_gui_ready)panel VSYNC pulse firesxSemaphoreTake(sem_gui_ready)xSemaphoreGive(sem_vsync_end)xSemaphoreTake(sem_vsync_end) unblocksesp_lcd_panel_draw_bitmap()lv_display_flush_ready()

RGB + SD card conflict (ESP3D_PATCH_FS_ACCESS_RELEASE): On boards where SPI data pins overlap with the RGB pixel-clock path, accessing the SD card while the RGB panel runs at full speed causes glitches or data corruption. The BSP exposes bsp_accessFs() and bsp_releaseFs() to temporarily lower the pixel-clock frequency (DISPLAY_PATCH_FS_FREQ_HZ) during SD operations. See display_drivers_rgb.md.


All touch touch_read_cb implementations share the same activity-manager wake-up protocol: the first press event after the display has been idle is silently consumed — it wakes the screen but is not forwarded to LVGL, preventing accidental UI actions on wake.

touch_data.is_pressed\n(screen was idle)

activity_process_event() == false\n(was sleeping)

activity_process_event() == true\n(already active)

finger lifted\n(event suppressed to LVGL)

finger lifted\n(event forwarded to LVGL)

touch_data.is_pressed\n(screen already active)

Released

FirstPress

WakeUpConsumed

NormalPress


When ESP3D_SNAPSHOT_FEATURE is enabled, lvgl_flush_cb intercepts the pixel buffer on each flush and writes it to a file in 120-byte chunks. The snapshot_state_t structure coordinates access between the LVGL task (writing) and any task that initiates a snapshot:

typedef struct {
FILE* file; // Open output file
volatile bool error; // Write error flag
uint32_t expected_pixels; // Full-frame pixel count
volatile uint32_t captured_pixels; // Pixels flushed so far
SemaphoreHandle_t mutex; // Guards concurrent flush access
volatile bool initialized; // Snapshot system ready
volatile bool ongoing; // Capture in progress
} snapshot_state_t;

The snapshot is considered complete when captured_pixels >= expected_pixels.


Sub-moduleDescriptionFile
Board InitializationPer-board board_init(), LVGL buffer allocation, flush strategiesbsp_bsp_board_initialization.md
Control EventsCustom LVGL event-code registration for switches and potentiometersbsp_bsp_control_events.md
SPI Display DriversILI9341 and ST7796 SPI panel drivers + PWM backlight controllerbsp_display_drivers_spi.md
Intel 8080 Display DriversRM68120 and ST7796-i80 parallel bus panel driversbsp_display_drivers_i80.md
RGB Display DriversILI9485, ST7262, EK9716 RGB parallel panel configurationbsp_display_drivers_rgb.md
Touch ControllersGT911, FT5x06, FT6336U, XPT2046 touch IC driversbsp_touch_controllers.md
IO ExpandersCH422G and TCA9554 I²C GPIO expandersbsp_io_expanders.md
Bus DriversShared I²C bus and software (bit-banged) SPI bus driversbsp_bus_drivers.md
Physical InputsRotary encoder (PCNT), pushbuttons, 4-position switch, potentiometerbsp_physical_inputs.md
USB Serial HostUSB OTG host stack and CH9102 / PL2303 / STM32 VCP implementationsbsp_usb_serial.md
BuzzerPWM buzzer driver and FreeRTOS tone-sequencer taskbsp_buzzer.md
Analog SensorADC-based analog sensor driverbsp_sensor_analog.md

  • UI Framework (ESP3DXUi / tft_ui_task): calls get_lvgl_display(), get_lvgl_lock(), and get_touch_indev() after board_init() completes to drive the LVGL event loop on Core 1.
  • Core Platform (esp3d_lvgl.cpp): uses lv_timer_pause_all() / lv_timer_resume_all() and integrates the snapshot deinit hook.
  • Filesystem (ESP3DFlash, ESP3DSd): calls bsp_accessFs() / bsp_releaseFs() on boards with pixel-clock / SPI-bus contention (RGB display + SD card).
  • Sound module (main/modules/buzzer/esp3d_sound.h): the application-level ESP3DSound (esp3d_sound) drives the BSP buzzer driver in hardware/common/drivers/buzzer/ through its tone backend.
  • Activity Manager: initialized by board_init() and consulted on every touch or physical-input event to manage screen idle/wake state.