mirror of
https://github.com/olikraus/u8g2.git
synced 2026-07-27 20:05:57 +00:00
Add pico hal files
Add RP2040/RP2350 Pico HAL example
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
## Raspberry Pi Pico / RP2040 HAL Example
|
||||
|
||||
This directory contains an example **HAL implementation for Raspberry Pi Pico–class 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user