Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Keyboard] Add PloopyCo devices #7935

Merged
merged 35 commits into from
Sep 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b5ecc60
Initial Commit for Ploopyco Trackball
drashna Oct 13, 2019
d6d3e35
Convert SPI commands from arduino to LUFA
drashna Oct 13, 2019
66ddbe1
Update keyboard readme
drashna Oct 16, 2019
5fd3686
Clean up ploopyco trackball
drashna Jan 18, 2020
8d6adac
Update readme
drashna Jan 18, 2020
148cf6d
Update mouse key stuff
drashna Jan 18, 2020
b4c072a
last minutue cleanup
drashna Jan 18, 2020
0af6aef
Add caveat about scroll wheel
drashna Jan 19, 2020
33cf7ef
Fixup to code
drashna Feb 12, 2020
d21a8b3
Additional fixup
drashna Feb 12, 2020
805904f
Add movement multiplier
drashna Feb 12, 2020
10fc5eb
Rename folders
drashna Jun 20, 2020
4a4836b
mid changes
drashna Jun 25, 2020
7392cf0
temp
drashna Sep 11, 2020
447b2ee
Got it working!!!!!
drashna Sep 11, 2020
cf76ceb
Additional cleanup of code
drashna Sep 11, 2020
abde984
Make unused pin calls more compact
drashna Sep 11, 2020
e49bdf1
Rotation info
drashna Sep 11, 2020
7846fc7
Add debouncing checks
drashna Sep 11, 2020
d409885
Make everything replaceable
drashna Sep 11, 2020
4ba6feb
Add info.json
drashna Sep 11, 2020
a612aa3
Include ISP flashing info
drashna Sep 11, 2020
d94ec4c
Better handling for user customization
drashna Sep 12, 2020
f3c88f1
Reconfigure CPI stuff
drashna Sep 13, 2020
2bb20f4
fix issues with debug printing
drashna Sep 19, 2020
acda230
Fix tiny scroll issue
drashna Sep 21, 2020
7208d6a
Add and update scroll code from ploopy mouse
drashna Sep 27, 2020
b64d73f
Update licensing
drashna Sep 27, 2020
742e641
Add PloopyCo Mouse
drashna Sep 27, 2020
54e8b36
Cleanup and layout stuff
drashna Sep 27, 2020
a84fb87
Move common files to main folder for reuse
drashna Sep 27, 2020
6fdb1ae
Increase polling rate
drashna Sep 27, 2020
4cde976
Update image for mouse
drashna Sep 27, 2020
177cff0
Apply changes from code review
drashna Sep 27, 2020
674c2e0
Add VIA support
drashna Sep 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions keyboards/ploopyco/mouse/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* 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 "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID 0x5043
#define PRODUCT_ID 0x4D6F
#define DEVICE_VER 0x0001
#define MANUFACTURER Ploopyco
#define PRODUCT Mouse

/* key matrix size */
#define MATRIX_ROWS 1
#define MATRIX_COLS 8

/*
* Keyboard Matrix Assignments
*
* Change this to how you wired your keyboard
* COLS: AVR pins used for columns, left to right
* ROWS: AVR pins used for rows, top to bottom
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
*
*/
#define DIRECT_PINS \
{ \
{ D4, D2, E6, B6, D7, C6, C7, B7 } \
}

// These pins are not broken out, and cannot be used normally.
// They are set as output and pulled high, by default
#define UNUSED_PINS \
{ B4, D6, F1, F5, F6, F7 }

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5

/* Much more so than a keyboard, speed matters for a mouse. So we'll go for as high
a polling rate as possible. */
#define USB_POLLING_INTERVAL_MS 1

/* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST

/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION

/* Bootmagic Lite key configuration */
#define BOOTMAGIC_LITE_ROW 0
#define BOOTMAGIC_LITE_COLUMN 3
21 changes: 21 additions & 0 deletions keyboards/ploopyco/mouse/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"keyboard_name": "PloopyCo Mouse",
"url": "",
"maintainer": "drashna",
"width": 8,
"height": 3,
"layouts": {
"LAYOUT": {
"layout": [
{"x":1, "y":0, "h":2},
{"x":2, "y":0, "h":2},
{"x":3, "y":0.25, "h":1.25},
{"x":4, "y":0, "h":2},
{"x":5, "y":0, "h":2},
{"x":0, "y":0},
{"x":0, "y":1},
{"x":3, "y":1.5}
]
}
}
}
23 changes: 23 additions & 0 deletions keyboards/ploopyco/mouse/keymaps/default/keymap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* 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, KC_BTN2, C(KC_C), KC_BTN4, KC_BTN5, C(KC_Z)),
};
1 change: 1 addition & 0 deletions keyboards/ploopyco/mouse/keymaps/default/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# The default keymap for Ploopyco Trackball
26 changes: 26 additions & 0 deletions keyboards/ploopyco/mouse/keymaps/via/keymap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* 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, KC_BTN2, C(KC_C), KC_BTN4, KC_BTN5, C(KC_Z)),
[1] = LAYOUT(_______, _______, _______, _______, _______, _______, _______, _______),
[2] = LAYOUT(_______, _______, _______, _______, _______, _______, _______, _______),
[3] = LAYOUT(_______, _______, _______, _______, _______, _______, _______, _______),
};
1 change: 1 addition & 0 deletions keyboards/ploopyco/mouse/keymaps/via/rules.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VIA_ENABLE = yes
237 changes: 237 additions & 0 deletions keyboards/ploopyco/mouse/mouse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/* 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

#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

// 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;

__attribute__((weak)) void process_wheel_user(report_mouse_t* mouse_report, int16_t h, int16_t v) {
mouse_report->h = h;
mouse_report->v = v;
}

__attribute__((weak)) void process_wheel(report_mouse_t* mouse_report) {
// 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);

uint8_t dir = opt_encoder_handler(p1, p2);

if (dir == 0) return;
process_wheel_user(mouse_report, mouse_report->h, (int)(mouse_report->v + (dir * OPT_SCALE)));
}

__attribute__((weak)) void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) {
mouse_report->x = x;
mouse_report->y = y;
}

__attribute__((weak)) void process_mouse(report_mouse_t* mouse_report) {
report_pmw_t data = pmw_read_burst();
if (data.isOnSurface && data.isMotion) {
// Reset timer if stopped moving
if (!data.isMotion) {
if (MotionStart != 0) MotionStart = 0;
return;
}

// Set timer if new motion
if ((MotionStart == 0) && data.isMotion) {
if (debug_mouse) dprintf("Starting motion.\n");
MotionStart = timer_read();
}

if (debug_mouse) {
dprintf("Delt] d: %d t: %u\n", abs(data.dx) + abs(data.dy), MotionStart);
}
if (debug_mouse) {
dprintf("Pre ] X: %d, Y: %d\n", data.dx, data.dy);
}
#if defined(PROFILE_LINEAR)
float scale = float(timer_elaspsed(MotionStart)) / 1000.0;
data.dx *= scale;
data.dy *= scale;
#elif defined(PROFILE_INVERSE)
// TODO
#else
// no post processing
#endif
// apply multiplier
// data.dx *= mouse_multiplier;
// data.dy *= mouse_multiplier;

// Wrap to HID size
data.dx = constrain(data.dx, -127, 127);
data.dy = constrain(data.dy, -127, 127);
if (debug_mouse) dprintf("Cons] X: %d, Y: %d\n", data.dx, data.dy);
// dprintf("Elapsed:%u, X: %f Y: %\n", i, pgm_read_byte(firmware_data+i));

process_mouse_user(mouse_report, data.dx, data.dy);
}
}

bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
if (debug_mouse) {
dprintf("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 == 2) && (record->event.key.row == 0)) {
lastMidClick = timer_read();
is_scroll_clicked = record->event.pressed;
}

/* 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) {
if (keycode == KC_MS_BTN1)
currentReport.buttons |= MOUSE_BTN1;
else if (keycode == KC_MS_BTN2)
currentReport.buttons |= MOUSE_BTN2;
else if (keycode == KC_MS_BTN3)
currentReport.buttons |= MOUSE_BTN3;
else if (keycode == KC_MS_BTN4)
currentReport.buttons |= MOUSE_BTN4;
else if (keycode == KC_MS_BTN5)
currentReport.buttons |= MOUSE_BTN5;
} else {
if (keycode == KC_MS_BTN1)
currentReport.buttons &= ~MOUSE_BTN1;
else if (keycode == KC_MS_BTN2)
currentReport.buttons &= ~MOUSE_BTN2;
else if (keycode == KC_MS_BTN3)
currentReport.buttons &= ~MOUSE_BTN3;
else if (keycode == KC_MS_BTN4)
currentReport.buttons &= ~MOUSE_BTN4;
else if (keycode == KC_MS_BTN5)
currentReport.buttons &= ~MOUSE_BTN5;
}
pointing_device_set_report(currentReport);
}
#endif

return process_record_user(keycode, record);
}

// 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);

// This is the debug LED.
setPinOutput(F7);
writePin(F7, debug_enable);

/* 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 UNUSED_PINS
const pin_t unused_pins[] = UNUSED_PINS;

for (uint8_t i = 0; i < (sizeof(unused_pins) / sizeof(pin_t)); i++) {
setPinOutput(unused_pins[i]);
writePinLow(unused_pins[i]);
}
#endif
keyboard_pre_init_user();
}

void pointing_device_init(void) {
// initialize ball sensor
pmw_spi_init();
// initialize the scroll wheel's optical encoder
opt_encoder_init();
}

bool has_report_changed (report_mouse_t first, report_mouse_t second) {
return !(
(!first.buttons && first.buttons == second.buttons) &&
(!first.x && first.x == second.x) &&
(!first.y && first.y == second.y) &&
(!first.h && first.h == second.h) &&
(!first.v && first.v == second.v) );
}

void pointing_device_task(void) {
report_mouse_t mouse_report = pointing_device_get_report();
process_wheel(&mouse_report);
process_mouse(&mouse_report);

pointing_device_set_report(mouse_report);
if (has_report_changed(mouse_report, pointing_device_get_report())) {
pointing_device_send();
}
}
Loading