qmk-firmware/drivers/sensors/analog_joystick.c

97 lines
3 KiB
C

/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "analog_joystick.h"
#include "analog.h"
#include "gpio.h"
#include "wait.h"
#include "timer.h"
#include <stdlib.h>
// Set Parameters
uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN;
uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX;
uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX;
uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement
int16_t xOrigin, yOrigin;
uint16_t lastCursor = 0;
int16_t axisCoordinate(pin_t pin, uint16_t origin) {
int8_t direction;
int16_t distanceFromOrigin;
int16_t range;
int16_t position = analogReadPin(pin);
if (origin == position) {
return 0;
} else if (origin > position) {
distanceFromOrigin = origin - position;
range = origin - minAxisValue;
direction = -1;
} else {
distanceFromOrigin = position - origin;
range = maxAxisValue - origin;
direction = 1;
}
float percent = (float)distanceFromOrigin / range;
int16_t coordinate = (int16_t)(percent * 100);
if (coordinate < 0) {
return 0;
} else if (coordinate > 100) {
return 100 * direction;
} else {
return coordinate * direction;
}
}
int8_t axisToMouseComponent(pin_t pin, int16_t origin, uint8_t maxSpeed) {
int16_t coordinate = axisCoordinate(pin, origin);
if (coordinate != 0) {
float percent = (float)coordinate / 100;
return percent * maxCursorSpeed * (abs(coordinate) / speedRegulator);
} else {
return 0;
}
}
report_analog_joystick_t analog_joystick_read(void) {
report_analog_joystick_t report = {0};
if (timer_elapsed(lastCursor) > ANALOG_JOYSTICK_READ_INTERVAL) {
lastCursor = timer_read();
report.x = axisToMouseComponent(ANALOG_JOYSTICK_X_AXIS_PIN, xOrigin, maxCursorSpeed);
report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed);
}
#ifdef ANALOG_JOYSTICK_CLICK_PIN
report.button = !readPin(ANALOG_JOYSTICK_CLICK_PIN);
#endif
return report;
}
void analog_joystick_init(void) {
#ifdef ANALOG_JOYSTICK_CLICK_PIN
setPinInputHigh(ANALOG_JOYSTICK_CLICK_PIN);
#endif
// Account for drift
xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN);
yOrigin = analogReadPin(ANALOG_JOYSTICK_Y_AXIS_PIN);
}