-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Open
Description
u8g2 doesn't give out any kind of output on the display (both shapes and text) using hardware i2c.
I tested it with both a SSD1306 and a SSD1309 (and both of them work when used with u8x8 with same callbacks).
During debugging I've found that between START_TRANSFER and END_TRANSFER, u8g2 tries to send more than 32 bytes:
[debug][byte][0x3c] msg: START_TRANSFER
[debug][byte][0x3c] msg: SET_DC
[debug][byte][0x3c] msg: BYTE_SEND, Len: 1
[debug][byte][0x3c] msg: SET_DC
[debug][byte][0x3c] msg: BYTE_SEND, Len: 1
[debug][byte][0x3c] msg: SET_DC
[debug][byte][0x3c] msg: BYTE_SEND, Len: 1
[debug][byte][0x3c] msg: SET_DC
[debug][byte][0x3c] msg: BYTE_SEND, Len: 1
[debug][byte][0x3c] msg: SET_DC
[debug][byte][0x3c] msg: BYTE_SEND, Len: 128
[debug][byte][0x3c] msg: END_TRANSFER, Len: 132
Main.cpp
#include <stdio.h>
#include <iostream>
#include <pico/stdlib.h>
#include <pico/cyw43_arch.h>
#include <pico/binary_info.h>
#include <u8g2.h>
#include "u8x8_hal_i2c.h"
//*
#define USE_U8G2
/**/
#ifdef USE_U8G2
u8g2_t display;
#else
u8x8_t display;
#endif
int main() {
stdio_init_all();
// Initialise the Wi-Fi chip
if (cyw43_arch_init()) {
printf("Wi-Fi init failed\n");
return -1;
}
u8x8_hal_i2c_init(&i2c0_inst, 100 * 1000, 4, 5, true);
#ifdef USE_U8G2
u8g2_Setup_ssd1306_128x64_noname_f(&display, U8G2_R0, u8x8_hal_i2c_byte, u8x8_hal_i2c_gpio_delay);
u8g2_SetI2CAddress(&display, (0x3c << 1));
u8g2_InitDisplay(&display);
u8g2_ClearDisplay(&display);
u8g2_SetPowerSave(&display, 0);
u8g2_SetFont(&display, u8g2_font_5x7_tf);
#else
u8x8_Setup(&display, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_hal_i2c_byte, u8x8_hal_i2c_gpio_delay);
// u8x8_SetI2CAddress(&display, (0x3c << 1));
u8x8_InitDisplay(&display);
u8x8_ClearDisplay(&display);
u8x8_SetPowerSave(&display, 0);
u8x8_SetFont(&display, u8x8_font_5x8_f);
#endif
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, true);
while (true) {
#ifdef USE_U8G2
u8g2_ClearDisplay(&display);
u8g2_ClearBuffer(&display);
for (size_t i = 0; i < 64; i++)
u8g2_DrawStr(&display, 0, i, "Hello world!");
u8g2_DrawBox(&display, 64, 32, 20, 20);
u8g2_SendBuffer(&display);
#else
u8x8_DrawString(&display, 0, 3, "Hello world!");
#endif
sleep_ms(1000);
}
return 0;
}
u8x8_hal_i2c.h
#pragma once
#ifndef U8X8_PICO_HAL_INCLUDE
#define U8X8_PICO_HAL_INCLUDE
#include <u8x8.h>
#include <hardware/i2c.h>
#include <hardware/gpio.h>
#ifndef ENV_DISABLE_PICOTOOL
#include <pico/binary_info.h>
#endif
/**
* @brief Sets up the needed data in order to initialize the i2c interface and all the needed pins. It's not necessary, by default i2c0_inst is used with pins 4 and 5 plus pullup enabled. The pins can be passed in any order (SDA, SCL)/(SCL, SDA).
* @param I2CInst i2c interface to use
* @param Baudrate i2c speed
* @param Pin0 First i2c pin
* @param Pin1 Second i2c pin
* @param PullUp Enables the pull up resistors on the SDA and SCL lines.
*/
void u8x8_hal_i2c_init(i2c_inst_t* I2CInst, uint Baudrate, uint Pin0, uint Pin1, bool PullUp);
/**
* @brief Callback used to interface u8x8 (and u8g2) with the Pico i2c interface as the `byte_cb`.
* @param u8x8 u8x8 instance
* @param msg message type
* @param arg_int argument 1
* @param arg_ptr argument 2
* @return `1` if the message has been handled, `0` otherwise.
*/
uint8_t u8x8_hal_i2c_byte(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr);
/**
* @brief Callback used to interface u8x8 (and u8g2) with the Pico i2c interface as the `gpio_and_delay_cb`.
* @param u8x8 u8x8 instance
* @param msg message type
* @param arg_int argument 1
* @param arg_ptr argument 2
* @return `1` if the message has been handled, `0` otherwise.
*/
uint8_t u8x8_hal_i2c_gpio_delay(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr);
#endif // Include guard
u8x8_hal_i2c.cpp
#include "u8x8_hal_i2c.h"
#include <iostream>
//*
#define BYTE_DEBUG
/**/
/*
#define GPIO_DEBUG
/**/
// i2c data
i2c_inst_t* Inst = PICO_DEFAULT_I2C_INSTANCE();
uint Baudrate = 100 * 1000;
// i2c pins
uint Pins[2] = { PICO_DEFAULT_I2C_SCL_PIN, PICO_DEFAULT_I2C_SDA_PIN };
bool PullUp = true;
// Buffer for sending data
uint8_t Buffer[256];
size_t Index;
// debug
#ifdef GPIO_DEBUG
uint8_t called = 0;
uint8_t debug_buff[256];
#endif
void u8x8_hal_i2c_init(i2c_inst_t* inst, uint br, uint p0, uint p1, bool pu) {
Inst = inst, Baudrate = br;
Pins[0] = p0, Pins[1] = p1, PullUp = pu;
}
uint8_t u8x8_hal_i2c_byte(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
uint8_t addr = u8x8_GetI2CAddress(u8x8) >> 1;
#ifdef GPIO_DEBUG
std::cout << '\t' << (uint)called << '\n';
for (uint8_t i = 0; i < called; i++)
std::cout << (uint)debug_buff[i] << '\n';
#endif
#ifdef BYTE_DEBUG
std::cout << "[debug][byte][0x" << std::hex << (uint16_t)addr << std::dec << "] msg: ";
#endif
switch(msg)
{
case U8X8_MSG_BYTE_INIT:
#ifdef BYTE_DEBUG
std::cout << "INIT\n";
#endif
// starts i2c interface
i2c_init(Inst, Baudrate);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
#ifdef BYTE_DEBUG
std::cout << "START_TRANSFER\n";
#endif
Index = 0;
break;
case U8X8_MSG_BYTE_SEND: {
#ifdef BYTE_DEBUG
std::cout << "BYTE_SEND, Len: " << (uint16_t)arg_int << "\n";
#endif
auto data = static_cast<uint8_t*>(arg_ptr);
for (size_t i = 0; i < arg_int; i++) {
Buffer[Index] = data[i];
Index += 1;
}
break;
}
case U8X8_MSG_BYTE_END_TRANSFER:
#ifdef BYTE_DEBUG
std::cout << "END_TRANSFER, Len: " << Index << "\n";
#endif
i2c_write_blocking(Inst, addr, Buffer, Index, false);
break;
case U8X8_MSG_BYTE_SET_DC:
#ifdef BYTE_DEBUG
std::cout << "SET_DC\n";
#endif
break;
default:
#ifdef BYTE_DEBUG
std::cout << "UNKNOWN (" << (uint16_t)msg << ")\n";
#endif
return 0;
}
return 1;
}
uint8_t u8x8_hal_i2c_gpio_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
uint8_t addr = u8x8_GetI2CAddress(u8x8) >> 1;
#ifdef GPIO_DEBUG
debug_buff[called] = msg;
called += 1;
std::cout << "[debug][byte][0x" << std::hex << (uint16_t)addr << std::dec << "] msg: ";
#endif
switch(msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT:
#ifdef GPIO_DEBUG
std::cout << "GPIO_AND_DELAY_INIT\n";
#endif
// sets gpio pins as i2c
gpio_set_function(Pins[0], GPIO_FUNC_I2C);
gpio_set_function(Pins[1], GPIO_FUNC_I2C);
// enables pull up if needed
if (PullUp)
gpio_pull_up(Pins[0]), gpio_pull_up(Pins[1]);
#ifndef ENV_DISABLE_PICOTOOL
// notifies picotool about i2c pins
bi_decl(bi_2pins_with_func(Pins[0], Pins[1], GPIO_FUNC_I2C));
#endif
break;
case U8X8_MSG_DELAY_MILLI:
#ifdef GPIO_DEBUG
std::cout << "DELAY_MILLI\n";
#endif
sleep_ms(arg_int);
break;
case U8X8_MSG_DELAY_NANO:
#ifdef GPIO_DEBUG
std::cout << "DELAY_NANO\n";
#endif
sleep_us(arg_int==0?0:1);
break;
case U8X8_MSG_DELAY_10MICRO:
case U8X8_MSG_DELAY_100NANO:
/* not used at the moment */
break;
default:
#ifdef GPIO_DEBUG
std::cout << "UNKNOWN(" << (uint16_t)msg << ")\n";
#endif
if (msg < U8X8_MSG_GPIO(0))
return 0;
u8x8_SetGPIOResult(u8x8, 1);
break;
}
return 1;
}
Metadata
Metadata
Assignees
Labels
No labels