#pragma once #include #include "config.h" struct Settings { uint16_t holdMs = DEFAULT_HOLD_MS; uint8_t orientation = DEFAULT_ORIENTATION; uint8_t typeDelay = DEFAULT_TYPE_DELAY; uint16_t resumeDelay = DEFAULT_RESUME_DELAY; // seconds, 0 = disabled uint16_t comboPreMs = DEFAULT_COMBO_PRE_MS; uint16_t comboPostMs = DEFAULT_COMBO_POST_MS; uint16_t probeTimeoutMs = DEFAULT_PROBE_TIMEOUT_MS; uint16_t mediaHoldMs = DEFAULT_MEDIA_HOLD_MS; uint16_t typeShiftExtraMs = DEFAULT_TYPE_SHIFT_EXTRA_MS; uint16_t typeSettleMs = DEFAULT_TYPE_SETTLE_MS; uint16_t typeHoldMinMs = DEFAULT_TYPE_HOLD_MIN_MS; uint16_t typeInterCharMs = DEFAULT_TYPE_INTER_CHAR_MS; // Pause-screen text-box padding. drawWrapped() uses these to compute // the text width and vertical center on every Pause node. uint8_t pauseMarginLeft = DEFAULT_PAUSE_MARGIN_LEFT; uint8_t pauseMarginRight = DEFAULT_PAUSE_MARGIN_RIGHT; uint8_t pauseMarginTop = DEFAULT_PAUSE_MARGIN_TOP; uint8_t pauseMarginBottom = DEFAULT_PAUSE_MARGIN_BOTTOM; // ESP-NOW mesh channel (1-13). Every device in a mesh must share it; // it's applied the next time the radio starts (node listen / hub on). uint8_t meshChannel = DEFAULT_MESH_CHANNEL; // Live-keyboard transport used when idle: LIVE_TX_MESH or LIVE_TX_BLE. // Toggled on-device by a long screen-button hold; persisted in NVS. uint8_t liveTransport = DEFAULT_LIVE_TRANSPORT; }; class SettingsManager { public: Settings settings; void begin() { _prefs.begin("macropad", false); settings.holdMs = _prefs.getUShort("hold_ms", DEFAULT_HOLD_MS); settings.orientation = _prefs.getUChar("orient", DEFAULT_ORIENTATION); settings.typeDelay = _prefs.getUChar("type_delay", DEFAULT_TYPE_DELAY); settings.resumeDelay = _prefs.getUShort("resume_dly", DEFAULT_RESUME_DELAY); settings.comboPreMs = _prefs.getUShort("combo_pre", DEFAULT_COMBO_PRE_MS); settings.comboPostMs = _prefs.getUShort("combo_post", DEFAULT_COMBO_POST_MS); settings.probeTimeoutMs = _prefs.getUShort("probe_to", DEFAULT_PROBE_TIMEOUT_MS); settings.mediaHoldMs = _prefs.getUShort("media_hold", DEFAULT_MEDIA_HOLD_MS); settings.typeShiftExtraMs = _prefs.getUShort("type_sh_ex", DEFAULT_TYPE_SHIFT_EXTRA_MS); settings.typeSettleMs = _prefs.getUShort("type_settle", DEFAULT_TYPE_SETTLE_MS); settings.typeHoldMinMs = _prefs.getUShort("type_hold_min", DEFAULT_TYPE_HOLD_MIN_MS); settings.typeInterCharMs = _prefs.getUShort("type_inter_ch", DEFAULT_TYPE_INTER_CHAR_MS); settings.pauseMarginLeft = _prefs.getUChar("p_mar_l", DEFAULT_PAUSE_MARGIN_LEFT); settings.pauseMarginRight = _prefs.getUChar("p_mar_r", DEFAULT_PAUSE_MARGIN_RIGHT); settings.pauseMarginTop = _prefs.getUChar("p_mar_t", DEFAULT_PAUSE_MARGIN_TOP); settings.pauseMarginBottom = _prefs.getUChar("p_mar_b", DEFAULT_PAUSE_MARGIN_BOTTOM); settings.meshChannel = _prefs.getUChar("mesh_ch", DEFAULT_MESH_CHANNEL); if (settings.meshChannel < 1 || settings.meshChannel > 13) { settings.meshChannel = DEFAULT_MESH_CHANNEL; } settings.liveTransport = _prefs.getUChar("live_tx", DEFAULT_LIVE_TRANSPORT); if (settings.liveTransport > LIVE_TX_BLE) { settings.liveTransport = DEFAULT_LIVE_TRANSPORT; } } void set(const char* key, int value) { if (strcmp(key, "hold_ms") == 0) { settings.holdMs = value; _prefs.putUShort("hold_ms", value); } else if (strcmp(key, "orientation") == 0) { settings.orientation = value; _prefs.putUChar("orient", value); } else if (strcmp(key, "type_delay") == 0) { settings.typeDelay = value; _prefs.putUChar("type_delay", value); } else if (strcmp(key, "resume_delay") == 0) { settings.resumeDelay = value; _prefs.putUShort("resume_dly", value); } else if (strcmp(key, "combo_pre_ms") == 0) { settings.comboPreMs = value; _prefs.putUShort("combo_pre", value); } else if (strcmp(key, "combo_post_ms") == 0) { settings.comboPostMs = value; _prefs.putUShort("combo_post", value); } else if (strcmp(key, "probe_timeout_ms") == 0) { settings.probeTimeoutMs = value; _prefs.putUShort("probe_to", value); } else if (strcmp(key, "media_hold_ms") == 0) { settings.mediaHoldMs = value; _prefs.putUShort("media_hold", value); } else if (strcmp(key, "type_shift_extra_ms") == 0) { settings.typeShiftExtraMs = value; _prefs.putUShort("type_sh_ex", value); } else if (strcmp(key, "type_settle_ms") == 0) { settings.typeSettleMs = value; _prefs.putUShort("type_settle", value); } else if (strcmp(key, "type_hold_min_ms") == 0) { settings.typeHoldMinMs = value; _prefs.putUShort("type_hold_min", value); } else if (strcmp(key, "type_inter_char_ms") == 0) { settings.typeInterCharMs = value; _prefs.putUShort("type_inter_ch", value); } else if (strcmp(key, "pause_margin_left") == 0) { settings.pauseMarginLeft = (uint8_t)value; _prefs.putUChar("p_mar_l", (uint8_t)value); } else if (strcmp(key, "pause_margin_right") == 0) { settings.pauseMarginRight = (uint8_t)value; _prefs.putUChar("p_mar_r", (uint8_t)value); } else if (strcmp(key, "pause_margin_top") == 0) { settings.pauseMarginTop = (uint8_t)value; _prefs.putUChar("p_mar_t", (uint8_t)value); } else if (strcmp(key, "pause_margin_bottom") == 0) { settings.pauseMarginBottom = (uint8_t)value; _prefs.putUChar("p_mar_b", (uint8_t)value); } else if (strcmp(key, "mesh_ch") == 0) { if (value >= 1 && value <= 13) { settings.meshChannel = (uint8_t)value; _prefs.putUChar("mesh_ch", (uint8_t)value); } } else if (strcmp(key, "live_tx") == 0) { if (value == LIVE_TX_MESH || value == LIVE_TX_BLE) { settings.liveTransport = (uint8_t)value; _prefs.putUChar("live_tx", (uint8_t)value); } } } int get(const char* key) { if (strcmp(key, "hold_ms") == 0) return settings.holdMs; if (strcmp(key, "orientation") == 0) return settings.orientation; if (strcmp(key, "type_delay") == 0) return settings.typeDelay; if (strcmp(key, "resume_delay") == 0) return settings.resumeDelay; if (strcmp(key, "combo_pre_ms") == 0) return settings.comboPreMs; if (strcmp(key, "combo_post_ms") == 0) return settings.comboPostMs; if (strcmp(key, "probe_timeout_ms") == 0) return settings.probeTimeoutMs; if (strcmp(key, "media_hold_ms") == 0) return settings.mediaHoldMs; if (strcmp(key, "type_shift_extra_ms") == 0) return settings.typeShiftExtraMs; if (strcmp(key, "type_settle_ms") == 0) return settings.typeSettleMs; if (strcmp(key, "type_hold_min_ms") == 0) return settings.typeHoldMinMs; if (strcmp(key, "type_inter_char_ms") == 0) return settings.typeInterCharMs; if (strcmp(key, "pause_margin_left") == 0) return settings.pauseMarginLeft; if (strcmp(key, "pause_margin_right") == 0) return settings.pauseMarginRight; if (strcmp(key, "pause_margin_top") == 0) return settings.pauseMarginTop; if (strcmp(key, "pause_margin_bottom") == 0) return settings.pauseMarginBottom; if (strcmp(key, "mesh_ch") == 0) return settings.meshChannel; if (strcmp(key, "live_tx") == 0) return settings.liveTransport; return -1; } private: Preferences _prefs; };