mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-09-30 22:09:01 +02:00
Initial potentiometer support
This commit is contained in:
@@ -60,6 +60,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifdef ENCODER_ENABLE
|
||||
# include "encoder.h"
|
||||
#endif
|
||||
#ifdef POTENTIOMETER_ENABLE
|
||||
# include "potentiometer.h"
|
||||
#endif
|
||||
#ifdef HAPTIC_ENABLE
|
||||
# include "haptic.h"
|
||||
#endif
|
||||
@@ -143,6 +146,9 @@ uint32_t last_input_activity_time(void) {
|
||||
uint32_t last_input_activity_elapsed(void) {
|
||||
return sync_timer_elapsed32(last_input_modification_time);
|
||||
}
|
||||
void last_input_activity_trigger(void) {
|
||||
last_input_modification_time = sync_timer_read32();
|
||||
}
|
||||
|
||||
static uint32_t last_matrix_modification_time = 0;
|
||||
uint32_t last_matrix_activity_time(void) {
|
||||
@@ -440,6 +446,9 @@ void keyboard_init(void) {
|
||||
#ifdef DIP_SWITCH_ENABLE
|
||||
dip_switch_init();
|
||||
#endif
|
||||
#ifdef POTENTIOMETER_ENABLE
|
||||
potentiometer_init();
|
||||
#endif
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_init();
|
||||
#endif
|
||||
@@ -669,6 +678,13 @@ void keyboard_task(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef POTENTIOMETER_ENABLE
|
||||
if (potentiometer_task()) {
|
||||
last_input_activity_trigger();
|
||||
activity_has_occurred = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef POINTING_DEVICE_ENABLE
|
||||
if (pointing_device_task()) {
|
||||
last_pointing_device_activity_trigger();
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include "potentiometer.h"
|
||||
#include "gpio.h"
|
||||
#include "util.h"
|
||||
#include "timer.h"
|
||||
#include "analog.h"
|
||||
|
||||
#ifndef POTENTIOMETER_THROTTLE_MS
|
||||
# define POTENTIOMETER_THROTTLE_MS 1
|
||||
#endif
|
||||
|
||||
#ifndef POTENTIOMETER_OUTPUT_MIN_VALUE
|
||||
# define POTENTIOMETER_OUTPUT_MIN_VALUE 0
|
||||
#endif
|
||||
#ifndef POTENTIOMETER_OUTPUT_MAX_VALUE
|
||||
# define POTENTIOMETER_OUTPUT_MAX_VALUE 127
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ADC Driver
|
||||
|
||||
// Matches default adc range
|
||||
#ifndef POTENTIOMETER_RAW_MIN_VALUE
|
||||
# define POTENTIOMETER_RAW_MIN_VALUE 0
|
||||
#endif
|
||||
#ifndef POTENTIOMETER_RAW_MAX_VALUE
|
||||
# define POTENTIOMETER_RAW_MAX_VALUE (1 << 10)
|
||||
#endif
|
||||
|
||||
static pin_t potentiometer_pads[] = POTENTIOMETER_PINS;
|
||||
#define NUM_POTENTIOMETERS (ARRAY_SIZE(potentiometer_pads))
|
||||
|
||||
__attribute__((weak)) void potentiometer_driver_init(void) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
__attribute__((weak)) uint16_t potentiometer_driver_sample(uint8_t index) {
|
||||
return analogReadPin(potentiometer_pads[index]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Callbacks
|
||||
|
||||
__attribute__((weak)) bool potentiometer_update_user(uint8_t index, uint16_t value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool potentiometer_update_kb(uint8_t index, uint16_t value) {
|
||||
return potentiometer_update_user(index, value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Default scanning routine
|
||||
|
||||
__attribute__((weak)) uint16_t potentiometer_map(uint8_t index, uint16_t value) {
|
||||
(void)index;
|
||||
|
||||
uint32_t a = POTENTIOMETER_OUTPUT_MIN_VALUE;
|
||||
uint32_t b = POTENTIOMETER_OUTPUT_MAX_VALUE;
|
||||
uint32_t min = POTENTIOMETER_RAW_MIN_VALUE;
|
||||
uint32_t max = POTENTIOMETER_RAW_MAX_VALUE;
|
||||
|
||||
// Scale value to min/max using the adc range
|
||||
return ((b - a) * (value - min) / (max - min)) + a;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool potentiometer_filter(uint8_t index, uint16_t value) {
|
||||
// ADC currently limited to max of 12 bits - init to max 16 ensures
|
||||
// we can correctly capture even a raw first sample at max adc bounds
|
||||
static uint16_t potentiometer_state[NUM_POTENTIOMETERS] = {UINT16_MAX};
|
||||
|
||||
if (value == potentiometer_state[index]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
potentiometer_state[index] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool potentiometer_throttle_task(void) {
|
||||
#if (POTENTIOMETER_THROTTLE_MS > 0)
|
||||
static uint32_t last_exec = 0;
|
||||
if (timer_elapsed32(last_exec) < POTENTIOMETER_THROTTLE_MS) {
|
||||
return false;
|
||||
}
|
||||
last_exec = timer_read32();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void potentiometer_init(void) {
|
||||
potentiometer_driver_init();
|
||||
}
|
||||
|
||||
bool potentiometer_task(void) {
|
||||
if (!potentiometer_throttle_task()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
for (uint8_t index = 0; index < NUM_POTENTIOMETERS; index++) {
|
||||
uint16_t raw = potentiometer_driver_sample(index);
|
||||
uint16_t value = potentiometer_map(index, raw);
|
||||
if (potentiometer_filter(index, value)) {
|
||||
changed |= true;
|
||||
|
||||
potentiometer_update_kb(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** \brief user hook called when sampled value has changed
|
||||
*/
|
||||
bool potentiometer_update_user(uint8_t index, uint16_t value);
|
||||
|
||||
/** \brief keyboard hook called when sampled value has changed
|
||||
*/
|
||||
bool potentiometer_update_kb(uint8_t index, uint16_t value);
|
||||
|
||||
/** \brief Handle various subsystem background tasks
|
||||
*/
|
||||
bool potentiometer_task(void);
|
||||
@@ -207,6 +207,10 @@ extern layer_state_t layer_state;
|
||||
# include "encoder.h"
|
||||
#endif
|
||||
|
||||
#ifdef POTENTIOMETER_ENABLE
|
||||
# include "potentiometer.h"
|
||||
#endif
|
||||
|
||||
#ifdef POINTING_DEVICE_ENABLE
|
||||
# include "pointing_device.h"
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user