[Keyboard] Overhaul ploopyco devices (#22967)
parent
359cec14fa
commit
68e8d74188
|
@ -142,7 +142,7 @@ int8_t opt_encoder_handler(uint16_t curA, uint16_t curB) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else { // state must be LOHI
|
else { // state must be LOHI
|
||||||
if (sA == HI && sB == HI) {
|
if (sA == HI && sB == HI) {
|
||||||
state = HIHI;
|
state = HIHI;
|
||||||
lohif = true;
|
lohif = true;
|
||||||
|
@ -157,9 +157,13 @@ int8_t opt_encoder_handler(uint16_t curA, uint16_t curB) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateThresholdA(int curA) { scrollThresholdA = calculateThreshold(curA, &lowA, &highA, &cLowA, &cHighA, arLowA, arHighA, &lowIndexA, &highIndexA, &lowOverflowA, &highOverflowA); }
|
void calculateThresholdA(int curA) {
|
||||||
|
scrollThresholdA = calculateThreshold(curA, &lowA, &highA, &cLowA, &cHighA, arLowA, arHighA, &lowIndexA, &highIndexA, &lowOverflowA, &highOverflowA);
|
||||||
|
}
|
||||||
|
|
||||||
void calculateThresholdB(int curB) { scrollThresholdB = calculateThreshold(curB, &lowB, &highB, &cLowB, &cHighB, arLowB, arHighB, &lowIndexB, &highIndexB, &lowOverflowB, &highOverflowB); }
|
void calculateThresholdB(int curB) {
|
||||||
|
scrollThresholdB = calculateThreshold(curB, &lowB, &highB, &cLowB, &cHighB, arLowB, arHighB, &lowIndexB, &highIndexB, &lowOverflowB, &highOverflowB);
|
||||||
|
}
|
||||||
|
|
||||||
int calculateThreshold(int cur, int* low, int* high, bool* cLow, bool* cHigh, int arLow[], int arHigh[], int* lowIndex, int* highIndex, bool* lowOverflow, bool* highOverflow) {
|
int calculateThreshold(int cur, int* low, int* high, bool* cLow, bool* cHigh, int arLow[], int arHigh[], int* lowIndex, int* highIndex, bool* lowOverflow, bool* highOverflow) {
|
||||||
if (cur < *low) *low = cur;
|
if (cur < *low) *low = cur;
|
||||||
|
@ -236,7 +240,9 @@ int calculateThreshold(int cur, int* low, int* high, bool* cLow, bool* cHigh, in
|
||||||
return thresholdEquation(calcLow, calcHigh);
|
return thresholdEquation(calcLow, calcHigh);
|
||||||
}
|
}
|
||||||
|
|
||||||
int thresholdEquation(int lo, int hi) { return ((hi - lo) / 3) + lo; }
|
int thresholdEquation(int lo, int hi) {
|
||||||
|
return ((hi - lo) / 3) + lo;
|
||||||
|
}
|
||||||
|
|
||||||
void incrementIndex(int* index, bool* ovflw) {
|
void incrementIndex(int* index, bool* ovflw) {
|
||||||
if (*index < SCROLLER_AR_SIZE - 1)
|
if (*index < SCROLLER_AR_SIZE - 1)
|
|
@ -63,7 +63,7 @@
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CALIBRATION, /* Recalibrate encoder state by waiting for a 01 -> 00 or 10 -> 00 transistion */
|
CALIBRATION, /* Recalibrate encoder state by waiting for a 01 -> 00 or 10 -> 00 transistion */
|
||||||
DECODE /* Translate changes in the encoder state into movement */
|
DECODE /* Translate changes in the encoder state into movement */
|
||||||
} encoder_state_t;
|
} encoder_state_t;
|
||||||
|
|
||||||
static encoder_state_t mode;
|
static encoder_state_t mode;
|
||||||
|
@ -87,15 +87,14 @@ static const uint8_t movement[] = {
|
||||||
// 10 -> 00, 01, 10, 11
|
// 10 -> 00, 01, 10, 11
|
||||||
MOVE_DOWN, MOVE_ERR, MOVE_NONE, MOVE_UP,
|
MOVE_DOWN, MOVE_ERR, MOVE_NONE, MOVE_UP,
|
||||||
// 11 -> 00, 01, 10, 11
|
// 11 -> 00, 01, 10, 11
|
||||||
MOVE_ERR, MOVE_UP, MOVE_DOWN, MOVE_NONE
|
MOVE_ERR, MOVE_UP, MOVE_DOWN, MOVE_NONE};
|
||||||
};
|
|
||||||
|
|
||||||
void opt_encoder_init(void) {
|
void opt_encoder_init(void) {
|
||||||
mode = CALIBRATION;
|
mode = CALIBRATION;
|
||||||
lastState = 0;
|
lastState = 0;
|
||||||
|
|
||||||
lowA = ENCODER_MAX;
|
lowA = ENCODER_MAX;
|
||||||
lowB = ENCODER_MAX;
|
lowB = ENCODER_MAX;
|
||||||
highA = ENCODER_MIN;
|
highA = ENCODER_MIN;
|
||||||
highB = ENCODER_MIN;
|
highB = ENCODER_MIN;
|
||||||
}
|
}
|
||||||
|
@ -104,26 +103,22 @@ int8_t opt_encoder_handler(uint16_t encA, uint16_t encB) {
|
||||||
int8_t result = 0;
|
int8_t result = 0;
|
||||||
|
|
||||||
highA = MAX(encA, highA);
|
highA = MAX(encA, highA);
|
||||||
lowA = MIN(encA, lowA);
|
lowA = MIN(encA, lowA);
|
||||||
highB = MAX(encB, highB);
|
highB = MAX(encB, highB);
|
||||||
lowB = MIN(encB, lowB);
|
lowB = MIN(encB, lowB);
|
||||||
|
|
||||||
/* Only compute the thresholds after a large enough range is established */
|
/* Only compute the thresholds after a large enough range is established */
|
||||||
if (highA - lowA > SCROLL_THRESH_RANGE_LIM && highB - lowB > SCROLL_THRESH_RANGE_LIM) {
|
if (highA - lowA > SCROLL_THRESH_RANGE_LIM && highB - lowB > SCROLL_THRESH_RANGE_LIM) {
|
||||||
const int16_t lowThresholdA = (highA + lowA) / 4;
|
const int16_t lowThresholdA = (highA + lowA) / 4;
|
||||||
const int16_t highThresholdA = (highA + lowA) - lowThresholdA;
|
const int16_t highThresholdA = (highA + lowA) - lowThresholdA;
|
||||||
const int16_t lowThresholdB = (highB + lowB) / 4;
|
const int16_t lowThresholdB = (highB + lowB) / 4;
|
||||||
const int16_t highThresholdB = (highB + lowB) - lowThresholdB;
|
const int16_t highThresholdB = (highB + lowB) - lowThresholdB;
|
||||||
|
|
||||||
uint8_t state = MAKE_STATE(
|
uint8_t state = MAKE_STATE(STATE_A(lastState) ? encA > lowThresholdA : encA > highThresholdA, STATE_B(lastState) ? encB > lowThresholdB : encB > highThresholdB);
|
||||||
STATE_A(lastState) ? encA > lowThresholdA : encA > highThresholdA,
|
|
||||||
STATE_B(lastState) ? encB > lowThresholdB : encB > highThresholdB
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CALIBRATION:
|
case CALIBRATION:
|
||||||
if ((lastState == HILO && state == LOLO)
|
if ((lastState == HILO && state == LOLO) || (lastState == LOHI && state == LOLO))
|
||||||
|| (lastState == LOHI && state == LOLO))
|
|
||||||
mode = DECODE;
|
mode = DECODE;
|
||||||
else
|
else
|
||||||
mode = CALIBRATION;
|
mode = CALIBRATION;
|
||||||
|
@ -134,7 +129,7 @@ int8_t opt_encoder_handler(uint16_t encA, uint16_t encB) {
|
||||||
/* If we detect a state change that should not be possible,
|
/* If we detect a state change that should not be possible,
|
||||||
* then the wheel might have moved too fast and we need to
|
* then the wheel might have moved too fast and we need to
|
||||||
* recalibrate the encoder position. */
|
* recalibrate the encoder position. */
|
||||||
mode = result == MOVE_ERR ? CALIBRATION : mode;
|
mode = result == MOVE_ERR ? CALIBRATION : mode;
|
||||||
result = result == MOVE_ERR ? MOVE_NONE : result;
|
result = result == MOVE_ERR ? MOVE_NONE : result;
|
||||||
|
|
||||||
break;
|
break;
|
|
@ -0,0 +1,116 @@
|
||||||
|
/* Copyright 2023 Leorize <leorize+oss@disroot.org>
|
||||||
|
* Copyright 2011 Ben Buxton <bb@cactii.net>
|
||||||
|
*
|
||||||
|
* 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 3 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 "opt_encoder.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* An extremely simple implementation of the encoder:
|
||||||
|
*
|
||||||
|
* For read out, the mechanism mimics that of a Schmitt trigger, with
|
||||||
|
* statically defined high/low thresholds used instead of computing
|
||||||
|
* one at runtime.
|
||||||
|
*
|
||||||
|
* The advantage of this approach is computing less in the decoder
|
||||||
|
* implementation and allow the state to be measured before the wheel
|
||||||
|
* moved.
|
||||||
|
*
|
||||||
|
* Compared to opt_encoder_simple.c, the use of an intermediary state
|
||||||
|
* reduces sensitivity and de-sensitize against tiny movements caused
|
||||||
|
* when lifting finger off the wheel.
|
||||||
|
*
|
||||||
|
* For turning decoded values into rotation, an algorithm inspired by
|
||||||
|
* http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
|
||||||
|
* is employed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ENCODER_LOW_THRES_A) || !defined(ENCODER_HIGH_THRES_A)
|
||||||
|
# error "The thresholds for phototransistors A is not defined in config.h"
|
||||||
|
#endif
|
||||||
|
#if !defined(ENCODER_LOW_THRES_B) || !defined(ENCODER_HIGH_THRES_B)
|
||||||
|
# error "The thresholds for phototransistors B is not defined in config.h"
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Sample values, captured for a Ploopy Mini Trackball
|
||||||
|
*
|
||||||
|
* The following min-max values was captured by aggregating data recorded
|
||||||
|
* when debug_encoder is enabled:
|
||||||
|
*
|
||||||
|
* A: min: 0, max: 214
|
||||||
|
* B: min: 0, max: 204
|
||||||
|
*
|
||||||
|
* The threshold specified is then defined at the 1/4 and the 3/4 points.
|
||||||
|
*
|
||||||
|
* As these values might vary between units, you're encouraged to
|
||||||
|
* measure your own.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
# define ENCODER_LOW_THRES_A 53
|
||||||
|
# define ENCODER_HIGH_THRES_A 161
|
||||||
|
# define ENCODER_LOW_THRES_B 52
|
||||||
|
# define ENCODER_HIGH_THRES_B 153
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Utilities for composing the encoder state */
|
||||||
|
#define MAKE_STATE(HI_A, HI_B) (((uint8_t)((HI_A) & 0x1) << 1) | ((uint8_t)((HI_B) & 0x1)))
|
||||||
|
#define STATE_A(st) ((st & 0x2) >> 1)
|
||||||
|
#define STATE_B(st) (st & 0x1)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
START,
|
||||||
|
DOWN_BEGIN,
|
||||||
|
UP_BEGIN,
|
||||||
|
START_MID,
|
||||||
|
DOWN_BEGIN_MID,
|
||||||
|
UP_BEGIN_MID,
|
||||||
|
STATE_MASK = 0xf, /* 0b1111 */
|
||||||
|
EMIT_UP = 0x10,
|
||||||
|
EMIT_UP_MID = EMIT_UP & START_MID,
|
||||||
|
EMIT_DOWN = 0x80,
|
||||||
|
EMIT_DOWN_MID = EMIT_DOWN & START_MID,
|
||||||
|
EMIT_MASK = 0xf0
|
||||||
|
} encoder_state_t;
|
||||||
|
|
||||||
|
static encoder_state_t state;
|
||||||
|
static uint8_t encState;
|
||||||
|
|
||||||
|
static const uint8_t transitions[] = {
|
||||||
|
// clang-format off
|
||||||
|
// START -> 00, 01, 10, 11
|
||||||
|
START, DOWN_BEGIN, UP_BEGIN, START_MID,
|
||||||
|
// DOWN_BEGIN -> 00, 01, 10, 11
|
||||||
|
START, DOWN_BEGIN, START, EMIT_DOWN_MID,
|
||||||
|
// UP_BEGIN -> 00, 01, 10, 11
|
||||||
|
START, START, UP_BEGIN, EMIT_UP_MID,
|
||||||
|
// START_MID -> 00, 01, 10, 11
|
||||||
|
START, UP_BEGIN_MID, DOWN_BEGIN_MID, START_MID,
|
||||||
|
// DOWN_BEGIN_MID -> 00, 01, 10, 11
|
||||||
|
EMIT_DOWN, START_MID, DOWN_BEGIN_MID, START_MID,
|
||||||
|
// UP_BEGIN_MID -> 00, 01, 10, 11
|
||||||
|
EMIT_UP, UP_BEGIN_MID, START_MID, START_MID,
|
||||||
|
// clang-format on
|
||||||
|
};
|
||||||
|
|
||||||
|
void opt_encoder_init(void) {
|
||||||
|
state = START;
|
||||||
|
encState = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t opt_encoder_handler(uint16_t encA, uint16_t encB) {
|
||||||
|
encState = MAKE_STATE((STATE_A(encState) & (encA > ENCODER_LOW_THRES_A)) | (encA > ENCODER_HIGH_THRES_A), (STATE_B(encState) & (encB > ENCODER_LOW_THRES_B)) | (encB > ENCODER_HIGH_THRES_B));
|
||||||
|
state = transitions[((state & STATE_MASK) << 2) + encState];
|
||||||
|
return state & EMIT_MASK;
|
||||||
|
}
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define UNUSABLE_PINS \
|
||||||
|
{ GP1, GP3, GP4, GP6, GP8, GP10, GP14, GP16, GP18, GP20, GP22, GP24, GP25, GP26, GP27, GP28, GP29 }
|
||||||
|
|
||||||
// #define ROTATIONAL_TRANSFORM_ANGLE 0
|
// #define ROTATIONAL_TRANSFORM_ANGLE 0
|
||||||
#define POINTING_DEVICE_INVERT_Y
|
#define POINTING_DEVICE_INVERT_Y
|
||||||
|
|
||||||
|
@ -26,4 +29,4 @@
|
||||||
#define PMW33XX_CS_PIN GP5
|
#define PMW33XX_CS_PIN GP5
|
||||||
#define SPI_SCK_PIN GP2
|
#define SPI_SCK_PIN GP2
|
||||||
#define SPI_MISO_PIN GP0
|
#define SPI_MISO_PIN GP0
|
||||||
#define SPI_MOSI_PIN GP7
|
#define SPI_MOSI_PIN GP7
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
"extrakey": true,
|
"extrakey": true,
|
||||||
"mousekey": true,
|
"mousekey": true,
|
||||||
"nkro": true,
|
"nkro": true,
|
||||||
"pointing_device": true,
|
"pointing_device": true
|
||||||
},
|
},
|
||||||
"layouts": {
|
"layouts": {
|
||||||
"LAYOUT": {
|
"LAYOUT": {
|
||||||
|
@ -31,5 +31,5 @@
|
||||||
},
|
},
|
||||||
"dynamic_keymap": {
|
"dynamic_keymap": {
|
||||||
"layer_count": 8
|
"layer_count": 8
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
/* Copyright 2023 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
*
|
|
||||||
* 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 "madromys.h"
|
|
||||||
|
|
||||||
#ifndef PLOOPY_DPI_OPTIONS
|
|
||||||
# define PLOOPY_DPI_OPTIONS \
|
|
||||||
{ 600, 900, 1200, 1600 }
|
|
||||||
# ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 0
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_DPI
|
|
||||||
# define PLOOPY_DRAGSCROLL_DPI 100 // Fixed-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_FIXED
|
|
||||||
# define PLOOPY_DRAGSCROLL_FIXED 1
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MULTIPLIER
|
|
||||||
# define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75 // Variable-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_SEMAPHORE
|
|
||||||
# define PLOOPY_DRAGSCROLL_SEMAPHORE 4
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MOMENTARY
|
|
||||||
# define PLOOPY_DRAGSCROLL_MOMENTARY 1
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_INVERT
|
|
||||||
# define PLOOPY_DRAGSCROLL_INVERT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_config_t keyboard_config;
|
|
||||||
uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
|
|
||||||
#define DPI_OPTION_SIZE (sizeof(dpi_array) / sizeof(uint16_t))
|
|
||||||
|
|
||||||
// TODO: Implement libinput profiles
|
|
||||||
// https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
|
|
||||||
// Compile time accel selection
|
|
||||||
// Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
|
|
||||||
|
|
||||||
// Trackball State
|
|
||||||
bool is_drag_scroll = false;
|
|
||||||
|
|
||||||
// drag scroll divisor state
|
|
||||||
int8_t drag_scroll_x_semaphore = 0;
|
|
||||||
int8_t drag_scroll_y_semaphore = 0;
|
|
||||||
|
|
||||||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
|
||||||
if (is_drag_scroll) {
|
|
||||||
int16_t mouse_report_x_temp = mouse_report.x;
|
|
||||||
int16_t mouse_report_y_temp = mouse_report.y;
|
|
||||||
int16_t mouse_report_x_calc = 0;
|
|
||||||
int16_t mouse_report_y_calc = 0;
|
|
||||||
int16_t valx = (mouse_report_x_temp > 0) ? -1 : 1;
|
|
||||||
int16_t valy = (mouse_report_y_temp > 0) ? -1 : 1;
|
|
||||||
|
|
||||||
while (mouse_report_x_temp != 0) {
|
|
||||||
mouse_report_x_temp += valx;
|
|
||||||
drag_scroll_x_semaphore -= valx;
|
|
||||||
|
|
||||||
if (abs(drag_scroll_x_semaphore) >= PLOOPY_DRAGSCROLL_SEMAPHORE) {
|
|
||||||
mouse_report_x_calc -= valx;
|
|
||||||
drag_scroll_x_semaphore = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (mouse_report_y_temp != 0) {
|
|
||||||
mouse_report_y_temp += valy;
|
|
||||||
drag_scroll_y_semaphore -= valy;
|
|
||||||
|
|
||||||
if (abs(drag_scroll_y_semaphore) >= PLOOPY_DRAGSCROLL_SEMAPHORE) {
|
|
||||||
mouse_report_y_calc -= valy;
|
|
||||||
drag_scroll_y_semaphore = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mouse_report.h = mouse_report_x_calc;
|
|
||||||
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_INVERT
|
|
||||||
// Invert vertical scroll direction
|
|
||||||
mouse_report.v = -mouse_report_y_calc;
|
|
||||||
#else
|
|
||||||
mouse_report.v = mouse_report_y_calc;
|
|
||||||
#endif
|
|
||||||
mouse_report.x = 0;
|
|
||||||
mouse_report.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointing_device_task_user(mouse_report);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
|
|
||||||
if (!process_record_user(keycode, record)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycode == DPI_CONFIG && record->event.pressed) {
|
|
||||||
keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycode == DRAG_SCROLL) {
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MOMENTARY
|
|
||||||
if (record->event.pressed)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
is_drag_scroll ^= 1;
|
|
||||||
}
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_FIXED
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? PLOOPY_DRAGSCROLL_DPI : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#else
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? (dpi_array[keyboard_config.dpi_config] * PLOOPY_DRAGSCROLL_MULTIPLIER) : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hardware Setup
|
|
||||||
void keyboard_pre_init_kb(void) {
|
|
||||||
// debug_enable = true;
|
|
||||||
// debug_matrix = true;
|
|
||||||
// debug_mouse = true;
|
|
||||||
// debug_encoder = true;
|
|
||||||
|
|
||||||
/* Ground all output pins connected to ground. This provides additional
|
|
||||||
* pathways to ground. If you're messing with this, know this: driving ANY
|
|
||||||
* of these pins high will cause a short. On the MCU. Ka-blooey.
|
|
||||||
*/
|
|
||||||
const pin_t unused_pins[] = { GP1, GP3, GP4, GP6, GP8, GP10, GP14, GP16,
|
|
||||||
GP18, GP20, GP22, GP24, GP25, GP26, GP27, GP28, GP29 };
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < (sizeof(unused_pins) / sizeof(pin_t)); i++) {
|
|
||||||
setPinOutput(unused_pins[i]);
|
|
||||||
writePinLow(unused_pins[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard_pre_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pointing_device_init_kb(void) { pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]); }
|
|
||||||
|
|
||||||
void eeconfig_init_kb(void) {
|
|
||||||
keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
eeconfig_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
// is safe to just read DPI setting since matrix init
|
|
||||||
// comes before pointing device init.
|
|
||||||
keyboard_config.raw = eeconfig_read_kb();
|
|
||||||
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
|
|
||||||
eeconfig_init_kb();
|
|
||||||
}
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/* Copyright 2023 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "quantum.h"
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uint32_t raw;
|
|
||||||
struct {
|
|
||||||
uint8_t dpi_config;
|
|
||||||
};
|
|
||||||
} keyboard_config_t;
|
|
||||||
_Static_assert(sizeof(keyboard_config_t) == sizeof(uint32_t), "keyboard_config_t size mismatch compared to EEPROM area");
|
|
||||||
|
|
||||||
extern keyboard_config_t keyboard_config;
|
|
||||||
extern uint16_t dpi_array[];
|
|
||||||
|
|
||||||
enum ploopy_keycodes {
|
|
||||||
DPI_CONFIG = QK_KB_0,
|
|
||||||
DRAG_SCROLL,
|
|
||||||
};
|
|
|
@ -27,17 +27,6 @@ If you want to upload a new firmware file (a ".uf2" file, like "madromys_awesome
|
||||||
|
|
||||||
**TIP**: If your firmware is in some kind of strange state and uploading new firmware isn't fixing it, try uploading [a flash nuke](https://learn.adafruit.com/getting-started-with-raspberry-pi-pico-circuitpython/circuitpython#flash-resetting-uf2-3083182) to the Madromys board before flashing the new firmware. It wipes the memory of the Madromys board completely clean, which can help clear a few types of errors.
|
**TIP**: If your firmware is in some kind of strange state and uploading new firmware isn't fixing it, try uploading [a flash nuke](https://learn.adafruit.com/getting-started-with-raspberry-pi-pico-circuitpython/circuitpython#flash-resetting-uf2-3083182) to the Madromys board before flashing the new firmware. It wipes the memory of the Madromys board completely clean, which can help clear a few types of errors.
|
||||||
|
|
||||||
# Drag Scroll
|
# Customizing your Ploopy Madromys
|
||||||
|
|
||||||
Drag Scroll is a custom keycode for Ploopy devices that allows you to hold or tap a button and have the mouse movement translate into scrolling instead.
|
You can find customziation options [here](../readme.md).
|
||||||
|
|
||||||
Nothing needs to be enabled to use this functionality; it's enabled on Madromys by default.
|
|
||||||
|
|
||||||
### Drag Scroll Configuration
|
|
||||||
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MOMENTARY` - Makes the key into a momentary key, rather than a toggle.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75` - Sets the DPI multiplier to use when drag scroll is enabled.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_FIXED` - Normally, when activating Drag Scroll, it uses a fraction of the current DPI. You can define this to use a specific, set DPI rather than a fraction of the current DPI.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_DPI 100` - When the fixed DPI option is enabled, this sets the DPI to be used for Drag Scroll.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_INVERT` - This reverses the direction that the scroll is performed.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_SEMAPHORE` - This is a divisor on the drag scroll sensitivity. The default is 0, which means that the drag scroll is at maximum sensitivity. A value of 4 would mean that the drag scroll is 4 times less sensitive.
|
|
||||||
|
|
|
@ -33,5 +33,10 @@
|
||||||
/* PMW33XX Settings */
|
/* PMW33XX Settings */
|
||||||
#define PMW33XX_CS_PIN B0
|
#define PMW33XX_CS_PIN B0
|
||||||
|
|
||||||
|
#define ENCODER_BUTTON_COL 1
|
||||||
|
#define ENCODER_BUTTON_ROW 0
|
||||||
/* Custom encoder needs to specify just how many encoders we have */
|
/* Custom encoder needs to specify just how many encoders we have */
|
||||||
#define NUM_ENCODERS 1
|
#define NUM_ENCODERS 1
|
||||||
|
|
||||||
|
#define ENCODERS_PAD_A { F0 }
|
||||||
|
#define ENCODERS_PAD_B { F4 }
|
||||||
|
|
|
@ -9,6 +9,15 @@
|
||||||
"device_version": "0.0.1",
|
"device_version": "0.0.1",
|
||||||
"max_power": 100
|
"max_power": 100
|
||||||
},
|
},
|
||||||
|
"features": {
|
||||||
|
"bootmagic": true,
|
||||||
|
"extrakey": true,
|
||||||
|
"mousekey": true,
|
||||||
|
"nkro": false,
|
||||||
|
"pointing_device": true,
|
||||||
|
"rgblight": false,
|
||||||
|
"encoder": true
|
||||||
|
},
|
||||||
"bootmagic": {
|
"bootmagic": {
|
||||||
"matrix": [0, 3]
|
"matrix": [0, 3]
|
||||||
},
|
},
|
||||||
|
@ -31,9 +40,6 @@
|
||||||
["D4", "D2", "E6", "B6", "D7", "C6", "C7", "B7"]
|
["D4", "D2", "E6", "B6", "D7", "C6", "C7", "B7"]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"features": {
|
|
||||||
"encoder": true
|
|
||||||
},
|
|
||||||
"encoder": {
|
"encoder": {
|
||||||
"driver": "custom"
|
"driver": "custom"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2020 Ploopy Corporation
|
|
||||||
*
|
|
||||||
* 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 QMK_KEYBOARD_H
|
|
||||||
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = LAYOUT(/* Base */
|
|
||||||
C(KC_C), KC_BTN1, KC_BTN3, LT(1, KC_BTN2), C(KC_V), KC_BTN4, KC_BTN5, DPI_CONFIG),
|
|
||||||
[1] = LAYOUT(/* Base */
|
|
||||||
_______, DRAG_SCROLL, _______, _______, _______, _______, _______, QK_BOOT),
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,3 +0,0 @@
|
||||||
# The Drag Scroll keymap for PloopyCo Mouse
|
|
||||||
|
|
||||||
This is a sample keymap showing off what you can do with the custom callback drivers.
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2020 Ploopy Corporation
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "quantum.h"
|
|
||||||
#include "analog.h"
|
|
||||||
#include "opt_encoder.h"
|
|
||||||
|
|
||||||
// Sensor defs
|
|
||||||
#define OPT_ENC1 F0
|
|
||||||
#define OPT_ENC2 F4
|
|
||||||
#define OPT_ENC1_MUX 0
|
|
||||||
#define OPT_ENC2_MUX 4
|
|
||||||
|
|
||||||
void process_wheel(void);
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uint32_t raw;
|
|
||||||
struct {
|
|
||||||
uint8_t dpi_config;
|
|
||||||
};
|
|
||||||
} keyboard_config_t;
|
|
||||||
|
|
||||||
extern keyboard_config_t keyboard_config;
|
|
||||||
extern uint16_t dpi_array[];
|
|
||||||
|
|
||||||
enum ploopy_keycodes {
|
|
||||||
DPI_CONFIG = QK_KB_0,
|
|
||||||
DRAG_SCROLL,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool encoder_update_user(uint8_t index, bool clockwise);
|
|
||||||
bool encoder_update_kb(uint8_t index, bool clockwise);
|
|
|
@ -19,48 +19,4 @@ See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_to
|
||||||
|
|
||||||
# Customizing your PloopyCo Mouse
|
# Customizing your PloopyCo Mouse
|
||||||
|
|
||||||
While the defaults are designed so that it can be plugged in and used right away, there are a number of things that you may want to change. Such as adding DPI control, or to use the ball to scroll while holding a button. To allow for this sort of control, there is a callback for both the scroll wheel and the mouse sensor.
|
You can find customziation options [here](../readme.md).
|
||||||
|
|
||||||
The default behavior for this is:
|
|
||||||
|
|
||||||
```c
|
|
||||||
void process_wheel_user(report_mouse_t* mouse_report, int16_t h, int16_t v) {
|
|
||||||
mouse_report->h = h;
|
|
||||||
mouse_report->v = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) {
|
|
||||||
mouse_report->x = x;
|
|
||||||
mouse_report->y = y;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This should allow you to more heavily customize the behavior.
|
|
||||||
|
|
||||||
Alternatively, the `process_wheel` and `process_mouse` functions can both be replaced too, to allow for even more functionality.
|
|
||||||
|
|
||||||
Additionally, you can change the DPI/CPI or speed of the trackball by calling `pointing_device_set_cpi` at any time. Additionally, there is a `DPI_CONFIG` macro that will cycle through an array of options for the DPI. This is set to 1200, 1600, and 2400, but can be changed. 1600 is also set to the default.
|
|
||||||
|
|
||||||
To configure/set your own array, there are two defines to use, `PLOOPY_DPI_OPTIONS` to set the array, and `PLOOPY_DPI_DEFAULT`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define PLOOPY_DPI_OPTIONS { 1200, 1600, 2400 }
|
|
||||||
#define PLOOPY_DPI_DEFAULT 1
|
|
||||||
```
|
|
||||||
The `PLOOPY_DPI_OPTIONS` array sets the values that you want to be able to cycle through, and the order they are in. The "default" define lets the firmware know which of these options is the default and should be loaded by default.
|
|
||||||
|
|
||||||
The `DPI_CONFIG` macro will cycle through the values in the array, each time you hit it. And it stores this value in persistent memory, so it will load it the next time the device powers up.
|
|
||||||
|
|
||||||
## Drag Scroll
|
|
||||||
|
|
||||||
Drag Sroll is a custom keycode for the Ploopy devices that allow you to hold or tap a button and have the mouse movement translate into scrolling instead.
|
|
||||||
|
|
||||||
Nothing needs to be enabled to use this functionality. Just add the `DRAG_SCROLL` to your keymap.
|
|
||||||
|
|
||||||
### Drag Scroll Configuration
|
|
||||||
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MOMENTARY` - Makes the key into a momentary key, rather than a toggle.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75` - Sets the DPI multiplier to use when drag scroll is enabled.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_FIXED` - Normally, when activating Drag Scroll, it uses a fraction of the current DPI. You can define this to use a specific, set DPI rather than a fraction of the current DPI.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_DPI 100` - When the fixed DPI option is enabled, this sets the DPI to be used for Drag Scroll.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_INVERT` - This reverses the direction that the scroll is performed.
|
|
||||||
|
|
|
@ -1,21 +1,4 @@
|
||||||
# Processor frequency
|
# Processor frequency
|
||||||
F_CPU = 8000000
|
F_CPU = 8000000
|
||||||
|
|
||||||
# Build Options
|
|
||||||
# change yes to no to disable
|
|
||||||
#
|
|
||||||
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
|
|
||||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
|
||||||
CONSOLE_ENABLE = no # Console for debug
|
|
||||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
|
||||||
NKRO_ENABLE = no # Enable N-Key Rollover
|
|
||||||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
|
|
||||||
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
|
|
||||||
AUDIO_ENABLE = no # Audio output
|
|
||||||
POINTING_DEVICE_ENABLE = yes
|
|
||||||
POINTING_DEVICE_DRIVER = pmw3360
|
POINTING_DEVICE_DRIVER = pmw3360
|
||||||
MOUSEKEY_ENABLE = yes # Mouse keys
|
|
||||||
|
|
||||||
ANALOG_DRIVER_REQUIRED = yes
|
|
||||||
|
|
||||||
SRC += opt_encoder.c
|
|
||||||
|
|
|
@ -16,23 +16,28 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mouse.h"
|
#include "ploopyco.h"
|
||||||
|
#include "analog.h"
|
||||||
|
#include "opt_encoder.h"
|
||||||
|
|
||||||
#ifndef OPT_DEBOUNCE
|
// for legacy support
|
||||||
# define OPT_DEBOUNCE 5 // (ms) Time between scroll events
|
#if defined(OPT_DEBOUNCE) && !defined(PLOOPY_SCROLL_DEBOUNCE)
|
||||||
|
# define PLOOPY_SCROLL_DEBOUNCE OPT_DEBOUNCE
|
||||||
#endif
|
#endif
|
||||||
#ifndef SCROLL_BUTT_DEBOUNCE
|
#if defined(SCROLL_BUTT_DEBOUNCE) && !defined(PLOOPY_SCROLL_BUTTON_DEBOUNCE)
|
||||||
# define SCROLL_BUTT_DEBOUNCE 100 // (ms) Time between scroll events
|
# define PLOOPY_SCROLL_BUTTON_DEBOUNCE SCROLL_BUTT_DEBOUNCE
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPT_THRES
|
|
||||||
# define OPT_THRES 150 // (0-1024) Threshold for actication
|
#ifndef PLOOPY_SCROLL_DEBOUNCE
|
||||||
|
# define PLOOPY_SCROLL_DEBOUNCE 5
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPT_SCALE
|
#ifndef PLOOPY_SCROLL_BUTTON_DEBOUNCE
|
||||||
# define OPT_SCALE 1 // Multiplier for wheel
|
# define PLOOPY_SCROLL_BUTTON_DEBOUNCE 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PLOOPY_DPI_OPTIONS
|
#ifndef PLOOPY_DPI_OPTIONS
|
||||||
# define PLOOPY_DPI_OPTIONS \
|
# define PLOOPY_DPI_OPTIONS \
|
||||||
{ 1200, 1600, 2400 }
|
{ 600, 900, 1200, 1600, 2400 }
|
||||||
# ifndef PLOOPY_DPI_DEFAULT
|
# ifndef PLOOPY_DPI_DEFAULT
|
||||||
# define PLOOPY_DPI_DEFAULT 1
|
# define PLOOPY_DPI_DEFAULT 1
|
||||||
# endif
|
# endif
|
||||||
|
@ -40,94 +45,110 @@
|
||||||
#ifndef PLOOPY_DPI_DEFAULT
|
#ifndef PLOOPY_DPI_DEFAULT
|
||||||
# define PLOOPY_DPI_DEFAULT 0
|
# define PLOOPY_DPI_DEFAULT 0
|
||||||
#endif
|
#endif
|
||||||
#ifndef PLOOPY_DRAGSCROLL_DPI
|
#ifndef PLOOPY_DRAGSCROLL_DIVISOR_H
|
||||||
# define PLOOPY_DRAGSCROLL_DPI 100 // Fixed-DPI Drag Scroll
|
# define PLOOPY_DRAGSCROLL_DIVISOR_H 8.0
|
||||||
#endif
|
#endif
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MULTIPLIER
|
#ifndef PLOOPY_DRAGSCROLL_DIVISOR_V
|
||||||
# define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75 // Variable-DPI Drag Scroll
|
# define PLOOPY_DRAGSCROLL_DIVISOR_V 8.0
|
||||||
|
#endif
|
||||||
|
#ifndef ENCODER_BUTTON_ROW
|
||||||
|
# define ENCODER_BUTTON_ROW 0
|
||||||
|
#endif
|
||||||
|
#ifndef ENCODER_BUTTON_COL
|
||||||
|
# define ENCODER_BUTTON_COL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
keyboard_config_t keyboard_config;
|
keyboard_config_t keyboard_config;
|
||||||
uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
|
uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
|
||||||
#define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array)
|
#define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array)
|
||||||
|
|
||||||
// TODO: Implement libinput profiles
|
|
||||||
// https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
|
|
||||||
// Compile time accel selection
|
|
||||||
// Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
|
|
||||||
|
|
||||||
// Trackball State
|
// Trackball State
|
||||||
bool is_scroll_clicked = false;
|
bool is_scroll_clicked = false;
|
||||||
bool BurstState = false; // init burst state for Trackball module
|
bool is_drag_scroll = false;
|
||||||
uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
|
float scroll_accumulated_h = 0;
|
||||||
uint16_t lastScroll = 0; // Previous confirmed wheel event
|
float scroll_accumulated_v = 0;
|
||||||
uint16_t lastMidClick = 0; // Stops scrollwheel from being read if it was pressed
|
|
||||||
uint8_t OptLowPin = OPT_ENC1;
|
#ifdef ENCODER_ENABLE
|
||||||
|
uint16_t lastScroll = 0; // Previous confirmed wheel event
|
||||||
|
uint16_t lastMidClick = 0; // Stops scrollwheel from being read if it was pressed
|
||||||
|
pin_t encoder_pins_a[1] = ENCODERS_PAD_A;
|
||||||
|
pin_t encoder_pins_b[1] = ENCODERS_PAD_B;
|
||||||
bool debug_encoder = false;
|
bool debug_encoder = false;
|
||||||
bool is_drag_scroll = false;
|
|
||||||
|
|
||||||
bool encoder_update_kb(uint8_t index, bool clockwise) {
|
bool encoder_update_kb(uint8_t index, bool clockwise) {
|
||||||
if (!encoder_update_user(index, clockwise)) {
|
if (!encoder_update_user(index, clockwise)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef MOUSEKEY_ENABLE
|
# ifdef MOUSEKEY_ENABLE
|
||||||
tap_code(clockwise ? KC_WH_U : KC_WH_D);
|
tap_code(clockwise ? KC_WH_U : KC_WH_D);
|
||||||
#else
|
# else
|
||||||
report_mouse_t mouse_report = pointing_device_get_report();
|
report_mouse_t mouse_report = pointing_device_get_report();
|
||||||
mouse_report.v = clockwise ? 1 : -1;
|
mouse_report.v = clockwise ? 1 : -1;
|
||||||
pointing_device_set_report(mouse_report);
|
pointing_device_set_report(mouse_report);
|
||||||
pointing_device_send();
|
pointing_device_send();
|
||||||
#endif
|
# endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void encoder_driver_init(void) {
|
void encoder_driver_init(void) {
|
||||||
setPinInput(OPT_ENC1);
|
for (uint8_t i = 0; i < ARRAY_SIZE(encoder_pins_a); i++) {
|
||||||
setPinInput(OPT_ENC2);
|
gpio_set_pin_input(encoder_pins_a[i]);
|
||||||
|
gpio_set_pin_input(encoder_pins_b[i]);
|
||||||
|
}
|
||||||
opt_encoder_init();
|
opt_encoder_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void encoder_driver_task(void) {
|
void encoder_driver_task(void) {
|
||||||
// Lovingly ripped from the Ploopy Source
|
uint16_t p1 = analogReadPin(encoder_pins_a[0]);
|
||||||
|
uint16_t p2 = analogReadPin(encoder_pins_b[0]);
|
||||||
|
|
||||||
|
if (debug_encoder) dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
|
||||||
|
|
||||||
|
int8_t dir = opt_encoder_handler(p1, p2);
|
||||||
// If the mouse wheel was just released, do not scroll.
|
// If the mouse wheel was just released, do not scroll.
|
||||||
if (timer_elapsed(lastMidClick) < SCROLL_BUTT_DEBOUNCE) {
|
if (timer_elapsed(lastMidClick) < PLOOPY_SCROLL_BUTTON_DEBOUNCE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit the number of scrolls per unit time.
|
// Limit the number of scrolls per unit time.
|
||||||
if (timer_elapsed(lastScroll) < OPT_DEBOUNCE) {
|
if (timer_elapsed(lastScroll) < PLOOPY_SCROLL_DEBOUNCE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't scroll if the middle button is depressed.
|
// Don't scroll if the middle button is depressed.
|
||||||
if (is_scroll_clicked) {
|
if (is_scroll_clicked) {
|
||||||
#ifndef IGNORE_SCROLL_CLICK
|
# ifndef PLOOPY_IGNORE_SCROLL_CLICK
|
||||||
return;
|
return;
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
lastScroll = timer_read();
|
|
||||||
uint16_t p1 = adc_read(OPT_ENC1_MUX);
|
|
||||||
uint16_t p2 = adc_read(OPT_ENC2_MUX);
|
|
||||||
if (debug_encoder) dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
|
|
||||||
|
|
||||||
int dir = opt_encoder_handler(p1, p2);
|
|
||||||
|
|
||||||
if (dir == 0) return;
|
if (dir == 0) return;
|
||||||
encoder_queue_event(0, dir == 1);
|
encoder_queue_event(0, dir > 0);
|
||||||
|
lastScroll = timer_read();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
||||||
if (is_drag_scroll) {
|
if (is_drag_scroll) {
|
||||||
mouse_report.h = mouse_report.x;
|
scroll_accumulated_h += (float)mouse_report.x / PLOOPY_DRAGSCROLL_DIVISOR_H;
|
||||||
|
scroll_accumulated_v += (float)mouse_report.y / PLOOPY_DRAGSCROLL_DIVISOR_V;
|
||||||
|
|
||||||
|
// Assign integer parts of accumulated scroll values to the mouse report
|
||||||
|
mouse_report.h = (int8_t)scroll_accumulated_h;
|
||||||
#ifdef PLOOPY_DRAGSCROLL_INVERT
|
#ifdef PLOOPY_DRAGSCROLL_INVERT
|
||||||
// Invert vertical scroll direction
|
mouse_report.v = -(int8_t)scroll_accumulated_v;
|
||||||
mouse_report.v = -mouse_report.y;
|
|
||||||
#else
|
#else
|
||||||
mouse_report.v = mouse_report.y;
|
mouse_report.v = (int8_t)scroll_accumulated_v;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Update accumulated scroll values by subtracting the integer parts
|
||||||
|
scroll_accumulated_h -= (int8_t)scroll_accumulated_h;
|
||||||
|
scroll_accumulated_v -= (int8_t)scroll_accumulated_v;
|
||||||
|
|
||||||
|
// Clear the X and Y values of the mouse report
|
||||||
|
mouse_report.x = 0;
|
||||||
|
mouse_report.y = 0;
|
||||||
|
|
||||||
mouse_report.x = 0;
|
mouse_report.x = 0;
|
||||||
mouse_report.y = 0;
|
mouse_report.y = 0;
|
||||||
}
|
}
|
||||||
|
@ -141,10 +162,12 @@ bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Timer to prevent accidental scrolls
|
// Update Timer to prevent accidental scrolls
|
||||||
if ((record->event.key.col == 1) && (record->event.key.row == 0)) {
|
#ifdef ENCODER_ENABLE
|
||||||
|
if ((record->event.key.col == ENCODER_BUTTON_COL) && (record->event.key.row == ENCODER_BUTTON_ROW)) {
|
||||||
lastMidClick = timer_read();
|
lastMidClick = timer_read();
|
||||||
is_scroll_clicked = record->event.pressed;
|
is_scroll_clicked = record->event.pressed;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!process_record_user(keycode, record)) {
|
if (!process_record_user(keycode, record)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -157,16 +180,12 @@ bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keycode == DRAG_SCROLL) {
|
if (keycode == DRAG_SCROLL) {
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MOMENTARY
|
#ifdef PLOOPY_DRAGSCROLL_MOMENTARY
|
||||||
if (record->event.pressed)
|
is_drag_scroll = record->event.pressed;
|
||||||
#endif
|
#else
|
||||||
{
|
if (record->event.pressed) {
|
||||||
is_drag_scroll ^= 1;
|
is_drag_scroll ^= 1;
|
||||||
}
|
}
|
||||||
#ifdef PLOOPY_DRAGSCROLL_FIXED
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? PLOOPY_DRAGSCROLL_DPI : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#else
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? (dpi_array[keyboard_config.dpi_config] * PLOOPY_DRAGSCROLL_MULTIPLIER) : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,21 +207,25 @@ void keyboard_pre_init_kb(void) {
|
||||||
const pin_t unused_pins[] = UNUSABLE_PINS;
|
const pin_t unused_pins[] = UNUSABLE_PINS;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ARRAY_SIZE(unused_pins); i++) {
|
for (uint8_t i = 0; i < ARRAY_SIZE(unused_pins); i++) {
|
||||||
setPinOutput(unused_pins[i]);
|
gpio_set_pin_output_push_pull(unused_pins[i]);
|
||||||
writePinLow(unused_pins[i]);
|
gpio_write_pin_low(unused_pins[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is the debug LED.
|
// This is the debug LED.
|
||||||
#if defined(DEBUG_LED_PIN)
|
#if defined(DEBUG_LED_PIN)
|
||||||
setPinOutput(DEBUG_LED_PIN);
|
gpio_set_pin_output_push_pull(DEBUG_LED_PIN);
|
||||||
writePin(DEBUG_LED_PIN, debug_enable);
|
gpio_write_pin(DEBUG_LED_PIN, debug_enable);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
keyboard_pre_init_user();
|
keyboard_pre_init_user();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pointing_device_init_kb(void) {
|
void pointing_device_init_kb(void) {
|
||||||
|
keyboard_config.raw = eeconfig_read_kb();
|
||||||
|
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
|
||||||
|
eeconfig_init_kb();
|
||||||
|
}
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,13 +234,3 @@ void eeconfig_init_kb(void) {
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
eeconfig_update_kb(keyboard_config.raw);
|
||||||
eeconfig_init_user();
|
eeconfig_init_user();
|
||||||
}
|
}
|
||||||
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
// is safe to just read DPI setting since matrix init
|
|
||||||
// comes before pointing device init.
|
|
||||||
keyboard_config.raw = eeconfig_read_kb();
|
|
||||||
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
|
|
||||||
eeconfig_init_kb();
|
|
||||||
}
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
|
@ -19,14 +19,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "quantum.h"
|
#include "quantum.h"
|
||||||
#include "analog.h"
|
|
||||||
#include "opt_encoder.h"
|
|
||||||
|
|
||||||
// Sensor defs
|
|
||||||
#define OPT_ENC1 F0
|
|
||||||
#define OPT_ENC2 F4
|
|
||||||
#define OPT_ENC1_MUX 0
|
|
||||||
#define OPT_ENC2_MUX 4
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t raw;
|
uint32_t raw;
|
|
@ -0,0 +1,12 @@
|
||||||
|
OPT_ENCODER_TYPE ?= default
|
||||||
|
VALID_OPT_ENCODER_TYPES := default simple tiny custom
|
||||||
|
|
||||||
|
ifeq ($(filter $(OPT_ENCODER_TYPE),$(VALID_OPT_ENCODER_TYPES)),)
|
||||||
|
$(call CATASTROPHIC_ERROR,Invalid OPT_ENCODER_TYPE,OPT_ENCODER_TYPE="$(OPT_ENCODER_TYPE)" is not a valid pointing device type)
|
||||||
|
else
|
||||||
|
ifneq ($(strip $(OPT_ENCODER_TYPE)), custom)
|
||||||
|
VPATH += keyboards/ploopyco/common
|
||||||
|
SRC += opt_encoder_$(strip $(OPT_ENCODER_TYPE)).c
|
||||||
|
ANALOG_DRIVER_REQUIRED = yes
|
||||||
|
endif
|
||||||
|
endif
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Ploopyco
|
||||||
|
|
||||||
|
* [Mouse](mouse/)
|
||||||
|
* [Trackball](trackball/)
|
||||||
|
* [Trackball Mini](trackball_mini/)
|
||||||
|
* [Trackball Nano](trackball_nano/)
|
||||||
|
* [Trackball Thumb](trackball_thumb/)
|
||||||
|
* [Adept/Madromys](manromys/)
|
||||||
|
|
||||||
|
# Customizing your PloopyCo Device
|
||||||
|
|
||||||
|
There are a number of behavioral settings that you can use to help customize your experience
|
||||||
|
| | | |
|
||||||
|
|---------------------------------|-------------------|-----------------------------------------------------------|
|
||||||
|
| `PLOOPY_IGNORE_SCROLL_CLICK` | *__not_defined__* | Ignores scroll wheel if it is pressed down. |
|
||||||
|
| `PLOOPY_SCROLL_DEBOUNCE` | `5` | Number of milliseconds between scroll events. |
|
||||||
|
| `PLOOPY_SCROLL_BUTTON_DEBOUNCE` | `100` | Time to ignore scroll events after pressing scroll wheel. |
|
||||||
|
|
||||||
|
## DPI
|
||||||
|
|
||||||
|
You can change the DPI/CPI or speed of the trackball by calling `pointing_device_set_cpi` at any time. Additionally, there is a `DPI_CONFIG` macro that will cycle through an array of options for the DPI. This is set to 1200, 1600, and 2400, but can be changed. 1600 is also set to the default.
|
||||||
|
|
||||||
|
To configure/set your own array, there are two defines to use, `PLOOPY_DPI_OPTIONS` to set the array, and `PLOOPY_DPI_DEFAULT`.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define PLOOPY_DPI_OPTIONS { 1200, 1600, 2400 }
|
||||||
|
#define PLOOPY_DPI_DEFAULT 1
|
||||||
|
```
|
||||||
|
|
||||||
|
The `PLOOPY_DPI_OPTIONS` array sets the values that you want to be able to cycle through, and the order they are in. The "default" define lets the firmware know which of these options is the default and should be loaded by default.
|
||||||
|
|
||||||
|
The `DPI_CONFIG` macro will cycle through the values in the array, each time you hit it. And it stores this value in persistent memory, so it will load it the next time the device powers up.
|
||||||
|
|
||||||
|
## Drag Scroll
|
||||||
|
|
||||||
|
Drag Sroll is a custom keycode for the Ploopy devices that allow you to hold or tap a button and have the mouse movement translate into scrolling instead.
|
||||||
|
|
||||||
|
Nothing needs to be enabled to use this functionality. Just add the `DRAG_SCROLL` to your keymap.
|
||||||
|
|
||||||
|
### Drag Scroll Configuration
|
||||||
|
|
||||||
|
* `#define PLOOPY_DRAGSCROLL_MOMENTARY` - Makes the key into a momentary key, rather than a toggle.
|
||||||
|
* `#define PLOOPY_DRAGSCROLL_DIVISOR_H 8.0` - Sets the horizontal movement divisor to use when drag scroll is enabled.
|
||||||
|
* `#define PLOOPY_DRAGSCROLL_DIVISOR_V 8.0` - Sets the vertical movement divisor to use when drag scroll is enabled.
|
||||||
|
* `#define PLOOPY_DRAGSCROLL_INVERT` - This reverses the direction that the scroll is performed.
|
|
@ -32,5 +32,11 @@
|
||||||
#define PMW33XX_CS_PIN B0
|
#define PMW33XX_CS_PIN B0
|
||||||
#define POINTING_DEVICE_INVERT_Y
|
#define POINTING_DEVICE_INVERT_Y
|
||||||
|
|
||||||
|
|
||||||
|
#define ENCODER_BUTTON_COL 1
|
||||||
|
#define ENCODER_BUTTON_ROW 0
|
||||||
/* Custom encoder needs to specify just how many encoders we have */
|
/* Custom encoder needs to specify just how many encoders we have */
|
||||||
#define NUM_ENCODERS 1
|
#define NUM_ENCODERS 1
|
||||||
|
|
||||||
|
#define ENCODERS_PAD_A { F0 }
|
||||||
|
#define ENCODERS_PAD_B { F4 }
|
||||||
|
|
|
@ -12,7 +12,13 @@
|
||||||
"bootmagic": {
|
"bootmagic": {
|
||||||
"matrix": [0, 3]
|
"matrix": [0, 3]
|
||||||
},
|
},
|
||||||
|
|
||||||
"features": {
|
"features": {
|
||||||
|
"bootmagic": true,
|
||||||
|
"extrakey": true,
|
||||||
|
"mousekey": true,
|
||||||
|
"nkro": false,
|
||||||
|
"pointing_device": true,
|
||||||
"encoder": true
|
"encoder": true
|
||||||
},
|
},
|
||||||
"encoder": {
|
"encoder": {
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2020 Ploopy Corporation
|
|
||||||
*
|
|
||||||
* 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 QMK_KEYBOARD_H
|
|
||||||
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = LAYOUT( /* Base */
|
|
||||||
KC_BTN1, KC_BTN3, KC_BTN2,
|
|
||||||
KC_BTN4, LT(1, KC_BTN5)
|
|
||||||
),
|
|
||||||
[1] = LAYOUT(
|
|
||||||
DRAG_SCROLL, _______, _______,
|
|
||||||
_______, _______
|
|
||||||
)
|
|
||||||
};
|
|
|
@ -1,3 +0,0 @@
|
||||||
# The Drag Scroll keymap for Ploopyco Trackball
|
|
||||||
|
|
||||||
This is a sample keymap showing off what you can do with the custom callback drivers.
|
|
|
@ -27,45 +27,4 @@ The PCB should indicate which revision this is.
|
||||||
|
|
||||||
# Customizing your PloopyCo Trackball
|
# Customizing your PloopyCo Trackball
|
||||||
|
|
||||||
While the defaults are designed so that it can be plugged in and used right away, there are a number of things that you may want to change. Such as adding DPI control, or to use the ball to scroll while holding a button. To allow for this sort of control, there is a callback for both the scroll wheel and the mouse sensor.
|
You can find customziation options [here](../readme.md).
|
||||||
|
|
||||||
|
|
||||||
```c
|
|
||||||
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report){
|
|
||||||
// executed each time the sensor is updated
|
|
||||||
// mouse_report.<attribute> - can be used to access indivdual mouse attributes
|
|
||||||
return mouse_report;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
More information on `report_mouse_t` may be found [here](https://docs.qmk.fm/#/feature_pointing_device?id=manipulating-mouse-reports).
|
|
||||||
|
|
||||||
This should allow you to more heavily customize the behavior.
|
|
||||||
|
|
||||||
Alternatively, the `process_wheel` and `process_mouse` functions can both be replaced too, to allow for even more functionality.
|
|
||||||
|
|
||||||
Additionally, you can change the DPI/CPI or speed of the trackball by calling `pointing_device_set_cpi` at any time. Additionally, there is a `DPI_CONFIG` macro that will cycle through an array of options for the DPI. This is set to 1200, 1600, and 2400, but can be changed. 1600 is also set to the default.
|
|
||||||
|
|
||||||
To configure/set your own array, there are two defines to use, `PLOOPY_DPI_OPTIONS` to set the array, and `PLOOPY_DPI_DEFAULT`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define PLOOPY_DPI_OPTIONS { 1200, 1600, 2400 }
|
|
||||||
#define PLOOPY_DPI_DEFAULT 1
|
|
||||||
```
|
|
||||||
The `PLOOPY_DPI_OPTIONS` array sets the values that you want to be able to cycle through, and the order they are in. The "default" define lets the firmware know which of these options is the default and should be loaded by default.
|
|
||||||
|
|
||||||
The `DPI_CONFIG` macro will cycle through the values in the array, each time you hit it. And it stores this value in persistent memory, so it will load it the next time the device powers up.
|
|
||||||
|
|
||||||
## Drag Scroll
|
|
||||||
|
|
||||||
Drag Sroll is a custom keycode for the Ploopy devices that allow you to hold or tap a button and have the mouse movement translate into scrolling instead.
|
|
||||||
|
|
||||||
Nothing needs to be enabled to use this functionality. Just add the `DRAG_SCROLL` to your keymap.
|
|
||||||
|
|
||||||
### Drag Scroll Configuration
|
|
||||||
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MOMENTARY` - Makes the key into a momentary key, rather than a toggle.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75` - Sets the DPI multiplier to use when drag scroll is enabled.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_FIXED` - Normally, when activating Drag Scroll, it uses a fraction of the current DPI. You can define this to use a specific, set DPI rather than a fraction of the current DPI.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_DPI 100` - When the fixed DPI option is enabled, this sets the DPI to be used for Drag Scroll.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_INVERT` - This reverses the direction that the scroll is performed.
|
|
||||||
|
|
|
@ -1,23 +1,6 @@
|
||||||
# Processor frequency
|
# Processor frequency
|
||||||
F_CPU = 8000000
|
F_CPU = 8000000
|
||||||
|
|
||||||
# Build Options
|
|
||||||
# change yes to no to disable
|
|
||||||
#
|
|
||||||
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
|
|
||||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
|
||||||
CONSOLE_ENABLE = no # Console for debug
|
|
||||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
|
||||||
NKRO_ENABLE = no # Enable N-Key Rollover
|
|
||||||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
|
|
||||||
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
|
|
||||||
AUDIO_ENABLE = no # Audio output
|
|
||||||
POINTING_DEVICE_ENABLE = yes
|
|
||||||
POINTING_DEVICE_DRIVER = pmw3360
|
POINTING_DEVICE_DRIVER = pmw3360
|
||||||
MOUSEKEY_ENABLE = yes # Mouse keys
|
|
||||||
|
|
||||||
ANALOG_DRIVER_REQUIRED = yes
|
|
||||||
|
|
||||||
SRC += opt_encoder.c
|
|
||||||
|
|
||||||
DEFAULT_FOLDER = ploopyco/trackball/rev1_005
|
DEFAULT_FOLDER = ploopyco/trackball/rev1_005
|
||||||
|
|
|
@ -1,243 +0,0 @@
|
||||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2020 Ploopy Corporation
|
|
||||||
*
|
|
||||||
* 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 "trackball.h"
|
|
||||||
|
|
||||||
#ifndef OPT_DEBOUNCE
|
|
||||||
# define OPT_DEBOUNCE 5 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
#ifndef SCROLL_BUTT_DEBOUNCE
|
|
||||||
# define SCROLL_BUTT_DEBOUNCE 100 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
#ifndef OPT_THRES
|
|
||||||
# define OPT_THRES 150 // (0-1024) Threshold for actication
|
|
||||||
#endif
|
|
||||||
#ifndef OPT_SCALE
|
|
||||||
# define OPT_SCALE 1 // Multiplier for wheel
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DPI_OPTIONS
|
|
||||||
# define PLOOPY_DPI_OPTIONS \
|
|
||||||
{ 1200, 1600, 2400 }
|
|
||||||
# ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 0
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_DPI
|
|
||||||
# define PLOOPY_DRAGSCROLL_DPI 100 // Fixed-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MULTIPLIER
|
|
||||||
# define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75 // Variable-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_config_t keyboard_config;
|
|
||||||
uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
|
|
||||||
#define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array)
|
|
||||||
|
|
||||||
// TODO: Implement libinput profiles
|
|
||||||
// https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
|
|
||||||
// Compile time accel selection
|
|
||||||
// Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
|
|
||||||
|
|
||||||
// Trackball State
|
|
||||||
bool is_scroll_clicked = false;
|
|
||||||
bool BurstState = false; // init burst state for Trackball module
|
|
||||||
uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
|
|
||||||
uint16_t lastScroll = 0; // Previous confirmed wheel event
|
|
||||||
uint16_t lastMidClick = 0; // Stops scrollwheel from being read if it was pressed
|
|
||||||
uint8_t OptLowPin = OPT_ENC1;
|
|
||||||
bool debug_encoder = false;
|
|
||||||
bool is_drag_scroll = false;
|
|
||||||
|
|
||||||
bool encoder_update_kb(uint8_t index, bool clockwise) {
|
|
||||||
if (!encoder_update_user(index, clockwise)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef MOUSEKEY_ENABLE
|
|
||||||
tap_code(clockwise ? KC_WH_U : KC_WH_D);
|
|
||||||
#else
|
|
||||||
report_mouse_t mouse_report = pointing_device_get_report();
|
|
||||||
mouse_report.v = clockwise ? 1 : -1;
|
|
||||||
pointing_device_set_report(mouse_report);
|
|
||||||
pointing_device_send();
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void encoder_driver_init(void) {
|
|
||||||
setPinInput(OPT_ENC1);
|
|
||||||
setPinInput(OPT_ENC2);
|
|
||||||
|
|
||||||
opt_encoder_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void encoder_driver_task(void) {
|
|
||||||
// TODO: Replace this with interrupt driven code, polling is S L O W
|
|
||||||
// Lovingly ripped from the Ploopy Source
|
|
||||||
|
|
||||||
// If the mouse wheel was just released, do not scroll.
|
|
||||||
if (timer_elapsed(lastMidClick) < SCROLL_BUTT_DEBOUNCE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit the number of scrolls per unit time.
|
|
||||||
if (timer_elapsed(lastScroll) < OPT_DEBOUNCE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't scroll if the middle button is depressed.
|
|
||||||
if (is_scroll_clicked) {
|
|
||||||
#ifndef IGNORE_SCROLL_CLICK
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
lastScroll = timer_read();
|
|
||||||
uint16_t p1 = adc_read(OPT_ENC1_MUX);
|
|
||||||
uint16_t p2 = adc_read(OPT_ENC2_MUX);
|
|
||||||
if (debug_encoder) dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
|
|
||||||
|
|
||||||
int dir = opt_encoder_handler(p1, p2);
|
|
||||||
|
|
||||||
if (dir == 0) return;
|
|
||||||
encoder_queue_event(0, dir == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
|
||||||
|
|
||||||
if (is_drag_scroll) {
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_H_INVERT
|
|
||||||
// Invert horizontal scroll direction
|
|
||||||
mouse_report.h = -mouse_report.x;
|
|
||||||
#else
|
|
||||||
mouse_report.h = mouse_report.x;
|
|
||||||
#endif
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_INVERT
|
|
||||||
// Invert vertical scroll direction
|
|
||||||
mouse_report.v = -mouse_report.y;
|
|
||||||
#else
|
|
||||||
mouse_report.v = mouse_report.y;
|
|
||||||
#endif
|
|
||||||
mouse_report.x = 0;
|
|
||||||
mouse_report.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointing_device_task_user(mouse_report);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
|
|
||||||
if (true) {
|
|
||||||
xprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Timer to prevent accidental scrolls
|
|
||||||
if ((record->event.key.col == 1) && (record->event.key.row == 0)) {
|
|
||||||
lastMidClick = timer_read();
|
|
||||||
is_scroll_clicked = record->event.pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process_record_user(keycode, record)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycode == DPI_CONFIG && record->event.pressed) {
|
|
||||||
keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycode == DRAG_SCROLL) {
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MOMENTARY
|
|
||||||
if (record->event.pressed)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
is_drag_scroll ^= 1;
|
|
||||||
}
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_FIXED
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? PLOOPY_DRAGSCROLL_DPI : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#else
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? (dpi_array[keyboard_config.dpi_config] * PLOOPY_DRAGSCROLL_MULTIPLIER) : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If Mousekeys is disabled, then use handle the mouse button
|
|
||||||
* keycodes. This makes things simpler, and allows usage of
|
|
||||||
* the keycodes in a consistent manner. But only do this if
|
|
||||||
* Mousekeys is not enable, so it's not handled twice.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hardware Setup
|
|
||||||
void keyboard_pre_init_kb(void) {
|
|
||||||
// debug_enable = true;
|
|
||||||
// debug_matrix = true;
|
|
||||||
// debug_mouse = true;
|
|
||||||
// debug_encoder = true;
|
|
||||||
|
|
||||||
/* Ground all output pins connected to ground. This provides additional
|
|
||||||
* pathways to ground. If you're messing with this, know this: driving ANY
|
|
||||||
* of these pins high will cause a short. On the MCU. Ka-blooey.
|
|
||||||
*/
|
|
||||||
#ifdef UNUSABLE_PINS
|
|
||||||
const pin_t unused_pins[] = UNUSABLE_PINS;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ARRAY_SIZE(unused_pins); i++) {
|
|
||||||
setPinOutput(unused_pins[i]);
|
|
||||||
writePinLow(unused_pins[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This is the debug LED.
|
|
||||||
#if defined(DEBUG_LED_PIN)
|
|
||||||
setPinOutput(DEBUG_LED_PIN);
|
|
||||||
writePin(DEBUG_LED_PIN, debug_enable);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_pre_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pointing_device_init_kb(void) {
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eeconfig_init_kb(void) {
|
|
||||||
keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
eeconfig_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
// is safe to just read DPI setting since matrix init
|
|
||||||
// comes before pointing device init.
|
|
||||||
keyboard_config.raw = eeconfig_read_kb();
|
|
||||||
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
|
|
||||||
eeconfig_init_kb();
|
|
||||||
}
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void keyboard_post_init_kb(void) {
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
|
|
||||||
keyboard_post_init_user();
|
|
||||||
}
|
|
|
@ -33,5 +33,10 @@
|
||||||
|
|
||||||
#define POINTING_DEVICE_ROTATION_270
|
#define POINTING_DEVICE_ROTATION_270
|
||||||
|
|
||||||
|
#define ENCODER_BUTTON_COL 1
|
||||||
|
#define ENCODER_BUTTON_ROW 0
|
||||||
/* Custom encoder needs to specify just how many encoders we have */
|
/* Custom encoder needs to specify just how many encoders we have */
|
||||||
#define NUM_ENCODERS 1
|
#define NUM_ENCODERS 1
|
||||||
|
|
||||||
|
#define ENCODERS_PAD_A { F0 }
|
||||||
|
#define ENCODERS_PAD_B { F4 }
|
||||||
|
|
|
@ -12,11 +12,16 @@
|
||||||
"bootmagic": {
|
"bootmagic": {
|
||||||
"matrix": [0, 3]
|
"matrix": [0, 3]
|
||||||
},
|
},
|
||||||
"processor": "atmega32u4",
|
|
||||||
"bootloader": "atmel-dfu",
|
|
||||||
"features": {
|
"features": {
|
||||||
|
"bootmagic": true,
|
||||||
|
"extrakey": true,
|
||||||
|
"mousekey": true,
|
||||||
|
"nkro": false,
|
||||||
|
"pointing_device": true,
|
||||||
"encoder": true
|
"encoder": true
|
||||||
},
|
},
|
||||||
|
"processor": "atmega32u4",
|
||||||
|
"bootloader": "atmel-dfu",
|
||||||
"encoder": {
|
"encoder": {
|
||||||
"driver": "custom"
|
"driver": "custom"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2020 Ploopy Corporation
|
|
||||||
*
|
|
||||||
* 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 QMK_KEYBOARD_H
|
|
||||||
|
|
||||||
// used for tracking the state
|
|
||||||
bool is_drag_scroll = false;
|
|
||||||
|
|
||||||
enum custom_keycodes {
|
|
||||||
DRAG_SCROLL = SAFE_RANGE,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
switch (keycode) {
|
|
||||||
case DRAG_SCROLL:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
// this toggles the state each time you tap it
|
|
||||||
is_drag_scroll ^= 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The real magic is here.
|
|
||||||
// This function is called to translate the processed sensor movement
|
|
||||||
// from the mouse sensor and translates it into x and y movement for
|
|
||||||
// the mouse report. Normally. So if "drag scroll" is toggled on,
|
|
||||||
// moving the ball scrolls instead. You could remove the x or y here
|
|
||||||
// to only scroll in one direction, if you wanted, as well. In fact,
|
|
||||||
// there is no reason that you need to send this to the mouse report.
|
|
||||||
// You could have it register a key, instead.
|
|
||||||
void process_mouse_user(report_mouse_t* mouse_report, int8_t x, int8_t y) {
|
|
||||||
if (is_drag_scroll) {
|
|
||||||
mouse_report->h = x;
|
|
||||||
mouse_report->v = y;
|
|
||||||
} else {
|
|
||||||
mouse_report->x = x;
|
|
||||||
mouse_report->y = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = LAYOUT( /* Base */
|
|
||||||
KC_BTN1, KC_BTN3, KC_BTN2,
|
|
||||||
KC_BTN4, LT(1, KC_BTN5)
|
|
||||||
),
|
|
||||||
[1] = LAYOUT(
|
|
||||||
DRAG_SCROLL, _______, _______,
|
|
||||||
_______, _______
|
|
||||||
)
|
|
||||||
};
|
|
|
@ -1,5 +0,0 @@
|
||||||
# The Drag Scroll keymap for the Ploopy Trackball Mini
|
|
||||||
|
|
||||||
This is a sample keymap showing off what you can do with the custom callback drivers.
|
|
||||||
|
|
||||||
This particular example enables "drag scrolling". The movement of the ball is used to scroll up and down.
|
|
|
@ -29,52 +29,6 @@ Occasionally, new revisions of the PCB will be released. Every board comes with
|
||||||
|
|
||||||
Match the firmware that you flash onto the board with the designator on the board.
|
Match the firmware that you flash onto the board with the designator on the board.
|
||||||
|
|
||||||
# Customizing your Ploopy Mini Trackball
|
|
||||||
|
|
||||||
While the defaults are designed so that it can be plugged in and used right away, there are a number of things that you may want to change, such as adding DPI control, or using the ball to scroll while holding a button. To allow for this sort of control, there is a callback for both the scroll wheel and the mouse sensor.
|
|
||||||
|
|
||||||
The default behavior for this is:
|
|
||||||
|
|
||||||
```c
|
|
||||||
void process_wheel_user(report_mouse_t* mouse_report, int16_t h, int16_t v) {
|
|
||||||
mouse_report->h = h;
|
|
||||||
mouse_report->v = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) {
|
|
||||||
mouse_report->x = x;
|
|
||||||
mouse_report->y = y;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This should allow you to more heavily customize the behavior.
|
|
||||||
|
|
||||||
Alternatively, the `process_wheel` and `process_mouse` functions can both be replaced too, to allow for even more functionality.
|
|
||||||
|
|
||||||
Additionally, you can change the DPI/CPI or speed of the trackball by calling `adns_set_cpi` at any time. Additionally, there is a `DPI_CONFIG` macro that will cycle through an array of options for the DPI. This is set to 375, 750, and 1375, but can be changed. 1375 is the default.
|
|
||||||
|
|
||||||
To configure/set your own array, there are two defines to use, `PLOOPY_DPI_OPTIONS` to set the array, and `PLOOPY_DPI_DEFAULT`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define PLOOPY_DPI_OPTIONS { 375, 750, 1375}
|
|
||||||
#define PLOOPY_DPI_DEFAULT 2
|
|
||||||
```
|
|
||||||
|
|
||||||
The `PLOOPY_DPI_OPTIONS` array sets the values that you want to be able to cycle through, and the order they are in. The "default" define lets the firmware know which of these options is the default and should be loaded by default.
|
|
||||||
|
|
||||||
The `DPI_CONFIG` macro will cycle through the values in the array, each time you hit it. It stores this value in persistent memory, so it will load it the next time the device powers up.
|
|
||||||
|
|
||||||
## Drag Scroll
|
|
||||||
|
|
||||||
Drag Sroll is a custom keycode for the Ploopy devices that allow you to hold or tap a button and have the mouse movement translate into scrolling instead.
|
|
||||||
|
|
||||||
Nothing needs to be enabled to use this functionality. Just add the `DRAG_SCROLL` to your keymap.
|
|
||||||
|
|
||||||
### Drag Scroll Configuration
|
|
||||||
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MOMENTARY` - Makes the key into a momentary key, rather than a toggle.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_DPI 375` - When the fixed DPI option is enabled, this sets the DPI to be used for Drag Scroll.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_INVERT` - This reverses the direction that the scroll is performed.
|
|
||||||
## Fuse settings
|
## Fuse settings
|
||||||
|
|
||||||
When flashing the bootloader, use the following fuse settings:
|
When flashing the bootloader, use the following fuse settings:
|
||||||
|
@ -84,3 +38,7 @@ When flashing the bootloader, use the following fuse settings:
|
||||||
| Low | `0x5E` |
|
| Low | `0x5E` |
|
||||||
| High | `0x99` |
|
| High | `0x99` |
|
||||||
| Extended | `0xC3` |
|
| Extended | `0xC3` |
|
||||||
|
|
||||||
|
# Customizing your Ploopy Mini Trackball
|
||||||
|
|
||||||
|
You can find customziation options [here](../readme.md).
|
||||||
|
|
|
@ -1,20 +1,3 @@
|
||||||
# Build Options
|
|
||||||
# change yes to no to disable
|
|
||||||
#
|
|
||||||
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
|
|
||||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
|
||||||
CONSOLE_ENABLE = yes # Console for debug
|
|
||||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
|
||||||
NKRO_ENABLE = no # Enable N-Key Rollover
|
|
||||||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
|
|
||||||
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
|
|
||||||
AUDIO_ENABLE = no # Audio output
|
|
||||||
POINTING_DEVICE_ENABLE = yes
|
|
||||||
POINTING_DEVICE_DRIVER = adns5050
|
POINTING_DEVICE_DRIVER = adns5050
|
||||||
MOUSEKEY_ENABLE = yes # Mouse keys
|
|
||||||
|
|
||||||
ANALOG_DRIVER_REQUIRED = yes
|
|
||||||
|
|
||||||
SRC += opt_encoder.c
|
|
||||||
|
|
||||||
DEFAULT_FOLDER = ploopyco/trackball_mini/rev1_001
|
DEFAULT_FOLDER = ploopyco/trackball_mini/rev1_001
|
||||||
|
|
|
@ -1,214 +0,0 @@
|
||||||
/* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2019 Hiroyuki Okada
|
|
||||||
*
|
|
||||||
* 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 "trackball_mini.h"
|
|
||||||
#include "wait.h"
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
#ifndef OPT_DEBOUNCE
|
|
||||||
# define OPT_DEBOUNCE 5 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SCROLL_BUTT_DEBOUNCE
|
|
||||||
# define SCROLL_BUTT_DEBOUNCE 100 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPT_THRES
|
|
||||||
# define OPT_THRES 150 // (0-1024) Threshold for actication
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPT_SCALE
|
|
||||||
# define OPT_SCALE 1 // Multiplier for wheel
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PLOOPY_DPI_OPTIONS
|
|
||||||
# define PLOOPY_DPI_OPTIONS \
|
|
||||||
{ 375, 750, 1375 }
|
|
||||||
# ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_DPI
|
|
||||||
# define PLOOPY_DRAGSCROLL_DPI 375 // Fixed-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MULTIPLIER
|
|
||||||
# define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75 // Variable-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_config_t keyboard_config;
|
|
||||||
uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
|
|
||||||
#define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array)
|
|
||||||
|
|
||||||
// TODO: Implement libinput profiles
|
|
||||||
// https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
|
|
||||||
// Compile time accel selection
|
|
||||||
// Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
|
|
||||||
|
|
||||||
// Trackball State
|
|
||||||
bool is_scroll_clicked = false;
|
|
||||||
bool BurstState = false; // init burst state for Trackball module
|
|
||||||
uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
|
|
||||||
uint16_t lastScroll = 0; // Previous confirmed wheel event
|
|
||||||
uint16_t lastMidClick = 0; // Stops scrollwheel from being read if it was pressed
|
|
||||||
uint8_t OptLowPin = OPT_ENC1;
|
|
||||||
bool debug_encoder = false;
|
|
||||||
bool is_drag_scroll = false;
|
|
||||||
|
|
||||||
bool encoder_update_kb(uint8_t index, bool clockwise) {
|
|
||||||
if (!encoder_update_user(index, clockwise)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef MOUSEKEY_ENABLE
|
|
||||||
tap_code(clockwise ? KC_WH_U : KC_WH_D);
|
|
||||||
#else
|
|
||||||
report_mouse_t mouse_report = pointing_device_get_report();
|
|
||||||
mouse_report.v = clockwise ? 1 : -1;
|
|
||||||
pointing_device_set_report(mouse_report);
|
|
||||||
pointing_device_send();
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void encoder_driver_init(void) {
|
|
||||||
setPinInput(OPT_ENC1);
|
|
||||||
setPinInput(OPT_ENC2);
|
|
||||||
|
|
||||||
opt_encoder_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void encoder_driver_task(void) {
|
|
||||||
uint16_t p1 = adc_read(OPT_ENC1_MUX);
|
|
||||||
uint16_t p2 = adc_read(OPT_ENC2_MUX);
|
|
||||||
|
|
||||||
if (debug_encoder) dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
|
|
||||||
|
|
||||||
int8_t dir = opt_encoder_handler(p1, p2);
|
|
||||||
|
|
||||||
// If the mouse wheel was just released, do not scroll.
|
|
||||||
if (timer_elapsed(lastMidClick) < SCROLL_BUTT_DEBOUNCE) return;
|
|
||||||
|
|
||||||
// Limit the number of scrolls per unit time.
|
|
||||||
if (timer_elapsed(lastScroll) < OPT_DEBOUNCE) return;
|
|
||||||
|
|
||||||
// Don't scroll if the middle button is depressed.
|
|
||||||
if (is_scroll_clicked) {
|
|
||||||
#ifndef IGNORE_SCROLL_CLICK
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir == 0) return;
|
|
||||||
encoder_queue_event(0, dir == 1);
|
|
||||||
|
|
||||||
lastScroll = timer_read();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pointing_device_init_kb(void) {
|
|
||||||
// set the DPI.
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
|
||||||
if (is_drag_scroll) {
|
|
||||||
mouse_report.h = mouse_report.x;
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_INVERT
|
|
||||||
// Invert vertical scroll direction
|
|
||||||
mouse_report.v = -mouse_report.y;
|
|
||||||
#else
|
|
||||||
mouse_report.v = mouse_report.y;
|
|
||||||
#endif
|
|
||||||
mouse_report.x = 0;
|
|
||||||
mouse_report.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointing_device_task_user(mouse_report);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
|
|
||||||
xprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
|
|
||||||
|
|
||||||
// Update Timer to prevent accidental scrolls
|
|
||||||
if ((record->event.key.col == 1) && (record->event.key.row == 0)) {
|
|
||||||
lastMidClick = timer_read();
|
|
||||||
is_scroll_clicked = record->event.pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process_record_user(keycode, record)) return false;
|
|
||||||
|
|
||||||
if (keycode == DPI_CONFIG && record->event.pressed) {
|
|
||||||
keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycode == DRAG_SCROLL) {
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MOMENTARY
|
|
||||||
if (record->event.pressed)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
is_drag_scroll ^= 1;
|
|
||||||
}
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? PLOOPY_DRAGSCROLL_DPI : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hardware Setup
|
|
||||||
void keyboard_pre_init_kb(void) {
|
|
||||||
// debug_enable = true;
|
|
||||||
// debug_matrix = true;
|
|
||||||
// debug_mouse = true;
|
|
||||||
// debug_encoder = true;
|
|
||||||
|
|
||||||
/* Ground all output pins connected to ground. This provides additional
|
|
||||||
* pathways to ground. If you're messing with this, know this: driving ANY
|
|
||||||
* of these pins high will cause a short. On the MCU. Ka-blooey.
|
|
||||||
*/
|
|
||||||
#ifdef UNUSABLE_PINS
|
|
||||||
const pin_t unused_pins[] = UNUSABLE_PINS;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ARRAY_SIZE(unused_pins); i++) {
|
|
||||||
setPinOutput(unused_pins[i]);
|
|
||||||
writePinLow(unused_pins[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_pre_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void eeconfig_init_kb(void) {
|
|
||||||
keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
eeconfig_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
// is safe to just read DPI setting since matrix init
|
|
||||||
// comes before pointing device init.
|
|
||||||
keyboard_config.raw = eeconfig_read_kb();
|
|
||||||
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
|
|
||||||
eeconfig_init_kb();
|
|
||||||
}
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2019 Hiroyuki Okada
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "quantum.h"
|
|
||||||
#include "analog.h"
|
|
||||||
#include "opt_encoder.h"
|
|
||||||
|
|
||||||
// Sensor defs
|
|
||||||
#define OPT_ENC1 F0
|
|
||||||
#define OPT_ENC2 F4
|
|
||||||
#define OPT_ENC1_MUX 0
|
|
||||||
#define OPT_ENC2_MUX 4
|
|
||||||
|
|
||||||
void process_wheel(void);
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uint32_t raw;
|
|
||||||
struct {
|
|
||||||
uint8_t dpi_config;
|
|
||||||
};
|
|
||||||
} keyboard_config_t;
|
|
||||||
|
|
||||||
extern keyboard_config_t keyboard_config;
|
|
||||||
|
|
||||||
enum ploopy_keycodes {
|
|
||||||
DPI_CONFIG = QK_KB_0,
|
|
||||||
DRAG_SCROLL,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool encoder_update_user(uint8_t index, bool clockwise);
|
|
||||||
bool encoder_update_kb(uint8_t index, bool clockwise);
|
|
|
@ -9,6 +9,9 @@
|
||||||
"device_version": "0.0.1",
|
"device_version": "0.0.1",
|
||||||
"max_power": 100
|
"max_power": 100
|
||||||
},
|
},
|
||||||
|
"features": {
|
||||||
|
"pointing_device": true
|
||||||
|
},
|
||||||
"processor": "atmega32u4",
|
"processor": "atmega32u4",
|
||||||
"bootloader": "atmel-dfu",
|
"bootloader": "atmel-dfu",
|
||||||
"debounce": 0,
|
"debounce": 0,
|
||||||
|
|
|
@ -1,167 +0,0 @@
|
||||||
/* Copyright 2022 Aidan Gauland
|
|
||||||
* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2019 Hiroyuki Okada
|
|
||||||
*
|
|
||||||
* 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 QMK_KEYBOARD_H
|
|
||||||
#include "print.h"
|
|
||||||
|
|
||||||
#define NUM_LOCK_BITMASK 0b01
|
|
||||||
#define CAPS_LOCK_BITMASK 0b10
|
|
||||||
|
|
||||||
// World record for fastest index finger tapping is 1092 taps per minute, which
|
|
||||||
// is 55ms for a single tap.
|
|
||||||
// https://recordsetter.com/world-record/index-finger-taps-minute/46066
|
|
||||||
#define LED_CMD_TIMEOUT 25
|
|
||||||
#define DELTA_X_THRESHOLD 60
|
|
||||||
#define DELTA_Y_THRESHOLD 15
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
// You could theoretically define 0b00 and send it by having a macro send
|
|
||||||
// the second tap after LED_CMD_TIMEOUT has elapsed.
|
|
||||||
// CMD_EXTRA = 0b00,
|
|
||||||
TG_SCROLL = 0b01,
|
|
||||||
CYC_DPI = 0b10,
|
|
||||||
CMD_RESET = 0b11 // CMD_ prefix to avoid clash with QMK macro
|
|
||||||
} led_cmd_t;
|
|
||||||
|
|
||||||
// State
|
|
||||||
static bool scroll_enabled = false;
|
|
||||||
static bool num_lock_state = false;
|
|
||||||
static bool caps_lock_state = false;
|
|
||||||
static bool in_cmd_window = false;
|
|
||||||
static int8_t delta_x = 0;
|
|
||||||
static int8_t delta_y = 0;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
led_cmd_t led_cmd;
|
|
||||||
uint8_t num_lock_count;
|
|
||||||
uint8_t caps_lock_count;
|
|
||||||
} cmd_window_state_t;
|
|
||||||
|
|
||||||
// Dummy
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {{{KC_NO}}};
|
|
||||||
|
|
||||||
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
|
|
||||||
if (scroll_enabled) {
|
|
||||||
delta_x += mouse_report.x;
|
|
||||||
delta_y += mouse_report.y;
|
|
||||||
|
|
||||||
if (delta_x > DELTA_X_THRESHOLD) {
|
|
||||||
mouse_report.h = 1;
|
|
||||||
delta_x = 0;
|
|
||||||
} else if (delta_x < -DELTA_X_THRESHOLD) {
|
|
||||||
mouse_report.h = -1;
|
|
||||||
delta_x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta_y > DELTA_Y_THRESHOLD) {
|
|
||||||
mouse_report.v = -1;
|
|
||||||
delta_y = 0;
|
|
||||||
} else if (delta_y < -DELTA_Y_THRESHOLD) {
|
|
||||||
mouse_report.v = 1;
|
|
||||||
delta_y = 0;
|
|
||||||
}
|
|
||||||
mouse_report.x = 0;
|
|
||||||
mouse_report.y = 0;
|
|
||||||
}
|
|
||||||
return mouse_report;
|
|
||||||
}
|
|
||||||
|
|
||||||
void keyboard_post_init_user(void) {
|
|
||||||
num_lock_state = host_keyboard_led_state().num_lock;
|
|
||||||
caps_lock_state = host_keyboard_led_state().caps_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t command_timeout(uint32_t trigger_time, void *cb_arg) {
|
|
||||||
cmd_window_state_t *cmd_window_state = (cmd_window_state_t *)cb_arg;
|
|
||||||
# ifdef CONSOLE_ENABLE
|
|
||||||
uprintf("Received command 0b%02b (", cmd_window_state->led_cmd);
|
|
||||||
# endif
|
|
||||||
switch (cmd_window_state->led_cmd) {
|
|
||||||
case TG_SCROLL:
|
|
||||||
# ifdef CONSOLE_ENABLE
|
|
||||||
uprint("TG_SCROLL)\n");
|
|
||||||
# endif
|
|
||||||
scroll_enabled = !scroll_enabled;
|
|
||||||
break;
|
|
||||||
case CYC_DPI:
|
|
||||||
# ifdef CONSOLE_ENABLE
|
|
||||||
uprint("CYC_DPI)\n");
|
|
||||||
# endif
|
|
||||||
cycle_dpi();
|
|
||||||
break;
|
|
||||||
case CMD_RESET:
|
|
||||||
# ifdef CONSOLE_ENABLE
|
|
||||||
uprint("QK_BOOT)\n");
|
|
||||||
# endif
|
|
||||||
reset_keyboard();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
# ifdef CONSOLE_ENABLE
|
|
||||||
uprint("unknown)\n");
|
|
||||||
# endif
|
|
||||||
// Ignore unrecognised commands.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmd_window_state->led_cmd = 0;
|
|
||||||
cmd_window_state->num_lock_count = 0;
|
|
||||||
cmd_window_state->caps_lock_count = 0;
|
|
||||||
in_cmd_window = false;
|
|
||||||
|
|
||||||
return 0; // Don't repeat
|
|
||||||
}
|
|
||||||
|
|
||||||
bool led_update_user(led_t led_state) {
|
|
||||||
static cmd_window_state_t cmd_window_state = {
|
|
||||||
.led_cmd = 0b00,
|
|
||||||
.num_lock_count = 0,
|
|
||||||
.caps_lock_count = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Start timer to end command window if we are not already in the middle of
|
|
||||||
// one.
|
|
||||||
if (!in_cmd_window) {
|
|
||||||
in_cmd_window = true;
|
|
||||||
defer_exec(LED_CMD_TIMEOUT, command_timeout, &cmd_window_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set num lock and caps lock bits when each is toggled on and off within
|
|
||||||
// the window.
|
|
||||||
if (led_state.num_lock != num_lock_state) {
|
|
||||||
cmd_window_state.num_lock_count++;
|
|
||||||
|
|
||||||
if (cmd_window_state.num_lock_count == 2) {
|
|
||||||
cmd_window_state.led_cmd |= NUM_LOCK_BITMASK;
|
|
||||||
cmd_window_state.num_lock_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (led_state.caps_lock != caps_lock_state) {
|
|
||||||
cmd_window_state.caps_lock_count++;
|
|
||||||
|
|
||||||
if (cmd_window_state.caps_lock_count == 2) {
|
|
||||||
cmd_window_state.led_cmd |= CAPS_LOCK_BITMASK;
|
|
||||||
cmd_window_state.caps_lock_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep our copy of the LED states in sync with the host.
|
|
||||||
num_lock_state = led_state.num_lock;
|
|
||||||
caps_lock_state = led_state.caps_lock;
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
# The keymap that takes commands as LED-Key BitMasks (lkbm)
|
|
||||||
Based on [maddie](../maddie), this keymap lets you send a 2-bit command by having a macro on your keyboard tap `KC_NUM_LOCK` and `KC_CAPS_LOCK` on and off within a very short window (25ms by default) to represent bits 1 and 2 respectively. The keymap uses this to allow toggling between sending mouse-movement events and scrolling events; cycling DPI presets, and resetting to the bootloader, so you can reflash without having to unscrew your Ploopy Nano.
|
|
|
@ -1 +0,0 @@
|
||||||
DEFERRED_EXEC_ENABLE = yes
|
|
|
@ -28,21 +28,6 @@ Occasionally, new revisions of the PCB will be released. Every board comes with
|
||||||
|
|
||||||
Match the firmware that you flash onto the board with the designator on the board.
|
Match the firmware that you flash onto the board with the designator on the board.
|
||||||
|
|
||||||
# Customizing your Ploopy Nano Trackball
|
|
||||||
|
|
||||||
You can change the DPI/CPI or speed of the trackball by calling `adns_set_cpi` at any time. Additionally, there is a `DPI_CONFIG` macro that will cycle through an array of options for the DPI. This is set to 375, 750, and 1375, but can be changed. 750 is the default.
|
|
||||||
|
|
||||||
To configure/set your own array, there are two defines to use, `PLOOPY_DPI_OPTIONS` to set the array, and `PLOOPY_DPI_DEFAULT`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define PLOOPY_DPI_OPTIONS { 375, 750, 1375}
|
|
||||||
#define PLOOPY_DPI_DEFAULT 1
|
|
||||||
```
|
|
||||||
|
|
||||||
The `PLOOPY_DPI_OPTIONS` array sets the values that you want to be able to cycle through, and the order they are in. The "default" define lets the firmware know which of these options is the default and should be loaded by default.
|
|
||||||
|
|
||||||
The `DPI_CONFIG` macro will cycle through the values in the array, each time you hit it. It stores this value in persistent memory, so it will load it the next time the device powers up.
|
|
||||||
|
|
||||||
## Fuse settings
|
## Fuse settings
|
||||||
|
|
||||||
When flashing the bootloader, use the following fuse settings:
|
When flashing the bootloader, use the following fuse settings:
|
||||||
|
@ -52,3 +37,7 @@ When flashing the bootloader, use the following fuse settings:
|
||||||
| Low | `0x5E` |
|
| Low | `0x5E` |
|
||||||
| High | `0x99` |
|
| High | `0x99` |
|
||||||
| Extended | `0xC3` |
|
| Extended | `0xC3` |
|
||||||
|
|
||||||
|
# Customizing your PloopyCo Trackball Nano
|
||||||
|
|
||||||
|
You can find customziation options [here](../readme.md).
|
||||||
|
|
|
@ -1,16 +1,3 @@
|
||||||
# Build Options
|
|
||||||
# change yes to no to disable
|
|
||||||
#
|
|
||||||
BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
|
|
||||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
|
||||||
CONSOLE_ENABLE = yes # Console for debug
|
|
||||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
|
||||||
NKRO_ENABLE = no # Enable N-Key Rollover
|
|
||||||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
|
|
||||||
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
|
|
||||||
AUDIO_ENABLE = no # Audio output
|
|
||||||
POINTING_DEVICE_ENABLE = yes
|
|
||||||
POINTING_DEVICE_DRIVER = adns5050
|
POINTING_DEVICE_DRIVER = adns5050
|
||||||
MOUSEKEY_ENABLE = no # Mouse keys
|
|
||||||
|
|
||||||
DEFAULT_FOLDER = ploopyco/trackball_nano/rev1_001
|
DEFAULT_FOLDER = ploopyco/trackball_nano/rev1_001
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
/* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2019 Hiroyuki Okada
|
|
||||||
*
|
|
||||||
* 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 "trackball_nano.h"
|
|
||||||
#include "wait.h"
|
|
||||||
|
|
||||||
#ifndef OPT_DEBOUNCE
|
|
||||||
# define OPT_DEBOUNCE 5 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SCROLL_BUTT_DEBOUNCE
|
|
||||||
# define SCROLL_BUTT_DEBOUNCE 100 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPT_THRES
|
|
||||||
# define OPT_THRES 150 // (0-1024) Threshold for actication
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPT_SCALE
|
|
||||||
# define OPT_SCALE 1 // Multiplier for wheel
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PLOOPY_DPI_OPTIONS
|
|
||||||
# define PLOOPY_DPI_OPTIONS \
|
|
||||||
{ 375, 750, 1375 }
|
|
||||||
# ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 2
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_config_t keyboard_config;
|
|
||||||
uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
|
|
||||||
#define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array)
|
|
||||||
|
|
||||||
void cycle_dpi(void) {
|
|
||||||
keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#ifdef CONSOLE_ENABLE
|
|
||||||
uprintf("DPI is now %d\n", dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement libinput profiles
|
|
||||||
// https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
|
|
||||||
// Compile time accel selection
|
|
||||||
// Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
|
|
||||||
|
|
||||||
// Trackball State
|
|
||||||
bool is_scroll_clicked = false;
|
|
||||||
bool BurstState = false; // init burst state for Trackball module
|
|
||||||
uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
|
|
||||||
|
|
||||||
void pointing_device_init_kb(void) {
|
|
||||||
// set the DPI.
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hardware Setup
|
|
||||||
void keyboard_pre_init_kb(void) {
|
|
||||||
// debug_enable = true;
|
|
||||||
// debug_matrix = true;
|
|
||||||
// debug_mouse = true;
|
|
||||||
// debug_encoder = true;
|
|
||||||
|
|
||||||
/* Ground all output pins connected to ground. This provides additional
|
|
||||||
* pathways to ground. If you're messing with this, know this: driving ANY
|
|
||||||
* of these pins high will cause a short. On the MCU. Ka-blooey.
|
|
||||||
*/
|
|
||||||
#ifdef UNUSABLE_PINS
|
|
||||||
const pin_t unused_pins[] = UNUSABLE_PINS;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ARRAY_SIZE(unused_pins); i++) {
|
|
||||||
setPinOutput(unused_pins[i]);
|
|
||||||
writePinLow(unused_pins[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_pre_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void eeconfig_init_kb(void) {
|
|
||||||
keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
eeconfig_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
// is safe to just read DPI setting since matrix init
|
|
||||||
// comes before pointing device init.
|
|
||||||
keyboard_config.raw = eeconfig_read_kb();
|
|
||||||
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
|
|
||||||
eeconfig_init_kb();
|
|
||||||
}
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
* Copyright 2019 Hiroyuki Okada
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "quantum.h"
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uint32_t raw;
|
|
||||||
struct {
|
|
||||||
uint8_t dpi_config;
|
|
||||||
};
|
|
||||||
} keyboard_config_t;
|
|
||||||
|
|
||||||
extern keyboard_config_t keyboard_config;
|
|
||||||
|
|
||||||
enum ploopy_keycodes {
|
|
||||||
DPI_CONFIG = QK_KB_0,
|
|
||||||
};
|
|
||||||
|
|
||||||
void cycle_dpi(void);
|
|
|
@ -19,9 +19,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/* disable action features */
|
/* disable action features */
|
||||||
//#define NO_ACTION_LAYER
|
// #define NO_ACTION_LAYER
|
||||||
//#define NO_ACTION_TAPPING
|
// #define NO_ACTION_TAPPING
|
||||||
//#define NO_ACTION_ONESHOT
|
// #define NO_ACTION_ONESHOT
|
||||||
|
|
||||||
// #define ROTATIONAL_TRANSFORM_ANGLE 0
|
// #define ROTATIONAL_TRANSFORM_ANGLE 0
|
||||||
#define POINTING_DEVICE_INVERT_Y
|
#define POINTING_DEVICE_INVERT_Y
|
||||||
|
@ -32,5 +32,15 @@
|
||||||
/* PMW3360 Settings */
|
/* PMW3360 Settings */
|
||||||
#define POINTING_DEVICE_CS_PIN B0
|
#define POINTING_DEVICE_CS_PIN B0
|
||||||
|
|
||||||
|
#define ENCODER_BUTTON_COL 1
|
||||||
|
#define ENCODER_BUTTON_ROW 0
|
||||||
|
|
||||||
|
#define ENCODER_LOW_THRES_A 20
|
||||||
|
#define ENCODER_HIGH_THRES_A 75
|
||||||
|
#define ENCODER_LOW_THRES_B 20
|
||||||
|
#define ENCODER_HIGH_THRES_B 90
|
||||||
/* Custom encoder needs to specify just how many encoders we have */
|
/* Custom encoder needs to specify just how many encoders we have */
|
||||||
#define NUM_ENCODERS 1
|
#define NUM_ENCODERS 1
|
||||||
|
|
||||||
|
#define ENCODERS_PAD_A { F4 }
|
||||||
|
#define ENCODERS_PAD_B { F0 }
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
*
|
|
||||||
* 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 QMK_KEYBOARD_H
|
|
||||||
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = LAYOUT( /* Base */
|
|
||||||
KC_BTN4, KC_BTN1, KC_BTN3, KC_BTN2, KC_BTN5,
|
|
||||||
MO(1)
|
|
||||||
),
|
|
||||||
[1] = LAYOUT(
|
|
||||||
_______, _______, _______, _______, _______,
|
|
||||||
DRAG_SCROLL
|
|
||||||
)
|
|
||||||
};
|
|
|
@ -1,3 +0,0 @@
|
||||||
# The Drag Scroll keymap for Ploopyco Thumb Trackball
|
|
||||||
|
|
||||||
This is a sample keymap showing off what you can do with the custom callback drivers.
|
|
|
@ -1 +1,2 @@
|
||||||
VIA_ENABLE = yes
|
VIA_ENABLE = yes
|
||||||
|
LTO_ENABLE = yes
|
||||||
|
|
|
@ -16,43 +16,4 @@ See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_to
|
||||||
|
|
||||||
# Customizing your PloopyCo Thumb
|
# Customizing your PloopyCo Thumb
|
||||||
|
|
||||||
While the defaults are designed so that it can be plugged in and used right away, there are a number of things that you may want to change. Such as adding DPI control, or to use the ball to scroll while holding a button. To allow for this sort of control, there is a callback for both the scroll wheel and the mouse sensor.
|
You can find customziation options [here](../readme.md).
|
||||||
|
|
||||||
The default behavior for this is:
|
|
||||||
|
|
||||||
```c
|
|
||||||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
|
||||||
|
|
||||||
return mouse_report;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This should allow you to more heavily customize the behavior.
|
|
||||||
|
|
||||||
Alternatively, the `process_wheel` and `process_mouse` functions can both be replaced too, to allow for even more functionality.
|
|
||||||
|
|
||||||
Additionally, you can change the DPI/CPI or speed of the trackball by calling `pmw_set_cpi` at any time. Additionally, there is a `DPI_CONFIG` keycode that will cycle through an array of options for the DPI. This is set to 1200, 1600, and 2400, but can be changed. 1600 is also set to the default.
|
|
||||||
|
|
||||||
To configure/set your own array, there are two defines to use, `PLOOPY_DPI_OPTIONS` to set the array, and `PLOOPY_DPI_DEFAULT`, which is the `0`-based index into the `PLOOPY_DPI_OPTIONS` array.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define PLOOPY_DPI_OPTIONS { 1200, 1600, 2400 }
|
|
||||||
#define PLOOPY_DPI_DEFAULT 1
|
|
||||||
```
|
|
||||||
The `PLOOPY_DPI_OPTIONS` array sets the values that you want to be able to cycle through, and the order they are in. The "default" define lets the firmware know which of these options is the default and should be loaded by default.
|
|
||||||
|
|
||||||
When inserted into your keymap, the `DPI_CONFIG` keycode will cycle through the values in the array each time you hit it. It stores this value in persistent memory, so it will remember your selection the next time the device powers up.
|
|
||||||
|
|
||||||
## Drag Scroll
|
|
||||||
|
|
||||||
Drag Scroll is a custom keycode for the Ploopy devices that allow you to hold or tap a button and have the mouse movement translate into scrolling instead.
|
|
||||||
|
|
||||||
Nothing needs to be enabled to use this functionality. Just add the `DRAG_SCROLL` to your keymap.
|
|
||||||
|
|
||||||
### Drag Scroll Configuration
|
|
||||||
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MOMENTARY` - Makes the key into a momentary key, rather than a toggle.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75` - Sets the DPI multiplier to use when drag scroll is enabled.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_FIXED` - Normally, when activating Drag Scroll, it uses a fraction of the current DPI. You can define this to use a specific, set DPI rather than a fraction of the current DPI.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_DPI 100` - When the fixed DPI option is enabled, this sets the DPI to be used for Drag Scroll.
|
|
||||||
* `#define PLOOPY_DRAGSCROLL_INVERT` - This reverses the direction that the scroll is performed.
|
|
||||||
|
|
|
@ -3,8 +3,4 @@ F_CPU = 8000000
|
||||||
|
|
||||||
POINTING_DEVICE_DRIVER = pmw3360
|
POINTING_DEVICE_DRIVER = pmw3360
|
||||||
|
|
||||||
ANALOG_DRIVER_REQUIRED = yes
|
|
||||||
|
|
||||||
SRC += opt_encoder.c
|
|
||||||
|
|
||||||
DEFAULT_FOLDER = ploopyco/trackball_thumb/rev1_001
|
DEFAULT_FOLDER = ploopyco/trackball_thumb/rev1_001
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
/* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
*
|
|
||||||
* 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 "trackball_thumb.h"
|
|
||||||
#include "encoder.h"
|
|
||||||
|
|
||||||
#ifndef OPT_DEBOUNCE
|
|
||||||
# define OPT_DEBOUNCE 5 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
#ifndef SCROLL_BUTT_DEBOUNCE
|
|
||||||
# define SCROLL_BUTT_DEBOUNCE 100 // (ms) Time between scroll events
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DPI_OPTIONS
|
|
||||||
# define PLOOPY_DPI_OPTIONS \
|
|
||||||
{ 600, 900, 1200, 1600 }
|
|
||||||
# ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DPI_DEFAULT
|
|
||||||
# define PLOOPY_DPI_DEFAULT 0
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_DPI
|
|
||||||
# define PLOOPY_DRAGSCROLL_DPI 100 // Fixed-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MULTIPLIER
|
|
||||||
# define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75 // Variable-DPI Drag Scroll
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_config_t keyboard_config;
|
|
||||||
uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
|
|
||||||
#define DPI_OPTION_SIZE (sizeof(dpi_array) / sizeof(uint16_t))
|
|
||||||
|
|
||||||
// TODO: Implement libinput profiles
|
|
||||||
// https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
|
|
||||||
// Compile time accel selection
|
|
||||||
// Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
|
|
||||||
|
|
||||||
// Trackball State
|
|
||||||
bool is_scroll_clicked = false;
|
|
||||||
uint16_t last_scroll = 0; // Previous confirmed wheel event
|
|
||||||
uint16_t last_mid_click = 0; // Stops scrollwheel from being read if it was pressed;
|
|
||||||
bool debug_encoder = false;
|
|
||||||
bool is_drag_scroll = false;
|
|
||||||
|
|
||||||
bool encoder_update_kb(uint8_t index, bool clockwise) {
|
|
||||||
if (!encoder_update_user(index, clockwise)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef MOUSEKEY_ENABLE
|
|
||||||
tap_code(clockwise ? KC_WH_U : KC_WH_D);
|
|
||||||
#else
|
|
||||||
report_mouse_t mouse_report = pointing_device_get_report();
|
|
||||||
mouse_report.v = clockwise ? 1 : -1;
|
|
||||||
pointing_device_set_report(mouse_report);
|
|
||||||
pointing_device_send();
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void encoder_driver_init(void) { opt_encoder_init(); }
|
|
||||||
|
|
||||||
void encoder_driver_task(void) {
|
|
||||||
// Lovingly ripped from the Ploopy Source
|
|
||||||
|
|
||||||
// If the mouse wheel was just released, do not scroll.
|
|
||||||
if (timer_elapsed(last_mid_click) < SCROLL_BUTT_DEBOUNCE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit the number of scrolls per unit time.
|
|
||||||
if (timer_elapsed(last_scroll) < OPT_DEBOUNCE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't scroll if the middle button is depressed.
|
|
||||||
if (is_scroll_clicked) {
|
|
||||||
#ifndef IGNORE_SCROLL_CLICK
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
last_scroll = timer_read();
|
|
||||||
uint16_t p1 = adc_read(OPT_ENC1_MUX);
|
|
||||||
uint16_t p2 = adc_read(OPT_ENC2_MUX);
|
|
||||||
if (debug_encoder) dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
|
|
||||||
|
|
||||||
int dir = opt_encoder_handler(p1, p2);
|
|
||||||
|
|
||||||
if (dir == 0) return;
|
|
||||||
encoder_queue_event(0, dir == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
|
||||||
if (is_drag_scroll) {
|
|
||||||
mouse_report.h = mouse_report.x;
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_INVERT
|
|
||||||
// Invert vertical scroll direction
|
|
||||||
mouse_report.v = -mouse_report.y;
|
|
||||||
#else
|
|
||||||
mouse_report.v = mouse_report.y;
|
|
||||||
#endif
|
|
||||||
mouse_report.x = 0;
|
|
||||||
mouse_report.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointing_device_task_user(mouse_report);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
|
|
||||||
// Update Timer to prevent accidental scrolls
|
|
||||||
if ((record->event.key.col == 1) && (record->event.key.row == 0)) {
|
|
||||||
last_mid_click = timer_read();
|
|
||||||
is_scroll_clicked = record->event.pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process_record_user(keycode, record)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycode == DPI_CONFIG && record->event.pressed) {
|
|
||||||
keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycode == DRAG_SCROLL) {
|
|
||||||
#ifndef PLOOPY_DRAGSCROLL_MOMENTARY
|
|
||||||
if (record->event.pressed)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
is_drag_scroll ^= 1;
|
|
||||||
}
|
|
||||||
#ifdef PLOOPY_DRAGSCROLL_FIXED
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? PLOOPY_DRAGSCROLL_DPI : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#else
|
|
||||||
pointing_device_set_cpi(is_drag_scroll ? (dpi_array[keyboard_config.dpi_config] * PLOOPY_DRAGSCROLL_MULTIPLIER) : dpi_array[keyboard_config.dpi_config]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If Mousekeys is disabled, then use handle the mouse button
|
|
||||||
* keycodes. This makes things simpler, and allows usage of
|
|
||||||
* the keycodes in a consistent manner. But only do this if
|
|
||||||
* Mousekeys is not enable, so it's not handled twice.
|
|
||||||
*/
|
|
||||||
#ifndef MOUSEKEY_ENABLE
|
|
||||||
if (IS_MOUSEKEY_BUTTON(keycode)) {
|
|
||||||
report_mouse_t currentReport = pointing_device_get_report();
|
|
||||||
if (record->event.pressed) {
|
|
||||||
currentReport.buttons |= 1 << (keycode - KC_MS_BTN1);
|
|
||||||
} else {
|
|
||||||
currentReport.buttons &= ~(1 << (keycode - KC_MS_BTN1));
|
|
||||||
}
|
|
||||||
pointing_device_set_report(currentReport);
|
|
||||||
pointing_device_send();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hardware Setup
|
|
||||||
void keyboard_pre_init_kb(void) {
|
|
||||||
// debug_enable = true;
|
|
||||||
// debug_matrix = true;
|
|
||||||
// debug_mouse = true;
|
|
||||||
// debug_encoder = true;
|
|
||||||
|
|
||||||
setPinInput(OPT_ENC1);
|
|
||||||
setPinInput(OPT_ENC2);
|
|
||||||
|
|
||||||
/* Ground all output pins connected to ground. This provides additional
|
|
||||||
* pathways to ground. If you're messing with this, know this: driving ANY
|
|
||||||
* of these pins high will cause a short. On the MCU. Ka-blooey.
|
|
||||||
*/
|
|
||||||
#ifdef UNUSABLE_PINS
|
|
||||||
const pin_t unused_pins[] = UNUSABLE_PINS;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < (sizeof(unused_pins) / sizeof(pin_t)); i++) {
|
|
||||||
setPinOutput(unused_pins[i]);
|
|
||||||
writePinLow(unused_pins[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This is the debug LED.
|
|
||||||
#if defined(DEBUG_LED_PIN)
|
|
||||||
setPinOutput(DEBUG_LED_PIN);
|
|
||||||
writePin(DEBUG_LED_PIN, debug_enable);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keyboard_pre_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pointing_device_init_kb(void) { pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]); }
|
|
||||||
|
|
||||||
void eeconfig_init_kb(void) {
|
|
||||||
keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
|
|
||||||
eeconfig_update_kb(keyboard_config.raw);
|
|
||||||
eeconfig_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
// is safe to just read DPI setting since matrix init
|
|
||||||
// comes before pointing device init.
|
|
||||||
keyboard_config.raw = eeconfig_read_kb();
|
|
||||||
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
|
|
||||||
eeconfig_init_kb();
|
|
||||||
}
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/* Copyright 2021 Colin Lam (Ploopy Corporation)
|
|
||||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
|
||||||
* Copyright 2019 Sunjun Kim
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "quantum.h"
|
|
||||||
#include "analog.h"
|
|
||||||
#include "opt_encoder.h"
|
|
||||||
|
|
||||||
// Sensor defs
|
|
||||||
#define OPT_ENC1 F4
|
|
||||||
#define OPT_ENC2 F0
|
|
||||||
#define OPT_ENC1_MUX 4
|
|
||||||
#define OPT_ENC2_MUX 0
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uint32_t raw;
|
|
||||||
struct {
|
|
||||||
uint8_t dpi_config;
|
|
||||||
};
|
|
||||||
} keyboard_config_t;
|
|
||||||
_Static_assert(sizeof(keyboard_config_t) == sizeof(uint32_t), "keyboard_config_t size mismatch compared to EEPROM area");
|
|
||||||
|
|
||||||
extern keyboard_config_t keyboard_config;
|
|
||||||
extern uint16_t dpi_array[];
|
|
||||||
|
|
||||||
enum ploopy_keycodes {
|
|
||||||
DPI_CONFIG = QK_KB_0,
|
|
||||||
DRAG_SCROLL,
|
|
||||||
};
|
|
Loading…
Reference in New Issue