Add pico hal files

Add RP2040/RP2350 Pico HAL example
This commit is contained in:
krishchan007
2026-01-21 17:08:35 +05:30
parent 764ee93150
commit b472b7cb74
4 changed files with 353 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
## Raspberry Pi Pico / RP2040 HAL Example
This directory contains an example **HAL implementation for Raspberry Pi Picoclass boards**
using the official Raspberry Pi Pico SDK.
This example is provided in response to the request made in
[u8g2 issue #2159](https://github.com/olikraus/u8g2/issues/2159), where example HAL
implementations were explicitly welcomed.
Although the display controller used here differs from the one discussed in that issue,
the overall structure and integration approach are the same and can be adapted to other
RP2040-based systems.
### Scope and Intent
- Demonstrates how to integrate u8g2 with the Raspberry Pi Pico SDK
- Provides a minimal HAL layer for GPIO, delay, and communication callbacks
- Intended as a **reference implementation**, not a fully generic or complete port
- Meant to be copied and adapted for specific projects
### Tested Hardware
- Raspberry Pi Pico (RP2040)
- Raspberry Pi Pico 2 (RP2350)
The same HAL implementation was tested on both platforms and works without modification.
### Notes
- No existing u8g2 HAL implementations are modified
- The example is self-contained and does not affect other platforms
- Display interface and controller specifics are intentionally kept minimal
@@ -0,0 +1,40 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "u8g2.h"
#include "u8g2_pico_hal.h"
u8g2_t u8g2;
/* Static lifetime config */
static const u8g2_pico_config_t display_cfg = {
.interface = U8G2_PICO_IF_HW_SPI,
.hw_spi = {
.spi = spi0,
.baudrate = 4000000,
.pin_sck = 2,
.pin_mosi = 3,
.pin_cs = 5,
.pin_dc = 4,
.pin_rst = 11,
},
};
int main(void)
{
stdio_init_all();
u8g2_pico_init(
&u8g2,
u8g2_Setup_st7305_168x384_f,
&display_cfg
);
u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2, u8g2_font_ncenB24_tr);
u8g2_DrawStr(&u8g2, 100, 100, "Hello World");
u8g2_SendBuffer(&u8g2);
sleep_ms(100);
while (true) {
sleep_ms(1000);
}
}
+181
View File
@@ -0,0 +1,181 @@
/*
* RP2040/RP2350 HAL example for u8g2
* Added in response to https://github.com/olikraus/u8g2/issues/2159
* This is a reference implementation intended for adaptation.
*/
#include "u8g2_pico_hal.h"
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/spi.h"
static u8g2_pico_spi_hw_config_t g_hw_cfg;
/* ------------------------------------------------------------
* Forward declarations of u8g2 callbacks
* ------------------------------------------------------------ */
static uint8_t u8x8_byte_pico_hw_spi(
u8x8_t *u8x8,
uint8_t msg,
uint8_t arg_int,
void *arg_ptr);
static uint8_t u8x8_gpio_and_delay_pico(
u8x8_t *u8x8,
uint8_t msg,
uint8_t arg_int,
void *arg_ptr);
/* ------------------------------------------------------------
* Public HAL API
* ------------------------------------------------------------ */
void u8g2_pico_init(
u8g2_t *u8g2,
u8g2_pico_setup_fn setup_fn,
const u8g2_pico_config_t *cfg)
{
if (cfg->interface != U8G2_PICO_IF_HW_SPI)
return;
g_hw_cfg = cfg->hw_spi;
setup_fn(
u8g2,
U8G2_R3,
u8x8_byte_pico_hw_spi,
u8x8_gpio_and_delay_pico
);
u8g2->u8x8.user_ptr = &g_hw_cfg;
u8g2_InitDisplay(u8g2);
u8g2_SetPowerSave(u8g2, 0);
}
static uint8_t u8x8_gpio_and_delay_pico(
u8x8_t *u8x8,
uint8_t msg,
uint8_t arg_int,
void *arg_ptr)
{
const u8g2_pico_spi_hw_config_t *cfg =
(const u8g2_pico_spi_hw_config_t *)u8x8->user_ptr;
switch (msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT:
spi_init(cfg->spi, cfg->baudrate);
spi_set_format(cfg->spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(cfg->pin_sck, GPIO_FUNC_SPI);
gpio_set_function(cfg->pin_mosi, GPIO_FUNC_SPI);
gpio_init(cfg->pin_cs);
gpio_init(cfg->pin_dc);
gpio_init(cfg->pin_rst);
gpio_set_dir(cfg->pin_cs, GPIO_OUT);
gpio_set_dir(cfg->pin_dc, GPIO_OUT);
gpio_set_dir(cfg->pin_rst, GPIO_OUT);
gpio_put(cfg->pin_cs, 1);
gpio_put(cfg->pin_rst, 1);
break;
case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
sleep_us(arg_int); // 1000 times slower, though generally fine in practice given rp2040 has no `sleep_ns()`
break;
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
sleep_us(arg_int);
break;
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
sleep_us(arg_int * 10);
break;
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
sleep_ms(arg_int);
break;
case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int
gpio_put(cfg->pin_cs, arg_int);
break;
case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level
gpio_put(cfg->pin_dc, arg_int);
break;
case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
gpio_put(cfg->pin_rst, arg_int); // printf("U8X8_MSG_GPIO_RESET %d\n", arg_int);
break;
default:
u8x8_SetGPIOResult(u8x8, 1); // default return value
break;
}
return 1;
}
static uint8_t u8x8_byte_pico_hw_spi(
u8x8_t *u8x8,
uint8_t msg,
uint8_t arg_int,
void *arg_ptr)
{
const u8g2_pico_spi_hw_config_t *cfg =
(const u8g2_pico_spi_hw_config_t *)u8x8->user_ptr;
switch (msg)
{
case U8X8_MSG_BYTE_INIT:
// Ensure CS is inactive
u8x8_gpio_SetCS(u8x8,
u8x8->display_info->chip_disable_level);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
// Assert CS
u8x8_gpio_SetCS(u8x8,
u8x8->display_info->chip_enable_level);
// Respect display timing
u8x8->gpio_and_delay_cb(
u8x8,
U8X8_MSG_DELAY_NANO,
u8x8->display_info->post_chip_enable_wait_ns,
NULL);
break;
case U8X8_MSG_BYTE_SEND:
spi_write_blocking(
cfg->spi,
(const uint8_t *)arg_ptr,
arg_int);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
// Respect display timing
u8x8->gpio_and_delay_cb(
u8x8,
U8X8_MSG_DELAY_NANO,
u8x8->display_info->pre_chip_disable_wait_ns,
NULL);
// Deassert CS
u8x8_gpio_SetCS(u8x8,
u8x8->display_info->chip_disable_level);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
default:
return 0;
}
return 1;
}
+100
View File
@@ -0,0 +1,100 @@
/*
* RP2040/RP2350 HAL example for u8g2
* Added in response to https://github.com/olikraus/u8g2/issues/2159
* This is a reference implementation intended for adaptation.
*/
#ifndef U8G2_PICO_HAL_H
#define U8G2_PICO_HAL_H
#include <stdint.h>
#include "u8g2.h"
#include "hardware/spi.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================
* Interface selection
* ============================================================ */
typedef enum {
U8G2_PICO_IF_HW_SPI = 0,
U8G2_PICO_IF_SW_SPI /* reserved for future */
} u8g2_pico_interface_t;
/* ============================================================
* Hardware SPI configuration
* ============================================================ */
typedef struct {
spi_inst_t *spi; /* spi0 or spi1 */
uint32_t baudrate;
uint8_t pin_sck;
uint8_t pin_mosi;
uint8_t pin_cs;
uint8_t pin_dc;
uint8_t pin_rst;
} u8g2_pico_spi_hw_config_t;
/* ============================================================
* Unified configuration object
* ============================================================ */
typedef struct {
u8g2_pico_interface_t interface;
u8g2_pico_spi_hw_config_t hw_spi;
} u8g2_pico_config_t;
/* ============================================================
* Display setup function type
*
* This matches u8g2_Setup_xxx() signatures exactly.
* ============================================================ */
typedef void (*u8g2_pico_setup_fn)(
u8g2_t *u8g2,
const u8g2_cb_t *rotation,
u8x8_msg_cb byte_cb,
u8x8_msg_cb gpio_cb
);
/* ============================================================
* Public HAL API
* ============================================================ */
/*
* Initialize U8g2 on RP2040 using the Pico SDK.
*
* Responsibilities:
* - configure SPI and GPIO
* - install U8g2 callbacks
* - initialize and wake the display
*
* After this call:
* - u8g2 is fully ready for drawing
* - no further hardware setup is required
*
* @param u8g2 Pointer to u8g2 instance
* @param setup_fn Display-specific u8g2_Setup_xxx() function
* @param cfg Pico hardware configuration
*/
void u8g2_pico_init(
u8g2_t *u8g2,
u8g2_pico_setup_fn setup_fn,
const u8g2_pico_config_t *cfg
);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* U8G2_PICO_HAL_H */