qmk_firmware/keyboards/aki27/cocot46plus/cocot46plus.c
Mark Stosberg 48f99880c5
refinements: right half no longer works
After this round of refinements, the left half of keyboard and the
pointing device work, but no keycodes are emitted from the right half
at all.
2024-11-13 20:22:50 -05:00

287 lines
8.5 KiB
C

/*
Copyright 2022 aki27
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 "cocot46plus.h"
#include <math.h>
// Invert vertical scroll direction
#ifndef COCOT_SCROLL_INV_DEFAULT
# define COCOT_SCROLL_INV_DEFAULT 1
#endif
#ifndef COCOT_CPI_OPTIONS
# define COCOT_CPI_OPTIONS { 250, 500, 750, 1000, 1250 }
#endif
#ifndef COCOT_CPI_DEFAULT
# define COCOT_CPI_DEFAULT 4
#endif
#ifndef COCOT_SCROLL_DIVIDERS
# define COCOT_SCROLL_DIVIDERS { 1, 2, 3, 4, 5, 6 }
#endif
#ifndef COCOT_SCROLL_DIV_DEFAULT
# define COCOT_SCROLL_DIV_DEFAULT 4
#endif
#ifndef COCOT_ROTATION_ANGLE
# define COCOT_ROTATION_ANGLE { -60, -45, -30, -15, 0, 15, 30, 45, 60 }
#endif
#ifndef COCOT_ROTATION_DEFAULT
# define COCOT_ROTATION_DEFAULT 2
#endif
cocot_config_t cocot_config;
uint16_t cpi_array[] = COCOT_CPI_OPTIONS;
uint16_t scrl_div_array[] = COCOT_SCROLL_DIVIDERS;
uint16_t angle_array[] = COCOT_ROTATION_ANGLE;
#define CPI_OPTION_SIZE (sizeof(cpi_array) / sizeof(uint16_t))
#define SCRL_DIV_SIZE (sizeof(scrl_div_array) / sizeof(uint16_t))
#define ANGLE_SIZE (sizeof(angle_array) / sizeof(uint16_t))
// Trackball State
bool BurstState = false; // init burst state for Trackball module
uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
// Scroll Accumulation
static int16_t h_acm = 0;
static int16_t v_acm = 0;
void pointing_device_init_kb(void) {
// set the CPI.
pointing_device_set_cpi(cpi_array[cocot_config.cpi_idx]);
adns5050_write_reg(0x22, 0b10000 | 0x80);
}
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
double rad = angle_array[cocot_config.rotation_angle] * (M_PI / 180) * -1;
int8_t x_rev = + mouse_report.x * cos(rad) - mouse_report.y * sin(rad);
int8_t y_rev = + mouse_report.x * sin(rad) + mouse_report.y * cos(rad);
if (cocot_get_scroll_mode()) {
// rock scroll direction
if (abs(x_rev) > abs(y_rev)) {
y_rev = 0;
} else {
x_rev = 0;
}
// accumulate scroll
h_acm += x_rev * cocot_config.scrl_inv;
v_acm += y_rev * cocot_config.scrl_inv * -1;
int8_t h_rev = h_acm >> scrl_div_array[cocot_config.scrl_div];
int8_t v_rev = v_acm >> scrl_div_array[cocot_config.scrl_div];
// clear accumulated scroll on assignment
if (h_rev != 0) {
if (mouse_report.h + h_rev > 127) {
h_rev = 127 - mouse_report.h;
} else if (mouse_report.h + h_rev < -127) {
h_rev = -127 - mouse_report.h;
}
mouse_report.h += h_rev;
h_acm -= h_rev << scrl_div_array[cocot_config.scrl_div];
}
if (v_rev != 0) {
if (mouse_report.v + v_rev > 127) {
v_rev = 127 - mouse_report.v;
} else if (mouse_report.v + v_rev < -127) {
v_rev = -127 - mouse_report.v;
}
mouse_report.v += v_rev;
v_acm -= v_rev << scrl_div_array[cocot_config.scrl_div];
}
mouse_report.x = 0;
mouse_report.y = 0;
} else {
mouse_report.x = x_rev;
mouse_report.y = y_rev;
}
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);
if (!process_record_user(keycode, record)) return false;
switch (keycode) {
#ifndef MOUSEKEY_ENABLE
// process KC_MS_BTN1~8 by myself
// See process_action() in quantum/action.c for details.
case KC_MS_BTN1 ... KC_MS_BTN8: {
extern void register_button(bool, enum mouse_buttons);
register_button(record->event.pressed, MOUSE_BTN_MASK(keycode - KC_MS_BTN1));
return false;
}
#endif
}
if (keycode == CPI_SW && record->event.pressed) {
cocot_config.cpi_idx = (cocot_config.cpi_idx + 1) % CPI_OPTION_SIZE;
eeconfig_update_kb(cocot_config.raw);
pointing_device_set_cpi(cpi_array[cocot_config.cpi_idx]);
}
if (keycode == SCRL_SW && record->event.pressed) {
cocot_config.scrl_div = (cocot_config.scrl_div + 1) % SCRL_DIV_SIZE;
eeconfig_update_kb(cocot_config.raw);
}
if (keycode == ROT_R15 && record->event.pressed) {
cocot_config.rotation_angle = (cocot_config.rotation_angle + 1) % ANGLE_SIZE;
eeconfig_update_kb(cocot_config.raw);
}
if (keycode == ROT_L15 && record->event.pressed) {
cocot_config.rotation_angle = (ANGLE_SIZE + cocot_config.rotation_angle - 1) % ANGLE_SIZE;
eeconfig_update_kb(cocot_config.raw);
}
if (keycode == SCRL_IN && record->event.pressed) {
cocot_config.scrl_inv = - cocot_config.scrl_inv;
eeconfig_update_kb(cocot_config.raw);
}
if (keycode == SCRL_TO && record->event.pressed) {
{ cocot_config.scrl_mode ^= 1; }
}
if (keycode == SCRL_MO) {
{ cocot_config.scrl_mode ^= 1; }
}
return true;
}
void eeconfig_init_kb(void) {
cocot_config.cpi_idx = COCOT_CPI_DEFAULT;
cocot_config.scrl_div = COCOT_SCROLL_DIV_DEFAULT;
cocot_config.rotation_angle = COCOT_ROTATION_DEFAULT;
cocot_config.scrl_inv = COCOT_SCROLL_INV_DEFAULT;
cocot_config.scrl_mode = false;
eeconfig_update_kb(cocot_config.raw);
eeconfig_init_user();
adns5050_write_reg(0x22, 0b10000 | 0x80);
}
void matrix_init_kb(void) {
// is safe to just read CPI setting since matrix init
// comes before pointing device init.
cocot_config.raw = eeconfig_read_kb();
if (cocot_config.cpi_idx > CPI_OPTION_SIZE) // || cocot_config.scrl_div > SCRL_DIV_SIZE || cocot_config.rotation_angle > ANGLE_SIZE)
{
eeconfig_init_kb();
}
matrix_init_user();
}
bool cocot_get_scroll_mode(void) {
return cocot_config.scrl_mode;
}
void cocot_set_scroll_mode(bool mode) {
cocot_config.scrl_mode = mode;
}
// OLED utility
#ifdef OLED_ENABLE
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
return OLED_ROTATION_0;
}
static const char PROGMEM cocot_logo[] = {
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
0};
void render_logo(void) {
oled_write_P(cocot_logo, false);
};
void oled_write_layer_state(void) {
oled_write_P(PSTR(" "), false);
switch (get_highest_layer(layer_state | default_layer_state)) {
case 0:
oled_write_P(PSTR("Base "), false);
break;
case 1:
oled_write_P(PSTR("Lower"), false);
break;
case 2:
oled_write_P(PSTR("Raise"), false);
break;
case 3:
oled_write_P(PSTR("Mouse"), false);
break;
case 4:
oled_write_P(PSTR("L4 "), false);
break;
case 5:
oled_write_P(PSTR("L5 "), false);
break;
case 6:
oled_write_P(PSTR("L6 "), false);
break;
default:
oled_write_P(PSTR("Undef"), false);
break;
}
oled_write_P(PSTR("/"), false);
if (cocot_get_scroll_mode()){
oled_write_P(PSTR("S"), false);
} else{
oled_write_P(PSTR("C"), false);
}
int cpi = cpi_array[cocot_config.cpi_idx];
int scroll_div = scrl_div_array[cocot_config.scrl_div];
int angle = angle_array[cocot_config.rotation_angle];
oled_write_P(PSTR("/"), false);
oled_write(get_u16_str(cpi,' '), false);
oled_write_P(PSTR("/"), false);
oled_write(get_u8_str(scroll_div,' '), false);
oled_write_P(PSTR("/"), false);
oled_write(get_u16_str(angle,' '), false);
}
#endif