Compare commits

..

4 Commits

Author SHA1 Message Date
Mark 2d7b6544fc
Increased animation fps 2022-07-20 21:19:31 -07:00
Mark ad63cbabc6
Whitespace 2022-07-20 21:19:20 -07:00
Mark 7a2ac34a23
Added basic spellcheck code 2022-07-20 21:19:13 -07:00
Mark 12e65bf02b
Cleaned up README 2022-07-20 21:12:32 -07:00
8 changed files with 174 additions and 36 deletions

View File

@ -121,7 +121,7 @@
// limits in milliseconds how frequently an animation will update the LEDs.
// 16 (16ms) is equivalent to limiting to 60fps
// (increases keyboard responsiveness)
#define RGB_MATRIX_LED_FLUSH_LIMIT 26
#define RGB_MATRIX_LED_FLUSH_LIMIT 16
// turn off effects when suspended
#define RGB_DISABLE_WHEN_USB_SUSPENDED true

View File

@ -1,6 +1,8 @@
#include "keymap.h"
#include "layers/layers.h"
#include "spellcheck.h"
// Values that should not be saved to git.
// Create a `secrets.h` in the keymap directory.
//
@ -31,9 +33,6 @@ void matrix_scan_user(void) {
// unregister_code(KC_S);
// unregister_code(KC_LGUI);
//}
}
}
@ -42,6 +41,7 @@ void matrix_scan_user(void) {
// Return FALSE to halt key processing,
// Return TRUE to allow QMK to handle keypress.
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (!process_spellcheck(keycode, record)) { return false; }
// Handle macros
switch (keycode) {
@ -53,7 +53,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
case M_SHUTDOWN:
if (record->event.pressed) {
SEND_STRING(SS_LGUI(SS_TAP(X_P)) SS_DELAY(100) SS_TAP(X_Y) SS_DELAY(100) SS_TAP(X_ENTER));
SEND_STRING(SS_LGUI(SS_TAP(X_P)) SS_DELAY(100) SS_TAP(X_Y) SS_DELAY(100) SS_TAP(X_ENTER));
}
return false;

View File

@ -6,4 +6,5 @@ TAP_DANCE_ENABLE = yes
SRC += \
tapdance/wmlayout.c \
tapdance/tapdance.c \
layers/layers.c
layers/layers.c \
spellcheck.c

View File

@ -0,0 +1,110 @@
#include "spellcheck.h"
#include "rawhid.h"
uint8_t spellcheck_buffer[SPELLCHECK_BUFFER_MAX] = {0};
uint8_t spellcheck_buffer_size = 0;
bool process_spellcheck(uint16_t keycode, keyrecord_t* record) {
// Ignore key release; we only process key presses.
if (!record->event.pressed) { return true; }
#ifndef NO_ACTION_ONESHOT
const uint8_t mods = get_mods() | get_oneshot_mods();
#else
const uint8_t mods = get_mods();
#endif
// Disable autocorrection while a mod other than shift is active.
if ((mods & ~MOD_MASK_SHIFT) != 0) {
spellcheck_buffer_size = 0;
return true;
}
// The following switch cases address various kinds of keycodes. This logic is
// split over two switches rather than merged into one. The first switch may
// extract a basic keycode which is then further handled by the second switch,
// e.g. a layer-tap key with Caps Lock `LT(layer, KC_CAPS)`.
switch (keycode) {
#ifndef NO_ACTION_TAPPING
case QK_MOD_TAP ... QK_MOD_TAP_MAX: // Tap-hold keys.
#ifndef NO_ACTION_LAYER
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
#endif
// Ignore when tap-hold keys are held.
if (record->tap.count == 0) { return true; }
// Otherwise when tapped, get the basic keycode.
// Fallthrough intended.
#endif
// Handle shifted keys, e.g. symbols like KC_EXLM = S(KC_1).
case QK_LSFT ... QK_LSFT + 255:
case QK_RSFT ... QK_RSFT + 255:
keycode &= 0xff; // Get the basic keycode.
break;
// NOTE: Space Cadet keys expose no info to check whether they are being
// tapped vs. held. This makes autocorrection ambiguous, e.g. KC_LCPO might
// be '(', which we would treat as a word break, or it might be shift, which
// we would treat as having no effect. To behave cautiously, we allow Space
// Cadet keycodes to fall to the logic below and clear autocorrection state.
}
switch (keycode) {
// Ignore shifts, Caps Lock, one-shot mods, and layer switch keys.
case KC_NO:
case KC_LSFT:
case KC_RSFT:
case KC_CAPS:
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
case QK_TO ... QK_TO_MAX:
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
return true; // Ignore these keys.
}
if (keycode == KC_QUOT) {
// Treat " (shifted ') as a word boundary.
if ((mods & MOD_MASK_SHIFT) != 0) { keycode = KC_SPC; }
} else if (!(KC_A <= keycode && keycode <= KC_Z)) {
if (keycode == KC_BSPC) {
// Remove last character from the buffer.
if (spellcheck_buffer_size > 0) { --spellcheck_buffer_size; }
return true;
} else if (KC_1 <= keycode && keycode <= KC_SLSH && keycode != KC_ESC) {
// Set a word boundary if space, period, digit, etc. is pressed.
// Behave more conservatively for the enter key. Reset, so that enter
// can't be used on a word ending.
if (keycode == KC_ENT) { spellcheck_buffer_size = 0; }
keycode = KC_SPC;
} else {
// Clear state if some other non-alpha key is pressed.
spellcheck_buffer_size = 0;
return true;
}
}
// If the buffer is full, rotate it to discard the oldest character.
if (spellcheck_buffer_size >= SPELLCHECK_BUFFER_MAX) {
memmove(spellcheck_buffer, spellcheck_buffer + 1, SPELLCHECK_BUFFER_MAX - 1);
spellcheck_buffer_size = SPELLCHECK_BUFFER_MAX - 1;
}
// NOTE: `keycode` must be a basic keycode (0-255) by this point.
// A to Z keycodes
if (keycode >= 0x04 && keycode <= 0x1D) {
spellcheck_buffer[spellcheck_buffer_size++] = (uint8_t) keycode;
} else if (spellcheck_buffer_size > 0) {
hid_send_word();
spellcheck_buffer_size = 0;
}
return true;
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "quantum.h"
// spellcheck_buffer holds keycode history.
// It can only contain values 0x00 - 0xFF, aka standard usb hid codes.
// Host software is responsible for turning this into a usable string.
//
// Note that SOME preprocessing is done,see spellcheck.c
#define SPELLCHECK_BUFFER_MAX 16
uint8_t spellcheck_buffer[SPELLCHECK_BUFFER_MAX];
uint8_t spellcheck_buffer_size;
bool process_spellcheck(uint16_t keycode, keyrecord_t* record);

View File

@ -1,6 +1,8 @@
#include "rawhid.h"
#include "extra_mappings.h"
#include "spellcheck.h"
// See rawhid.h for prococol documentation
void raw_hid_receive(uint8_t *data, uint8_t length) {
uint8_t cmd = data[0];
@ -20,6 +22,14 @@ void raw_hid_receive(uint8_t *data, uint8_t length) {
break;
#endif
case CMD_SPELLCHECK_WORD:
if (data[1]) {
ergodox_right_led_1_on();
_delay_ms(50);
ergodox_right_led_1_off();
}
break;
default:
break;
}
@ -61,6 +71,20 @@ void hid_send_state() {
}
void hid_send_word() {
uint8_t packet[RAW_EPSIZE] = {
CMD_SPELLCHECK_WORD,
spellcheck_buffer_size
};
for (int i = 0; i < 2 + spellcheck_buffer_size; i++) {
packet[i + 2] = spellcheck_buffer[i];
}
raw_hid_send(packet, RAW_EPSIZE);
}
#ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS

View File

@ -5,6 +5,7 @@
void raw_hid_receive(uint8_t *data, uint8_t length);
void hid_send_state(void);
void hid_send_word(void);
void cmd_animation(uint8_t *data, uint8_t length);
@ -43,6 +44,23 @@ extern uint8_t g_rgb_frame_buffer[MATRIX_ROWS][MATRIX_COLS];
// 0x02: FFT Animation
#define CMD_SEND_STATE 0x02
// Sent by keyboard to host when a complete word is typed.
// Host checks if this is a known word.
// If it is not, host responds with the same CMD (see below).
//
// Packet structure (sent by keyboard):
// Data: | cmd | word length | keycodes |
// # of Bytes: | 1 | 1 | ? |
//
// word length: number of bytes in `keycodes` block
//
//
// Packet structure (sent by host):
// Data: | cmd | typo? |
// # of Bytes: | 1 | 1 |
//
// typo: If this is 0x01, the word we got was a typo.
#define CMD_SPELLCHECK_WORD 0x04
// Animation data. Sent by host.
//

View File

@ -45,33 +45,3 @@ LIGHT_SPI, // Increase backlight speed
LIGHT_SPD, // Decrease backlight speed
LIGHT_MOD, // Change backlight animation mode
```
--------------------------------------------------------------------------------
# Notes from ZSA
### Indicator LEDs
You can use the `LED_LEVEL` keycode to cycle through the brightness levels for the LEDs on the top right of the keyboard. These settings are saved in eeprom (persistant memory).
Alternatively, you can set the brightness by calling the following functions:
```c
void ergodox_led_all_set(uint8_t level);
void ergodox_right_led_1_set(uint8_t level);
void ergodox_right_led_2_set(uint8_t level);
void ergodox_right_led_3_set(uint8_t level);
```
These settings are not persistent, so you'd need to reset it every time the board starts.
These are on a 0-255 scale
### RGB Matrix Features
If you're using the Smart LED (layer indication) feature from the Oryx Configurator, you want to make sure that you enable these options by adding `#define ORYX_CONFIGURATOR` to your keymap's `config.h`.
This changes the `RGB_TOG` keycode so that it will toggle the lights on and off, in a way that will allow the Smart LEDs to continue to work, even with the rest of the LEDs turned off.
Additionally, a new keycode has been added to toggle the Smart LEDs. Use `TOGGLE_LAYER_COLOR`, if you aren't already.