Initial physical button mapping implementation #4
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "ble_config.h"
|
||||
#include "tap.h"
|
||||
#include "battery.h"
|
||||
#include "buttons.h"
|
||||
#include <Adafruit_LittleFS.h>
|
||||
#include <InternalFileSystem.h>
|
||||
|
||||
@@ -77,6 +78,9 @@ 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
|
||||
@@ -122,6 +126,13 @@ 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);
|
||||
|
||||
52
source/buttons.cpp
Normal file
52
source/buttons.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "buttons.h"
|
||||
|
||||
#ifdef FEATURE_PHYSICAL_BUTTONS
|
||||
#include <bluefruit.h>
|
||||
|
||||
extern BLEHidAdafruit blehid;
|
||||
|
||||
static uint8_t physBtnMask = 0; // bitmask of currently-pressed physical buttons
|
||||
|
||||
// ─── Setup ────────────────────────────────────────────────────────────────────
|
||||
void setupPhysicalButtons() {
|
||||
// Release any held physical buttons before reconfiguring
|
||||
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);
|
||||
|
||||
bool any = (cfg.btnLeftPin != BTN_PIN_NONE) || (cfg.btnRightPin != BTN_PIN_NONE)
|
||||
|| (cfg.btnMiddlePin != BTN_PIN_NONE);
|
||||
if (any) {
|
||||
Serial.print("[BTN] L=");
|
||||
cfg.btnLeftPin == BTN_PIN_NONE ? Serial.print("--") : Serial.print(cfg.btnLeftPin);
|
||||
Serial.print(" R=");
|
||||
cfg.btnRightPin == BTN_PIN_NONE ? Serial.print("--") : Serial.print(cfg.btnRightPin);
|
||||
Serial.print(" M=");
|
||||
cfg.btnMiddlePin == BTN_PIN_NONE ? Serial.print("--") : Serial.print(cfg.btnMiddlePin);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Poll and report ──────────────────────────────────────────────────────────
|
||||
// Called every loop iteration (before rate limiter) for immediate response.
|
||||
// Uses active-low logic: INPUT_PULLUP, button connects pin to GND.
|
||||
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 (newMask != physBtnMask) {
|
||||
physBtnMask = newMask;
|
||||
if (physBtnMask) blehid.mouseButtonPress(physBtnMask);
|
||||
else blehid.mouseButtonRelease();
|
||||
Serial.print("[BTN] mask=0x"); Serial.println(physBtnMask, HEX);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // FEATURE_PHYSICAL_BUTTONS
|
||||
7
source/buttons.h
Normal file
7
source/buttons.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "config.h"
|
||||
|
||||
#ifdef FEATURE_PHYSICAL_BUTTONS
|
||||
void setupPhysicalButtons();
|
||||
void processPhysicalButtons();
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
#define FEATURE_AUTO_RECAL
|
||||
#define FEATURE_BATTERY_MONITOR
|
||||
#define FEATURE_BOOT_LOOP_DETECT
|
||||
#define FEATURE_PHYSICAL_BUTTONS
|
||||
|
||||
// ─── Debug ────────────────────────────────────────────────────────────────────
|
||||
// #define DEBUG
|
||||
@@ -53,7 +54,10 @@
|
||||
|
||||
// ─── Persistence ──────────────────────────────────────────────────────────────
|
||||
#define CONFIG_FILENAME "/imu_mouse_cfg.bin"
|
||||
#define CONFIG_MAGIC 0xDEAD123CUL
|
||||
#define CONFIG_MAGIC 0xDEAD123DUL
|
||||
|
||||
// ─── Physical button sentinel ─────────────────────────────────────────────────
|
||||
#define BTN_PIN_NONE 0xFF // Stored in btn*Pin when that button is disabled
|
||||
|
||||
// ─── Runtime feature-override flags (cfg.featureFlags bitmask) ───────────────
|
||||
// These mirror the compile-time FEATURE_* defines but can be toggled at runtime
|
||||
@@ -94,6 +98,9 @@ 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;
|
||||
@@ -113,8 +120,11 @@ 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) == 25, "ConfigBlob must be 25 bytes");
|
||||
static_assert(sizeof(ConfigBlob) == 28, "ConfigBlob must be 28 bytes");
|
||||
|
||||
// ─── TelemetryPacket (24 bytes) ───────────────────────────────────────────────
|
||||
#ifdef FEATURE_TELEMETRY
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "ble_config.h"
|
||||
#include "battery.h"
|
||||
#include "tap.h"
|
||||
#include "buttons.h"
|
||||
#include <bluefruit.h>
|
||||
#include <Adafruit_LittleFS.h>
|
||||
#include <InternalFileSystem.h>
|
||||
@@ -60,7 +61,8 @@ 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
|
||||
/*jerkThreshold=*/2000.0f, /*tapFreezeEnabled=*/1, /*featureFlags=*/FLAG_ALL_DEFAULT,
|
||||
/*btnLeftPin=*/BTN_PIN_NONE, /*btnRightPin=*/BTN_PIN_NONE, /*btnMiddlePin=*/BTN_PIN_NONE
|
||||
};
|
||||
|
||||
// ─── Telemetry definition ─────────────────────────────────────────────────────
|
||||
@@ -224,6 +226,10 @@ void setup() {
|
||||
if (cfg.featureFlags & FLAG_TAP_ENABLED) setupTapDetection();
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_PHYSICAL_BUTTONS
|
||||
setupPhysicalButtons();
|
||||
#endif
|
||||
|
||||
cachedTempC = readIMUTemp();
|
||||
|
||||
#ifdef FEATURE_BATTERY_MONITOR
|
||||
@@ -280,6 +286,9 @@ void setup() {
|
||||
#ifdef FEATURE_BOOT_LOOP_DETECT
|
||||
Serial.print(" BOOTDET");
|
||||
#endif
|
||||
#ifdef FEATURE_PHYSICAL_BUTTONS
|
||||
Serial.print(" PHYSBTN");
|
||||
#endif
|
||||
Serial.println();
|
||||
|
||||
bootStartMs = millis();
|
||||
@@ -323,6 +332,10 @@ void loop() {
|
||||
if (cfg.featureFlags & FLAG_TAP_ENABLED) processTaps(now);
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_PHYSICAL_BUTTONS
|
||||
processPhysicalButtons();
|
||||
#endif
|
||||
|
||||
if (now - lastTime < (unsigned long)LOOP_RATE_MS) return;
|
||||
float dt = (now - lastTime) / 1000.0f;
|
||||
lastTime = now;
|
||||
|
||||
Reference in New Issue
Block a user