Complete icon map: Bluetooth (f13 bit3) and battery (f13 bit4) with °C composition
- 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
This commit is contained in:
parent
d9bac7cf28
commit
b5cf59b39a
3 changed files with 77 additions and 58 deletions
|
|
@ -93,19 +93,29 @@ All three are **bit 5 (0x20) of the SECOND byte of the pair**, matching the manu
|
||||||
| **Decimal point (bottom)** | `f[8]` | bit 5 (0x20) | after bottom-line **ones** → `88.8` |
|
| **Decimal point (bottom)** | `f[8]` | bit 5 (0x20) | after bottom-line **ones** → `88.8` |
|
||||||
| **% sign (humidity)** | `f[10]` | bit 5 (0x20) | after bottom-line **tenths** → `88.8%` |
|
| **% sign (humidity)** | `f[10]` | bit 5 (0x20) | after bottom-line **tenths** → `88.8%` |
|
||||||
|
|
||||||
### Bluetooth / power icons (probed — NOT found, likely multi-bit or unpopulated)
|
### Bluetooth / power icons (FOUND! 🎯 — in f[13], not a special byte)
|
||||||
|
|
||||||
A single-bit probe of the remaining frame bytes (0 bits5-7, 4/8/10 bits 4/6/7,
|
All status icons live in **`f[13]`**, the same byte as the °C/°F letter. The
|
||||||
14 all) found **no standalone Bluetooth or battery/power icon**. Bits found:
|
manual's "3rd and 4th position on the 13th bit" = bits 3 and 4 of `f[13]`.
|
||||||
- byte 0 bit7 → a cross-wired glyph dot (top-ones region)
|
Probing on a blank panel confirmed each bit, and combos compose cleanly.
|
||||||
- byte 4 bit7 → a cross-wired glyph dot (bottom-ones region)
|
|
||||||
- byte 8 bit4 → caused an **I²C hardware timeout**
|
|
||||||
- most other candidate bits → blank
|
|
||||||
|
|
||||||
The Waveshare reference code does NOT drive any Bluetooth/power icon, and the
|
| f[13] value | Bits | Displays |
|
||||||
IST7134 datasheet doesn't name one either. Conclusion: if the icons exist on
|
|:---|:---|:---|
|
||||||
the glass they are **multi-bit patterns** (like °C = 0x05), not a simple single
|
| `0x01` | bit0 | part of C letter (standalone = black-control risk) |
|
||||||
bit reachable by a bare frame write — not worth more bench time. Cosmetic only.
|
| `0x02` | bit1 | degree sign ° line |
|
||||||
|
| `0x04` | bit2 | C/F letter strokes |
|
||||||
|
| **`0x05`** | bits0+2 | **°C** (degree + C) |
|
||||||
|
| **`0x06`** | bits1+2 | **°F** (per manual) |
|
||||||
|
| **`0x08`** | bit3 | **Bluetooth icon** |
|
||||||
|
| **`0x10`** | bit4 | **Battery/power icon** |
|
||||||
|
| **`0x0D`** | 0x05+0x08 | °C + Bluetooth |
|
||||||
|
| **`0x15`** | 0x05+0x10 | °C + battery |
|
||||||
|
| **`0x1D`** | 0x05+0x08+0x10 | **°C + Bluetooth + battery** |
|
||||||
|
| bits 5-7 | — | unused |
|
||||||
|
|
||||||
|
All compositions verified live on the panel. (The earlier "no icon found"
|
||||||
|
conclusion was wrong - the icons were in f[13] bits 3/4, which the first
|
||||||
|
probe had not isolated.)
|
||||||
|
|
||||||
### Verified glyph segment map (from probing)
|
### Verified glyph segment map (from probing)
|
||||||
|
|
||||||
|
|
@ -273,7 +283,7 @@ nix run .#flash
|
||||||
- [x] **Port Waveshare digit lookup table** — all 10 digits (0–9) verified working on the display
|
- [x] **Port Waveshare digit lookup table** — all 10 digits (0–9) verified working on the display
|
||||||
- [x] **Internal temperature sensor** — reads ESP32-H2 internal temp sensor, shows on display line 1, updates every 1s
|
- [x] **Internal temperature sensor** — reads ESP32-H2 internal temp sensor, shows on display line 1, updates every 1s
|
||||||
- [x] **Find decimal point & % bits** — probing session mapped them: `f[4]/f[8]` bit5 = decimals, `f[10]` bit5 = %
|
- [x] **Find decimal point & % bits** — probing session mapped them: `f[4]/f[8]` bit5 = decimals, `f[10]` bit5 = %
|
||||||
- [~] **Power/Bluetooth icons** — single-bit probe found no standalone icon bits; likely multi-bit patterns or unpopulated (cosmetic, deprioritized)
|
- [x] **Find Bluetooth & battery icons** — `f[13]` bit3 = Bluetooth, bit4 = battery; combos with °C work (0x0D/0x15/0x1D)
|
||||||
- [ ] **Add humidity sensor** — wire up an external I²C sensor (SHT40, BME280, etc.) and show on display line 2
|
- [ ] **Add humidity sensor** — wire up an external I²C sensor (SHT40, BME280, etc.) and show on display line 2
|
||||||
- [ ] **Configure Matter/Thread** — enable OpenThread / Matter components in `sdkconfig`
|
- [ ] **Configure Matter/Thread** — enable OpenThread / Matter components in `sdkconfig`
|
||||||
- [ ] **Implement Matter cluster** — temperature and humidity measurement clusters
|
- [ ] **Implement Matter cluster** — temperature and humidity measurement clusters
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,13 @@
|
||||||
/**
|
/**
|
||||||
* iconfinder — ESP32-H2 Zero + 1.9" Segment E-Paper (IST7134 via I²C)
|
* iconfinder2 — ESP32-H2 Zero + 1.9" Segment E-Paper (IST7134 via I²C)
|
||||||
*
|
*
|
||||||
* Hunt the POWER (battery) and BLUETOOTH icons.
|
* Hunt the BLUETOOTH and BATTERY icons specifically.
|
||||||
* Per the manual: "13th position = °C/°F, 14th unused, and icons at other
|
* Per user: they are at the "3rd and 4th position on the 13th bit" —
|
||||||
* positions" — we empirically probe the remaining untested frame bytes on a
|
* i.e. frame byte 13 (the °C/°F byte), bits 3 and 4.
|
||||||
* BLANK background (so a lone icon is unmistakable).
|
|
||||||
*
|
*
|
||||||
* Bytes probed (0-indexed):
|
* We probe byte 13 bits 0..7 one at a time on a BLANK panel so any icon is
|
||||||
* byte 0 bits 5-7 (high bits we never tested; leading-1 glyph is 0-4)
|
* unmistakable. (We already know: bit0+bit2 = °C letter; bit1 = black
|
||||||
* byte 2 all 8 (second byte of top-tens pair)
|
* control, so it's guarded.)
|
||||||
* byte 6 all 8 (second byte of bottom-tens pair)
|
|
||||||
* byte 13 bits 3-7 (after the C/F letter bits 0-2)
|
|
||||||
* byte 14 all 8 (manual says unused, confirm)
|
|
||||||
* Dangerous black-control bits (byte 2 bit4, byte 4 bit7, byte 13 bit1)
|
|
||||||
* are SKIPPED to keep the panel stable.
|
|
||||||
*
|
*
|
||||||
* Wiring (GPIO4→SDA, GPIO5→SCL, GPIO10→RST, GPIO11→BUSY, 3V3→VCC, GND→GND)
|
* Wiring (GPIO4→SDA, GPIO5→SCL, GPIO10→RST, GPIO11→BUSY, 3V3→VCC, GND→GND)
|
||||||
*/
|
*/
|
||||||
|
|
@ -95,14 +89,13 @@ static void epd_write(const uint8_t *frame, uint8_t extra_byte)
|
||||||
i2c_master_transmit(cmd_dev, s, sizeof(s), pdMS_TO_TICKS(100));
|
i2c_master_transmit(cmd_dev, s, sizeof(s), pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show one bit of one byte on a BLANK background. */
|
/* Show byte13 with ONLY the given bit set (blank elsewhere). */
|
||||||
static void show_blank_plus(uint8_t frame_byte, uint8_t phys_bit, int tag)
|
static void show_b13(uint8_t value, int tag, const char *note)
|
||||||
{
|
{
|
||||||
uint8_t f[FRAME_LEN];
|
uint8_t f[FRAME_LEN];
|
||||||
memset(f, 0, FRAME_LEN);
|
memset(f, 0, FRAME_LEN);
|
||||||
f[frame_byte] |= (uint8_t)(1u << phys_bit);
|
f[13] = value;
|
||||||
ESP_LOGI("iconfinder", "T%d: byte %d bit %d (global %d)",
|
ESP_LOGI("icon2", "T%d: f[13]=0x%02x (%s)", tag, value, note);
|
||||||
tag, frame_byte, phys_bit, frame_byte * 8 + phys_bit);
|
|
||||||
|
|
||||||
uint8_t off[FRAME_LEN];
|
uint8_t off[FRAME_LEN];
|
||||||
memset(off, 0, FRAME_LEN);
|
memset(off, 0, FRAME_LEN);
|
||||||
|
|
@ -125,7 +118,7 @@ static void boot_init(void)
|
||||||
static void wait_for_advance(void)
|
static void wait_for_advance(void)
|
||||||
{
|
{
|
||||||
if (ADVANCE_MODE == 0) { vTaskDelay(pdMS_TO_TICKS(AUTO_HOLD_MS)); return; }
|
if (ADVANCE_MODE == 0) { vTaskDelay(pdMS_TO_TICKS(AUTO_HOLD_MS)); return; }
|
||||||
ESP_LOGI("iconfinder", "press BOOT to advance next...");
|
ESP_LOGI("icon2", "press BOOT to advance next...");
|
||||||
int64_t t_start = esp_timer_get_time();
|
int64_t t_start = esp_timer_get_time();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (gpio_get_level(PIN_BOOT) == 0) {
|
if (gpio_get_level(PIN_BOOT) == 0) {
|
||||||
|
|
@ -136,7 +129,7 @@ static void wait_for_advance(void)
|
||||||
}
|
}
|
||||||
if (BOOT_TIMEOUT_MS > 0 &&
|
if (BOOT_TIMEOUT_MS > 0 &&
|
||||||
esp_timer_get_time() - t_start > BOOT_TIMEOUT_MS * 1000LL) {
|
esp_timer_get_time() - t_start > BOOT_TIMEOUT_MS * 1000LL) {
|
||||||
ESP_LOGW("iconfinder", "no BOOT press in %d ms", BOOT_TIMEOUT_MS);
|
ESP_LOGW("icon2", "no BOOT press in %d ms", BOOT_TIMEOUT_MS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(20));
|
vTaskDelay(pdMS_TO_TICKS(20));
|
||||||
|
|
@ -176,38 +169,47 @@ void app_main(void)
|
||||||
boot_init();
|
boot_init();
|
||||||
epd_init();
|
epd_init();
|
||||||
|
|
||||||
ESP_LOGI("iconfinder", "== Probe icon-region bytes on blank panel ==");
|
ESP_LOGI("icon2", "== Probe f[13] bits for Bluetooth (3) & power (4) icons ==");
|
||||||
|
|
||||||
int tag = 0;
|
/* Single bits of byte 13 (skip bit1 = known black control). */
|
||||||
|
show_b13(0x01, 1, "bit0 (C stroke)");
|
||||||
|
wait_for_advance();
|
||||||
|
|
||||||
/* byte 0 bits 5-7 (leading-1 glyph is bits 0-4; high bits unknown) */
|
show_b13(0x02, 2, "bit1 (SKIPPED-guard, black ctrl)");
|
||||||
for (int b = 5; b < 8; b++) { show_blank_plus(0, b, ++tag); wait_for_advance(); }
|
wait_for_advance(); // just wait, we already know it blackens
|
||||||
|
|
||||||
/* byte 4 (top-ones second byte): we know bits 0-3 = glyph right col,
|
show_b13(0x04, 3, "bit2 (C stroke)");
|
||||||
* bit 5 = decimal. The icon candidates are bits 4,6,7. Probe those. */
|
wait_for_advance();
|
||||||
for (int b = 4; b < 8; b++) {
|
|
||||||
if (b == 5) continue; /* decimal, already known */
|
|
||||||
show_blank_plus(4, b, ++tag); wait_for_advance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* byte 8 (bottom-ones second byte): same reasoning, bits 4,6,7 */
|
show_b13(0x08, 4, "bit3 = BLUETOOTH?");
|
||||||
for (int b = 4; b < 8; b++) {
|
wait_for_advance();
|
||||||
if (b == 5) continue; /* decimal, already known */
|
|
||||||
show_blank_plus(8, b, ++tag); wait_for_advance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* byte 10 (bottom-tenths second byte): bits 4,6,7 (bit5=percent) */
|
show_b13(0x10, 5, "bit4 = POWER/BATTERY?");
|
||||||
for (int b = 4; b < 8; b++) {
|
wait_for_advance();
|
||||||
if (b == 5) continue; /* percent, already known */
|
|
||||||
show_blank_plus(10, b, ++tag); wait_for_advance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* byte 14 all bits (manual says unused - confirm) */
|
show_b13(0x20, 6, "bit5");
|
||||||
for (int b = 0; b < 8; b++) {
|
wait_for_advance();
|
||||||
show_blank_plus(14, b, ++tag); wait_for_advance();
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI("iconfinder", "== Done. ==");
|
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];
|
uint8_t off[FRAME_LEN];
|
||||||
memset(off, 0, FRAME_LEN);
|
memset(off, 0, FRAME_LEN);
|
||||||
epd_lut_DU_WB();
|
epd_lut_DU_WB();
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,13 @@ static const uint8_t DIG_L[10][2] = {
|
||||||
#define BIT_DP_BOT 0x20 /* f[8] */
|
#define BIT_DP_BOT 0x20 /* f[8] */
|
||||||
#define BIT_PERCENT 0x20 /* f[10] */
|
#define BIT_PERCENT 0x20 /* f[10] */
|
||||||
|
|
||||||
|
/* Status icons in f[13] (empirically verified, see PROJECT_MEMORY.md) */
|
||||||
|
#define ICON_DEGC 0x05 /* °C (degree + C) */
|
||||||
|
#define ICON_DEGF 0x06 /* °F */
|
||||||
|
#define ICON_BT 0x08 /* Bluetooth */
|
||||||
|
#define ICON_BAT 0x10 /* battery/power */
|
||||||
|
#define ICON_BT_BAT 0x1D /* °C + Bluetooth + battery */
|
||||||
|
|
||||||
static void epd_wait_busy(void) {
|
static void epd_wait_busy(void) {
|
||||||
/* BUSY_N: LOW = busy, HIGH = ready */
|
/* BUSY_N: LOW = busy, HIGH = ready */
|
||||||
while (gpio_get_level(PIN_BUSY) == 0) vTaskDelay(1);
|
while (gpio_get_level(PIN_BUSY) == 0) vTaskDelay(1);
|
||||||
|
|
@ -123,7 +130,7 @@ static void render_temp(uint8_t *f, float t) {
|
||||||
f[0] |= 0x1f; /* left column of the leading "1" glyph */
|
f[0] |= 0x1f; /* left column of the leading "1" glyph */
|
||||||
}
|
}
|
||||||
// °C
|
// °C
|
||||||
f[13] = 0x05;
|
f[13] = ICON_DEGC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render a value (0-99.9) to the bottom line: [tens][ones].[tenths]% */
|
/* Render a value (0-99.9) to the bottom line: [tens][ones].[tenths]% */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue