Skip to content

Commit

Permalink
[Keyboard] Overhaul ploopyco devices (qmk#22967)
Browse files Browse the repository at this point in the history
  • Loading branch information
drashna authored and mechlovin committed Apr 15, 2024
1 parent 069b9d1 commit 89e3fcf
Show file tree
Hide file tree
Showing 51 changed files with 355 additions and 1,909 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
state = HIHI;
lohif = true;
Expand All @@ -157,9 +157,13 @@ int8_t opt_encoder_handler(uint16_t curA, uint16_t curB) {
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) {
if (cur < *low) *low = cur;
Expand Down Expand Up @@ -236,7 +240,9 @@ int calculateThreshold(int cur, int* low, int* high, bool* cLow, bool* cHigh, in
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) {
if (*index < SCROLLER_AR_SIZE - 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

typedef enum {
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;

static encoder_state_t mode;
Expand All @@ -87,15 +87,14 @@ static const uint8_t movement[] = {
// 10 -> 00, 01, 10, 11
MOVE_DOWN, MOVE_ERR, MOVE_NONE, MOVE_UP,
// 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) {
mode = CALIBRATION;
mode = CALIBRATION;
lastState = 0;

lowA = ENCODER_MAX;
lowB = ENCODER_MAX;
lowA = ENCODER_MAX;
lowB = ENCODER_MAX;
highA = ENCODER_MIN;
highB = ENCODER_MIN;
}
Expand All @@ -104,26 +103,22 @@ int8_t opt_encoder_handler(uint16_t encA, uint16_t encB) {
int8_t result = 0;

highA = MAX(encA, highA);
lowA = MIN(encA, lowA);
lowA = MIN(encA, lowA);
highB = MAX(encB, highB);
lowB = MIN(encB, lowB);
lowB = MIN(encB, lowB);

/* Only compute the thresholds after a large enough range is established */
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 lowThresholdB = (highB + lowB) / 4;
const int16_t lowThresholdB = (highB + lowB) / 4;
const int16_t highThresholdB = (highB + lowB) - lowThresholdB;

uint8_t state = MAKE_STATE(
STATE_A(lastState) ? encA > lowThresholdA : encA > highThresholdA,
STATE_B(lastState) ? encB > lowThresholdB : encB > highThresholdB
);
uint8_t state = MAKE_STATE(STATE_A(lastState) ? encA > lowThresholdA : encA > highThresholdA, STATE_B(lastState) ? encB > lowThresholdB : encB > highThresholdB);

switch (mode) {
case CALIBRATION:
if ((lastState == HILO && state == LOLO)
|| (lastState == LOHI && state == LOLO))
if ((lastState == HILO && state == LOLO) || (lastState == LOHI && state == LOLO))
mode = DECODE;
else
mode = CALIBRATION;
Expand All @@ -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,
* then the wheel might have moved too fast and we need to
* recalibrate the encoder position. */
mode = result == MOVE_ERR ? CALIBRATION : mode;
mode = result == MOVE_ERR ? CALIBRATION : mode;
result = result == MOVE_ERR ? MOVE_NONE : result;

break;
Expand Down
116 changes: 116 additions & 0 deletions keyboards/ploopyco/common/opt_encoder_tiny.c
Original file line number Diff line number Diff line change
@@ -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;
}
5 changes: 4 additions & 1 deletion keyboards/ploopyco/madromys/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

#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 POINTING_DEVICE_INVERT_Y

Expand All @@ -26,4 +29,4 @@
#define PMW33XX_CS_PIN GP5
#define SPI_SCK_PIN GP2
#define SPI_MISO_PIN GP0
#define SPI_MOSI_PIN GP7
#define SPI_MOSI_PIN GP7
4 changes: 2 additions & 2 deletions keyboards/ploopyco/madromys/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"extrakey": true,
"mousekey": true,
"nkro": true,
"pointing_device": true,
"pointing_device": true
},
"layouts": {
"LAYOUT": {
Expand All @@ -31,5 +31,5 @@
},
"dynamic_keymap": {
"layer_count": 8
},
}
}
Loading

0 comments on commit 89e3fcf

Please sign in to comment.