#pragma once #define FW_VERSION "1.1.0" #define DEVICE_ID "ATOMS3-MACROPAD" // Universal binary: the same build runs on the AtomS3 (LCD) and the // AtomS3 Lite (no LCD, SK6812 RGB LED on GPIO 35 — driven by M5.Led, // which M5Unified wires up from its board pin table). The board is // detected at boot via M5GFX panel autodetect + M5.getBoard(); these // names are what cmdPing reports to the host app. #define BOARD_NAME_ATOMS3 "atoms3" #define BOARD_NAME_ATOMS3_LITE "atoms3_lite" // Display (AtomS3; all rendering is gated off on the Lite) #define SCREEN_W 128 #define SCREEN_H 128 #define IMG_SIZE (SCREEN_W * SCREEN_H * 2) // RGB565 = 32768 bytes // Default settings #define DEFAULT_HOLD_MS 500 #define DEFAULT_TYPE_DELAY 15 #define DEFAULT_ORIENTATION 0 // Serial protocol #define SERIAL_BAUD 115200 #define CMD_BUF_SIZE 4096 #define JSON_DOC_SIZE 8192 // LittleFS paths #define CONFIG_PATH "/config.json" #define MACRO_DIR_PREFIX "/m" // Timing #define DEBOUNCE_MS 10 #define COMBO_KEY_PRE_DELAY 10 // ms between individual modifier presses within a combo #define COMBO_KEY_POST_DELAY 25 // ms hold time after all keys pressed before release // Default timing settings (user-configurable via GUI) #define DEFAULT_COMBO_PRE_MS 500 // ms delay before sending a key combo #define DEFAULT_COMBO_POST_MS 500 // ms delay after sending a key combo #define DEFAULT_PROBE_TIMEOUT_MS 300 // ms to wait for host LED response #define DEFAULT_MEDIA_HOLD_MS 100 // ms to hold media key before release #define DEFAULT_TYPE_SHIFT_EXTRA_MS 25 // extra ms per shifted char (uppercase, !@#$ etc.) #define DEFAULT_TYPE_SETTLE_MS 150 // ms to wait after the last char to let HID reports drain #define DEFAULT_TYPE_HOLD_MIN_MS 8 // floor for keydown-to-keyup hold; raised when a host needs longer poll-cycle observation #define DEFAULT_TYPE_INTER_CHAR_MS 5 // floor for gap between consecutive characters; raised for slow/remote hosts that drop fast input // Pause-screen text margins (host-configurable via GUI). Padding the text // box from each screen edge — used by drawWrapped() in display_ui.h. #define DEFAULT_PAUSE_MARGIN_LEFT 4 #define DEFAULT_PAUSE_MARGIN_RIGHT 4 #define DEFAULT_PAUSE_MARGIN_TOP 16 #define DEFAULT_PAUSE_MARGIN_BOTTOM 12 // Max limits #define MAX_MACROS 40 #define MAX_NODES_PER_MACRO 200 #define MAX_BRANCH_CHOICES 20 #define MAX_LOOPS 16 // per-macro max number of Loop nodes (for iteration tracking) // RS232 via Atomic RS232 Base (MAX232) #define RS232_RX_PIN 5 #define RS232_TX_PIN 6 #define RS232_BUF_SIZE 256 // Resume settings #define DEFAULT_RESUME_DELAY 0 // seconds, 0 = disabled // Legacy single-file path — kept ONLY so clearExecutionState() can sweep any // stale file left over from older firmware. The live save path uses the // A/B double-buffer + sentinel below. #define RESUME_STATE_PATH "/resume.json" // Double-buffer + sentinel scheme: each save writes the inactive slot // (A or B), then flips the 1-byte sentinel. There is no window where zero // valid resume files exist on disk. Both files carry a monotonic `seq` and // a CRC32; reader prefers the sentinel-chosen file but falls back to "any // file that deserializes AND CRC-matches, highest seq wins" if the // sentinel is missing/garbage. #define RESUME_STATE_A_PATH "/resume.a.json" #define RESUME_STATE_B_PATH "/resume.b.json" #define RESUME_STATE_IDX_PATH "/resume.idx" // 1 byte: 'A' or 'B' // Sub-routines #define MAX_SUBROUTINES 20 #define MAX_SUB_CALL_DEPTH 4 #define SUB_DIR_PREFIX "/sub/s" // BLE variable sync #define BLE_SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define BLE_VARS_CHAR_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" // host -> device (write) #define BLE_VARS_NOTIFY_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a9" // device -> host (notify) // BLE live-keystroke streaming (separate characteristics on the same // service so a single advertisement covers both protocols; see // ble_live.py for the binary frame format) #define BLE_LIVE_KEYS_WRITE_UUID "4fafc202-1fb5-459e-8fcc-c5c9c331914b" // host -> device (WWR) #define BLE_LIVE_KEYS_NOTIFY_UUID "4fafc203-1fb5-459e-8fcc-c5c9c331914b" // device -> host (notify) // Advertised service UUID specifically for live mode. The device advertises // THIS UUID (instead of BLE_SERVICE_UUID) when it's in EX_LIVE so the host's // var-sync and live-keystroke scanners filter to disjoint device sets — // they never race for the same connection. The actual GATT characteristics // still live in the same internal service (Bleak discovers characteristics // by UUID regardless of advertised service). #define BLE_LIVE_SERVICE_UUID "4fafc204-1fb5-459e-8fcc-c5c9c331914b" #define MAX_BLE_VARS 32 #define BLE_VAR_NAME_LEN 32 #define BLE_VAR_VALUE_LEN 256 #define BLE_VAR_BUF_SIZE 512 // max plaintext+overhead per frame #define BLE_FRAME_BUF_SIZE 768 // tag(<=64) + nonce(12) + ct+tag(BLE_VAR_BUF_SIZE+16) #define BLE_DEVICE_TAG_PREFIX "M5Stack|" #define BLE_DEVICE_TAG_MAX 40 // "M5Stack|AA:BB:CC:DD:EE:FF" + slack #define BLE_DEV_VARS_PATH "/ble_dev_vars.json" #define BLE_UNI_VARS_PATH "/ble_uni_vars.json" #define BLE_REPLAY_STATE_PATH "/ble_replay.json" // 1-byte flag: '1' while a live keystroke session is active. If power is // lost mid-session it survives to the next boot, which uses it to skip the // BLE boot grace and immediately re-advertise for the host to reconnect. #define BLE_LIVE_RESUME_PATH "/live_resume.flag" // --------------------------------------------------------------------------- // ESP-NOW mesh (live keyboard transport) // --------------------------------------------------------------------------- // All nodes idle-listen on a fixed WiFi channel (STA mode, no AP // association anywhere). One USB-attached device is switched into hub // mode by the host app and bridges USB-CDC <-> ESP-NOW broadcast. #define DEFAULT_MESH_CHANNEL 1 // 1-13, persisted in NVS ("mesh_ch") // --------------------------------------------------------------------------- // Live keyboard transport selection // --------------------------------------------------------------------------- // Which radio a device brings up when idle to receive a live-keyboard // session. Only one is ever up at a time (BLE and WiFi/ESP-NOW contend on // the ESP32-S3). Persisted in NVS ("live_tx") and toggled on-device by // holding the screen button for MODE_SWITCH_HOLD_MS while idle. // LIVE_TX_MESH — idle-listen on the ESP-NOW mesh (the hub broadcasts). // LIVE_TX_BLE — advertise the BLE live service for direct host links. #define LIVE_TX_MESH 0 #define LIVE_TX_BLE 1 #define DEFAULT_LIVE_TRANSPORT LIVE_TX_MESH // Screen-button hold time (ms) that toggles the transport while idle. Well // above the routine-run hold (settings.holdMs, ~500 ms) so the two gestures // are unambiguous — the run gesture is classified on release, below 5 s. #define MODE_SWITCH_HOLD_MS 5000 // Transport header (plaintext, precedes the encrypted ble_frame envelope) #define MESH_MAGIC 0xE5 #define MESH_HDR_LEN 14 // Hub -> nodes (broadcast) #define MESH_T_DATA 0x01 // reliable lane (group-key ble_frame) #define MESH_T_DATA_U 0x02 // unreliable lane: pure mouse moves #define MESH_T_JOIN 0x03 // per-device-key ble_frame (session invite) #define MESH_T_POLL 0x04 // discovery poll (plaintext) // Nodes -> hub (unicast) #define MESH_T_BEACON 0x81 // discovery reply (plaintext identity) #define MESH_T_ACK 0x82 // cumulative ack (group key) #define MESH_T_JOIN_ACK 0x83 // join accepted (per-device key) #define MESH_T_NACK 0x84 // missing-range report (group key) #define MESH_T_ERR 0x85 // error report (group key) // Transport flags #define MESH_F_RETX 0x01 // retransmission // Reliability tuning (see espnow_manager.h) #define MESH_RING_FRAMES 128 // hub retransmit ring (power of two) #define MESH_RING_SLOT 256 // max cached DATA frame size #define MESH_REORDER_SLOTS 32 // node-side out-of-order buffer #define MESH_ACK_EVERY_N 16 // ack at least every N frames... #define MESH_ACK_MAX_DELAY_MS 50 // ...or this long after first unacked #define MESH_NACK_AFTER_MS 8 // gap age before first NACK #define MESH_NACK_REPEAT_MS 30 // re-NACK while gap persists #define MESH_RETX_MIN_GAP_MS 15 // hub per-seq retransmit rate limit #define MESH_STALL_REBCAST_MS 60 // hub proactive rebroadcast on stall #define MESH_NODE_OFFLINE_MS 1500 // hub marks node offline after silence #define MESH_HUB_HOST_TIMEOUT_MS 5000 // hub reverts to node w/o host traffic #define MESH_BEACON_LABEL_LEN 24 // CDC binary bridge framing (host <-> hub); JSON lines keep working in // parallel — the dispatcher peeks at the first byte. #define HUB_MAGIC0 0xC8 #define HUB_MAGIC1 0x35 #define HUB_H2D_SEND 0x01 // payload = complete mesh frame #define HUB_D2H_RX 0x81 // src_mac[6] + received node frame #define HUB_D2H_ACKTAB 0x82 // periodic per-node ack table #define HUB_ACKTAB_PERIOD_MS 250 #define HUB_MAX_FRAME 1500