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 aki27/cocot46plus #23892

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8bd2c19
[Keyboard] add aki27/cocot46plus
markstos Jun 10, 2024
08d28e0
Apply suggestions from code review
markstos Jun 11, 2024
123b5b4
remove unnecessary custom_lite key
markstos Jun 11, 2024
56d3759
encoders: use encoder_map instead of custom code
markstos Jun 11, 2024
20ec376
simplify layer definitions
markstos Jun 13, 2024
61960ab
minimize includes in cocot46plus.c
markstos Jun 13, 2024
742049b
code review suggestions: use alternate functions in matrix.c
markstos Jun 13, 2024
48f9988
refinements: right half no longer works
markstos Jun 19, 2024
b0fad57
fixup: remove unnecesssary header include
markstos Jun 20, 2024
a97ebfe
fixup: remove apparently unnecessary MOUSEKEY section and re-indent
markstos Jun 20, 2024
a2605f9
fixup: remove necesesary DIODE_DIRECTION due to custom matrix code
markstos Jun 20, 2024
154b9ef
docs: Refine docs
markstos Jun 20, 2024
a9fec76
Re-enable OLED. Was not working before.
markstos Jun 20, 2024
a4ba098
fixup: make sure custom matrix code is loaded
markstos Jun 20, 2024
c7c04c1
refinemts: OLED is working better, but new problems.
markstos Jun 21, 2024
b2ab70d
fixup: comment, whitespace
markstos Jul 17, 2024
8d6b340
BugFixes: Typing, switch to RP2040 & sprintf
markstos Jul 17, 2024
636b95a
WIP: getting rid of CONVERT_TO
markstos Jul 23, 2024
5ad0ccc
Update config.h
markstos Jul 23, 2024
44f6e22
fixup: quite disabling Space Cadet
markstos Jul 24, 2024
f987a86
fix: fix incorrect pin assignments
yudai-nkt Aug 3, 2024
7c34400
fixup: Update vid to be unique.
markstos Sep 19, 2024
25a4d5f
fixup: move OLED task logic from default keyboard to keyboard level.
markstos Sep 19, 2024
3721832
linting: qmk format-c on matrix.c
markstos Nov 14, 2024
d382503
fixup: recommended change from drashna
markstos Nov 14, 2024
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
289 changes: 289 additions & 0 deletions keyboards/aki27/cocot46plus/cocot46plus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
/*
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include QMK_KEYBOARD_H
#include "cocot46plus.h"

Copy link
Contributor Author

@markstos markstos Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this proposed change was made, the keyboard no longer compiles:

Compiling: keyboards/aki27/cocot46plus/cocot46plus.c                                               keyboards/aki27/cocot46plus/cocot46plus.c: In function 'process_record_kb':
keyboards/aki27/cocot46plus/cocot46plus.c:135:20: error: 'CPI_SW' undeclared (first use in this function)
  135 |     if (keycode == CPI_SW && record->event.pressed) {
      |                    ^~~~~~
keyboards/aki27/cocot46plus/cocot46plus.c:135:20: note: each undeclared identifier is reported only once for each function it appears in
keyboards/aki27/cocot46plus/cocot46plus.c:141:20: error: 'SCRL_SW' undeclared (first use in this function)
  141 |     if (keycode == SCRL_SW && record->event.pressed) {
      |                    ^~~~~~~
keyboards/aki27/cocot46plus/cocot46plus.c:146:20: error: 'ROT_R15' undeclared (first use in this function)
  146 |     if (keycode == ROT_R15 && record->event.pressed) {
      |                    ^~~~~~~
keyboards/aki27/cocot46plus/cocot46plus.c:151:20: error: 'ROT_L15' undeclared (first use in this function)
  151 |     if (keycode == ROT_L15 && record->event.pressed) {
      |                    ^~~~~~~
keyboards/aki27/cocot46plus/cocot46plus.c:156:20: error: 'SCRL_IN' undeclared (first use in this function)
  156 |     if (keycode == SCRL_IN && record->event.pressed) {
      |                    ^~~~~~~
keyboards/aki27/cocot46plus/cocot46plus.c:161:20: error: 'SCRL_TO' undeclared (first use in this function)
  161 |     if (keycode == SCRL_TO && record->event.pressed) {
      |                    ^~~~~~~
keyboards/aki27/cocot46plus/cocot46plus.c:167:20: error: 'SCRL_MO' undeclared (first use in this function)
  167 |     if (keycode == SCRL_MO) {

#include <math.h>

// Invert vertical scroll direction
#ifndef COCOT_SCROLL_INV_DEFAULT
# define COCOT_SCROLL_INV_DEFAULT 1
#endif

// All the default values here refer to O-based array indexes
// not actual values

#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;
int8_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(int8_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 = (double)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;
}

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();
}
markstos marked this conversation as resolved.
Show resolved Hide resolved


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

bool oled_task_kb(void) {
if (!oled_task_user()) {
return false;
}
render_logo();
oled_write_layer_state();
return false;
}

oled_rotation_t oled_init_kb(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);
}

char cpi[5];
char scroll_div[3];
char angle[4];
snprintf(cpi, 5, "%4d", cpi_array[cocot_config.cpi_idx]);
snprintf(scroll_div, 3, "%2d", scrl_div_array[cocot_config.scrl_div]);
snprintf(angle, 4, "%3d", angle_array[cocot_config.rotation_angle]);
markstos marked this conversation as resolved.
Show resolved Hide resolved

oled_write_P(PSTR("/"), false);
oled_write(cpi, false);
oled_write_P(PSTR("/"), false);
oled_write(scroll_div, false);
oled_write_P(PSTR("/"), false);
oled_write(angle, false);
}

#endif

41 changes: 41 additions & 0 deletions keyboards/aki27/cocot46plus/cocot46plus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
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/>.
*/

#pragma once

#include "quantum.h"

typedef union {
uint32_t raw;
struct {
uint8_t cpi_idx;
uint8_t scrl_div;
uint8_t rotation_angle;
int8_t scrl_inv;
bool scrl_mode;
report_mouse_t last_mouse;
};
} cocot_config_t;

extern cocot_config_t cocot_config;


bool cocot_get_scroll_mode(void);
void cocot_set_scroll_mode(bool mode);

void render_logo(void);
void oled_write_layer_state(void);
33 changes: 33 additions & 0 deletions keyboards/aki27/cocot46plus/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
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/>.
*/

#pragma once

// These do not seem to have keyboard.json support yet.
#define ADNS5050_SCLK_PIN GP23
#define ADNS5050_SDIO_PIN GP8
#define ADNS5050_CS_PIN GP9

#define I2C1_SDA_PIN GP2
#define I2C1_SCL_PIN GP3

/* key matrix size */
#define MATRIX_ROWS 10
#define MATRIX_COLS 6

#define POINTING_DEVICE_ROTATION_180
#define OLED_FONT_H "keyboards/aki27/cocot46plus/glcdfont.c"
Loading