qmk_firmware

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

matrix.c (6353B)


      1 /*
      2 Copyright 2012 Jun Wako <wakojun@gmail.com>
      3 Copyright 2017 Cole Markham <cole@ccmcomputing.net>
      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 /*
     20  * scan matrix
     21  */
     22 #include "matrix.h"
     23 #include "meira.h"
     24 #include "wait.h"
     25 #include "print.h"
     26 #include "debug.h"
     27 #include "timer.h"
     28 
     29 #ifndef DEBOUNCE
     30 #   define DEBOUNCE 5
     31 #endif
     32 
     33 #if (DEBOUNCE > 0)
     34     static uint16_t debouncing_time;
     35     static bool debouncing = false;
     36 #endif
     37 
     38 #if (MATRIX_COLS <= 8)
     39 #    define print_matrix_header()  print("\nr/c 01234567\n")
     40 #    define print_matrix_row(row)  print_bin_reverse8(matrix_get_row(row))
     41 #    define ROW_SHIFTER ((uint8_t)1)
     42 #elif (MATRIX_COLS <= 16)
     43 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF\n")
     44 #    define print_matrix_row(row)  print_bin_reverse16(matrix_get_row(row))
     45 #    define ROW_SHIFTER ((uint16_t)1)
     46 #elif (MATRIX_COLS <= 32)
     47 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
     48 #    define print_matrix_row(row)  print_bin_reverse32(matrix_get_row(row))
     49 #    define ROW_SHIFTER  ((uint32_t)1)
     50 #endif
     51 
     52 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
     53 
     54 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     55 static const uint8_t col_pins[4] = MATRIX_COL_PINS_SCANNED;
     56 //static const uint8_t lrow_pins[MATRIX_ROWS] = LED_ROW_PINS;
     57 //static const uint8_t lcol_pins[4] = LED_COL_PINS;
     58 
     59 /* matrix state(1:on, 0:off) */
     60 static matrix_row_t matrix[MATRIX_ROWS];
     61 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
     62 static void init_rows(void);
     63 //static void init_lcols(void);
     64 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
     65 static void unselect_cols(void);
     66 static void select_col(uint8_t col);
     67 
     68 
     69 __attribute__ ((weak))
     70 void matrix_init_kb(void) {
     71     matrix_init_user();
     72 }
     73 
     74 __attribute__ ((weak))
     75 void matrix_scan_kb(void) {
     76     matrix_scan_user();
     77 }
     78 
     79 __attribute__ ((weak))
     80 void matrix_init_user(void) {
     81 }
     82 
     83 __attribute__ ((weak))
     84 void matrix_scan_user(void) {
     85 }
     86 
     87 inline
     88 uint8_t matrix_rows(void)
     89 {
     90     return MATRIX_ROWS;
     91 }
     92 
     93 inline
     94 uint8_t matrix_cols(void)
     95 {
     96     return MATRIX_COLS;
     97 }
     98 
     99 void matrix_init(void)
    100 {
    101     debug_enable = true;
    102     debug_matrix = true;
    103     debug_mouse = true;
    104     // initialize row and col
    105     unselect_cols();
    106     init_rows();
    107 //    init_lcols();
    108 
    109     // initialize matrix state: all keys off
    110     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
    111         matrix[i] = 0;
    112         matrix_debouncing[i] = 0;
    113     }
    114 
    115     matrix_init_kb();
    116 
    117 }
    118 
    119 uint8_t _matrix_scan(void)
    120 {
    121     // Set col, read rows
    122     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
    123 #       if (DEBOUNCE > 0)
    124             bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
    125             if (matrix_changed) {
    126                 debouncing = true;
    127                 debouncing_time = timer_read();
    128             }
    129 #       else
    130              read_rows_on_col(matrix, current_col);
    131 #       endif
    132 
    133     }
    134 
    135 #   if (DEBOUNCE > 0)
    136         if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) {
    137             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    138                 matrix[i] = matrix_debouncing[i];
    139             }
    140             debouncing = false;
    141         }
    142 #   endif
    143 
    144 	return 1;
    145 }
    146 
    147 uint8_t matrix_scan(void)
    148 {
    149 	uint8_t ret = _matrix_scan();
    150 	matrix_scan_kb();
    151 	return ret;
    152 }
    153 
    154 inline
    155 bool matrix_is_on(uint8_t row, uint8_t col)
    156 {
    157     return (matrix[row] & ((matrix_row_t)1<<col));
    158 }
    159 
    160 inline
    161 matrix_row_t matrix_get_row(uint8_t row)
    162 {
    163     return matrix[row];
    164 }
    165 
    166 void matrix_print(void)
    167 {
    168     print("\nr/c 0123456789ABCDEF\n");
    169     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    170         print_hex8(row); print(": ");
    171         print_bin_reverse16(matrix_get_row(row));
    172         print("\n");
    173     }
    174 }
    175 
    176 static void init_rows(void)
    177 {
    178     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
    179         uint8_t pin = row_pins[x];
    180         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    181         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    182     }
    183 }
    184 
    185 
    186 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
    187 {
    188     bool matrix_changed = false;
    189 
    190     // Select col and wait for col selection to stabilize
    191     select_col(current_col);
    192     wait_us(30);
    193 
    194     // For each row...
    195     for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
    196     {
    197 
    198         // Store last value of row prior to reading
    199         matrix_row_t last_row_value = current_matrix[row_index];
    200 
    201         // Check row pin state
    202         if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
    203         {
    204             // Pin LO, set col bit
    205             current_matrix[row_index] |= (ROW_SHIFTER << current_col);
    206         }
    207         else
    208         {
    209             // Pin HI, clear col bit
    210             current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
    211         }
    212 
    213         // Determine if the matrix changed state
    214         if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
    215         {
    216             matrix_changed = true;
    217         }
    218     }
    219 
    220     // Unselect col
    221     unselect_cols();
    222 
    223     return matrix_changed;
    224 }
    225 
    226 static void select_col(uint8_t col)
    227 {
    228 #ifdef FLIPPED_BOARD
    229 	col = MATRIX_COLS - col - 1;
    230 #endif
    231     for(uint8_t x = 0; x < 4; x++) {
    232 		uint8_t pin = col_pins[x];
    233         _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
    234 		if (((col >> x) & 0x1) == 1){
    235 			_SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HIGH
    236 		} else {
    237 			_SFR_IO8((pin >> 4) + 2) &=  ~_BV(pin & 0xF); // LOW
    238 		}
    239 	}
    240 }
    241 
    242 static void unselect_cols(void)
    243 {
    244 	// FIXME This really needs to use the global enable on the decoder, because currently this sets the value to col1
    245     for(uint8_t x = 0; x < 4; x++) {
    246         uint8_t pin = col_pins[x];
    247         _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
    248         _SFR_IO8((pin >> 4) + 2) &=  ~_BV(pin & 0xF); // LOW
    249     }
    250 }