i2c fixes + server improvements

This commit is contained in:
2026-10-05 19:28:37 +02:00
parent 7094d05030
commit 02f3df8c41
9 changed files with 254 additions and 52 deletions
+35 -6
View File
@@ -6,14 +6,19 @@
#include "esp_lcd_panel_ops.h"
#include "esp_timer.h"
#include "esp_lcd_panel_sh1106.h"
#include "esp_log.h"
#include "ygg_bmp280.h"
#include "ygg_lock.h"
#define I2C_HOST I2C_NUM_0
#define EXAMPLE_I2C_MASTER_FREQ_HZ 400000
#define EXAMPLE_I2C_MASTER_FREQ_HZ YGG_I2C_FREQ_HZ
#define EXAMPLE_LCD_V_RES 64
#define EXAMPLE_LCD_H_RES 128
#define EXAMPLE_LVGL_PALETTE_SIZE 8
#define SH1106_I2C_SDA_GPIO 19
#define SH1106_I2C_SCL_GPIO 23
#define SH1106_I2C_SDA_GPIO I2C_MASTER_SDA
#define SH1106_I2C_SCL_GPIO I2C_MASTER_SCL
static const char *TAG = "ygg_sh1106";
static uint8_t oled_buffer[EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES / 8];
@@ -51,8 +56,21 @@ static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uin
}
}
}
// pass the draw buffer to the driver
esp_lcd_panel_draw_bitmap(panel_handle, x1, y1, x2 + 1, y2 + 1, oled_buffer);
// pass the draw buffer to the driver.
// Cały transfer pod wspólnym mutexem I2C - BMP280 (i2cdev) używa
// tego samego busa. Bez tego odczyt sensora potrafi wejść w środek
// rysowania -> I2C hardware timeout po obu stronach.
// UWAGA: nie bierzemy tu mutexa LVGL - flush jest wołany z lvgl_task
// już pod mutexem LVGL (z lv_timer_handler). Branie go tu = deadlock.
if (ygg_i2c_lock_take(pdMS_TO_TICKS(1000))) {
esp_err_t err = esp_lcd_panel_draw_bitmap(panel_handle, x1, y1, x2 + 1, y2 + 1, oled_buffer);
ygg_i2c_lock_give();
if (err != ESP_OK) {
ESP_LOGW(TAG, "draw_bitmap failed: %s", esp_err_to_name(err));
}
} else {
ESP_LOGW(TAG, "I2C busy, skipping flush");
}
lv_display_flush_ready(disp);
}
@@ -71,7 +89,8 @@ void ygg_init_tick_cb() {
}
lv_display_t* ygg_sh1106_init() {
ESP_ERROR_CHECK(i2cdev_init());
// UWAGA: i2cdev_init() + ygg_lock_init() robi app_main() raz przed
// wszystkimi initami. Tutaj już nie tworzymy magistrali.
static i2c_dev_t oled_i2c_dev;
memset(&oled_i2c_dev, 0, sizeof(oled_i2c_dev));
@@ -102,6 +121,9 @@ lv_display_t* ygg_sh1106_init() {
// Create the i2c io handle
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i2c_config_t io_config = ESP_SH1106_DEFAULT_IO_CONFIG;
// Zejście z domyślnych 400kHz na 100kHz - wspólna magistrala z BMP280,
// pająk + słabe pull-upy. 400kHz/1MHz = timeouty.
io_config.scl_speed_hz = EXAMPLE_I2C_MASTER_FREQ_HZ;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_handle, &io_config, &io_handle));
@@ -149,9 +171,16 @@ lv_display_t* ygg_sh1106_init() {
}
void ygg_set_display_label(lv_display_t *display, lv_obj_t *label, const char *str) {
// LVGL nie jest thread-safe. Ta funkcja jest wołana z sensor_task,
// a lv_timer_handler chodzi w lvgl_task - wszystko pod jednym mutexem.
if (!ygg_lvgl_lock_take(pdMS_TO_TICKS(500))) {
ESP_LOGW(TAG, "LVGL busy, skipping label update");
return;
}
lv_label_set_text(label, str);
/* Size of the screen (if you use rotation 90 or 270, please use lv_display_get_vertical_resolution) */
lv_obj_set_width(label, lv_display_get_horizontal_resolution(display));
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0);
ygg_lvgl_lock_give();
}