- probed f[13] on blank panel: bit3=Bluetooth, bit4=battery icon, 0x05=°C, 0x06=°F, bits5-7 unused - combos verified live: 0x0D (°C+BT), 0x15 (°C+bat), 0x1D (°C+BT+bat) - add ICON_* constants to temphummon.c; restore as active build - update PROJECT_MEMORY.md with complete f[13] icon table
218 lines
6.7 KiB
C
218 lines
6.7 KiB
C
/**
|
|
* iconfinder2 — ESP32-H2 Zero + 1.9" Segment E-Paper (IST7134 via I²C)
|
|
*
|
|
* Hunt the BLUETOOTH and BATTERY icons specifically.
|
|
* Per user: they are at the "3rd and 4th position on the 13th bit" —
|
|
* i.e. frame byte 13 (the °C/°F byte), bits 3 and 4.
|
|
*
|
|
* We probe byte 13 bits 0..7 one at a time on a BLANK panel so any icon is
|
|
* unmistakable. (We already know: bit0+bit2 = °C letter; bit1 = black
|
|
* control, so it's guarded.)
|
|
*
|
|
* Wiring (GPIO4→SDA, GPIO5→SCL, GPIO10→RST, GPIO11→BUSY, 3V3→VCC, GND→GND)
|
|
*/
|
|
#include <string.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/i2c_master.h"
|
|
#include "driver/gpio.h"
|
|
#include "esp_log.h"
|
|
#include "esp_timer.h"
|
|
|
|
#define PIN_SDA GPIO_NUM_4
|
|
#define PIN_SCL GPIO_NUM_5
|
|
#define PIN_RST GPIO_NUM_10
|
|
#define PIN_BUSY GPIO_NUM_11
|
|
#define PIN_BOOT GPIO_NUM_9
|
|
|
|
#define FRAME_LEN 15
|
|
#define ADVANCE_MODE 1
|
|
#define AUTO_HOLD_MS 3000
|
|
#define BOOT_TIMEOUT_MS 0
|
|
|
|
static i2c_master_bus_handle_t bus;
|
|
static i2c_master_dev_handle_t cmd_dev, dat_dev;
|
|
|
|
static void epd_reset(void)
|
|
{
|
|
gpio_set_level(PIN_RST, 1); vTaskDelay(pdMS_TO_TICKS(200));
|
|
gpio_set_level(PIN_RST, 0); vTaskDelay(pdMS_TO_TICKS(20));
|
|
gpio_set_level(PIN_RST, 1); vTaskDelay(pdMS_TO_TICKS(200));
|
|
}
|
|
|
|
static void epd_wait_busy(void)
|
|
{
|
|
while (gpio_get_level(PIN_BUSY) == 0) vTaskDelay(pdMS_TO_TICKS(1));
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
static void epd_lut_GC(void)
|
|
{
|
|
uint8_t lut[] = {0x82, 0x20, 0x00, 0xA0, 0x80, 0x40, 0x63};
|
|
i2c_master_transmit(cmd_dev, lut, sizeof(lut), pdMS_TO_TICKS(100));
|
|
}
|
|
static void epd_lut_DU_WB(void)
|
|
{
|
|
uint8_t lut[] = {0x82, 0x80, 0x00, 0xC0, 0x80, 0x80, 0x62};
|
|
i2c_master_transmit(cmd_dev, lut, sizeof(lut), pdMS_TO_TICKS(100));
|
|
}
|
|
|
|
static void epd_temperature(void)
|
|
{
|
|
uint8_t a[] = {0x7E, 0x81, 0xB4};
|
|
i2c_master_transmit(cmd_dev, a, sizeof(a), pdMS_TO_TICKS(100));
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
uint8_t b[] = {0xE7, 0x0E};
|
|
i2c_master_transmit(cmd_dev, b, sizeof(b), pdMS_TO_TICKS(100));
|
|
}
|
|
|
|
static void epd_init(void)
|
|
{
|
|
epd_reset();
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
uint8_t p[] = {0x2B, 0xA7, 0xE0};
|
|
i2c_master_transmit(cmd_dev, p, sizeof(p), pdMS_TO_TICKS(100));
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
epd_temperature();
|
|
}
|
|
|
|
static void epd_write(const uint8_t *frame, uint8_t extra_byte)
|
|
{
|
|
uint8_t w[] = {0xAC, 0x2B, 0x40, 0xA9, 0xA8};
|
|
i2c_master_transmit(cmd_dev, w, sizeof(w), pdMS_TO_TICKS(100));
|
|
i2c_master_transmit(dat_dev, frame, FRAME_LEN, pdMS_TO_TICKS(100));
|
|
i2c_master_transmit(dat_dev, &extra_byte, 1, pdMS_TO_TICKS(100));
|
|
uint8_t d[] = {0xAB, 0xAA, 0xAF};
|
|
i2c_master_transmit(cmd_dev, d, sizeof(d), pdMS_TO_TICKS(100));
|
|
epd_wait_busy();
|
|
uint8_t s[] = {0xAE, 0x28, 0xAD};
|
|
i2c_master_transmit(cmd_dev, s, sizeof(s), pdMS_TO_TICKS(100));
|
|
}
|
|
|
|
/* Show byte13 with ONLY the given bit set (blank elsewhere). */
|
|
static void show_b13(uint8_t value, int tag, const char *note)
|
|
{
|
|
uint8_t f[FRAME_LEN];
|
|
memset(f, 0, FRAME_LEN);
|
|
f[13] = value;
|
|
ESP_LOGI("icon2", "T%d: f[13]=0x%02x (%s)", tag, value, note);
|
|
|
|
uint8_t off[FRAME_LEN];
|
|
memset(off, 0, FRAME_LEN);
|
|
epd_lut_GC();
|
|
epd_write(off, 0x00);
|
|
epd_lut_DU_WB();
|
|
epd_write(f, 0x00);
|
|
}
|
|
|
|
static void boot_init(void)
|
|
{
|
|
gpio_config_t bc = {
|
|
.pin_bit_mask = (1ULL << PIN_BOOT), .mode = GPIO_MODE_INPUT,
|
|
.pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE,
|
|
.intr_type = GPIO_INTR_DISABLE,
|
|
};
|
|
gpio_config(&bc);
|
|
}
|
|
|
|
static void wait_for_advance(void)
|
|
{
|
|
if (ADVANCE_MODE == 0) { vTaskDelay(pdMS_TO_TICKS(AUTO_HOLD_MS)); return; }
|
|
ESP_LOGI("icon2", "press BOOT to advance next...");
|
|
int64_t t_start = esp_timer_get_time();
|
|
for (;;) {
|
|
if (gpio_get_level(PIN_BOOT) == 0) {
|
|
vTaskDelay(pdMS_TO_TICKS(30));
|
|
while (gpio_get_level(PIN_BOOT) == 0) vTaskDelay(pdMS_TO_TICKS(10));
|
|
vTaskDelay(pdMS_TO_TICKS(30));
|
|
break;
|
|
}
|
|
if (BOOT_TIMEOUT_MS > 0 &&
|
|
esp_timer_get_time() - t_start > BOOT_TIMEOUT_MS * 1000LL) {
|
|
ESP_LOGW("icon2", "no BOOT press in %d ms", BOOT_TIMEOUT_MS);
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(20));
|
|
}
|
|
}
|
|
|
|
void app_main(void)
|
|
{
|
|
i2c_master_bus_config_t bc = {
|
|
.i2c_port = -1, .sda_io_num = PIN_SDA, .scl_io_num = PIN_SCL,
|
|
.clk_source = I2C_CLK_SRC_DEFAULT, .glitch_ignore_cnt = 7,
|
|
.flags.enable_internal_pullup = 1,
|
|
};
|
|
ESP_ERROR_CHECK(i2c_new_master_bus(&bc, &bus));
|
|
i2c_device_config_t cc = {
|
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = 0x3C, .scl_speed_hz = 100000,
|
|
};
|
|
i2c_device_config_t dc = {
|
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = 0x3D, .scl_speed_hz = 100000,
|
|
};
|
|
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus, &cc, &cmd_dev));
|
|
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus, &dc, &dat_dev));
|
|
|
|
gpio_config_t rc = {
|
|
.pin_bit_mask = (1ULL << PIN_RST), .mode = GPIO_MODE_OUTPUT,
|
|
.pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE,
|
|
.intr_type = GPIO_INTR_DISABLE,
|
|
};
|
|
gpio_config(&rc); gpio_set_level(PIN_RST, 1);
|
|
gpio_config_t busy_cfg = {
|
|
.pin_bit_mask = (1ULL << PIN_BUSY), .mode = GPIO_MODE_INPUT,
|
|
.pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE,
|
|
.intr_type = GPIO_INTR_DISABLE,
|
|
};
|
|
gpio_config(&busy_cfg);
|
|
|
|
boot_init();
|
|
epd_init();
|
|
|
|
ESP_LOGI("icon2", "== Probe f[13] bits for Bluetooth (3) & power (4) icons ==");
|
|
|
|
/* Single bits of byte 13 (skip bit1 = known black control). */
|
|
show_b13(0x01, 1, "bit0 (C stroke)");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x02, 2, "bit1 (SKIPPED-guard, black ctrl)");
|
|
wait_for_advance(); // just wait, we already know it blackens
|
|
|
|
show_b13(0x04, 3, "bit2 (C stroke)");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x08, 4, "bit3 = BLUETOOTH?");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x10, 5, "bit4 = POWER/BATTERY?");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x20, 6, "bit5");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x40, 7, "bit6");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x80, 8, "bit7");
|
|
wait_for_advance();
|
|
|
|
/* Combo reference: full °C (0x05) and, if icons exist, try adding them. */
|
|
show_b13(0x05, 9, "0x05 = °C full");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x05 | 0x08, 10, "0x0D = °C + BT?");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x05 | 0x10, 11, "0x15 = °C + bat?");
|
|
wait_for_advance();
|
|
|
|
show_b13(0x05 | 0x08 | 0x10, 12, "0x1D = °C + BT + bat?");
|
|
wait_for_advance();
|
|
|
|
ESP_LOGI("icon2", "== Done. ==");
|
|
uint8_t off[FRAME_LEN];
|
|
memset(off, 0, FRAME_LEN);
|
|
epd_lut_DU_WB();
|
|
epd_write(off, 0x00);
|
|
while (1) vTaskDelay(pdMS_TO_TICKS(1000));
|
|
}
|