From 351c23cc4449d040c749c7b1b7ccac3e8691470c Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Fri, 27 Feb 2026 18:36:19 +1100 Subject: [PATCH] new emojis --- .../companion_radio/ui-new/Emojisprites.h | 207 +++++++++++++++++- examples/companion_radio/ui-new/emojipicker.h | 21 +- 2 files changed, 224 insertions(+), 4 deletions(-) diff --git a/examples/companion_radio/ui-new/Emojisprites.h b/examples/companion_radio/ui-new/Emojisprites.h index 5319f307..b9b21587 100644 --- a/examples/companion_radio/ui-new/Emojisprites.h +++ b/examples/companion_radio/ui-new/Emojisprites.h @@ -3,7 +3,7 @@ // Emoji sprites for e-ink display - dual size // Large (12x12) for compose/picker, Small (10x10) for channel view // MSB-first, 2 bytes per row -// 46 total emoji: joy/thumbsup/frown first, then 43 original (telephone removed) +// 65 total emoji: joy/thumbsup/frown first, then 43 original, then 19 new #include #ifdef ESP32 @@ -15,11 +15,11 @@ #define EMOJI_SM_W 10 #define EMOJI_SM_H 10 -#define EMOJI_COUNT 46 +#define EMOJI_COUNT 65 // Escape codes in 0x80+ range - safe from keyboard ASCII (32-126) #define EMOJI_ESCAPE_START 0x80 -#define EMOJI_ESCAPE_END 0xAD // 0x80 + 45 +#define EMOJI_ESCAPE_END 0xC0 // 0x80 + 64 #define EMOJI_PAD_BYTE 0x7F // DEL, not typeable (key < 127 guard) // ======== LARGE 12x12 SPRITES ======== @@ -208,6 +208,82 @@ static const uint8_t emoji_lg_peach[] PROGMEM = { static const uint8_t emoji_lg_racing_car[] PROGMEM = { 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x07,0x80, 0x0F,0xC0, 0x7F,0xE0, 0xFF,0xF0, 0xFF,0xF0, 0x6F,0x60, 0x49,0x20, 0x00,0x00, 0x00,0x00, }; +// [46] mouse 🐭 +static const uint8_t emoji_lg_mouse[] PROGMEM = { + 0x30,0xC0, 0x79,0xE0, 0x79,0xE0, 0x3F,0xC0, 0x49,0x20, 0x80,0x10, 0x86,0x10, 0x89,0x10, 0x40,0x20, 0x20,0x40, 0x1F,0x80, 0x00,0x00, +}; +// [47] mushroom 🍄 +static const uint8_t emoji_lg_mushroom[] PROGMEM = { + 0x1F,0x80, 0x3F,0xC0, 0x7F,0xE0, 0xE6,0x70, 0xE6,0x70, 0x7F,0xE0, 0x3F,0xC0, 0x0F,0x00, 0x0F,0x00, 0x0F,0x00, 0x1F,0x80, 0x00,0x00, +}; +// [48] biohazard ☣️ +static const uint8_t emoji_lg_biohazard[] PROGMEM = { + 0x0F,0x00, 0x1F,0x80, 0x3F,0xC0, 0x1F,0x80, 0x0F,0x00, 0x66,0x60, 0x76,0xE0, 0x70,0xE0, 0x79,0xE0, 0x39,0xC0, 0x19,0x80, 0x00,0x00, +}; +// [49] panda 🐼 +static const uint8_t emoji_lg_panda[] PROGMEM = { + 0x00,0x00, 0x60,0x60, 0xF0,0xF0, 0xF0,0xF0, 0x7F,0xE0, 0x59,0xA0, 0x59,0xA0, 0x40,0x20, 0x46,0x20, 0x20,0x40, 0x1F,0x80, 0x00,0x00, +}; +// [50] anger 💢 +static const uint8_t emoji_lg_anger[] PROGMEM = { + 0x00,0x00, 0x3C,0xC0, 0x3C,0xC0, 0x30,0xC0, 0x30,0x00, 0x00,0x00, 0x00,0x00, 0x00,0xC0, 0x30,0xC0, 0x33,0xC0, 0x33,0xC0, 0x00,0x00, +}; +// [51] dragon_face 🐲 +static const uint8_t emoji_lg_dragon_face[] PROGMEM = { + 0xC0,0x30, 0xE0,0x70, 0x76,0xE0, 0x3F,0xC0, 0x69,0x60, 0x40,0x20, 0x4F,0x20, 0x29,0x40, 0x30,0xC0, 0x1F,0x80, 0x00,0x00, 0x00,0x00, +}; +// [52] pager 📟 +static const uint8_t emoji_lg_pager[] PROGMEM = { + 0x00,0x00, 0x7F,0xE0, 0x40,0x20, 0x5F,0xA0, 0x5F,0xA0, 0x40,0x20, 0x5B,0x20, 0x5B,0x20, 0x40,0x20, 0x7F,0xE0, 0x00,0x00, 0x00,0x00, +}; +// [53] bee 🐝 +static const uint8_t emoji_lg_bee[] PROGMEM = { + 0x00,0x00, 0x19,0x80, 0x19,0x80, 0x3F,0x80, 0x7F,0xC0, 0x7F,0xE0, 0x7F,0xE0, 0x7F,0xC0, 0x3F,0x80, 0x1F,0x40, 0x0A,0x00, 0x00,0x00, +}; +// [54] bulb 💡 +static const uint8_t emoji_lg_bulb[] PROGMEM = { + 0x1F,0x80, 0x20,0x40, 0x40,0x20, 0x40,0x20, 0x40,0x20, 0x20,0x40, 0x30,0xC0, 0x1F,0x80, 0x16,0x80, 0x1F,0x80, 0x0F,0x00, 0x00,0x00, +}; +// [55] cat 🐱 +static const uint8_t emoji_lg_cat[] PROGMEM = { + 0x40,0x20, 0x60,0x60, 0x70,0xE0, 0x3F,0xC0, 0x59,0xA0, 0x40,0x20, 0x40,0x20, 0x46,0x20, 0x29,0x40, 0x30,0xC0, 0x1F,0x80, 0x00,0x00, +}; +// [56] fleur ⚜️ +static const uint8_t emoji_lg_fleur[] PROGMEM = { + 0x06,0x00, 0x06,0x00, 0x0F,0x00, 0x6F,0x60, 0xF6,0xF0, 0xF6,0xF0, 0x76,0xE0, 0x3F,0xC0, 0x1F,0x80, 0x0F,0x00, 0x19,0x80, 0x00,0x00, +}; +// [57] moon 🌔 +static const uint8_t emoji_lg_moon[] PROGMEM = { + 0x1F,0x80, 0x3F,0xC0, 0x7F,0xE0, 0x7F,0x80, 0xFF,0x80, 0xFF,0x00, 0xFF,0x00, 0xFF,0x80, 0x7F,0x80, 0x7F,0xE0, 0x3F,0xC0, 0x1F,0x80, +}; +// [58] coffee ☕ +static const uint8_t emoji_lg_coffee[] PROGMEM = { + 0x24,0x80, 0x12,0x40, 0x00,0x00, 0x7F,0xC0, 0x40,0x70, 0x40,0x50, 0x40,0x50, 0x40,0x70, 0x7F,0xC0, 0x00,0x00, 0xFF,0xC0, 0x00,0x00, +}; +// [59] tooth 🦷 +static const uint8_t emoji_lg_tooth[] PROGMEM = { + 0x3F,0xC0, 0x7F,0xE0, 0xFF,0xF0, 0xFF,0xF0, 0xFF,0xF0, 0x7F,0xE0, 0x3F,0xC0, 0x3F,0xC0, 0x39,0xC0, 0x39,0xC0, 0x30,0xC0, 0x20,0x40, +}; +// [60] pretzel 🥨 +static const uint8_t emoji_lg_pretzel[] PROGMEM = { + 0x39,0xC0, 0x46,0x20, 0x80,0x20, 0x86,0x10, 0x49,0x20, 0x30,0xC0, 0x30,0xC0, 0x49,0x20, 0x86,0x10, 0x80,0x10, 0x46,0x20, 0x39,0xC0, +}; +// [61] abacus 🧮 +static const uint8_t emoji_lg_abacus[] PROGMEM = { + 0xFF,0xF0, 0x80,0x10, 0xB6,0x50, 0x80,0x10, 0xA6,0x90, 0x80,0x10, 0x94,0xD0, 0x80,0x10, 0xB2,0x50, 0x80,0x10, 0xFF,0xF0, 0x00,0x00, +}; +// [62] moai 🗿 +static const uint8_t emoji_lg_moai[] PROGMEM = { + 0x3F,0xC0, 0x7F,0xC0, 0x7F,0xC0, 0x39,0xC0, 0x39,0xC0, 0x3F,0xC0, 0x27,0x40, 0x3F,0x80, 0x2F,0x00, 0x3F,0x00, 0x3F,0x00, 0x1E,0x00, +}; +// [63] tipping 💁 +static const uint8_t emoji_lg_tipping[] PROGMEM = { + 0x1E,0x00, 0x3F,0x00, 0x3F,0x00, 0x1E,0x00, 0x0C,0x00, 0x1E,0x00, 0x3F,0x00, 0x7F,0x80, 0x0C,0xE0, 0x0D,0xE0, 0x12,0xE0, 0x33,0x00, +}; +// [64] hedgehog 🦔 +static const uint8_t emoji_lg_hedgehog[] PROGMEM = { + 0x00,0x00, 0x0A,0x80, 0x15,0x40, 0x2A,0xA0, 0x55,0x60, 0x7E,0xF0, 0xDB,0x90, 0xFF,0xD0, 0x7F,0xE0, 0x3F,0xC0, 0x24,0x80, 0x00,0x00, +}; static const uint8_t* const EMOJI_SPRITES_LG[] PROGMEM = { emoji_lg_joy, emoji_lg_thumbsup, emoji_lg_frown, @@ -220,6 +296,11 @@ static const uint8_t* const EMOJI_SPRITES_LG[] PROGMEM = { emoji_lg_kangaroo, emoji_lg_feather, emoji_lg_bright, emoji_lg_part_alt, emoji_lg_motorboat, emoji_lg_domino, emoji_lg_satellite, emoji_lg_customs, emoji_lg_cowboy, emoji_lg_wheel, emoji_lg_koala, emoji_lg_control_knobs, emoji_lg_peach, emoji_lg_racing_car, + emoji_lg_mouse, emoji_lg_mushroom, emoji_lg_biohazard, emoji_lg_panda, + emoji_lg_anger, emoji_lg_dragon_face, emoji_lg_pager, emoji_lg_bee, + emoji_lg_bulb, emoji_lg_cat, emoji_lg_fleur, emoji_lg_moon, + emoji_lg_coffee, emoji_lg_tooth, emoji_lg_pretzel, emoji_lg_abacus, + emoji_lg_moai, emoji_lg_tipping, emoji_lg_hedgehog, }; // ======== SMALL 10x10 SPRITES ======== @@ -362,6 +443,82 @@ static const uint8_t emoji_sm_peach[] PROGMEM = { static const uint8_t emoji_sm_racing_car[] PROGMEM = { 0x00,0x00, 0x00,0x00, 0x0E,0x00, 0x1F,0x00, 0x7F,0x80, 0xFF,0xC0, 0xFF,0xC0, 0x5E,0x80, 0x00,0x00, 0x00,0x00, }; +// [46] mouse 🐭 +static const uint8_t emoji_sm_mouse[] PROGMEM = { + 0x61,0x80, 0xF3,0xC0, 0x7F,0x80, 0x92,0x40, 0x80,0x40, 0x8C,0x40, 0x52,0x80, 0x40,0x80, 0x3F,0x00, 0x00,0x00, +}; +// [47] mushroom 🍄 +static const uint8_t emoji_sm_mushroom[] PROGMEM = { + 0x3F,0x00, 0x7F,0x80, 0xED,0xC0, 0xED,0xC0, 0x7F,0x80, 0x3F,0x00, 0x1E,0x00, 0x1E,0x00, 0x3F,0x00, 0x00,0x00, +}; +// [48] biohazard ☣️ +static const uint8_t emoji_sm_biohazard[] PROGMEM = { + 0x1E,0x00, 0x3F,0x00, 0x3F,0x00, 0x1E,0x00, 0x6D,0x80, 0x73,0x80, 0x73,0x80, 0x7B,0x80, 0x33,0x00, 0x00,0x00, +}; +// [49] panda 🐼 +static const uint8_t emoji_sm_panda[] PROGMEM = { + 0xC0,0xC0, 0xF3,0xC0, 0x7F,0x80, 0xB3,0x40, 0xB3,0x40, 0x80,0x40, 0x4C,0x80, 0x21,0x00, 0x3F,0x00, 0x00,0x00, +}; +// [50] anger 💢 +static const uint8_t emoji_sm_anger[] PROGMEM = { + 0x00,0x00, 0x73,0x00, 0x73,0x00, 0x63,0x00, 0x60,0x00, 0x01,0x80, 0x63,0x00, 0x67,0x00, 0x67,0x00, 0x00,0x00, +}; +// [51] dragon_face 🐲 +static const uint8_t emoji_sm_dragon_face[] PROGMEM = { + 0xC0,0xC0, 0xED,0xC0, 0x7F,0x80, 0x52,0x80, 0x40,0x80, 0x4C,0x80, 0x33,0x00, 0x2D,0x00, 0x1E,0x00, 0x00,0x00, +}; +// [52] pager 📟 +static const uint8_t emoji_sm_pager[] PROGMEM = { + 0x00,0x00, 0x7F,0x80, 0x40,0x80, 0x5E,0x80, 0x40,0x80, 0x5A,0x80, 0x5A,0x80, 0x40,0x80, 0x7F,0x80, 0x00,0x00, +}; +// [53] bee 🐝 +static const uint8_t emoji_sm_bee[] PROGMEM = { + 0x33,0x00, 0x33,0x00, 0x7F,0x00, 0xFF,0x80, 0xFF,0xC0, 0xFF,0x80, 0x7F,0x00, 0x3E,0x80, 0x14,0x00, 0x00,0x00, +}; +// [54] bulb 💡 +static const uint8_t emoji_sm_bulb[] PROGMEM = { + 0x3F,0x00, 0x40,0x80, 0x80,0x40, 0x80,0x40, 0x40,0x80, 0x33,0x00, 0x3F,0x00, 0x1E,0x00, 0x1E,0x00, 0x00,0x00, +}; +// [55] cat 🐱 +static const uint8_t emoji_sm_cat[] PROGMEM = { + 0x80,0x40, 0xC0,0xC0, 0x7F,0x80, 0xB3,0x40, 0x80,0x40, 0x8C,0x40, 0x52,0x80, 0x61,0x80, 0x3F,0x00, 0x00,0x00, +}; +// [56] fleur ⚜️ +static const uint8_t emoji_sm_fleur[] PROGMEM = { + 0x0C,0x00, 0x0C,0x00, 0x6D,0x80, 0xED,0xC0, 0xED,0xC0, 0x6D,0x80, 0x3F,0x00, 0x1E,0x00, 0x33,0x00, 0x00,0x00, +}; +// [57] moon 🌔 +static const uint8_t emoji_sm_moon[] PROGMEM = { + 0x3F,0x00, 0x7F,0x80, 0xFF,0x80, 0xFE,0x00, 0xFE,0x00, 0xFE,0x00, 0xFE,0x00, 0xFF,0x80, 0x7F,0x80, 0x3F,0x00, +}; +// [58] coffee ☕ +static const uint8_t emoji_sm_coffee[] PROGMEM = { + 0x49,0x00, 0x24,0x80, 0x00,0x00, 0xFF,0x00, 0x81,0xC0, 0x81,0x40, 0x81,0xC0, 0xFF,0x00, 0x00,0x00, 0xFE,0x00, +}; +// [59] tooth 🦷 +static const uint8_t emoji_sm_tooth[] PROGMEM = { + 0x7F,0x80, 0xFF,0xC0, 0xFF,0xC0, 0xFF,0xC0, 0x7F,0x80, 0x3F,0x00, 0x3B,0x80, 0x31,0x80, 0x20,0x80, 0x00,0x00, +}; +// [60] pretzel 🥨 +static const uint8_t emoji_sm_pretzel[] PROGMEM = { + 0x73,0x80, 0x9E,0x40, 0x8C,0x40, 0x52,0x80, 0x33,0x00, 0x33,0x00, 0x52,0x80, 0x8C,0x40, 0x9E,0x40, 0x73,0x80, +}; +// [61] abacus 🧮 +static const uint8_t emoji_sm_abacus[] PROGMEM = { + 0xFF,0xC0, 0x80,0x40, 0xB5,0x40, 0x80,0x40, 0xAD,0x40, 0x80,0x40, 0xAB,0x40, 0x80,0x40, 0xFF,0xC0, 0x00,0x00, +}; +// [62] moai 🗿 +static const uint8_t emoji_sm_moai[] PROGMEM = { + 0x7F,0x00, 0x7F,0x00, 0x33,0x00, 0x33,0x00, 0x3F,0x00, 0x2E,0x00, 0x3E,0x00, 0x3E,0x00, 0x3E,0x00, 0x1C,0x00, +}; +// [63] tipping 💁 +static const uint8_t emoji_sm_tipping[] PROGMEM = { + 0x3C,0x00, 0x7E,0x00, 0x7E,0x00, 0x3C,0x00, 0x18,0x00, 0x3C,0x00, 0x7E,0x00, 0x1B,0x80, 0x1B,0x80, 0x36,0x00, +}; +// [64] hedgehog 🦔 +static const uint8_t emoji_sm_hedgehog[] PROGMEM = { + 0x15,0x00, 0x2A,0x80, 0x55,0x40, 0xFF,0xC0, 0xDB,0x40, 0xFF,0x80, 0x7F,0x80, 0x3F,0x00, 0x24,0x00, 0x00,0x00, +}; static const uint8_t* const EMOJI_SPRITES_SM[] PROGMEM = { emoji_sm_joy, emoji_sm_thumbsup, emoji_sm_frown, @@ -374,6 +531,11 @@ static const uint8_t* const EMOJI_SPRITES_SM[] PROGMEM = { emoji_sm_kangaroo, emoji_sm_feather, emoji_sm_bright, emoji_sm_part_alt, emoji_sm_motorboat, emoji_sm_domino, emoji_sm_satellite, emoji_sm_customs, emoji_sm_cowboy, emoji_sm_wheel, emoji_sm_koala, emoji_sm_control_knobs, emoji_sm_peach, emoji_sm_racing_car, + emoji_sm_mouse, emoji_sm_mushroom, emoji_sm_biohazard, emoji_sm_panda, + emoji_sm_anger, emoji_sm_dragon_face, emoji_sm_pager, emoji_sm_bee, + emoji_sm_bulb, emoji_sm_cat, emoji_sm_fleur, emoji_sm_moon, + emoji_sm_coffee, emoji_sm_tooth, emoji_sm_pretzel, emoji_sm_abacus, + emoji_sm_moai, emoji_sm_tipping, emoji_sm_hedgehog, }; // ---- Codepoint lookup for UTF-8 conversion ---- @@ -426,10 +588,37 @@ static const EmojiCodepoint EMOJI_CODEPOINTS[EMOJI_COUNT] = { { 0x1F39B, 0x0000, 0xAB }, // control_knobs { 0x1F351, 0x0000, 0xAC }, // peach { 0x1F3CE, 0x0000, 0xAD }, // racing_car + { 0x1F42D, 0x0000, 0xAE }, // mouse + { 0x1F344, 0x0000, 0xAF }, // mushroom + { 0x2623, 0x0000, 0xB0 }, // biohazard + { 0x1F43C, 0x0000, 0xB1 }, // panda + { 0x1F4A2, 0x0000, 0xB2 }, // anger + { 0x1F432, 0x0000, 0xB3 }, // dragon_face + { 0x1F4DF, 0x0000, 0xB4 }, // pager + { 0x1F41D, 0x0000, 0xB5 }, // bee + { 0x1F4A1, 0x0000, 0xB6 }, // bulb + { 0x1F431, 0x0000, 0xB7 }, // cat + { 0x269C, 0x0000, 0xB8 }, // fleur + { 0x1F314, 0x0000, 0xB9 }, // moon + { 0x2615, 0x0000, 0xBA }, // coffee + { 0x1F9B7, 0x0000, 0xBB }, // tooth + { 0x1F968, 0x0000, 0xBC }, // pretzel + { 0x1F9EE, 0x0000, 0xBD }, // abacus + { 0x1F5FF, 0x0000, 0xBE }, // moai + { 0x1F481, 0x0000, 0xBF }, // tipping + { 0x1F994, 0x0000, 0xC0 }, // hedgehog }; // ---- Helper functions ---- +// Alias table: extra codepoints that map to existing emoji escape bytes. +// Used for variant codepoints (e.g. MWD node identifier 🂎 U+1F08E -> domino sprite) +struct EmojiAlias { uint32_t cp; uint8_t escape; }; +#define EMOJI_ALIAS_COUNT 1 +static const EmojiAlias EMOJI_ALIASES[EMOJI_ALIAS_COUNT] = { + { 0x1F08E, 0xA5 }, // domino tile (MWD node signifier) -> domino sprite +}; + static uint32_t emojiDecodeUtf8(const uint8_t* s, int remaining, int* bytes_consumed) { uint8_t b0 = s[0]; if (b0 < 0x80) { *bytes_consumed = 1; return b0; } @@ -483,6 +672,18 @@ static void emojiSanitize(const char* src, char* dst, int dstLen) { found = true; break; } } + if (!found) { + // Check alias table for variant codepoints + for (int a = 0; a < EMOJI_ALIAS_COUNT; a++) { + if (EMOJI_ALIASES[a].cp == cp) { + dst[di++] = EMOJI_ALIASES[a].escape; + si += consumed; + // Skip trailing variation selector U+FE0F + if (si + 2 < srcLen && s[si] == 0xEF && s[si+1] == 0xB8 && s[si+2] == 0x8F) si += 3; + found = true; break; + } + } + } if (!found) si += consumed; // Skip unknown multi-byte chars } else { dst[di++] = (char)b; diff --git a/examples/companion_radio/ui-new/emojipicker.h b/examples/companion_radio/ui-new/emojipicker.h index 6ebb2969..0469ca1c 100644 --- a/examples/companion_radio/ui-new/emojipicker.h +++ b/examples/companion_radio/ui-new/emojipicker.h @@ -1,7 +1,7 @@ #pragma once // Emoji Picker with scrolling grid and scroll bar -// 5 columns, 4 visible rows, scrollable through all 46 emoji +// 5 columns, 4 visible rows, scrollable through all 65 emoji // WASD navigation, Enter to select, $/Q/Backspace to cancel #include @@ -58,6 +58,25 @@ static const char* EMOJI_LABELS[EMOJI_COUNT] = { "Knob", // 43 control_knobs "Pch", // 44 peach "Race", // 45 racing_car + "Mous", // 46 mouse + "Shrm", // 47 mushroom + "Bio", // 48 biohazard + "Pnda", // 49 panda + "Bang", // 50 anger + "DrgF", // 51 dragon_face + "Pagr", // 52 pager + "Bee", // 53 bee + "Bulb", // 54 bulb + "Cat", // 55 cat + "Flur", // 56 fleur + "Moon", // 57 moon + "Cafe", // 58 coffee + "Toth", // 59 tooth + "Prtz", // 60 pretzel + "Abac", // 61 abacus + "Moai", // 62 moai + "Hiii", // 63 tipping + "Hedg", // 64 hedgehog }; struct EmojiPicker {