qmk_firmware

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

matrix.c (4709B)


      1 /*
      2   Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>
      3 
      4   This program is free software: you can redistribute it and/or modify
      5   it under the terms of the GNU General Public License as published by
      6   the Free Software Foundation, either version 2 of the License, or
      7   (at your option) any later version.
      8 
      9   This program is distributed in the hope that it will be useful,
     10   but WITHOUT ANY WARRANTY; without even the implied warranty of
     11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12   GNU General Public License for more details.
     13 
     14   You should have received a copy of the GNU General Public License
     15   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17 
     18 #include <stdint.h>
     19 #include <stdbool.h>
     20 #include <avr/io.h>
     21 #include <util/delay.h>
     22 #include "print.h"
     23 #include "debug.h"
     24 #include "util.h"
     25 #include "matrix.h"
     26 
     27 #ifndef DEBOUNCE
     28 #   define DEBOUNCE 5
     29 #endif
     30 static uint8_t debouncing = DEBOUNCE;
     31 
     32 static matrix_row_t matrix[MATRIX_ROWS];
     33 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
     34 
     35 static uint8_t read_rows(void);
     36 static void select_col(uint8_t col);
     37 
     38 __attribute__ ((weak))
     39 void matrix_init_kb(void) {
     40     matrix_init_user();
     41 }
     42 
     43 __attribute__ ((weak))
     44 void matrix_scan_kb(void) {
     45     matrix_scan_user();
     46 }
     47 
     48 __attribute__ ((weak))
     49 void matrix_init_user(void) {
     50 }
     51 
     52 __attribute__ ((weak))
     53 void matrix_scan_user(void) {
     54 }
     55 
     56 inline uint8_t matrix_rows(void) {
     57   return MATRIX_ROWS;
     58 }
     59 
     60 inline uint8_t matrix_cols(void) {
     61   return MATRIX_COLS;
     62 }
     63 
     64 /* Column pin configuration
     65  *
     66  * col: 0    1    2    3    4    5    6    7
     67  * pin: PC7  PD5  PD3  PD1  PC2  PD6  PD4  PD2
     68  *
     69  * Rrr pin configuration
     70  *
     71  * These rrrs uses one 74HC154 4 to 16 bit demultiplexer (low
     72  * active), together with 2 rrrs driven directly from the micro
     73  * controller, to control the 18 rrrs. The rrrs are driven from
     74  * pins B6,5,4,3,2,1,0.
     75  */
     76 void matrix_init(void) {
     77   DDRC  &= ~0b10000100;  // Row input pins
     78   DDRD  &= ~0b01111110;
     79   PORTC |=  0b10000100;
     80   PORTD |=  0b01111110;
     81 
     82   DDRB  |=  0b01111111;  // Column output pins
     83 
     84   for (uint8_t i=0; i < MATRIX_ROWS; i++)  {
     85     matrix[i] = 0;
     86     matrix_debouncing[i] = 0;
     87   }
     88   matrix_init_kb();
     89 }
     90 
     91 uint8_t matrix_scan(void) {
     92   for (uint8_t col = 0; col < MATRIX_COLS; col++) {
     93     select_col(col);
     94     _delay_us(3);
     95     uint8_t rows = read_rows();
     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         debouncing = DEBOUNCE;
    102       }
    103     }
    104   }
    105 
    106   if (debouncing) {
    107     if (--debouncing) {
    108       _delay_ms(1);
    109     }
    110     else {
    111       for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    112         matrix[i] = matrix_debouncing[i];
    113       }
    114     }
    115   }
    116   matrix_scan_kb();
    117   return 1;
    118 }
    119 
    120 inline bool matrix_is_on(uint8_t row, uint8_t col) {
    121   return (matrix[row] & ((matrix_row_t)1<<col));
    122 }
    123 
    124 inline matrix_row_t matrix_get_row(uint8_t row) {
    125   return matrix[row];
    126 }
    127 
    128 void matrix_print(void) {
    129   print("\nr/c 0123456789ABCDEF\n");
    130   for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    131     xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
    132   }
    133 }
    134 
    135 static uint8_t read_rows(void) {
    136   return
    137     (PINC&(1<<7) ? 0 : (1<<0)) |
    138     (PIND&(1<<5) ? 0 : (1<<1)) |
    139     (PIND&(1<<3) ? 0 : (1<<2)) |
    140     (PIND&(1<<1) ? 0 : (1<<3)) |
    141     (PINC&(1<<2) ? 0 : (1<<4)) |
    142     (PIND&(1<<2) ? 0 : (1<<5)) |
    143     (PIND&(1<<4) ? 0 : (1<<6)) |
    144     (PIND&(1<<6) ? 0 : (1<<7));
    145 }
    146 
    147 static void select_col(uint8_t col) {
    148   switch (col) {
    149   case  0: PORTB = (PORTB & ~0b01111111) | 0b01100100; break;
    150   case  1: PORTB = (PORTB & ~0b01111111) | 0b01101100; break;
    151   case  2: PORTB = (PORTB & ~0b01111111) | 0b01100010; break;
    152   case  3: PORTB = (PORTB & ~0b01111111) | 0b01111010; break;
    153   case  4: PORTB = (PORTB & ~0b01111111) | 0b01100110; break;
    154   case  5: PORTB = (PORTB & ~0b01111111) | 0b01110110; break;
    155   case  6: PORTB = (PORTB & ~0b01111111) | 0b01101110; break;
    156   case  7: PORTB = (PORTB & ~0b01111111) | 0b01111110; break;
    157   case  8: PORTB = (PORTB & ~0b01111111) | 0b01000001; break;
    158   case  9: PORTB = (PORTB & ~0b01111111) | 0b00100001; break;
    159   case 10: PORTB = (PORTB & ~0b01111111) | 0b01101010; break;
    160   case 11: PORTB = (PORTB & ~0b01111111) | 0b01110010; break;
    161   case 12: PORTB = (PORTB & ~0b01111111) | 0b01111100; break;
    162   case 13: PORTB = (PORTB & ~0b01111111) | 0b01110100; break;
    163   case 14: PORTB = (PORTB & ~0b01111111) | 0b01111000; break;
    164   case 15: PORTB = (PORTB & ~0b01111111) | 0b01110000; break;
    165   case 16: PORTB = (PORTB & ~0b01111111) | 0b01100000; break;
    166   case 17: PORTB = (PORTB & ~0b01111111) | 0b01101000; break;
    167   }
    168 }