qmk_firmware

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

matrix.c (6222B)


      1 /*
      2 Copyright 2016 Ralf Schmitt <ralf@bunkertor.net>
      3 This program is free software: you can redistribute it and/or modify
      4 it under the terms of the GNU General Public License as published by
      5 the Free Software Foundation, either version 2 of the License, or
      6 (at your option) any later version.
      7 This program is distributed in the hope that it will be useful,
      8 but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 GNU General Public License for more details.
     11 You should have received a copy of the GNU General Public License
     12 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     13 */
     14 
     15 #include <stdint.h>
     16 #include <stdbool.h>
     17 #include <avr/io.h>
     18 #include <util/delay.h>
     19 #include "print.h"
     20 #include "debug.h"
     21 #include "util.h"
     22 #include "matrix.h"
     23 
     24 #ifndef DEBOUNCE
     25 #    define DEBOUNCE 5
     26 #endif
     27 
     28 static uint8_t debouncing = DEBOUNCE;
     29 
     30 /* matrix state(1:on, 0:off) */
     31 static matrix_row_t matrix[MATRIX_ROWS];
     32 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
     33 
     34 static uint8_t read_rows(uint8_t col);
     35 static void init_ports(void);
     36 static void unselect_cols(void);
     37 static void select_col(uint8_t col);
     38 
     39 __attribute__ ((weak))
     40 void matrix_init_kb(void) {
     41     matrix_init_user();
     42 }
     43 
     44 __attribute__ ((weak))
     45 void matrix_scan_kb(void) {
     46     matrix_scan_user();
     47 }
     48 
     49 __attribute__ ((weak))
     50 void matrix_init_user(void) {
     51 }
     52 
     53 __attribute__ ((weak))
     54 void matrix_scan_user(void) {
     55 }
     56 
     57 inline
     58 uint8_t matrix_rows(void)
     59 {
     60     return MATRIX_ROWS;
     61 }
     62 
     63 inline
     64 uint8_t matrix_cols(void)
     65 {
     66     return MATRIX_COLS;
     67 }
     68 
     69 void backlight_init_ports(void)
     70 {
     71   DDRD  |=  0b01010000;
     72   PORTD &=  0b10101111;
     73   DDRB  |=  0b00001110;
     74   PORTB &=  0b11110001;
     75   DDRE  |=  0b01000000;
     76   PORTE &=  0b10111111;
     77 }
     78 
     79 void matrix_init(void)
     80 {
     81     backlight_init_ports();
     82     unselect_cols();
     83     init_ports();
     84     for (uint8_t i=0; i < MATRIX_ROWS; i++)  {
     85         matrix[i] = 0;
     86         matrix_debouncing[i] = 0;
     87     }
     88 }
     89 
     90 uint8_t matrix_scan(void)
     91 {
     92     for (uint8_t col = 0; col < MATRIX_COLS; col++) {
     93         select_col(col);
     94         _delay_us(3);
     95         uint8_t rows = read_rows(col);
     96         for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
     97             bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
     98             bool curr_bit = rows & (1<<row);
     99             if (prev_bit != curr_bit) {
    100                 matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
    101                 if (debouncing) {
    102                     dprint("bounce!: "); dprintf("%02X", debouncing); dprintln();
    103                 }
    104                 debouncing = DEBOUNCE;
    105             }
    106         }
    107         unselect_cols();
    108     }
    109 
    110     if (debouncing) {
    111         if (--debouncing) {
    112             _delay_ms(1);
    113         } else {
    114             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    115                 matrix[i] = matrix_debouncing[i];
    116             }
    117         }
    118     }
    119 
    120     return 1;
    121 }
    122 
    123 inline
    124 bool matrix_is_on(uint8_t row, uint8_t col)
    125 {
    126     return (matrix[row] & ((matrix_row_t)1<<col));
    127 }
    128 
    129 inline
    130 matrix_row_t matrix_get_row(uint8_t row)
    131 {
    132     return matrix[row];
    133 }
    134 
    135 void matrix_print(void)
    136 {
    137     print("\nr/c 0123456789ABCDEF\n");
    138     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    139         xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
    140     }
    141 }
    142 
    143 static void init_ports(void)
    144 {
    145     // Rows are inputs (inputs are 0)
    146     DDRD  &= 0b11010000;
    147     DDRB  &= 0b01111111;
    148     DDRE  &= 0b11111011;
    149 
    150     // Columns are outputs (outputs are high)
    151     DDRF  |= 0b00000011;
    152     DDRC  |= 0b11000000;
    153     DDRB  |= 0b01110001;
    154     DDRD  |= 0b10000000;
    155 }
    156 
    157 static uint8_t read_rows(uint8_t col)
    158 {
    159   if(col == 15) {
    160     return (PINE&(1<<2) ? 0 : (1<<0)) |
    161            (PIND&(1<<0) ? (1<<1) : 0) |
    162            (PIND&(1<<1) ? (1<<2) : 0) |
    163            (PIND&(1<<2) ? (1<<3) : 0) |
    164            (PIND&(1<<3) ? (1<<4) : 0) |
    165            (PIND&(1<<5) ? (1<<5) : 0);
    166 
    167   } else {
    168     return (PINB&(1<<7) ? (1<<0) : 0) |
    169            (PIND&(1<<0) ? (1<<1) : 0) |
    170            (PIND&(1<<1) ? (1<<2) : 0) |
    171            (PIND&(1<<2) ? (1<<3) : 0) |
    172            (PIND&(1<<3) ? (1<<4) : 0) |
    173            (PIND&(1<<5) ? (1<<5) : 0);
    174 
    175   }
    176 }
    177 
    178 static void unselect_cols(void)
    179 {
    180     PORTF &= 0b11111100;
    181     PORTC &= 0b00111111;
    182     PORTB &= 0b10001110;
    183     PORTD &= 0b01111111;
    184 }
    185 
    186 static void select_col(uint8_t col)
    187 {
    188     switch (col) {
    189         case 0:
    190             PORTC |= 0b01000000;
    191             break;
    192         case 1:
    193             PORTC |= 0b01000000;
    194             PORTF |= 0b00000001;
    195             break;
    196         case 2:
    197             PORTC |= 0b01000000;
    198             PORTF |= 0b00000010;
    199             break;
    200         case 3:
    201             PORTC |= 0b01000000;
    202             PORTF |= 0b00000011;
    203             break;
    204         case 4:
    205             PORTC |= 0b11000000;
    206             break;
    207         case 5:
    208             PORTC |= 0b11000000;
    209             PORTF |= 0b00000001;
    210             break;
    211         case 6:
    212             PORTC |= 0b11000000;
    213             PORTF |= 0b00000010;
    214             break;
    215         case 7:
    216             PORTC |= 0b11000000;
    217             PORTF |= 0b00000011;
    218             break;
    219         case 8:
    220             PORTB |= 0b01000000;
    221             break;
    222         case 9:
    223             PORTB |= 0b01000000;
    224             PORTF |= 0b00000001;
    225             break;
    226         case 10:
    227             PORTB |= 0b01000000;
    228             PORTF |= 0b00000010;
    229             break;
    230         case 11:
    231             PORTB |= 0b01000000;
    232             PORTF |= 0b00000011;
    233             break;
    234         case 12:
    235             PORTB |= 0b01000000;
    236             PORTC |= 0b10000000;
    237             break;
    238         case 13:
    239             PORTB |= 0b01000000;
    240             PORTF |= 0b00000001;
    241             PORTC |= 0b10000000;
    242             break;
    243         case 14:
    244             PORTB |= 0b01000000;
    245             PORTF |= 0b00000010;
    246             PORTC |= 0b10000000;
    247             break;
    248         case 15:
    249             PORTB |= 0b01000000;
    250             PORTF |= 0b00000011;
    251             PORTC |= 0b10000000;
    252             break;
    253         case 16:
    254             PORTB |= 0b00100000;
    255             break;
    256         case 17:
    257             PORTB |= 0b00010000;
    258             break;
    259         case 18:
    260             PORTD |= 0b10000000;
    261             break;
    262         case 19:
    263             PORTB |= 0b00000001;
    264             break;
    265     }
    266 }