reference: 早先那版 C 写的装甲板固件(ESP-IDF 工程)
`armor/` 是它的 Rust 改写版,这一份留着当参考:ADC 阈值的 2000 就是从它标定出来的 (`.env.example` 里那句 "same as the reference firmware" 指的就是它),而且它的 README 记着实测设备与 MAC,换硬件时是有用的现场记录。 只收了 20 个源文件。它自带的 `.gitignore` 已经排掉 `build/`(211 MB 的 ESP-IDF 构建产物) 与生成的 `sdkconfig`,所以仓库里不会多出这些东西。 两处顺带处理: - `reference/armor/.git` 是一个**空的**仓库壳(`git init` 过,零提交、零 remote、零 ref), 而外层 git 正因为它的存在而拒绝索引 `reference/` 下的任何文件 (`error: 'reference/armor/' does not have a commit checked out`)。它被挪到 `desktop/.dev/backup/reference-armor-git`(可逆,且该目录已被忽略),不是删除。 - 它的 README 指着 `../armor-platformio-backup/`,那份备份并不存在。改成明说"没有进仓库", 免得以后有人照着找一个不存在的目录。 另外把 `/docs/` 加进 .gitignore:那是工作区里另起的一个 Astro 文档站,与本仓库无关。
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#include "button.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "armor_time.hpp"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
Button::Button(int gpio, bool active_low) : _pin(gpio), _active_low(active_low) {
|
||||
gpio_config_t cfg = {};
|
||||
cfg.pin_bit_mask = 1ULL << gpio;
|
||||
cfg.mode = GPIO_MODE_INPUT;
|
||||
cfg.pull_up_en = active_low ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
|
||||
cfg.pull_down_en = active_low ? GPIO_PULLDOWN_DISABLE : GPIO_PULLDOWN_ENABLE;
|
||||
cfg.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_config(&cfg);
|
||||
}
|
||||
|
||||
void Button::attachClick(callback_t cb) {
|
||||
_clickFunc = cb;
|
||||
}
|
||||
|
||||
void Button::attachLongPressStart(callback_t cb) {
|
||||
_longPressStartFunc = cb;
|
||||
}
|
||||
|
||||
void Button::setClickMs(uint32_t ms) {
|
||||
_click_ms = ms;
|
||||
}
|
||||
|
||||
void Button::setPressMs(uint32_t ms) {
|
||||
_press_ms = ms;
|
||||
}
|
||||
|
||||
// Port of OneButton::debounce(): a level only becomes the debounced level once
|
||||
// it has been stable for _debounce_ms.
|
||||
bool Button::debounce(bool value) {
|
||||
now = millis();
|
||||
|
||||
if (_lastDebounceLevel == value) {
|
||||
if (now - _lastDebounceTime >= static_cast<unsigned long>(std::abs(_debounce_ms))) {
|
||||
debouncedLevel = value;
|
||||
}
|
||||
} else {
|
||||
_lastDebounceTime = now;
|
||||
_lastDebounceLevel = value;
|
||||
}
|
||||
return debouncedLevel;
|
||||
}
|
||||
|
||||
void Button::tick() {
|
||||
if (_pin < 0) {
|
||||
return;
|
||||
}
|
||||
const int level = gpio_get_level(static_cast<gpio_num_t>(_pin));
|
||||
const bool active_level = _active_low ? (level == 0) : (level != 0);
|
||||
fsm(debounce(active_level));
|
||||
}
|
||||
|
||||
void Button::reset() {
|
||||
_state = OCS_INIT;
|
||||
_nClicks = 0;
|
||||
_startTime = millis();
|
||||
}
|
||||
|
||||
// Port of OneButton::_fsm() (single click + long press start only).
|
||||
void Button::fsm(bool active_level) {
|
||||
const unsigned long waitTime = now - _startTime;
|
||||
|
||||
switch (_state) {
|
||||
case OCS_INIT:
|
||||
// Waiting for the level to become active.
|
||||
if (active_level) {
|
||||
_state = OCS_DOWN;
|
||||
_startTime = now;
|
||||
_nClicks = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OCS_DOWN:
|
||||
// Waiting for the level to become inactive again... or a long press.
|
||||
if (!active_level) {
|
||||
_state = OCS_UP;
|
||||
_startTime = now;
|
||||
} else if (waitTime > _press_ms) {
|
||||
if (_longPressStartFunc) {
|
||||
_longPressStartFunc();
|
||||
}
|
||||
_state = OCS_PRESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case OCS_UP:
|
||||
// Level is inactive: count as a short button down.
|
||||
_nClicks++;
|
||||
_state = OCS_COUNT;
|
||||
break;
|
||||
|
||||
case OCS_COUNT:
|
||||
if (active_level) {
|
||||
// Button is down again.
|
||||
_state = OCS_DOWN;
|
||||
_startTime = now;
|
||||
} else if ((waitTime >= _click_ms) || (_nClicks == _maxClicks)) {
|
||||
if (_nClicks == 1 && _clickFunc) {
|
||||
_clickFunc();
|
||||
}
|
||||
reset();
|
||||
}
|
||||
break;
|
||||
|
||||
case OCS_PRESS:
|
||||
// Waiting for the pin to be released after a long press.
|
||||
if (!active_level) {
|
||||
_state = OCS_PRESSEND;
|
||||
}
|
||||
break;
|
||||
|
||||
case OCS_PRESSEND:
|
||||
reset();
|
||||
break;
|
||||
|
||||
default:
|
||||
_state = OCS_INIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user