~ruther/qmk_firmware

b72a1aa3fec986bfa7e439b68d6b7546ab1e280b — Dustin L. Howett 5 years ago 78069d4
Rewrite the Bathroom Epiphanies Frosty Flake matrix and LED handling (#8243)

* Keyboard: revamp frosty-flake leds

This commit transitions bpiphany/frosty_flake to led_update_{kb,user}
and rewrites the AVR bit twiddling logic to use the standard QMK GPIO
API.

* Keyboard: rewrite frosty_flake's matrix reader to be a lite custom matrix

This commit replaces frosty_flake's custom matrix and debounce logic
with a "lite" custom matrix. In addition to being somewhat clearer, this
allows a consumer of the flake board to choose their own debouncing
algorithm. The one closest to the implementation originally in use is
sym_g, but this opens us up to supporting eager_pk and eager_pr.

The original matrix code was 18 columns for 8 rows, but using a single
row read and unpacking the bits into individual columns. To simplify,
I've changed the key layout to be 8C 18R instead of 18C 8R: this lets us
use a single read directly into the matrix _and_ drop down to a uint8_t
instead of a uint32_t for matrix_row_t.

Since we're no longer implementing our own debouncing and row unpacking,
we save ~400 bytes on the final firmware image.

Fully tested against a CM Storm QFR hosting the flake -- this commit
message was written using the new matrix code.

Firmware Sizes (assuming stock configuration as of 42d6270f2)

Matrix+Debounce     Size (bytes)
---------------     ------------
original            17740
new + sym_g         17284
new + eager_pr      18106
new + eager_pk      18204

I expect that there are some scanning speed benefits as well.

* Keyboard: update frosty_flake's UNUSED_PINS

* Keyboard: Remove meaningless weak redefinitions from frosty

These are not necessary (and all of them already live somewhere in
Quantum).
M keyboards/bpiphany/frosty_flake/config.h => keyboards/bpiphany/frosty_flake/config.h +3 -3
@@ 36,13 36,13 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* key matrix size */
#define MATRIX_ROWS 8   // Row0 - Row7 in the schematic
#define MATRIX_COLS 18  // ColA - ColR in the schematic
#define MATRIX_ROWS 18 // ColA - ColR in the schematic
#define MATRIX_COLS 8  // Row0 - Row7 in the schematic

/*
 * Keyboard Matrix Assignments
 */
#define UNUSED_PINS { B0, C4, D3 }
#define UNUSED_PINS { C0, C1, C2, C3, C4, D2, D7 }

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

M keyboards/bpiphany/frosty_flake/frosty_flake.c => keyboards/bpiphany/frosty_flake/frosty_flake.c +17 -56
@@ 1,63 1,24 @@
#include "frosty_flake.h"

void matrix_init_kb(void) {
    // put your keyboard start-up code here
    // runs once when the firmware starts up

    matrix_init_user();
void keyboard_pre_init_kb() {
    setPinOutput(B7); // num lock
    writePinHigh(B7);
    setPinOutput(C5); // caps lock
    writePinHigh(C7);
    setPinOutput(C6); // scroll lock
    writePinHigh(C6);

    keyboard_pre_init_user();
}

void matrix_scan_kb(void) {
    // put your looping keyboard code here
    // runs every cycle (a lot)

    matrix_scan_user();
}
bool led_update_kb(led_t usb_led) {
    // user requests no further processing
    if (!led_update_user(usb_led))
        return true;

bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
    // put your per-action keyboard code here
    // runs for every action, just before processing by the firmware
    writePin(C5, !usb_led.caps_lock);
    writePin(B7, !usb_led.num_lock);
    writePin(C6, !usb_led.scroll_lock);

    return process_record_user(keycode, record);
    return true;
}

void led_set_kb(uint8_t usb_led) {
    DDRB |= (1<<7);
    DDRC |= (1<<5) | (1<<6);

    print_dec(usb_led);

    if (usb_led & (1<<USB_LED_CAPS_LOCK))
        PORTC &= ~(1<<5);
    else
        PORTC |=  (1<<5);

    if (usb_led & (1<<USB_LED_NUM_LOCK))
        PORTB &= ~(1<<7);
    else
        PORTB |=  (1<<7);

    if (usb_led & (1<<USB_LED_SCROLL_LOCK))
        PORTC &= ~(1<<6);
    else
        PORTC |=  (1<<6);

    led_set_user(usb_led);
}

__attribute__ ((weak))
void matrix_init_user(void) {
}

__attribute__ ((weak))
void matrix_scan_user(void) {
}

__attribute__ ((weak))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  return true;
}

__attribute__ ((weak))
void led_set_user(uint8_t usb_led) {
}
\ No newline at end of file

M keyboards/bpiphany/frosty_flake/frosty_flake.h => keyboards/bpiphany/frosty_flake/frosty_flake.h +38 -20
@@ 34,16 34,25 @@
  KA4, KP2, KC6,                KK6,                KC0, KM3, KD0, KA1,   KO0, KK0, KL0,   KL6,      KQ6       \
) \
{ \
/* Columns and rows need to be swapped in the below definition */ \
/*          A       B       C       D       E       F       G       H       I       J       K       L       M       N       O       P       Q       R       */ \
/* 0 */ {   KC_NO,  KB0,    KC0,    KD0,    KC_NO,  KF0,    KG0,    KC_NO,  KC_NO,  KC_NO,  KK0,    KL0,    KC_NO,  KC_NO,  KO0,    KC_NO,  KQ0,    KR0     }, \
/* 1 */ {   KA1,    KB1,    KC_NO,  KD1,    KE1,    KF1,    KG1,    KH1,    KI1,    KJ1,    KK1,    KL1,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KQ1,    KC_NO   }, \
/* 2 */ {   KC_NO,  KB2,    KC_NO,  KD2,    KE2,    KF2,    KG2,    KH2,    KI2,    KJ2,    KK2,    KL2,    KC_NO,  KN2,    KC_NO,  KP2,    KQ2,    KR2     }, \
/* 3 */ {   KC_NO,  KB3,    KC_NO,  KD3,    KE3,    KF3,    KG3,    KH3,    KI3,    KJ3,    KK3,    KL3,    KM3,    KN3,    KO3,    KC_NO,  KQ3,    KR3     }, \
/* 4 */ {   KA4,    KB4,    KC_NO,  KD4,    KE4,    KF4,    KG4,    KH4,    KI4,    KJ4,    KK4,    KL4,    KC_NO,  KC_NO,  KO4,    KC_NO,  KQ4,    KR4     }, \
/* 5 */ {   KA5,    KC_NO,  KC5,    KD5,    KE5,    KF5,    KG5,    KH5,    KI5,    KJ5,    KK5,    KL5,    KC_NO,  KC_NO,  KO5,    KC_NO,  KQ5,    KR5     }, \
/* 6 */ {   KC_NO,  KB6,    KC6,    KC_NO,  KE6,    KF6,    KG6,    KH6,    KI6,    KJ6,    KK6,    KL6,    KC_NO,  KC_NO,  KO6,    KC_NO,  KQ6,    KR6     }, \
/* 7 */ {   KA7,    KB7,    KC7,    KD7,    KE7,    KF7,    KG7,    KH7,    KI7,    KJ7,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KO7,    KC_NO,  KQ7,    KR7     }  \
/*        0        1        2        3        4        5        6        7        */ \
/* A */ { KC_NO,   KA1,     KC_NO,   KC_NO,   KA4,     KA5,     KC_NO,   KA7,     }, \
/* B */ { KB0,     KB1,     KB2,     KB3,     KB4,     KC_NO,   KB6,     KB7,     }, \
/* C */ { KC0,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC5,     KC6,     KC7,     }, \
/* D */ { KD0,     KD1,     KD2,     KD3,     KD4,     KD5,     KC_NO,   KD7,     }, \
/* E */ { KC_NO,   KE1,     KE2,     KE3,     KE4,     KE5,     KE6,     KE7,     }, \
/* F */ { KF0,     KF1,     KF2,     KF3,     KF4,     KF5,     KF6,     KF7,     }, \
/* G */ { KG0,     KG1,     KG2,     KG3,     KG4,     KG5,     KG6,     KG7,     }, \
/* H */ { KC_NO,   KH1,     KH2,     KH3,     KH4,     KH5,     KH6,     KH7,     }, \
/* I */ { KC_NO,   KI1,     KI2,     KI3,     KI4,     KI5,     KI6,     KI7,     }, \
/* J */ { KC_NO,   KJ1,     KJ2,     KJ3,     KJ4,     KJ5,     KJ6,     KJ7,     }, \
/* K */ { KK0,     KK1,     KK2,     KK3,     KK4,     KK5,     KK6,     KC_NO,   }, \
/* L */ { KL0,     KL1,     KL2,     KL3,     KL4,     KL5,     KL6,     KC_NO,   }, \
/* M */ { KC_NO,   KC_NO,   KC_NO,   KM3,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* N */ { KC_NO,   KC_NO,   KN2,     KN3,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* O */ { KO0,     KC_NO,   KC_NO,   KO3,     KO4,     KO5,     KO6,     KO7,     }, \
/* P */ { KC_NO,   KC_NO,   KP2,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* Q */ { KQ0,     KQ1,     KQ2,     KQ3,     KQ4,     KQ5,     KQ6,     KQ7,     }, \
/* R */ { KR0,     KC_NO,   KR2,     KR3,     KR4,     KR5,     KR6,     KR7,     }, \
}

/*


@@ 74,16 83,25 @@
  KA4, KP2, KC6,                KK6,                KC0, KM3, KD0, KA1,   KO0, KK0, KL0  \
) \
{ \
/* Columns and rows need to be swapped in the below definition */ \
/*          A       B       C       D       E       F       G       H       I       J       K       L       M       N       O       P       Q       R       */ \
/* 0 */ {   KC_NO,  KB0,    KC0,    KD0,    KC_NO,  KF0,    KG0,    KC_NO,  KC_NO,  KC_NO,  KK0,    KL0,    KC_NO,  KC_NO,  KO0,    KC_NO,  KC_NO,  KR0     }, \
/* 1 */ {   KA1,    KB1,    KC_NO,  KD1,    KE1,    KF1,    KG1,    KH1,    KI1,    KJ1,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO   }, \
/* 2 */ {   KC_NO,  KB2,    KC_NO,  KD2,    KE2,    KF2,    KG2,    KH2,    KI2,    KJ2,    KC_NO,  KC_NO,  KC_NO,  KN2,    KC_NO,  KP2,    KC_NO,  KR2     }, \
/* 3 */ {   KC_NO,  KB3,    KC_NO,  KD3,    KE3,    KF3,    KG3,    KH3,    KI3,    KJ3,    KC_NO,  KC_NO,  KM3,    KN3,    KC_NO,  KC_NO,  KC_NO,  KR3     }, \
/* 4 */ {   KA4,    KB4,    KC_NO,  KD4,    KE4,    KF4,    KG4,    KH4,    KI4,    KJ4,    KK4,    KL4,    KC_NO,  KC_NO,  KO4,    KC_NO,  KQ4,    KR4     }, \
/* 5 */ {   KA5,    KC_NO,  KC5,    KD5,    KE5,    KF5,    KG5,    KH5,    KI5,    KJ5,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KR5     }, \
/* 6 */ {   KC_NO,  KB6,    KC6,    KC_NO,  KE6,    KF6,    KG6,    KH6,    KI6,    KJ6,    KK6,    KC_NO,  KC_NO,  KC_NO,  KO6,    KC_NO,  KC_NO,  KR6     }, \
/* 7 */ {   KA7,    KB7,    KC7,    KD7,    KE7,    KF7,    KG7,    KH7,    KI7,    KJ7,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KO7,    KC_NO,  KQ7,    KR7     }  \
/*        0        1        2        3        4        5        6        7        */ \
/* A */ { KC_NO,   KA1,     KC_NO,   KC_NO,   KA4,     KA5,     KC_NO,   KA7,     }, \
/* B */ { KB0,     KB1,     KB2,     KB3,     KB4,     KC_NO,   KB6,     KB7,     }, \
/* C */ { KC0,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC5,     KC6,     KC7,     }, \
/* D */ { KD0,     KD1,     KD2,     KD3,     KD4,     KD5,     KC_NO,   KD7,     }, \
/* E */ { KC_NO,   KE1,     KE2,     KE3,     KE4,     KE5,     KE6,     KE7,     }, \
/* F */ { KF0,     KF1,     KF2,     KF3,     KF4,     KF5,     KF6,     KF7,     }, \
/* G */ { KG0,     KG1,     KG2,     KG3,     KG4,     KG5,     KG6,     KG7,     }, \
/* H */ { KC_NO,   KH1,     KH2,     KH3,     KH4,     KH5,     KH6,     KH7,     }, \
/* I */ { KC_NO,   KI1,     KI2,     KI3,     KI4,     KI5,     KI6,     KI7,     }, \
/* J */ { KC_NO,   KJ1,     KJ2,     KJ3,     KJ4,     KJ5,     KJ6,     KJ7,     }, \
/* K */ { KK0,     KC_NO,   KC_NO,   KC_NO,   KK4,     KC_NO,   KK6,     KC_NO,   }, \
/* L */ { KL0,     KC_NO,   KC_NO,   KC_NO,   KL4,     KC_NO,   KC_NO,   KC_NO,   }, \
/* M */ { KC_NO,   KC_NO,   KC_NO,   KM3,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* N */ { KC_NO,   KC_NO,   KN2,     KN3,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* O */ { KO0,     KC_NO,   KC_NO,   KC_NO,   KO4,     KC_NO,   KO6,     KO7,     }, \
/* P */ { KC_NO,   KC_NO,   KP2,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* Q */ { KC_NO,   KC_NO,   KC_NO,   KC_NO,   KQ4,     KC_NO,   KC_NO,   KQ7,     }, \
/* R */ { KR0,     KC_NO,   KR2,     KR3,     KR4,     KR5,     KR6,     KR7,     }, \
}

#define LAYOUT_tkl_ansi( \

M keyboards/bpiphany/frosty_flake/matrix.c => keyboards/bpiphany/frosty_flake/matrix.c +18 -88
@@ 15,42 15,15 @@
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"

#ifndef DEBOUNCE
#   define DEBOUNCE 5
#endif
static uint8_t debouncing = DEBOUNCE;

static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];

__attribute__ ((weak))
void matrix_init_kb(void) {
    matrix_init_user();
}

__attribute__ ((weak))
void matrix_scan_kb(void) {
    matrix_scan_user();
}

__attribute__ ((weak))
void matrix_init_user(void) {
}

__attribute__ ((weak))
void matrix_scan_user(void) {
}

static matrix_row_t scan_col(void) {
    // Each of the 8 columns is read off pins as below
    //   7  6  5  4  3  2  1  0
    // ,--,--,--,--,--,--,--,--,
    // |B0|B3|B2|B1|B6|B4|B5|C7|
    // `--`--`--`--`--`--`--`--`
    return (
        (PINC&(1<<7) ? 0 : ((matrix_row_t)1<<0)) |
        (PINB&(1<<5) ? 0 : ((matrix_row_t)1<<1)) |


@@ 63,8 36,8 @@ static matrix_row_t scan_col(void) {
    );
}

static void select_col(uint8_t col) {
    switch (col) {
static void select_row(uint8_t row) {
    switch (row) {
        case  0: PORTD = (PORTD & ~0b01111011) | 0b00011011; break;
        case  1: PORTD = (PORTD & ~0b01111011) | 0b01000011; break;
        case  2: PORTD = (PORTD & ~0b01111011) | 0b01101010; break;


@@ 86,7 59,7 @@ static void select_col(uint8_t col) {
    }
}

void matrix_init(void) {
void matrix_init_custom(void) {
    /* Row output pins */
    DDRD  |=  0b01111011;
    /* Column input pins */


@@ 94,62 67,19 @@ void matrix_init(void) {
    DDRB  &= ~0b01111111;
    PORTC |=  0b10000000;
    PORTB |=  0b01111111;

    for (uint8_t i=0; i < MATRIX_ROWS; i++)
        matrix[i] = matrix_debouncing[i] = 0;

    matrix_init_quantum();
}

uint8_t matrix_scan(void) {
    for (uint8_t col = 0; col < MATRIX_COLS; col++) {
        select_col(col);
        _delay_us(3);
        matrix_row_t col_scan = scan_col();
        for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
            bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
            bool curr_bit = col_scan & (1<<row);
            if (prev_bit != curr_bit) {
                matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
                debouncing = DEBOUNCE;
            }
        }
    }

    if (debouncing) {
        if (--debouncing)
            _delay_ms(1);
        else
            for (uint8_t i = 0; i < MATRIX_ROWS; i++)
                matrix[i] = matrix_debouncing[i];
    }

    matrix_scan_quantum();
    return 1;
}

inline matrix_row_t matrix_get_row(uint8_t row) {
    return matrix[row];
}

void matrix_print(void) {
#ifndef NO_PRINT
    print("\nr\\c ABCDEFGHIJKLMNOPQR\n");
// matrix is 18 uint8_t.
// we select the row (one of 18), then read the column
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
	bool has_changed = false;
    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
        matrix_row_t matrix_row = matrix_get_row(row);
        xprintf("%02X: ", row);
        for (uint8_t col = 0; col < MATRIX_COLS; col++) {
            bool curr_bit = matrix_row & (1<<col);
            xprintf("%c", curr_bit ? '*' : '.');
        }
        print("\n");
        matrix_row_t orig = current_matrix[row];
        select_row(row);
        _delay_us(3);
        current_matrix[row] = scan_col();
        has_changed |= (orig != current_matrix[row]);
    }
#endif
}

uint8_t matrix_key_count(void) {
    uint8_t count = 0;
    for (uint8_t row = 0; row < MATRIX_ROWS; row++)
        count += bitpop32(matrix[row]);
    return count;
    return has_changed;
}

M keyboards/bpiphany/frosty_flake/rules.mk => keyboards/bpiphany/frosty_flake/rules.mk +1 -1
@@ 30,7 30,7 @@ BLUETOOTH_ENABLE = no       # Enable Bluetooth with the Adafruit EZ-Key HID
AUDIO_ENABLE = no           # Audio output on port C6
FAUXCLICKY_ENABLE = no      # Use buzzer to emulate clicky switches

CUSTOM_MATRIX = yes
CUSTOM_MATRIX = lite
SRC += matrix.c

LAYOUTS = tkl_ansi