mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
- Replace single-letter M/B/A/G top-bar indicators with scalable mini-icons: ICON_MUTE (speaker+cross), ICON_BLUETOOTH (rune), ICON_ADVERT (broadcast mast+waves), ICON_TRAIL (map pin). Centred in the cw+2 indicator box; disconnected BT shows the plain glyph instead of lowercase b. - fix(settings): right-side values used display.valCol() without the scrollbar reserve, so after expanding a section they rendered under the indicator. Route all value cursors through valCol(display) = display.valCol() - _reserve. - fix(settings): font toggle used ^=1, which on a stale value of 2 (older Hybrid build) flips 2<->3 — both nonzero, locking applyFont() on Lemon with no way back. Normalise: use_lemon_font = use_lemon_font ? 0 : 1. - docs(settings): document Messages > Resend setting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
405 lines
17 KiB
C++
405 lines
17 KiB
C++
#pragma once
|
||
|
||
#include <stdint.h>
|
||
#include <helpers/ui/DisplayDriver.h>
|
||
|
||
// ── Scalable mini-icons ──────────────────────────────────────────────────────
|
||
// Small procedural glyphs (delivery markers, etc.) authored on a 1× pixel grid
|
||
// and scaled to the current font, so they stay legible on large-font layouts
|
||
// (e.g. landscape e-ink renders text at 2×). Distinct from the XBM page icons
|
||
// further down, which are fixed-size full bitmaps drawn via drawXbm().
|
||
//
|
||
// To add a mini-icon:
|
||
// 1. Draw it as ASCII-art rows, one string per row (width ≤ 8): any char
|
||
// other than ' ' or '.' is a filled pixel. packRow() packs each string
|
||
// into one byte at compile time, so the strings never reach flash — the
|
||
// binary holds only the packed bytes, identical to hand-written hex.
|
||
// 2. Wrap the rows in a MINI_ICON(name, width, ...) — width and row count are
|
||
// bundled with the data, so the draw site carries no magic numbers.
|
||
// 3. Draw it with miniIconDraw(display, x, topY, name).
|
||
// Scaling is automatic — no per-display handling needed.
|
||
//
|
||
// packRow() is written as a single-expression recursion so it stays a valid
|
||
// constant expression on any C++ standard the firmware targets (≥ C++11), not
|
||
// just the relaxed C++14 constexpr with loops. It packs up to the string's NUL
|
||
// (capped at 8 cols), so width lives once in MINI_ICON, not in every row.
|
||
constexpr uint8_t packBit(const char* s, int x) {
|
||
return (s[x] && s[x] != ' ' && s[x] != '.') ? (uint8_t)(1u << x) : 0;
|
||
}
|
||
constexpr uint8_t packRow(const char* s, int x = 0) {
|
||
return (!s[x] || x >= 8) ? 0 : (uint8_t)(packBit(s, x) | packRow(s, x + 1));
|
||
}
|
||
|
||
// A mini-icon bundles its pixel data with its dimensions, so call sites can't
|
||
// pass a stale width/height. Built via the MINI_ICON macro below.
|
||
struct MiniIcon { uint8_t w, h; const uint8_t* rows; };
|
||
|
||
// Define a mini-icon: the row count (height) is derived from the initializer,
|
||
// the width is stated once. Emits a packed byte array plus a MiniIcon view.
|
||
#define MINI_ICON(name, width, ...) \
|
||
static constexpr uint8_t name##_rows[] = { __VA_ARGS__ }; \
|
||
static constexpr MiniIcon name = { (uint8_t)(width), \
|
||
(uint8_t)sizeof(name##_rows), name##_rows }
|
||
|
||
// Pixel scale from the font: 1× on an 8px OLED line, 2× on a 16px landscape
|
||
// e-ink line, etc. Bitmaps are authored on the 1× grid.
|
||
inline int miniIconScale(DisplayDriver& d) {
|
||
int s = d.getLineHeight() / 8;
|
||
return s < 1 ? 1 : s;
|
||
}
|
||
|
||
// Draw a w×h (w ≤ 8) bitmap with the current ink colour, scaled by the font and
|
||
// vertically centred in the text line that starts at top_y.
|
||
inline void miniIconDraw(DisplayDriver& d, int x, int top_y,
|
||
const uint8_t* rows, int w, int h) {
|
||
const int s = miniIconScale(d);
|
||
int y = top_y + (d.getLineHeight() - h * s) / 2;
|
||
if (y < top_y) y = top_y;
|
||
for (int r = 0; r < h; r++)
|
||
for (int c = 0; c < w; c++)
|
||
if (rows[r] & (1 << c)) d.fillRect(x + c * s, y + r * s, s, s);
|
||
}
|
||
|
||
// Preferred overload: dimensions travel with the icon — no magic numbers.
|
||
inline void miniIconDraw(DisplayDriver& d, int x, int top_y, const MiniIcon& ic) {
|
||
miniIconDraw(d, x, top_y, ic.rows, ic.w, ic.h);
|
||
}
|
||
|
||
// Draw a mini-icon at an exact top-left (no vertical centring). Used where the
|
||
// caller controls placement, e.g. flush to the top/bottom of a scroll track.
|
||
inline void miniIconDrawTop(DisplayDriver& d, int x, int y, const MiniIcon& ic) {
|
||
const int s = miniIconScale(d);
|
||
for (int r = 0; r < ic.h; r++)
|
||
for (int c = 0; c < ic.w; c++)
|
||
if (ic.rows[r] & (1 << c)) d.fillRect(x + c * s, y + r * s, s, s);
|
||
}
|
||
|
||
// Like miniIconDrawTop, but first lays down a 1px DARK halo that hugs the icon's
|
||
// shape (each pixel dilated by 1px), then the icon in LIGHT. Invisible on a dark
|
||
// row; on the LIGHT selection bar it outlines just the glyph — no boxed-in
|
||
// rectangle around it. Restores ink to LIGHT. clip_top bounds the halo so it
|
||
// can't bleed above a given y (e.g. onto a header separator just above the icon).
|
||
inline void miniIconDrawHalo(DisplayDriver& d, int x, int y, const MiniIcon& ic,
|
||
int clip_top = -100000) {
|
||
const int s = miniIconScale(d);
|
||
d.setColor(DisplayDriver::DARK);
|
||
for (int r = 0; r < ic.h; r++)
|
||
for (int c = 0; c < ic.w; c++)
|
||
if (ic.rows[r] & (1 << c)) {
|
||
int hy = y + r * s - 1, hh = s + 2;
|
||
if (hy < clip_top) { hh -= clip_top - hy; hy = clip_top; }
|
||
if (hh > 0) d.fillRect(x + c * s - 1, hy, s + 2, hh);
|
||
}
|
||
d.setColor(DisplayDriver::LIGHT);
|
||
for (int r = 0; r < ic.h; r++)
|
||
for (int c = 0; c < ic.w; c++)
|
||
if (ic.rows[r] & (1 << c)) d.fillRect(x + c * s, y + r * s, s, s);
|
||
}
|
||
|
||
// Horizontal row of `count` square dots (scaled, vertically centred). Used by
|
||
// the "awaiting ACK" marker, where the dot count = number of send attempts.
|
||
inline void miniIconDotRow(DisplayDriver& d, int x, int top_y, int count) {
|
||
const int s = miniIconScale(d);
|
||
const int dot = 2 * s, pitch = 3 * s; // 2px dot + 1px gap, scaled
|
||
int y = top_y + (d.getLineHeight() - dot) / 2;
|
||
if (y < top_y) y = top_y;
|
||
for (int i = 0; i < count; i++) d.fillRect(x + i * pitch, y, dot, dot);
|
||
}
|
||
|
||
// Mini-icon bitmaps (authored on the 1× grid as ASCII-art; see packRow above).
|
||
MINI_ICON(ICON_CHECK, 5, // ✓
|
||
packRow("....#"),
|
||
packRow("...#."),
|
||
packRow("#.#.."),
|
||
packRow(".#..."));
|
||
MINI_ICON(ICON_CROSS, 4, // ✗
|
||
packRow("#..#"),
|
||
packRow(".##."),
|
||
packRow(".##."),
|
||
packRow("#..#"));
|
||
|
||
// Top-bar status glyphs (replace the single-letter M / B / A indicators).
|
||
MINI_ICON(ICON_MUTE, 6, // speaker + cross (sound off)
|
||
packRow("..#..."),
|
||
packRow(".##..."),
|
||
packRow("####.#"),
|
||
packRow("###.#."),
|
||
packRow("####.#"),
|
||
packRow(".##..."),
|
||
packRow("..#..."));
|
||
MINI_ICON(ICON_BLUETOOTH, 5, // ᛒ bluetooth rune
|
||
packRow("..#.."),
|
||
packRow("..##."),
|
||
packRow("#.#.#"),
|
||
packRow(".###."),
|
||
packRow("#.#.#"),
|
||
packRow("..##."),
|
||
packRow("..#.."));
|
||
MINI_ICON(ICON_ADVERT, 6, // broadcast mast + radiating waves (auto-advert)
|
||
packRow("#....#"),
|
||
packRow(".#..#."),
|
||
packRow("..##.."),
|
||
packRow("..##.."),
|
||
packRow(".####."),
|
||
packRow(".####."));
|
||
|
||
MINI_ICON(ICON_TRAIL, 6, // map pin / location marker (GPS trail logging)
|
||
packRow(".####."),
|
||
packRow("######"),
|
||
packRow("##..##"),
|
||
packRow("######"),
|
||
packRow(".####."),
|
||
packRow("..##.."));
|
||
|
||
// Keyboard special-key glyphs.
|
||
MINI_ICON(ICON_SHIFT, 7, // ⇧ caps
|
||
packRow("...#..."),
|
||
packRow("..###.."),
|
||
packRow(".#####."),
|
||
packRow("#######"),
|
||
packRow("..###.."),
|
||
packRow("..###.."),
|
||
packRow("..###.."));
|
||
MINI_ICON(ICON_BACKSPACE, 8, // ⌫ delete-left (× knocked out of the arrow body)
|
||
packRow("...#####"),
|
||
packRow("..######"),
|
||
packRow(".###.#.#"),
|
||
packRow("#####.##"),
|
||
packRow(".###.#.#"),
|
||
packRow("..######"),
|
||
packRow("...#####"));
|
||
// Space ⎵ is wider than the 8-px mini-icon limit, so it is two halves drawn
|
||
// side by side (offset by ICON_SPACE_L.w * scale): ticks at both far ends + bar.
|
||
MINI_ICON(ICON_SPACE_L, 8,
|
||
packRow("#......."),
|
||
packRow("#......."),
|
||
packRow("#......."),
|
||
packRow("########"));
|
||
MINI_ICON(ICON_SPACE_R, 8,
|
||
packRow(".......#"),
|
||
packRow(".......#"),
|
||
packRow(".......#"),
|
||
packRow("########"));
|
||
|
||
// Scroll-indicator caps — small up/down triangles (authored on the 1× grid).
|
||
MINI_ICON(ICON_SCROLL_UP, 5, // ▲
|
||
packRow("..#.."),
|
||
packRow(".###."),
|
||
packRow("#####"));
|
||
MINI_ICON(ICON_SCROLL_DOWN, 5, // ▼
|
||
packRow("#####"),
|
||
packRow(".###."),
|
||
packRow("..#.."));
|
||
|
||
// Width of the right-edge column drawScrollIndicator occupies, or 0 when the
|
||
// list fits and no indicator is drawn. Subtract from a row's content width so
|
||
// text never runs under the scrollbar. Mirrors the column math below (5*scale
|
||
// triangle + 1px gap).
|
||
inline int scrollIndicatorReserve(DisplayDriver& d, int total, int visible) {
|
||
return (total > visible) ? 5 * miniIconScale(d) + 1 : 0;
|
||
}
|
||
|
||
// Right-edge scroll indicator: a proportional track + thumb topped/tailed with
|
||
// up/down triangle mini-icon caps. Drop-in replacement for
|
||
// DisplayDriver::drawScrollArrows that also shows how much of the list is on
|
||
// screen and where you are within it. Everything lives in a ~5px column at the
|
||
// right edge and scales with the font (mini-icon scale).
|
||
// top_y : y of the first visible row (top of the viewport)
|
||
// track_h : pixel height of the viewport (e.g. visible_rows * row_pitch)
|
||
// total : total number of items
|
||
// visible : items shown at once
|
||
// first : index of the first visible item (scroll offset)
|
||
inline void drawScrollIndicator(DisplayDriver& d, int top_y, int track_h,
|
||
int total, int visible, int first) {
|
||
if (total <= visible || track_h <= 0) return; // whole list fits — no indicator
|
||
if (first < 0) first = 0;
|
||
if (first > total - visible) first = total - visible;
|
||
|
||
const int s = miniIconScale(d);
|
||
const int col = 5 * s; // triangle / column width
|
||
const int th = 3 * s; // triangle height
|
||
const int x = d.width() - col; // indicator column origin
|
||
|
||
// Caps are static end-markers, always drawn flush at the very top / bottom of
|
||
// the track; the thumb travels in the fixed band between them. (They mark the
|
||
// track ends, not "more above/below", so they never vanish at the extremes.)
|
||
const int cap = th + 2; // triangle height + 2px gap
|
||
const int band_t = top_y + cap;
|
||
const int band_b = top_y + track_h - cap;
|
||
int band = band_b - band_t;
|
||
if (band < s) band = s;
|
||
|
||
const int bar_w = 3 * s; // odd width → centres exactly in the 5*s column
|
||
const int bar_x = x + (col - bar_w) / 2;
|
||
|
||
int thumb_h = (int)((long)band * visible / total);
|
||
if (thumb_h < th) thumb_h = th;
|
||
if (thumb_h > band) thumb_h = band;
|
||
const int span = total - visible; // > 0 here (total > visible)
|
||
const int thumb_y = band_t + (int)((long)(band - thumb_h) * first / span);
|
||
|
||
// Each marker is drawn with a 1px DARK halo: invisible on a normal (dark) row,
|
||
// but on the LIGHT selection bar it carves out contrast so the LIGHT marker
|
||
// stays visible. Avoids having to know which row is currently selected.
|
||
// Thumb: a rectangle, so a plain box halo matches its shape.
|
||
d.setColor(DisplayDriver::DARK);
|
||
d.fillRect(bar_x - 1, thumb_y - 1, bar_w + 2, thumb_h + 2);
|
||
d.setColor(DisplayDriver::LIGHT);
|
||
d.fillRect(bar_x, thumb_y, bar_w, thumb_h);
|
||
|
||
// Arrows: shape-hugging halo so they aren't boxed in on the selection bar.
|
||
// The top arrow clips its halo at top_y so it can't bite into the header
|
||
// separator sitting one pixel above the list area.
|
||
miniIconDrawHalo(d, x, top_y, ICON_SCROLL_UP, top_y);
|
||
miniIconDrawHalo(d, x, top_y + track_h - th, ICON_SCROLL_DOWN);
|
||
}
|
||
|
||
// ── Big ASCII-art icons (skeleton, not yet used) ─────────────────────────────
|
||
// Same authoring idea as the mini-icons but for full page glyphs up to 32 px
|
||
// wide: one uint32_t per row. The existing XBM bitmaps below (logo/bluetooth/…)
|
||
// stay hand-encoded; reach for this when adding a *new* big icon so it's
|
||
// readable in source. Drawn at 1× (page icons aren't font-scaled).
|
||
//
|
||
// To add one:
|
||
// BIG_ICON(MY_ICON, 16,
|
||
// packRow32("......####......"),
|
||
// packRow32(".....######....."),
|
||
// ...);
|
||
// bigIconDraw(display, x, y, MY_ICON);
|
||
constexpr uint32_t packBit32(const char* s, int x) {
|
||
return (s[x] && s[x] != ' ' && s[x] != '.') ? (1u << x) : 0u;
|
||
}
|
||
constexpr uint32_t packRow32(const char* s, int x = 0) {
|
||
return (!s[x] || x >= 32) ? 0u : (packBit32(s, x) | packRow32(s, x + 1));
|
||
}
|
||
|
||
struct BigIcon { uint8_t w, h; const uint32_t* rows; };
|
||
|
||
#define BIG_ICON(name, width, ...) \
|
||
static constexpr uint32_t name##_rows[] = { __VA_ARGS__ }; \
|
||
static constexpr BigIcon name = { \
|
||
(uint8_t)(width), \
|
||
(uint8_t)(sizeof(name##_rows) / sizeof(uint32_t)), name##_rows }
|
||
|
||
// Draw a packed big icon at 1× with the current ink colour, top-left at (x, y).
|
||
inline void bigIconDraw(DisplayDriver& d, int x, int y, const BigIcon& ic) {
|
||
for (int r = 0; r < ic.h; r++)
|
||
for (int c = 0; c < ic.w; c++)
|
||
if (ic.rows[r] & (1u << c)) d.fillRect(x + c, y + r, 1, 1);
|
||
}
|
||
|
||
// 'meshcore', 128x13px
|
||
static const uint8_t meshcore_logo [] = {
|
||
0x3c, 0x01, 0xe3, 0xff, 0xc7, 0xff, 0x8f, 0x03, 0x87, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe,
|
||
0x3c, 0x03, 0xe3, 0xff, 0xc7, 0xff, 0x8e, 0x03, 0x8f, 0xfe, 0x3f, 0xfe, 0x1f, 0xff, 0x1f, 0xfe,
|
||
0x3e, 0x03, 0xc3, 0xff, 0x8f, 0xff, 0x0e, 0x07, 0x8f, 0xfe, 0x7f, 0xfe, 0x1f, 0xff, 0x1f, 0xfc,
|
||
0x3e, 0x07, 0xc7, 0x80, 0x0e, 0x00, 0x0e, 0x07, 0x9e, 0x00, 0x78, 0x0e, 0x3c, 0x0f, 0x1c, 0x00,
|
||
0x3e, 0x0f, 0xc7, 0x80, 0x1e, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x70, 0x0e, 0x38, 0x0f, 0x3c, 0x00,
|
||
0x7f, 0x0f, 0xc7, 0xfe, 0x1f, 0xfc, 0x1f, 0xff, 0x1c, 0x00, 0x70, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
|
||
0x7f, 0x1f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
|
||
0x7f, 0x3f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x1e, 0x3f, 0xfe, 0x3f, 0xf0,
|
||
0x77, 0x3b, 0x87, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xfc, 0x38, 0x00,
|
||
0x77, 0xfb, 0x8f, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xf8, 0x38, 0x00,
|
||
0x73, 0xf3, 0x8f, 0xff, 0x0f, 0xff, 0x1c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x78, 0x7f, 0xf8,
|
||
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfe, 0x3c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x3c, 0x7f, 0xf8,
|
||
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfc, 0x3c, 0x0e, 0x1f, 0xf8, 0xff, 0xf8, 0x70, 0x3c, 0x7f, 0xf8,
|
||
};
|
||
|
||
static const uint8_t bluetooth_on[] = {
|
||
0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x30, 0x00, 0x00,
|
||
0x00, 0x3C, 0x00, 0x00,
|
||
0x00, 0x3E, 0x00, 0x00,
|
||
0x00, 0x3F, 0x80, 0x00,
|
||
0x00, 0x3F, 0xC0, 0x00,
|
||
0x00, 0x3B, 0xE0, 0x00,
|
||
0x30, 0x38, 0xF8, 0x00,
|
||
0x3C, 0x38, 0x7C, 0x00,
|
||
0x3E, 0x38, 0x7C, 0x00,
|
||
0x1F, 0xB8, 0xF8, 0x70,
|
||
0x07, 0xF9, 0xF0, 0x78,
|
||
0x03, 0xFF, 0xC0, 0x78,
|
||
0x00, 0xFF, 0x80, 0x3C,
|
||
0x00, 0x7F, 0x07, 0x1C,
|
||
0x00, 0x7E, 0x07, 0x1C,
|
||
0x03, 0xFF, 0x82, 0x1C,
|
||
0x03, 0xFF, 0xC0, 0x78,
|
||
0x07, 0xFB, 0xE0, 0x78,
|
||
0x0F, 0xB8, 0xF8, 0x70,
|
||
0x3E, 0x38, 0x7C, 0x00,
|
||
0x3C, 0x38, 0x7C, 0x00,
|
||
0x38, 0x38, 0xF8, 0x00,
|
||
0x00, 0x39, 0xF0, 0x00,
|
||
0x00, 0x3F, 0xC0, 0x00,
|
||
0x00, 0x3F, 0x80, 0x00,
|
||
0x00, 0x3E, 0x00, 0x00,
|
||
0x00, 0x3C, 0x00, 0x00,
|
||
0x00, 0x38, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00,
|
||
};
|
||
|
||
static const uint8_t bluetooth_off[] = {
|
||
0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x03, 0x80, 0x00,
|
||
0x00, 0x03, 0xC0, 0x00,
|
||
0x00, 0x03, 0xE0, 0x00,
|
||
0x38, 0x03, 0xF8, 0x00,
|
||
0x3C, 0x03, 0xFC, 0x00,
|
||
0x3E, 0x03, 0xBF, 0x00,
|
||
0x0F, 0x83, 0x8F, 0x80,
|
||
0x07, 0xC3, 0x87, 0xC0,
|
||
0x03, 0xF0, 0x03, 0xC0,
|
||
0x00, 0xF8, 0x0F, 0x80,
|
||
0x00, 0x7C, 0x0F, 0x00,
|
||
0x00, 0x1F, 0x0E, 0x00,
|
||
0x00, 0x0F, 0x80, 0x00,
|
||
0x00, 0x07, 0xE0, 0x00,
|
||
0x00, 0x07, 0xF0, 0x00,
|
||
0x00, 0x0F, 0xF8, 0x00,
|
||
0x00, 0x3F, 0xBE, 0x00,
|
||
0x00, 0x7F, 0x9F, 0x00,
|
||
0x00, 0xFB, 0x8F, 0xC0,
|
||
0x03, 0xE3, 0x83, 0xE0,
|
||
0x03, 0xC3, 0x87, 0xF0,
|
||
0x03, 0x83, 0x8F, 0xFC,
|
||
0x00, 0x03, 0xBF, 0x3C,
|
||
0x00, 0x03, 0xFC, 0x1C,
|
||
0x00, 0x03, 0xF8, 0x00,
|
||
0x00, 0x03, 0xE0, 0x00,
|
||
0x00, 0x03, 0xC0, 0x00,
|
||
0x00, 0x03, 0x80, 0x00,
|
||
0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00,
|
||
};
|
||
|
||
static const uint8_t power_icon[] = {
|
||
0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00,
|
||
0x00, 0x33, 0xCC, 0x00, 0x00, 0xF3, 0xCF, 0x00, 0x01, 0xF3, 0xCF, 0x80,
|
||
0x03, 0xF3, 0xCF, 0xC0, 0x07, 0xF3, 0xCF, 0xE0, 0x0F, 0xE3, 0xC7, 0xF0,
|
||
0x1F, 0xC3, 0xC3, 0xF8, 0x1F, 0x83, 0xC1, 0xF8, 0x3F, 0x03, 0xC0, 0xFC,
|
||
0x3E, 0x03, 0xC0, 0x7C, 0x3E, 0x03, 0xC0, 0x7C, 0x7E, 0x01, 0x80, 0x7E,
|
||
0x7C, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0x3E,
|
||
0x7C, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0x3E, 0x3E, 0x00, 0x00, 0x7C,
|
||
0x3E, 0x00, 0x00, 0x7C, 0x3F, 0x00, 0x00, 0xFC, 0x1F, 0x80, 0x01, 0xF8,
|
||
0x1F, 0xC0, 0x03, 0xF8, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0xF0,
|
||
0x07, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00,
|
||
0x00, 0x3F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00,
|
||
};
|
||
|
||
static const uint8_t advert_icon[] = {
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x30,
|
||
0x1C, 0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0x18, 0x30, 0x00, 0x00, 0x0C,
|
||
0x30, 0x60, 0x06, 0x0C, 0x60, 0xE0, 0x07, 0x06, 0x61, 0xC0, 0x03, 0x86,
|
||
0xE1, 0x81, 0x81, 0x87, 0xC3, 0x07, 0xE0, 0xC3, 0xC3, 0x0F, 0xF0, 0xC3,
|
||
0xC3, 0x0F, 0xF0, 0xC3, 0xC3, 0x0F, 0xF0, 0xC3, 0xC3, 0x0F, 0xF0, 0xC3,
|
||
0xC3, 0x07, 0xE0, 0xC3, 0xC1, 0x83, 0xC1, 0x83, 0x61, 0x80, 0x01, 0x86,
|
||
0x60, 0xC0, 0x03, 0x06, 0x70, 0xE0, 0x07, 0x0E, 0x30, 0x40, 0x02, 0x0C,
|
||
0x38, 0x00, 0x00, 0x1C, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x30,
|
||
0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
};
|