Compare commits
No commits in common. "main" and "v0.1" have entirely different histories.
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,2 +1,5 @@
|
||||||
.pio
|
.pio
|
||||||
.vscode
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
|
|
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
|
// for the documentation about the extensions.json format
|
||||||
|
"recommendations": [
|
||||||
|
"platformio.platformio-ide"
|
||||||
|
],
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
"ms-vscode.cpptools-extension-pack"
|
||||||
|
]
|
||||||
|
}
|
78
.vscode/settings.json
vendored
Normal file
78
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"optional": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"streambuf": "cpp"
|
||||||
|
},
|
||||||
|
"C_Cpp_Runner.cCompilerPath": "gcc",
|
||||||
|
"C_Cpp_Runner.cppCompilerPath": "g++",
|
||||||
|
"C_Cpp_Runner.debuggerPath": "gdb",
|
||||||
|
"C_Cpp_Runner.cStandard": "",
|
||||||
|
"C_Cpp_Runner.cppStandard": "",
|
||||||
|
"C_Cpp_Runner.msvcBatchPath": "",
|
||||||
|
"C_Cpp_Runner.useMsvc": false,
|
||||||
|
"C_Cpp_Runner.warnings": [
|
||||||
|
"-Wall",
|
||||||
|
"-Wextra",
|
||||||
|
"-Wpedantic",
|
||||||
|
"-Wshadow",
|
||||||
|
"-Wformat=2",
|
||||||
|
"-Wcast-align",
|
||||||
|
"-Wconversion",
|
||||||
|
"-Wsign-conversion",
|
||||||
|
"-Wnull-dereference"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.msvcWarnings": [
|
||||||
|
"/W4",
|
||||||
|
"/permissive-",
|
||||||
|
"/w14242",
|
||||||
|
"/w14287",
|
||||||
|
"/w14296",
|
||||||
|
"/w14311",
|
||||||
|
"/w14826",
|
||||||
|
"/w44062",
|
||||||
|
"/w44242",
|
||||||
|
"/w14905",
|
||||||
|
"/w14906",
|
||||||
|
"/w14263",
|
||||||
|
"/w44265",
|
||||||
|
"/w14928"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.enableWarnings": true,
|
||||||
|
"C_Cpp_Runner.warningsAsError": false,
|
||||||
|
"C_Cpp_Runner.compilerArgs": [],
|
||||||
|
"C_Cpp_Runner.linkerArgs": [],
|
||||||
|
"C_Cpp_Runner.includePaths": [],
|
||||||
|
"C_Cpp_Runner.includeSearch": [
|
||||||
|
"*",
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.excludeSearch": [
|
||||||
|
"**/build",
|
||||||
|
"**/build/**",
|
||||||
|
"**/.*",
|
||||||
|
"**/.*/**",
|
||||||
|
"**/.vscode",
|
||||||
|
"**/.vscode/**"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.useAddressSanitizer": false,
|
||||||
|
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||||
|
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||||
|
"C_Cpp_Runner.showCompilationTime": false,
|
||||||
|
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||||
|
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||||
|
}
|
|
@ -13,5 +13,4 @@ platform = raspberrypi
|
||||||
board = adafruit_kb2040
|
board = adafruit_kb2040
|
||||||
framework = arduino
|
framework = arduino
|
||||||
upload_protocol = picotool
|
upload_protocol = picotool
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
lib_deps = fastled/FastLED@^3.9.4
|
|
133
src/main.cpp
133
src/main.cpp
|
@ -2,45 +2,27 @@
|
||||||
#include <pico.h>
|
#include <pico.h>
|
||||||
#include <hardware/pwm.h>
|
#include <hardware/pwm.h>
|
||||||
#include <Keyboard.h>
|
#include <Keyboard.h>
|
||||||
#include <FastLED.h>
|
|
||||||
|
|
||||||
#define PORT 2
|
#define PORT 2
|
||||||
#define PORT2 3
|
#define PORT2 3
|
||||||
#define THRESHOLD 10
|
|
||||||
#define LEDPORT 5
|
|
||||||
|
|
||||||
CRGB leds[2];
|
|
||||||
|
|
||||||
class HallButton
|
class HallButton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
uint64_t firstPulseStart;
|
uint64_t firstPulseStart;
|
||||||
uint8_t counter = 0;
|
uint64_t firstPulseLength;
|
||||||
uint64_t firstPulseLength[3]; // value of button
|
bool isDataReadyToRead;
|
||||||
int64_t value;
|
|
||||||
uint64_t _median;
|
|
||||||
int64_t maxValue;
|
|
||||||
bool isFirstClick = true;
|
|
||||||
bool isDataReadyToRead = false;
|
|
||||||
bool isButtonPressed = false;
|
|
||||||
uint64_t nextTogglePoint = 0; // value when to toggle state of button
|
|
||||||
size_t ledId;
|
|
||||||
|
|
||||||
HallButton(uint8_t gpioNum, char buttonOnKeyboard, size_t ledId)
|
HallButton(uint8_t gpioNum, char buttonOnKeyboard)
|
||||||
{
|
{
|
||||||
this->gpioNum = gpioNum;
|
this->gpioNum = gpioNum;
|
||||||
this->buttonOnKeyboard = buttonOnKeyboard;
|
this->buttonOnKeyboard = buttonOnKeyboard;
|
||||||
this->ledId = ledId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleISR(bool gpioState, uint64_t currentTime)
|
void HandleISR(bool gpioState, uint64_t currentTime)
|
||||||
{
|
{
|
||||||
if (gpioState)
|
if (gpioState)
|
||||||
{
|
{
|
||||||
firstPulseLength[counter] = currentTime - firstPulseStart;
|
firstPulseLength = currentTime - firstPulseStart;
|
||||||
isDataReadyToRead = true;
|
isDataReadyToRead = true;
|
||||||
if (++counter >= 3)
|
|
||||||
counter = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -49,84 +31,24 @@ public:
|
||||||
}
|
}
|
||||||
void HandleButton()
|
void HandleButton()
|
||||||
{
|
{
|
||||||
if (!isDataReadyToRead)
|
if (!buttonPressed && firstPulseLength > 310)
|
||||||
return;
|
|
||||||
_median = median(firstPulseLength[0], firstPulseLength[1], firstPulseLength[2]);
|
|
||||||
value = filtered((float)_median);
|
|
||||||
if (value > maxValue)
|
|
||||||
if (isFirstClick)
|
|
||||||
maxValue = value;
|
|
||||||
else
|
|
||||||
value = maxValue;
|
|
||||||
|
|
||||||
if (isButtonPressed)
|
|
||||||
{
|
{
|
||||||
if (value < nextTogglePoint)
|
Keyboard.press(buttonOnKeyboard);
|
||||||
{
|
buttonPressed = true;
|
||||||
Release();
|
|
||||||
if (isFirstClick)
|
|
||||||
isFirstClick = false;
|
|
||||||
}
|
|
||||||
if ((int64_t)value - (int64_t)nextTogglePoint > THRESHOLD)
|
|
||||||
nextTogglePoint = value - THRESHOLD;
|
|
||||||
}
|
}
|
||||||
else
|
else if (buttonPressed && firstPulseLength < 300)
|
||||||
{
|
{
|
||||||
if (value >= nextTogglePoint)
|
Keyboard.release(buttonOnKeyboard);
|
||||||
{
|
buttonPressed = false;
|
||||||
Press();
|
|
||||||
}
|
|
||||||
if ((int64_t)nextTogglePoint - (int64_t)value > THRESHOLD)
|
|
||||||
nextTogglePoint = value + THRESHOLD;
|
|
||||||
}
|
}
|
||||||
isDataReadyToRead = false;
|
|
||||||
}
|
|
||||||
uint64_t median(uint64_t a, uint64_t b, uint64_t c)
|
|
||||||
{
|
|
||||||
return (a < b) ? ((b < c) ? b : ((c < a) ? a : c)) : ((a < c) ? a : ((c < b) ? b : c));
|
|
||||||
}
|
|
||||||
float filtered(float value)
|
|
||||||
{
|
|
||||||
float _kalman_gain, _current_estimate;
|
|
||||||
_kalman_gain = _err_estimate / (_err_estimate + _err_measure);
|
|
||||||
_current_estimate = _last_estimate + _kalman_gain * (value - _last_estimate);
|
|
||||||
_err_estimate = (1.0 - _kalman_gain) * _err_estimate + fabs(_last_estimate - _current_estimate) * _q;
|
|
||||||
_last_estimate = _current_estimate;
|
|
||||||
return _current_estimate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float _err_measure = 15;
|
bool buttonPressed;
|
||||||
float _err_estimate = 15;
|
|
||||||
float _q = 0.1;
|
|
||||||
float _last_estimate = 0.0;
|
|
||||||
uint8_t gpioNum;
|
uint8_t gpioNum;
|
||||||
char buttonOnKeyboard;
|
char buttonOnKeyboard;
|
||||||
void Press()
|
|
||||||
{
|
|
||||||
if (isButtonPressed)
|
|
||||||
return;
|
|
||||||
Keyboard.press(buttonOnKeyboard);
|
|
||||||
isButtonPressed = true;
|
|
||||||
LEDTick(isButtonPressed, ledId);
|
|
||||||
}
|
|
||||||
void Release()
|
|
||||||
{
|
|
||||||
if (!isButtonPressed)
|
|
||||||
return;
|
|
||||||
Keyboard.release(buttonOnKeyboard);
|
|
||||||
isButtonPressed = false;
|
|
||||||
LEDTick(isButtonPressed, ledId);
|
|
||||||
}
|
|
||||||
static void LEDTick(bool status, size_t ledId)
|
|
||||||
{
|
|
||||||
leds[ledId] = status ? CRGB::Red : CRGB::Black;
|
|
||||||
FastLED.show();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
HallButton btn[2] = {HallButton(PORT, 't'), HallButton(PORT2, 'y')};
|
||||||
HallButton btn[2] = {HallButton(PORT, 't', 1), HallButton(PORT2, 'y', 0)};
|
|
||||||
|
|
||||||
void isr(uint gpio, uint32_t events)
|
void isr(uint gpio, uint32_t events)
|
||||||
{
|
{
|
||||||
uint64_t currentTime = time_us_64();
|
uint64_t currentTime = time_us_64();
|
||||||
|
@ -144,6 +66,8 @@ void isr(uint gpio, uint32_t events)
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
|
Keyboard.begin();
|
||||||
|
Serial.begin(115200);
|
||||||
gpio_init(PORT);
|
gpio_init(PORT);
|
||||||
gpio_set_dir(PORT, false);
|
gpio_set_dir(PORT, false);
|
||||||
gpio_pull_up(PORT);
|
gpio_pull_up(PORT);
|
||||||
|
@ -152,20 +76,29 @@ void setup()
|
||||||
gpio_set_dir(PORT2, false);
|
gpio_set_dir(PORT2, false);
|
||||||
gpio_pull_up(PORT2);
|
gpio_pull_up(PORT2);
|
||||||
gpio_set_irq_enabled_with_callback(PORT2, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, isr);
|
gpio_set_irq_enabled_with_callback(PORT2, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, isr);
|
||||||
// Serial.begin(9600);
|
|
||||||
Keyboard.begin();
|
|
||||||
FastLED.addLeds<NEOPIXEL, LEDPORT>(leds, 2);
|
|
||||||
}
|
}
|
||||||
|
#define printf Serial.printf
|
||||||
|
byte counter = 0;
|
||||||
void printDebugInfo()
|
void printDebugInfo()
|
||||||
{
|
{
|
||||||
static uint32_t lastTime = 0;
|
if (counter < 1 && btn[0].isDataReadyToRead)
|
||||||
uint32_t time = millis();
|
|
||||||
if (time - lastTime >= 1)
|
|
||||||
{
|
{
|
||||||
Serial.printf("%d,%d,%llu,%llu,%i,", btn[0].isFirstClick, btn[0].maxValue, btn[0].value, btn[0].nextTogglePoint, btn[0].isButtonPressed);
|
btn[0].isDataReadyToRead = false;
|
||||||
Serial.printf("%d,%d,%llu,%llu,%i\n", btn[1].isFirstClick, btn[1].maxValue, btn[1].value, btn[1].nextTogglePoint, btn[1].isButtonPressed);
|
printf("BTN1: %lu", btn[0].firstPulseLength);
|
||||||
lastTime = time;
|
counter++;
|
||||||
|
}
|
||||||
|
if (btn[1].isDataReadyToRead)
|
||||||
|
{
|
||||||
|
btn[1].isDataReadyToRead = false;
|
||||||
|
if (counter > 0)
|
||||||
|
printf("\t");
|
||||||
|
printf("BTN2: %lu", btn[1].firstPulseLength);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
if (counter > 1)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
counter = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void loop()
|
void loop()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user