qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

matrix.c (5039B)


      1 /*
      2   Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>
      3   Copyright 2016 Daniel Svensson <dsvensson@gmail.com>
      4 
      5   This program is free software: you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License as published by
      7   the Free Software Foundation, either version 2 of the License, or
      8   (at your option) any later version.
      9 
     10   This program is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public License
     16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 */
     18 
     19 #include <stdint.h>
     20 #include <stdbool.h>
     21 #include <avr/io.h>
     22 #include <util/delay.h>
     23 #include "wait.h"
     24 #include "print.h"
     25 #include "debug.h"
     26 #include "util.h"
     27 #include "matrix.h"
     28 #include "debounce.h"
     29 
     30 static matrix_row_t matrix[MATRIX_ROWS];
     31 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
     32 
     33 static matrix_row_t read_cols(void);
     34 static void         select_row(uint8_t col);
     35 
     36 // user-defined overridable functions
     37 
     38 __attribute__((weak)) void matrix_init_kb(void) {
     39     matrix_init_user();
     40 }
     41 
     42 __attribute__((weak)) void matrix_scan_kb(void) {
     43     matrix_scan_user();
     44 }
     45 
     46 __attribute__((weak)) void matrix_init_user(void) {}
     47 
     48 __attribute__((weak)) void matrix_scan_user(void) {}
     49 
     50 // helper functions
     51 
     52 inline uint8_t matrix_rows(void) {
     53     return MATRIX_ROWS;
     54 }
     55 
     56 inline uint8_t matrix_cols(void) {
     57     return MATRIX_COLS;
     58 }
     59 
     60 void matrix_init(void) {
     61     /* Column output pins */
     62     DDRD |= 0b01111011;
     63     /* Row input pins */
     64     DDRC &= ~0b10000000;
     65     DDRB &= ~0b01111111;
     66     PORTC |= 0b10000000;
     67     PORTB |= 0b01111111;
     68 
     69     for (uint8_t i = 0; i < matrix_rows(); i++) {
     70         matrix[i]            = 0;
     71         matrix_debouncing[i] = 0;
     72     }
     73 
     74     matrix_init_kb();
     75 }
     76 
     77 uint8_t matrix_scan(void) {
     78     bool changed = false;
     79     for (uint8_t col = 0; col < MATRIX_COLS; col++) {
     80         select_row(col);
     81         wait_us(30);
     82         matrix_row_t rows = read_cols();
     83         for (uint8_t row = 0; row < matrix_rows(); row++) {
     84             bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1 << col);
     85             bool curr_bit = rows & (1 << row);
     86             if ((changed |= prev_bit != curr_bit)) {
     87                 matrix_debouncing[row] ^= (matrix_row_t)1 << col;
     88             }
     89         }
     90     }
     91 
     92     debounce(matrix_debouncing, matrix, changed);
     93     matrix_scan_kb();
     94 
     95     return (uint8_t)changed;
     96 }
     97 
     98 inline matrix_row_t matrix_get_row(uint8_t row) {
     99     return matrix[row];
    100 }
    101 
    102 void matrix_print(void) {
    103     print("\nr/c 0123456789ABCDEF\n");
    104     for (uint8_t row = 0; row < matrix_rows(); row++) {
    105         print_hex8(row);
    106         print(": ");
    107         print_bin_reverse16(matrix_get_row(row));
    108         print("\n");
    109     }
    110 }
    111 
    112 static matrix_row_t read_cols(void) {
    113     return (PINB & (1 << 5) ? 0 : ((matrix_row_t)1 << 0)) | (PINC & (1 << 7) ? 0 : ((matrix_row_t)1 << 1)) | (PINB & (1 << 4) ? 0 : ((matrix_row_t)1 << 2)) | (PINB & (1 << 6) ? 0 : ((matrix_row_t)1 << 3)) | (PINB & (1 << 1) ? 0 : ((matrix_row_t)1 << 4)) | (PINB & (1 << 2) ? 0 : ((matrix_row_t)1 << 5)) | (PINB & (1 << 3) ? 0 : ((matrix_row_t)1 << 6)) | (PINB & (1 << 0) ? 0 : ((matrix_row_t)1 << 7));
    114 }
    115 
    116 static void select_row(uint8_t col) {
    117     switch (col) {
    118         case 0:
    119             PORTD = (PORTD & ~0b01111011) | 0b00011011;
    120             break;
    121         case 1:
    122             PORTD = (PORTD & ~0b01111011) | 0b01000011;
    123             break;
    124         case 2:
    125             PORTD = (PORTD & ~0b01111011) | 0b01100000;
    126             break;
    127         case 3:
    128             PORTD = (PORTD & ~0b01111011) | 0b01111001;
    129             break;
    130         case 4:
    131             PORTD = (PORTD & ~0b01111011) | 0b01100010;
    132             break;
    133         case 5:
    134             PORTD = (PORTD & ~0b01111011) | 0b01101010;
    135             break;
    136         case 6:
    137             PORTD = (PORTD & ~0b01111011) | 0b01110001;
    138             break;
    139         case 7:
    140             PORTD = (PORTD & ~0b01111011) | 0b01101001;
    141             break;
    142         case 8:
    143             PORTD = (PORTD & ~0b01111011) | 0b01100001;
    144             break;
    145         case 9:
    146             PORTD = (PORTD & ~0b01111011) | 0b01111000;
    147             break;
    148         case 10:
    149             PORTD = (PORTD & ~0b01111011) | 0b00100011;
    150             break;
    151         case 11:
    152             PORTD = (PORTD & ~0b01111011) | 0b00101011;
    153             break;
    154         case 12:
    155             PORTD = (PORTD & ~0b01111011) | 0b00110011;
    156             break;
    157         case 13:
    158             PORTD = (PORTD & ~0b01111011) | 0b01110000;
    159             break;
    160         case 14:
    161             PORTD = (PORTD & ~0b01111011) | 0b00010011;
    162             break;
    163         case 15:
    164             PORTD = (PORTD & ~0b01111011) | 0b01101000;
    165             break;
    166         case 16:
    167             PORTD = (PORTD & ~0b01111011) | 0b00001011;
    168             break;
    169         case 17:
    170             PORTD = (PORTD & ~0b01111011) | 0b00111011;
    171             break;
    172     }
    173 }