diff --git a/source/ble_config.cpp b/source/ble_config.cpp index abcf1db..690f968 100644 --- a/source/ble_config.cpp +++ b/source/ble_config.cpp @@ -77,9 +77,6 @@ void pushConfigBlob() { b.tapFreezeEnabled = cfg.tapFreezeEnabled; b.jerkThreshold = cfg.jerkThreshold; b.featureFlags = cfg.featureFlags; - b.btnLeftPin = cfg.btnLeftPin; - b.btnRightPin = cfg.btnRightPin; - b.btnMiddlePin = cfg.btnMiddlePin; cfgBlob.write((uint8_t*)&b, sizeof(b)); } #endif @@ -125,13 +122,6 @@ void onConfigBlobWrite(uint16_t h, BLECharacteristic* c, uint8_t* d, uint16_t l) cfg.tapFreezeEnabled = b->tapFreezeEnabled ? 1 : 0; if (b->jerkThreshold >= 100.0f && b->jerkThreshold <= 50000.0f) cfg.jerkThreshold = b->jerkThreshold; cfg.featureFlags = b->featureFlags & (FLAG_TAP_ENABLED | FLAG_TEMP_COMP_ENABLED | FLAG_AUTO_RECAL_ENABLED); - // btnXPin: accept BTN_PIN_NONE (0xFF) or a valid Arduino pin number (0-10 = D0-D10) - cfg.btnLeftPin = (b->btnLeftPin <= 10 || b->btnLeftPin == BTN_PIN_NONE) ? b->btnLeftPin : BTN_PIN_NONE; - cfg.btnRightPin = (b->btnRightPin <= 10 || b->btnRightPin == BTN_PIN_NONE) ? b->btnRightPin : BTN_PIN_NONE; - cfg.btnMiddlePin = (b->btnMiddlePin <= 10 || b->btnMiddlePin == BTN_PIN_NONE) ? b->btnMiddlePin : BTN_PIN_NONE; - #ifdef FEATURE_PHYSICAL_BUTTONS - setupPhysicalButtons(); // reconfigure pins immediately (no restart needed) - #endif saveConfig(); Serial.print("[CFG] Written - sens="); Serial.print(cfg.sensitivity,0); Serial.print(" dz="); Serial.print(cfg.deadZone,3); diff --git a/source/buttons.cpp b/source/buttons.cpp index 3af0ef2..1153c4f 100644 --- a/source/buttons.cpp +++ b/source/buttons.cpp @@ -13,19 +13,19 @@ void setupPhysicalButtons() { if (physBtnMask && Bluefruit.connected()) { blehid.mouseButtonRelease(); } physBtnMask = 0; - if (cfg.btnLeftPin != BTN_PIN_NONE) pinMode(cfg.btnLeftPin, INPUT_PULLUP); - if (cfg.btnRightPin != BTN_PIN_NONE) pinMode(cfg.btnRightPin, INPUT_PULLUP); - if (cfg.btnMiddlePin != BTN_PIN_NONE) pinMode(cfg.btnMiddlePin, INPUT_PULLUP); + if (BTN_LEFT_PIN != BTN_PIN_NONE) pinMode(BTN_LEFT_PIN, INPUT_PULLUP); + if (BTN_RIGHT_PIN != BTN_PIN_NONE) pinMode(BTN_RIGHT_PIN, INPUT_PULLUP); + if (BTN_MIDDLE_PIN != BTN_PIN_NONE) pinMode(BTN_MIDDLE_PIN, INPUT_PULLUP); - bool any = (cfg.btnLeftPin != BTN_PIN_NONE) || (cfg.btnRightPin != BTN_PIN_NONE) - || (cfg.btnMiddlePin != BTN_PIN_NONE); + bool any = (BTN_LEFT_PIN != BTN_PIN_NONE) || (BTN_RIGHT_PIN != BTN_PIN_NONE) + || (BTN_MIDDLE_PIN != BTN_PIN_NONE); if (any) { Serial.print("[BTN] L="); - cfg.btnLeftPin == BTN_PIN_NONE ? Serial.print("--") : Serial.print(cfg.btnLeftPin); + BTN_LEFT_PIN == BTN_PIN_NONE ? Serial.print("--") : Serial.print(BTN_LEFT_PIN); Serial.print(" R="); - cfg.btnRightPin == BTN_PIN_NONE ? Serial.print("--") : Serial.print(cfg.btnRightPin); + BTN_RIGHT_PIN == BTN_PIN_NONE ? Serial.print("--") : Serial.print(BTN_RIGHT_PIN); Serial.print(" M="); - cfg.btnMiddlePin == BTN_PIN_NONE ? Serial.print("--") : Serial.print(cfg.btnMiddlePin); + BTN_MIDDLE_PIN == BTN_PIN_NONE ? Serial.print("--") : Serial.print(BTN_MIDDLE_PIN); Serial.println(); } } @@ -37,9 +37,9 @@ void processPhysicalButtons() { if (!Bluefruit.connected()) return; uint8_t newMask = 0; - if (cfg.btnLeftPin != BTN_PIN_NONE && digitalRead(cfg.btnLeftPin) == LOW) newMask |= MOUSE_BUTTON_LEFT; - if (cfg.btnRightPin != BTN_PIN_NONE && digitalRead(cfg.btnRightPin) == LOW) newMask |= MOUSE_BUTTON_RIGHT; - if (cfg.btnMiddlePin != BTN_PIN_NONE && digitalRead(cfg.btnMiddlePin) == LOW) newMask |= MOUSE_BUTTON_MIDDLE; + if (BTN_LEFT_PIN != BTN_PIN_NONE && digitalRead(BTN_LEFT_PIN) == LOW) newMask |= MOUSE_BUTTON_LEFT; + if (BTN_RIGHT_PIN != BTN_PIN_NONE && digitalRead(BTN_RIGHT_PIN) == LOW) newMask |= MOUSE_BUTTON_RIGHT; + if (BTN_MIDDLE_PIN != BTN_PIN_NONE && digitalRead(BTN_MIDDLE_PIN) == LOW) newMask |= MOUSE_BUTTON_MIDDLE; if (newMask != physBtnMask) { physBtnMask = newMask; diff --git a/source/config.h b/source/config.h index b0999fa..8ee2bb7 100644 --- a/source/config.h +++ b/source/config.h @@ -56,8 +56,12 @@ #define CONFIG_FILENAME "/imu_mouse_cfg.bin" #define CONFIG_MAGIC 0xDEAD123EUL -// Physical button sentinel -#define BTN_PIN_NONE 0xFF // Stored in btn*Pin when that button is disabled +// Physical button pin assignments (hardcoded - set to 0xFF to disable a button) +// Valid pin numbers: 0-10 (Arduino D0-D10 on XIAO nRF52840 Sense) +#define BTN_PIN_NONE 0xFF +#define BTN_LEFT_PIN BTN_PIN_NONE // e.g. 0 for D0 +#define BTN_RIGHT_PIN BTN_PIN_NONE // e.g. 1 for D1 +#define BTN_MIDDLE_PIN BTN_PIN_NONE // e.g. 2 for D2 // Runtime feature-override flags (cfg.featureFlags bitmask) // These mirror the compile-time FEATURE_* defines but can be toggled at runtime @@ -98,9 +102,6 @@ struct Config { float jerkThreshold; // jerk² threshold for tap-freeze detection uint8_t tapFreezeEnabled; // 1 = enable jerk-based cursor freeze during taps uint8_t featureFlags; // bitmask of FLAG_* - runtime feature overrides - uint8_t btnLeftPin; // BTN_PIN_NONE or Arduino pin number (0-10 = D0-D10) - uint8_t btnRightPin; - uint8_t btnMiddlePin; }; extern Config cfg; extern const Config CFG_DEFAULTS; @@ -120,11 +121,8 @@ struct __attribute__((packed)) ConfigBlob { uint8_t tapFreezeEnabled; // [19] 1 = enable jerk-based cursor freeze during taps float jerkThreshold; // [20] jerk² tap-freeze threshold uint8_t featureFlags; // [24] FLAG_* bitmask - runtime feature overrides - uint8_t btnLeftPin; // [25] BTN_PIN_NONE or Arduino pin (0-10 = D0-D10) - uint8_t btnRightPin; // [26] - uint8_t btnMiddlePin; // [27] }; -static_assert(sizeof(ConfigBlob) == 28, "ConfigBlob must be 28 bytes"); +static_assert(sizeof(ConfigBlob) == 25, "ConfigBlob must be 25 bytes"); // TelemetryPacket (24 bytes) #ifdef FEATURE_TELEMETRY diff --git a/source/main.cpp b/source/main.cpp index 8791ff3..98fc830 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -47,8 +47,7 @@ Config cfg; const Config CFG_DEFAULTS = { CONFIG_MAGIC, 600.0f, 0.060f, 0.08f, CURVE_LINEAR, 0x00, CHARGE_SLOW, /*tapThreshold=*/12, /*tapAction=*/TAP_ACTION_LEFT, /*tapKey=*/0, /*tapMod=*/0, - /*jerkThreshold=*/2000.0f, /*tapFreezeEnabled=*/1, /*featureFlags=*/FLAG_ALL_DEFAULT, - /*btnLeftPin=*/BTN_PIN_NONE, /*btnRightPin=*/BTN_PIN_NONE, /*btnMiddlePin=*/BTN_PIN_NONE + /*jerkThreshold=*/2000.0f, /*tapFreezeEnabled=*/1, /*featureFlags=*/FLAG_ALL_DEFAULT }; // Telemetry definition diff --git a/web/app.js b/web/app.js index f9cb1c6..3f369ab 100644 --- a/web/app.js +++ b/web/app.js @@ -19,7 +19,7 @@ const FLAG_ALL_DEFAULT = FLAG_TAP_ENABLED | FLAG_TEMP_COMP_ENABLED | FLAG const config = { sensitivity:600, deadZone:0.06, accelStrength:0.08, curve:0, axisFlip:0, chargeMode:0, tapThreshold:12, tapAction:0, tapKey:0, tapMod:0, tapFreezeEnabled:1, jerkThreshold:2000, featureFlags:FLAG_ALL_DEFAULT, - btnLeftPin:0xFF, btnRightPin:0xFF, btnMiddlePin:0xFF }; + }; let device=null, server=null, chars={}, userDisconnected=false; let currentChargeStatus=0, currentBattPct=null, currentBattVoltage=null; @@ -247,13 +247,6 @@ async function readConfigBlob() { } else { config.featureFlags = FLAG_ALL_DEFAULT; // old firmware - assume all on } - if (view.byteLength >= 28) { - config.btnLeftPin = view.getUint8(25); - config.btnRightPin = view.getUint8(26); - config.btnMiddlePin = view.getUint8(27); - } else { - config.btnLeftPin = config.btnRightPin = config.btnMiddlePin = 0xFF; // disabled - } applyConfigToUI(); log(`Config loaded - sens=${config.sensitivity.toFixed(0)} dz=${config.deadZone.toFixed(3)} tapThr=${config.tapThreshold}`,'ok'); } catch(e) { log(`Config read error: ${e.message}`,'err'); } @@ -285,38 +278,8 @@ function applyConfigToUI() { document.getElementById('capTapEnabled').checked = !!(config.featureFlags & FLAG_TAP_ENABLED); document.getElementById('capTempComp').checked = !!(config.featureFlags & FLAG_TEMP_COMP_ENABLED); document.getElementById('capAutoRecal').checked = !!(config.featureFlags & FLAG_AUTO_RECAL_ENABLED); - document.getElementById('btnLeftPin').value = config.btnLeftPin; - document.getElementById('btnRightPin').value = config.btnRightPin; - document.getElementById('btnMiddlePin').value = config.btnMiddlePin; - updatePinDiagram(); } -// XIAO pin diagram -function updatePinDiagram() { - const st = getComputedStyle(document.documentElement); - const COL_L = st.getPropertyValue('--ok').trim(); - const COL_R = st.getPropertyValue('--accent2').trim(); - const COL_M = st.getPropertyValue('--accent').trim(); - const DEF_F = '#0c1828', DEF_S = '#162234'; - - for (let i = 0; i <= 10; i++) { - const el = document.getElementById(`xiaoPin${i}`); - if (el) { el.setAttribute('fill', DEF_F); el.setAttribute('stroke', DEF_S); } - } - - const apply = (pin, col) => { - if (pin > 10) return; - const el = document.getElementById(`xiaoPin${pin}`); - if (el) { el.setAttribute('fill', col); el.setAttribute('stroke', col); } - }; - - const l = parseInt(document.getElementById('btnLeftPin').value, 10); - const r = parseInt(document.getElementById('btnRightPin').value, 10); - const m = parseInt(document.getElementById('btnMiddlePin').value, 10); - if (l <= 10) apply(l, COL_L); - if (r <= 10) apply(r, COL_R); - if (m <= 10) apply(m, COL_M); -} let _writeConfigTimer = null; function writeConfigBlob() { @@ -344,11 +307,7 @@ async function _doWriteConfigBlob() { | (document.getElementById('capAutoRecal').checked ? FLAG_AUTO_RECAL_ENABLED : 0); // config.curve, config.chargeMode, config.tapAction, config.tapKey updated directly - config.btnLeftPin = parseInt(document.getElementById('btnLeftPin').value, 10); - config.btnRightPin = parseInt(document.getElementById('btnRightPin').value, 10); - config.btnMiddlePin = parseInt(document.getElementById('btnMiddlePin').value, 10); - - const buf = new ArrayBuffer(28); + const buf = new ArrayBuffer(25); const view = new DataView(buf); view.setFloat32(0, config.sensitivity, true); view.setFloat32(4, config.deadZone, true); @@ -363,9 +322,6 @@ async function _doWriteConfigBlob() { view.setUint8(19, config.tapFreezeEnabled); view.setFloat32(20, config.jerkThreshold, true); view.setUint8(24, config.featureFlags); - view.setUint8(25, config.btnLeftPin); - view.setUint8(26, config.btnRightPin); - view.setUint8(27, config.btnMiddlePin); try { await gattWrite(chars.configBlob, buf); @@ -661,7 +617,7 @@ function setStatus(state) { pill.className='status-pill '+state; document.body.className=state; const cBtn=document.getElementById('connectBtn'), dBtn=document.getElementById('disconnectBtn'); - const inputs=document.querySelectorAll('input[type=range],.seg-btn,.toggle input,.cmd-btn,#tapKeyHex,.mod-btn input,.pin-select'); + const inputs=document.querySelectorAll('input[type=range],.seg-btn,.toggle input,.cmd-btn,#tapKeyHex,.mod-btn input'); if (state==='connected') { cBtn.style.display='none'; dBtn.style.display=''; inputs.forEach(el=>el.disabled=false); @@ -1043,7 +999,6 @@ function applyTheme(t) { localStorage.setItem('theme', t); if (!chars.imuStream) drawInitState(); orientUpdateColors(); - updatePinDiagram(); } (function(){ const saved = localStorage.getItem('theme') ?? 'auto'; diff --git a/web/index.html b/web/index.html index 3ba723d..2e00201 100644 --- a/web/index.html +++ b/web/index.html @@ -180,122 +180,6 @@ -
Physical Buttons
-
- -
- - - - - USB·C - - - - - - - - - XIAO nRF52840 Sense - - - ANT - - - nRF52840 - HOLYIOT - - - - - LSM6DS3 - IMU - - - BQ25100 - - - - - LED - - - - - - - - - - - - - - - - - - - - - - - D0D1D2D3D4D5D6 - A0A1A2A3SDASCLTX - - D7D8D9D10 - RXSCKMISOMOSI - - RST - GND - 3V3 - -
- ● Left - ● Right - ● Middle -
-
-
-
-
Left Click
-
Pin wired to GND when pressed
- -
-
-
Right Click
-
Pin wired to GND when pressed
- -
-
-
Middle Click
-
Pin wired to GND when pressed
- -
-
- Pull-up built-in · wire button between chosen pin and GND -
-
-
Device Commands